diff options
| author | Eli Zaretskii | 2011-06-08 21:01:56 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-06-08 21:01:56 +0300 |
| commit | 87e67904f15fda542426c9159c95a19142aecbad (patch) | |
| tree | e5ccb1ee1fdb9e135f2f8a7f3e09a382cdd2beef /src | |
| parent | 9d68c2a9abaddbed86a1b2f166625c93e8f88326 (diff) | |
| download | emacs-87e67904f15fda542426c9159c95a19142aecbad.tar.gz emacs-87e67904f15fda542426c9159c95a19142aecbad.zip | |
Started work on string reordering. Just compiled, not yet tested.
src/bidi.c (bidi_paragraph_info): Delete unused struct.
(bidi_cache_idx, bidi_cache_last_idx): Declare EMACS_INT.
(bidi_cache_start): New variable.
(bidi_cache_reset): Reset bidi_cache_idx to bidi_cache_start, not
to zero.
(bidi_cache_fetch_state, bidi_cache_search)
(bidi_cache_find_level_change, bidi_cache_iterator_state)
(bidi_cache_find, bidi_peek_at_next_level)
(bidi_level_of_next_char, bidi_find_other_level_edge)
(bidi_move_to_visually_next): Compare cache index with
bidi_cache_start rather than with zero.
(bidi_fetch_char): Accept new argument STRING; all callers
changed. Support iteration over a string.
(bidi_paragraph_init, bidi_resolve_explicit_1)
(bidi_resolve_explicit, bidi_resolve_weak)
(bidi_level_of_next_char, bidi_move_to_visually_next): Support
iteration over a string.
(bidi_set_sor_type, bidi_resolve_explicit_1)
(bidi_resolve_explicit, bidi_type_of_next_char): ignore_bn_limit
can now be zero (for strings); special values 0 and -1 were
changed to -1 and -2, respectively.
(bidi_char_at_pos): New function.
(bidi_paragraph_init, bidi_resolve_explicit, bidi_resolve_weak):
Call it instead of FETCH_MULTIBYTE_CHAR.
(bidi_move_to_visually_next): Abort if charpos or bytepos were not
initialized to valid values.
(bidi_init_it): Don't initialize charpos and bytepos with invalid
values.
src/xdisp.c (compute_display_string_pos)
(compute_display_string_end): Accept additional argument STRING.
(init_iterator, reseat_1): Initialize bidi_it->string.s to NULL.
(reseat_to_string): Initialize bidi_it->string.s and
bidi_it->string.schars.
src/dispextern.h (struct bidi_string_data): New structure.
(struct bidi_it): New member `string'. Make flag members be 1-bit
fields, and put them last in the struct.
(compute_display_string_pos, compute_display_string_end): Update
prototypes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 43 | ||||
| -rw-r--r-- | src/bidi.c | 328 | ||||
| -rw-r--r-- | src/dispextern.h | 24 | ||||
| -rw-r--r-- | src/xdisp.c | 39 |
4 files changed, 312 insertions, 122 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 63353b31d4d..c303839b14d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,46 @@ | |||
| 1 | 2011-06-08 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * bidi.c (bidi_paragraph_info): Delete unused struct. | ||
| 4 | (bidi_cache_idx, bidi_cache_last_idx): Declare EMACS_INT. | ||
| 5 | (bidi_cache_start): New variable. | ||
| 6 | (bidi_cache_reset): Reset bidi_cache_idx to bidi_cache_start, not | ||
| 7 | to zero. | ||
| 8 | (bidi_cache_fetch_state, bidi_cache_search) | ||
| 9 | (bidi_cache_find_level_change, bidi_cache_iterator_state) | ||
| 10 | (bidi_cache_find, bidi_peek_at_next_level) | ||
| 11 | (bidi_level_of_next_char, bidi_find_other_level_edge) | ||
| 12 | (bidi_move_to_visually_next): Compare cache index with | ||
| 13 | bidi_cache_start rather than with zero. | ||
| 14 | (bidi_fetch_char): Accept new argument STRING; all callers | ||
| 15 | changed. Support iteration over a string. | ||
| 16 | (bidi_paragraph_init, bidi_resolve_explicit_1) | ||
| 17 | (bidi_resolve_explicit, bidi_resolve_weak) | ||
| 18 | (bidi_level_of_next_char, bidi_move_to_visually_next): Support | ||
| 19 | iteration over a string. | ||
| 20 | (bidi_set_sor_type, bidi_resolve_explicit_1) | ||
| 21 | (bidi_resolve_explicit, bidi_type_of_next_char): ignore_bn_limit | ||
| 22 | can now be zero (for strings); special values 0 and -1 were | ||
| 23 | changed to -1 and -2, respectively. | ||
| 24 | (bidi_char_at_pos): New function. | ||
| 25 | (bidi_paragraph_init, bidi_resolve_explicit, bidi_resolve_weak): | ||
| 26 | Call it instead of FETCH_MULTIBYTE_CHAR. | ||
| 27 | (bidi_move_to_visually_next): Abort if charpos or bytepos were not | ||
| 28 | initialized to valid values. | ||
| 29 | (bidi_init_it): Don't initialize charpos and bytepos with invalid | ||
| 30 | values. | ||
| 31 | |||
| 32 | * xdisp.c (compute_display_string_pos) | ||
| 33 | (compute_display_string_end): Accept additional argument STRING. | ||
| 34 | (init_iterator, reseat_1): Initialize bidi_it->string.s to NULL. | ||
| 35 | (reseat_to_string): Initialize bidi_it->string.s and | ||
| 36 | bidi_it->string.schars. | ||
| 37 | |||
| 38 | * dispextern.h (struct bidi_string_data): New structure. | ||
| 39 | (struct bidi_it): New member `string'. Make flag members be 1-bit | ||
| 40 | fields, and put them last in the struct. | ||
| 41 | (compute_display_string_pos, compute_display_string_end): Update | ||
| 42 | prototypes. | ||
| 43 | |||
| 1 | 2011-06-04 Eli Zaretskii <eliz@gnu.org> | 44 | 2011-06-04 Eli Zaretskii <eliz@gnu.org> |
| 2 | 45 | ||
| 3 | * bidi.c (bidi_level_of_next_char): clen should be EMACS_NT, not int. | 46 | * bidi.c (bidi_level_of_next_char): clen should be EMACS_NT, not int. |
diff --git a/src/bidi.c b/src/bidi.c index ccf21827fc1..ac950a9000a 100644 --- a/src/bidi.c +++ b/src/bidi.c | |||
| @@ -66,16 +66,6 @@ static Lisp_Object bidi_type_table, bidi_mirror_table; | |||
| 66 | #define RLM_CHAR 0x200F | 66 | #define RLM_CHAR 0x200F |
| 67 | #define BIDI_EOB -1 | 67 | #define BIDI_EOB -1 |
| 68 | 68 | ||
| 69 | /* Local data structures. (Look in dispextern.h for the rest.) */ | ||
| 70 | |||
| 71 | /* What we need to know about the current paragraph. */ | ||
| 72 | struct bidi_paragraph_info { | ||
| 73 | EMACS_INT start_bytepos; /* byte position where it begins */ | ||
| 74 | EMACS_INT end_bytepos; /* byte position where it ends */ | ||
| 75 | int embedding_level; /* its basic embedding level */ | ||
| 76 | bidi_dir_t base_dir; /* its base direction */ | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* Data type for describing the bidirectional character categories. */ | 69 | /* Data type for describing the bidirectional character categories. */ |
| 80 | typedef enum { | 70 | typedef enum { |
| 81 | UNKNOWN_BC, | 71 | UNKNOWN_BC, |
| @@ -265,16 +255,28 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from) | |||
| 265 | static struct bidi_it *bidi_cache; | 255 | static struct bidi_it *bidi_cache; |
| 266 | static size_t bidi_cache_size = 0; | 256 | static size_t bidi_cache_size = 0; |
| 267 | static size_t elsz = sizeof (struct bidi_it); | 257 | static size_t elsz = sizeof (struct bidi_it); |
| 268 | static int bidi_cache_idx; /* next unused cache slot */ | 258 | static EMACS_INT bidi_cache_idx; /* next unused cache slot */ |
| 269 | static int bidi_cache_last_idx; /* slot of last cache hit */ | 259 | static EMACS_INT bidi_cache_last_idx; /* slot of last cache hit */ |
| 270 | 260 | static EMACS_INT bidi_cache_start = 0; /* start of cache for this | |
| 261 | "stack" level */ | ||
| 262 | |||
| 263 | /* Reset the cache state to the empty state. We only reset the part | ||
| 264 | of the cache relevant to iteration of the current object. Previous | ||
| 265 | objects, which are pushed on the display iterator's stack, are left | ||
| 266 | intact. This is called when the cached information is no more | ||
| 267 | useful for the current iteration, e.g. when we were reseated to a | ||
| 268 | new position on the same object. */ | ||
| 271 | static INLINE void | 269 | static INLINE void |
| 272 | bidi_cache_reset (void) | 270 | bidi_cache_reset (void) |
| 273 | { | 271 | { |
| 274 | bidi_cache_idx = 0; | 272 | bidi_cache_idx = bidi_cache_start; |
| 275 | bidi_cache_last_idx = -1; | 273 | bidi_cache_last_idx = -1; |
| 276 | } | 274 | } |
| 277 | 275 | ||
| 276 | /* Shrink the cache to its minimal size. Called when we init the bidi | ||
| 277 | iterator for reordering a buffer or a string that does not come | ||
| 278 | from display properties, because that means all the previously | ||
| 279 | cached info is of no further use. */ | ||
| 278 | static INLINE void | 280 | static INLINE void |
| 279 | bidi_cache_shrink (void) | 281 | bidi_cache_shrink (void) |
| 280 | { | 282 | { |
| @@ -292,7 +294,7 @@ bidi_cache_fetch_state (int idx, struct bidi_it *bidi_it) | |||
| 292 | { | 294 | { |
| 293 | int current_scan_dir = bidi_it->scan_dir; | 295 | int current_scan_dir = bidi_it->scan_dir; |
| 294 | 296 | ||
| 295 | if (idx < 0 || idx >= bidi_cache_idx) | 297 | if (idx < bidi_cache_start || idx >= bidi_cache_idx) |
| 296 | abort (); | 298 | abort (); |
| 297 | 299 | ||
| 298 | bidi_copy_it (bidi_it, &bidi_cache[idx]); | 300 | bidi_copy_it (bidi_it, &bidi_cache[idx]); |
| @@ -333,7 +335,7 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir) | |||
| 333 | if (dir < 0) | 335 | if (dir < 0) |
| 334 | { | 336 | { |
| 335 | /* Linear search for now; FIXME! */ | 337 | /* Linear search for now; FIXME! */ |
| 336 | for (i = i_start; i >= 0; i--) | 338 | for (i = i_start; i >= bidi_cache_start; i--) |
| 337 | if (bidi_cache[i].charpos <= charpos | 339 | if (bidi_cache[i].charpos <= charpos |
| 338 | && charpos < bidi_cache[i].charpos + bidi_cache[i].nchars | 340 | && charpos < bidi_cache[i].charpos + bidi_cache[i].nchars |
| 339 | && (level == -1 || bidi_cache[i].resolved_level <= level)) | 341 | && (level == -1 || bidi_cache[i].resolved_level <= level)) |
| @@ -355,8 +357,9 @@ bidi_cache_search (EMACS_INT charpos, int level, int dir) | |||
| 355 | /* Find a cached state where the resolved level changes to a value | 357 | /* Find a cached state where the resolved level changes to a value |
| 356 | that is lower than LEVEL, and return its cache slot index. DIR is | 358 | that is lower than LEVEL, and return its cache slot index. DIR is |
| 357 | the direction to search, starting with the last used cache slot. | 359 | the direction to search, starting with the last used cache slot. |
| 358 | BEFORE, if non-zero, means return the index of the slot that is | 360 | If DIR is zero, we search backwards from the last occupied cache |
| 359 | ``before'' the level change in the search direction. That is, | 361 | slot. BEFORE, if non-zero, means return the index of the slot that |
| 362 | is ``before'' the level change in the search direction. That is, | ||
| 360 | given the cached levels like this: | 363 | given the cached levels like this: |
| 361 | 364 | ||
| 362 | 1122333442211 | 365 | 1122333442211 |
| @@ -381,7 +384,7 @@ bidi_cache_find_level_change (int level, int dir, int before) | |||
| 381 | 384 | ||
| 382 | if (dir < 0) | 385 | if (dir < 0) |
| 383 | { | 386 | { |
| 384 | while (i >= incr) | 387 | while (i >= bidi_cache_start + incr) |
| 385 | { | 388 | { |
| 386 | if (bidi_cache[i - incr].resolved_level >= 0 | 389 | if (bidi_cache[i - incr].resolved_level >= 0 |
| 387 | && bidi_cache[i - incr].resolved_level < level) | 390 | && bidi_cache[i - incr].resolved_level < level) |
| @@ -427,13 +430,13 @@ bidi_cache_iterator_state (struct bidi_it *bidi_it, int resolved) | |||
| 427 | /* Character positions should correspond to cache positions 1:1. | 430 | /* Character positions should correspond to cache positions 1:1. |
| 428 | If we are outside the range of cached positions, the cache is | 431 | If we are outside the range of cached positions, the cache is |
| 429 | useless and must be reset. */ | 432 | useless and must be reset. */ |
| 430 | if (idx > 0 && | 433 | if (idx > bidi_cache_start && |
| 431 | (bidi_it->charpos > (bidi_cache[idx - 1].charpos | 434 | (bidi_it->charpos > (bidi_cache[idx - 1].charpos |
| 432 | + bidi_cache[idx - 1].nchars) | 435 | + bidi_cache[idx - 1].nchars) |
| 433 | || bidi_it->charpos < bidi_cache[0].charpos)) | 436 | || bidi_it->charpos < bidi_cache[0].charpos)) |
| 434 | { | 437 | { |
| 435 | bidi_cache_reset (); | 438 | bidi_cache_reset (); |
| 436 | idx = 0; | 439 | idx = bidi_cache_start; |
| 437 | } | 440 | } |
| 438 | if (bidi_it->nchars <= 0) | 441 | if (bidi_it->nchars <= 0) |
| 439 | abort (); | 442 | abort (); |
| @@ -470,7 +473,7 @@ bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it) | |||
| 470 | { | 473 | { |
| 471 | int i = bidi_cache_search (charpos, level, bidi_it->scan_dir); | 474 | int i = bidi_cache_search (charpos, level, bidi_it->scan_dir); |
| 472 | 475 | ||
| 473 | if (i >= 0) | 476 | if (i >= bidi_cache_start) |
| 474 | { | 477 | { |
| 475 | bidi_dir_t current_scan_dir = bidi_it->scan_dir; | 478 | bidi_dir_t current_scan_dir = bidi_it->scan_dir; |
| 476 | 479 | ||
| @@ -488,7 +491,7 @@ bidi_cache_find (EMACS_INT charpos, int level, struct bidi_it *bidi_it) | |||
| 488 | static INLINE int | 491 | static INLINE int |
| 489 | bidi_peek_at_next_level (struct bidi_it *bidi_it) | 492 | bidi_peek_at_next_level (struct bidi_it *bidi_it) |
| 490 | { | 493 | { |
| 491 | if (bidi_cache_idx == 0 || bidi_cache_last_idx == -1) | 494 | if (bidi_cache_idx == bidi_cache_start || bidi_cache_last_idx == -1) |
| 492 | abort (); | 495 | abort (); |
| 493 | return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level; | 496 | return bidi_cache[bidi_cache_last_idx + bidi_it->scan_dir].resolved_level; |
| 494 | } | 497 | } |
| @@ -550,7 +553,7 @@ bidi_set_sor_type (struct bidi_it *bidi_it, int level_before, int level_after) | |||
| 550 | bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos; | 553 | bidi_it->prev_for_neutral.bytepos = bidi_it->bytepos; |
| 551 | bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1 = | 554 | bidi_it->next_for_neutral.type = bidi_it->next_for_neutral.type_after_w1 = |
| 552 | bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; | 555 | bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; |
| 553 | bidi_it->ignore_bn_limit = 0; /* meaning it's unknown */ | 556 | bidi_it->ignore_bn_limit = -1; /* meaning it's unknown */ |
| 554 | } | 557 | } |
| 555 | 558 | ||
| 556 | /* Perform initializations for reordering a new line of bidi text. */ | 559 | /* Perform initializations for reordering a new line of bidi text. */ |
| @@ -571,6 +574,40 @@ bidi_line_init (struct bidi_it *bidi_it) | |||
| 571 | bidi_cache_reset (); | 574 | bidi_cache_reset (); |
| 572 | } | 575 | } |
| 573 | 576 | ||
| 577 | /* Count bytes in multibyte string S between BEG/BEGBYTE and END. BEG | ||
| 578 | and END are zero-based character positions in S, BEGBYTE is byte | ||
| 579 | position corresponding to BEG. */ | ||
| 580 | static inline EMACS_INT | ||
| 581 | bidi_count_bytes (const unsigned char *s, const EMACS_INT beg, | ||
| 582 | const EMACS_INT begbyte, const EMACS_INT end) | ||
| 583 | { | ||
| 584 | EMACS_INT pos = beg; | ||
| 585 | const unsigned char *p = s + begbyte, *start = p; | ||
| 586 | |||
| 587 | if (!CHAR_HEAD_P (*p)) | ||
| 588 | abort (); | ||
| 589 | |||
| 590 | while (pos < end) | ||
| 591 | { | ||
| 592 | p += BYTES_BY_CHAR_HEAD (*p); | ||
| 593 | pos++; | ||
| 594 | } | ||
| 595 | |||
| 596 | return p - start; | ||
| 597 | } | ||
| 598 | |||
| 599 | /* Fetch and returns the character at byte position BYTEPOS. If S is | ||
| 600 | non-NULL, fetch the character from string S; otherwise fetch the | ||
| 601 | character from the current buffer. */ | ||
| 602 | static inline int | ||
| 603 | bidi_char_at_pos (EMACS_INT bytepos, const unsigned char *s) | ||
| 604 | { | ||
| 605 | if (s) | ||
| 606 | return STRING_CHAR (s + bytepos); | ||
| 607 | else | ||
| 608 | return FETCH_MULTIBYTE_CHAR (bytepos); | ||
| 609 | } | ||
| 610 | |||
| 574 | /* Fetch and return the character at BYTEPOS/CHARPOS. If that | 611 | /* Fetch and return the character at BYTEPOS/CHARPOS. If that |
| 575 | character is covered by a display string, treat the entire run of | 612 | character is covered by a display string, treat the entire run of |
| 576 | covered characters as a single character u+FFFC, and return their | 613 | covered characters as a single character u+FFFC, and return their |
| @@ -578,26 +615,28 @@ bidi_line_init (struct bidi_it *bidi_it) | |||
| 578 | character position of the next display string, or -1 if not yet | 615 | character position of the next display string, or -1 if not yet |
| 579 | computed. When the next character is at or beyond that position, | 616 | computed. When the next character is at or beyond that position, |
| 580 | the function updates DISP_POS with the position of the next display | 617 | the function updates DISP_POS with the position of the next display |
| 581 | string. */ | 618 | string. STRING->s is the string to iterate, or NULL if iterating over |
| 582 | static INLINE int | 619 | a buffer. */ |
| 620 | static inline int | ||
| 583 | bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos, | 621 | bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos, |
| 622 | struct bidi_string_data *string, | ||
| 584 | int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars) | 623 | int frame_window_p, EMACS_INT *ch_len, EMACS_INT *nchars) |
| 585 | { | 624 | { |
| 586 | int ch; | 625 | int ch; |
| 626 | EMACS_INT endpos = string->s ? string->schars : ZV; | ||
| 587 | 627 | ||
| 588 | /* FIXME: Support strings in addition to buffers. */ | ||
| 589 | /* If we got past the last known position of display string, compute | 628 | /* 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. */ | 629 | the position of the next one. That position could be at CHARPOS. */ |
| 591 | if (charpos < ZV && charpos > *disp_pos) | 630 | if (charpos < endpos && charpos > *disp_pos) |
| 592 | *disp_pos = compute_display_string_pos (charpos, frame_window_p); | 631 | *disp_pos = compute_display_string_pos (charpos, string, frame_window_p); |
| 593 | 632 | ||
| 594 | /* Fetch the character at BYTEPOS. */ | 633 | /* Fetch the character at BYTEPOS. */ |
| 595 | if (bytepos >= ZV_BYTE) | 634 | if (charpos >= endpos) |
| 596 | { | 635 | { |
| 597 | ch = BIDI_EOB; | 636 | ch = BIDI_EOB; |
| 598 | *ch_len = 1; | 637 | *ch_len = 1; |
| 599 | *nchars = 1; | 638 | *nchars = 1; |
| 600 | *disp_pos = ZV; | 639 | *disp_pos = endpos; |
| 601 | } | 640 | } |
| 602 | else if (charpos >= *disp_pos) | 641 | else if (charpos >= *disp_pos) |
| 603 | { | 642 | { |
| @@ -608,24 +647,38 @@ bidi_fetch_char (EMACS_INT bytepos, EMACS_INT charpos, EMACS_INT *disp_pos, | |||
| 608 | if (charpos > *disp_pos) | 647 | if (charpos > *disp_pos) |
| 609 | abort (); | 648 | abort (); |
| 610 | /* Return the Unicode Object Replacement Character to represent | 649 | /* Return the Unicode Object Replacement Character to represent |
| 611 | the entire run of characters covered by the display | 650 | the entire run of characters covered by the display string. */ |
| 612 | string. */ | ||
| 613 | ch = 0xFFFC; | 651 | ch = 0xFFFC; |
| 614 | disp_end_pos = compute_display_string_end (*disp_pos); | 652 | disp_end_pos = compute_display_string_end (*disp_pos, string); |
| 615 | *nchars = disp_end_pos - *disp_pos; | 653 | *nchars = disp_end_pos - *disp_pos; |
| 616 | *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos; | 654 | if (string->s) |
| 655 | *ch_len = bidi_count_bytes (string->s, *disp_pos, bytepos, | ||
| 656 | disp_end_pos); | ||
| 657 | else | ||
| 658 | *ch_len = CHAR_TO_BYTE (disp_end_pos) - bytepos; | ||
| 617 | } | 659 | } |
| 618 | else | 660 | else |
| 619 | { | 661 | { |
| 620 | ch = FETCH_MULTIBYTE_CHAR (bytepos); | 662 | if (string->s) |
| 663 | { | ||
| 664 | EMACS_INT len; | ||
| 665 | |||
| 666 | ch = STRING_CHAR_AND_LENGTH (string->s + bytepos, len); | ||
| 667 | *ch_len = len; | ||
| 668 | } | ||
| 669 | else | ||
| 670 | { | ||
| 671 | ch = FETCH_MULTIBYTE_CHAR (bytepos); | ||
| 672 | *ch_len = CHAR_BYTES (ch); | ||
| 673 | } | ||
| 621 | *nchars = 1; | 674 | *nchars = 1; |
| 622 | *ch_len = CHAR_BYTES (ch); | ||
| 623 | } | 675 | } |
| 624 | 676 | ||
| 625 | /* If we just entered a run of characters covered by a display | 677 | /* If we just entered a run of characters covered by a display |
| 626 | string, compute the position of the next display string. */ | 678 | string, compute the position of the next display string. */ |
| 627 | if (charpos + *nchars <= ZV && charpos + *nchars > *disp_pos) | 679 | if (charpos + *nchars <= endpos && charpos + *nchars > *disp_pos) |
| 628 | *disp_pos = compute_display_string_pos (charpos + *nchars, frame_window_p); | 680 | *disp_pos = compute_display_string_pos (charpos + *nchars, string, |
| 681 | frame_window_p); | ||
| 629 | 682 | ||
| 630 | return ch; | 683 | return ch; |
| 631 | } | 684 | } |
| @@ -670,13 +723,19 @@ void | |||
| 670 | bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | 723 | bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) |
| 671 | { | 724 | { |
| 672 | EMACS_INT bytepos = bidi_it->bytepos; | 725 | EMACS_INT bytepos = bidi_it->bytepos; |
| 726 | int string_p = bidi_it->string.s != NULL; | ||
| 673 | EMACS_INT pstartbyte; | 727 | EMACS_INT pstartbyte; |
| 728 | /* Note that begbyte is a byte position, while end is a character | ||
| 729 | position. Yes, this is ugly, but we are trying to avoid costly | ||
| 730 | calls to BYTE_TO_CHAR and its ilk. */ | ||
| 731 | EMACS_INT begbyte = string_p ? 0 : BEGV_BYTE; | ||
| 732 | EMACS_INT end = string_p ? bidi_it->string.schars : ZV; | ||
| 674 | 733 | ||
| 675 | /* Special case for an empty buffer. */ | 734 | /* Special case for an empty buffer. */ |
| 676 | if (bytepos == BEGV_BYTE && bytepos == ZV_BYTE) | 735 | if (bytepos == begbyte && bidi_it->charpos == end) |
| 677 | dir = L2R; | 736 | dir = L2R; |
| 678 | /* We should never be called at EOB or before BEGV. */ | 737 | /* We should never be called at EOB or before BEGV. */ |
| 679 | else if (bytepos >= ZV_BYTE || bytepos < BEGV_BYTE) | 738 | else if (bidi_it->charpos >= end || bytepos < begbyte) |
| 680 | abort (); | 739 | abort (); |
| 681 | 740 | ||
| 682 | if (dir == L2R) | 741 | if (dir == L2R) |
| @@ -712,7 +771,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 712 | we are potentially in a new paragraph that doesn't yet | 771 | we are potentially in a new paragraph that doesn't yet |
| 713 | exist. */ | 772 | exist. */ |
| 714 | pos = bidi_it->charpos; | 773 | pos = bidi_it->charpos; |
| 715 | if (bytepos > BEGV_BYTE && FETCH_CHAR (bytepos) == '\n') | 774 | if (bytepos > begbyte |
| 775 | && bidi_char_at_pos (bytepos, bidi_it->string.s) == '\n') | ||
| 716 | { | 776 | { |
| 717 | bytepos++; | 777 | bytepos++; |
| 718 | pos++; | 778 | pos++; |
| @@ -720,17 +780,25 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 720 | 780 | ||
| 721 | /* We are either at the beginning of a paragraph or in the | 781 | /* We are either at the beginning of a paragraph or in the |
| 722 | middle of it. Find where this paragraph starts. */ | 782 | middle of it. Find where this paragraph starts. */ |
| 723 | pstartbyte = bidi_find_paragraph_start (pos, bytepos); | 783 | if (string_p) |
| 784 | { | ||
| 785 | /* We don't support changes of paragraph direction inside a | ||
| 786 | string. It is treated as a single paragraph. */ | ||
| 787 | pstartbyte = 0; | ||
| 788 | } | ||
| 789 | else | ||
| 790 | pstartbyte = bidi_find_paragraph_start (pos, bytepos); | ||
| 724 | bidi_it->separator_limit = -1; | 791 | bidi_it->separator_limit = -1; |
| 725 | bidi_it->new_paragraph = 0; | 792 | bidi_it->new_paragraph = 0; |
| 726 | 793 | ||
| 727 | /* The following loop is run more than once only if NO_DEFAULT_P | 794 | /* The following loop is run more than once only if NO_DEFAULT_P |
| 728 | is non-zero. */ | 795 | is non-zero, and only if we are iterating on a buffer. */ |
| 729 | do { | 796 | do { |
| 730 | bytepos = pstartbyte; | 797 | bytepos = pstartbyte; |
| 731 | pos = BYTE_TO_CHAR (bytepos); | 798 | if (!string_p) |
| 732 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, bidi_it->frame_window_p, | 799 | pos = BYTE_TO_CHAR (bytepos); |
| 733 | &ch_len, &nchars); | 800 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, &bidi_it->string, |
| 801 | bidi_it->frame_window_p, &ch_len, &nchars); | ||
| 734 | type = bidi_get_type (ch, NEUTRAL_DIR); | 802 | type = bidi_get_type (ch, NEUTRAL_DIR); |
| 735 | 803 | ||
| 736 | for (pos += nchars, bytepos += ch_len; | 804 | for (pos += nchars, bytepos += ch_len; |
| @@ -744,17 +812,19 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 744 | || type == LRE || type == LRO)); | 812 | || type == LRE || type == LRO)); |
| 745 | type = bidi_get_type (ch, NEUTRAL_DIR)) | 813 | type = bidi_get_type (ch, NEUTRAL_DIR)) |
| 746 | { | 814 | { |
| 747 | if (type == NEUTRAL_B && bidi_at_paragraph_end (pos, bytepos) >= -1) | 815 | if (!string_p |
| 816 | && type == NEUTRAL_B | ||
| 817 | && bidi_at_paragraph_end (pos, bytepos) >= -1) | ||
| 748 | break; | 818 | break; |
| 749 | if (bytepos >= ZV_BYTE) | 819 | if (pos >= end) |
| 750 | { | 820 | { |
| 751 | /* Pretend there's a paragraph separator at end of | 821 | /* Pretend there's a paragraph separator at end of |
| 752 | buffer. */ | 822 | buffer/string. */ |
| 753 | type = NEUTRAL_B; | 823 | type = NEUTRAL_B; |
| 754 | break; | 824 | break; |
| 755 | } | 825 | } |
| 756 | /* Fetch next character and advance to get past it. */ | 826 | /* Fetch next character and advance to get past it. */ |
| 757 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, | 827 | ch = bidi_fetch_char (bytepos, pos, &disp_pos, &bidi_it->string, |
| 758 | bidi_it->frame_window_p, &ch_len, &nchars); | 828 | bidi_it->frame_window_p, &ch_len, &nchars); |
| 759 | pos += nchars; | 829 | pos += nchars; |
| 760 | bytepos += ch_len; | 830 | bytepos += ch_len; |
| @@ -763,7 +833,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 763 | bidi_it->paragraph_dir = R2L; | 833 | bidi_it->paragraph_dir = R2L; |
| 764 | else if (type == STRONG_L) | 834 | else if (type == STRONG_L) |
| 765 | bidi_it->paragraph_dir = L2R; | 835 | bidi_it->paragraph_dir = L2R; |
| 766 | if (no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR) | 836 | if (!string_p |
| 837 | && no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR) | ||
| 767 | { | 838 | { |
| 768 | /* If this paragraph is at BEGV, default to L2R. */ | 839 | /* If this paragraph is at BEGV, default to L2R. */ |
| 769 | if (pstartbyte == BEGV_BYTE) | 840 | if (pstartbyte == BEGV_BYTE) |
| @@ -786,7 +857,8 @@ bidi_paragraph_init (bidi_dir_t dir, struct bidi_it *bidi_it, int no_default_p) | |||
| 786 | pstartbyte = prevpbyte; | 857 | pstartbyte = prevpbyte; |
| 787 | } | 858 | } |
| 788 | } | 859 | } |
| 789 | } while (no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR); | 860 | } while (!string_p |
| 861 | && no_default_p && bidi_it->paragraph_dir == NEUTRAL_DIR); | ||
| 790 | } | 862 | } |
| 791 | else | 863 | else |
| 792 | abort (); | 864 | abort (); |
| @@ -822,8 +894,10 @@ bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, int frame_window_p, | |||
| 822 | { | 894 | { |
| 823 | if (! bidi_initialized) | 895 | if (! bidi_initialized) |
| 824 | bidi_initialize (); | 896 | bidi_initialize (); |
| 825 | bidi_it->charpos = charpos; | 897 | if (charpos >= 0) |
| 826 | bidi_it->bytepos = bytepos; | 898 | bidi_it->charpos = charpos; |
| 899 | if (bytepos >= 0) | ||
| 900 | bidi_it->bytepos = bytepos; | ||
| 827 | bidi_it->frame_window_p = frame_window_p; | 901 | bidi_it->frame_window_p = frame_window_p; |
| 828 | bidi_it->nchars = -1; /* to be computed in bidi_resolve_explicit_1 */ | 902 | bidi_it->nchars = -1; /* to be computed in bidi_resolve_explicit_1 */ |
| 829 | bidi_it->first_elt = 1; | 903 | bidi_it->first_elt = 1; |
| @@ -848,7 +922,10 @@ bidi_init_it (EMACS_INT charpos, EMACS_INT bytepos, int frame_window_p, | |||
| 848 | bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; | 922 | bidi_it->prev_for_neutral.orig_type = UNKNOWN_BT; |
| 849 | bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */ | 923 | bidi_it->sor = L2R; /* FIXME: should it be user-selectable? */ |
| 850 | bidi_it->disp_pos = -1; /* invalid/unknown */ | 924 | bidi_it->disp_pos = -1; /* invalid/unknown */ |
| 851 | bidi_cache_shrink (); | 925 | /* We can only shrink the cache if we are at the bottom level of its |
| 926 | "stack". */ | ||
| 927 | if (bidi_cache_start == 0) | ||
| 928 | bidi_cache_shrink (); | ||
| 852 | } | 929 | } |
| 853 | 930 | ||
| 854 | /* Push the current embedding level and override status; reset the | 931 | /* Push the current embedding level and override status; reset the |
| @@ -934,19 +1011,31 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 934 | int current_level; | 1011 | int current_level; |
| 935 | int new_level; | 1012 | int new_level; |
| 936 | bidi_dir_t override; | 1013 | bidi_dir_t override; |
| 1014 | int string_p = bidi_it->string.s != NULL; | ||
| 937 | 1015 | ||
| 938 | /* If reseat()'ed, don't advance, so as to start iteration from the | 1016 | /* 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 | 1017 | position where we were reseated. bidi_it->bytepos can be less |
| 940 | than BEGV_BYTE after reseat to BEGV. */ | 1018 | than BEGV_BYTE after reseat to BEGV. */ |
| 941 | if (bidi_it->bytepos < BEGV_BYTE | 1019 | if (bidi_it->bytepos < (string_p ? 0 : BEGV_BYTE) |
| 942 | || bidi_it->first_elt) | 1020 | || bidi_it->first_elt) |
| 943 | { | 1021 | { |
| 944 | bidi_it->first_elt = 0; | 1022 | bidi_it->first_elt = 0; |
| 945 | if (bidi_it->charpos < BEGV) | 1023 | if (string_p) |
| 946 | bidi_it->charpos = BEGV; | 1024 | { |
| 947 | bidi_it->bytepos = CHAR_TO_BYTE (bidi_it->charpos); | 1025 | if (bidi_it->charpos < 0) |
| 1026 | bidi_it->charpos = 0; | ||
| 1027 | bidi_it->bytepos = bidi_count_bytes (bidi_it->string.s, 0, 0, | ||
| 1028 | bidi_it->charpos); | ||
| 1029 | } | ||
| 1030 | else | ||
| 1031 | { | ||
| 1032 | if (bidi_it->charpos < BEGV) | ||
| 1033 | bidi_it->charpos = BEGV; | ||
| 1034 | bidi_it->bytepos = CHAR_TO_BYTE (bidi_it->charpos); | ||
| 1035 | } | ||
| 948 | } | 1036 | } |
| 949 | else if (bidi_it->bytepos < ZV_BYTE) /* don't move at ZV */ | 1037 | /* Don't move at end of buffer/string. */ |
| 1038 | else if (bidi_it->charpos < (string_p ? bidi_it->string.schars : ZV)) | ||
| 950 | { | 1039 | { |
| 951 | /* Advance to the next character, skipping characters covered by | 1040 | /* Advance to the next character, skipping characters covered by |
| 952 | display strings (nchars > 1). */ | 1041 | display strings (nchars > 1). */ |
| @@ -962,12 +1051,12 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 962 | override = bidi_it->level_stack[bidi_it->stack_idx].override; | 1051 | override = bidi_it->level_stack[bidi_it->stack_idx].override; |
| 963 | new_level = current_level; | 1052 | new_level = current_level; |
| 964 | 1053 | ||
| 965 | if (bidi_it->bytepos >= ZV_BYTE) | 1054 | if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV)) |
| 966 | { | 1055 | { |
| 967 | curchar = BIDI_EOB; | 1056 | curchar = BIDI_EOB; |
| 968 | bidi_it->ch_len = 1; | 1057 | bidi_it->ch_len = 1; |
| 969 | bidi_it->nchars = 1; | 1058 | bidi_it->nchars = 1; |
| 970 | bidi_it->disp_pos = ZV; | 1059 | bidi_it->disp_pos = (string_p ? bidi_it->string.schars : ZV); |
| 971 | } | 1060 | } |
| 972 | else | 1061 | else |
| 973 | { | 1062 | { |
| @@ -975,7 +1064,8 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 975 | display string, treat the entire run of covered characters as | 1064 | display string, treat the entire run of covered characters as |
| 976 | a single character u+FFFC. */ | 1065 | a single character u+FFFC. */ |
| 977 | curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos, | 1066 | curchar = bidi_fetch_char (bidi_it->bytepos, bidi_it->charpos, |
| 978 | &bidi_it->disp_pos, bidi_it->frame_window_p, | 1067 | &bidi_it->disp_pos, &bidi_it->string, |
| 1068 | bidi_it->frame_window_p, | ||
| 979 | &bidi_it->ch_len, &bidi_it->nchars); | 1069 | &bidi_it->ch_len, &bidi_it->nchars); |
| 980 | } | 1070 | } |
| 981 | bidi_it->ch = curchar; | 1071 | bidi_it->ch = curchar; |
| @@ -1000,7 +1090,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 1000 | bidi_it->type_after_w1 = type; | 1090 | bidi_it->type_after_w1 = type; |
| 1001 | bidi_check_type (bidi_it->type_after_w1); | 1091 | bidi_check_type (bidi_it->type_after_w1); |
| 1002 | type = WEAK_BN; /* X9/Retaining */ | 1092 | type = WEAK_BN; /* X9/Retaining */ |
| 1003 | if (bidi_it->ignore_bn_limit <= 0) | 1093 | if (bidi_it->ignore_bn_limit <= -1) |
| 1004 | { | 1094 | { |
| 1005 | if (current_level <= BIDI_MAXLEVEL - 4) | 1095 | if (current_level <= BIDI_MAXLEVEL - 4) |
| 1006 | { | 1096 | { |
| @@ -1033,7 +1123,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 1033 | bidi_it->type_after_w1 = type; | 1123 | bidi_it->type_after_w1 = type; |
| 1034 | bidi_check_type (bidi_it->type_after_w1); | 1124 | bidi_check_type (bidi_it->type_after_w1); |
| 1035 | type = WEAK_BN; /* X9/Retaining */ | 1125 | type = WEAK_BN; /* X9/Retaining */ |
| 1036 | if (bidi_it->ignore_bn_limit <= 0) | 1126 | if (bidi_it->ignore_bn_limit <= -1) |
| 1037 | { | 1127 | { |
| 1038 | if (current_level <= BIDI_MAXLEVEL - 5) | 1128 | if (current_level <= BIDI_MAXLEVEL - 5) |
| 1039 | { | 1129 | { |
| @@ -1068,7 +1158,7 @@ bidi_resolve_explicit_1 (struct bidi_it *bidi_it) | |||
| 1068 | bidi_it->type_after_w1 = type; | 1158 | bidi_it->type_after_w1 = type; |
| 1069 | bidi_check_type (bidi_it->type_after_w1); | 1159 | bidi_check_type (bidi_it->type_after_w1); |
| 1070 | type = WEAK_BN; /* X9/Retaining */ | 1160 | type = WEAK_BN; /* X9/Retaining */ |
| 1071 | if (bidi_it->ignore_bn_limit <= 0) | 1161 | if (bidi_it->ignore_bn_limit <= -1) |
| 1072 | { | 1162 | { |
| 1073 | if (!bidi_it->invalid_rl_levels) | 1163 | if (!bidi_it->invalid_rl_levels) |
| 1074 | { | 1164 | { |
| @@ -1111,13 +1201,15 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) | |||
| 1111 | { | 1201 | { |
| 1112 | int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; | 1202 | int prev_level = bidi_it->level_stack[bidi_it->stack_idx].level; |
| 1113 | int new_level = bidi_resolve_explicit_1 (bidi_it); | 1203 | int new_level = bidi_resolve_explicit_1 (bidi_it); |
| 1204 | EMACS_INT eob = bidi_it->string.s ? bidi_it->string.schars : ZV; | ||
| 1114 | 1205 | ||
| 1115 | if (prev_level < new_level | 1206 | if (prev_level < new_level |
| 1116 | && bidi_it->type == WEAK_BN | 1207 | && bidi_it->type == WEAK_BN |
| 1117 | && bidi_it->ignore_bn_limit == 0 /* only if not already known */ | 1208 | && bidi_it->ignore_bn_limit == -1 /* only if not already known */ |
| 1118 | && bidi_it->bytepos < ZV_BYTE /* not already at EOB */ | 1209 | && bidi_it->charpos < eob /* not already at EOB */ |
| 1119 | && bidi_explicit_dir_char (FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1210 | && bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos |
| 1120 | + bidi_it->ch_len))) | 1211 | + bidi_it->ch_len, |
| 1212 | bidi_it->string.s))) | ||
| 1121 | { | 1213 | { |
| 1122 | /* Avoid pushing and popping embedding levels if the level run | 1214 | /* Avoid pushing and popping embedding levels if the level run |
| 1123 | is empty, as this breaks level runs where it shouldn't. | 1215 | is empty, as this breaks level runs where it shouldn't. |
| @@ -1129,8 +1221,9 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) | |||
| 1129 | 1221 | ||
| 1130 | bidi_copy_it (&saved_it, bidi_it); | 1222 | bidi_copy_it (&saved_it, bidi_it); |
| 1131 | 1223 | ||
| 1132 | while (bidi_explicit_dir_char (FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1224 | while (bidi_explicit_dir_char (bidi_char_at_pos (bidi_it->bytepos |
| 1133 | + bidi_it->ch_len))) | 1225 | + bidi_it->ch_len, |
| 1226 | bidi_it->string.s))) | ||
| 1134 | { | 1227 | { |
| 1135 | /* This advances to the next character, skipping any | 1228 | /* This advances to the next character, skipping any |
| 1136 | characters covered by display strings. */ | 1229 | characters covered by display strings. */ |
| @@ -1142,10 +1235,10 @@ bidi_resolve_explicit (struct bidi_it *bidi_it) | |||
| 1142 | if (level == prev_level) /* empty embedding */ | 1235 | if (level == prev_level) /* empty embedding */ |
| 1143 | saved_it.ignore_bn_limit = bidi_it->charpos + bidi_it->nchars; | 1236 | saved_it.ignore_bn_limit = bidi_it->charpos + bidi_it->nchars; |
| 1144 | else /* this embedding is non-empty */ | 1237 | else /* this embedding is non-empty */ |
| 1145 | saved_it.ignore_bn_limit = -1; | 1238 | saved_it.ignore_bn_limit = -2; |
| 1146 | 1239 | ||
| 1147 | bidi_copy_it (bidi_it, &saved_it); | 1240 | bidi_copy_it (bidi_it, &saved_it); |
| 1148 | if (bidi_it->ignore_bn_limit > 0) | 1241 | if (bidi_it->ignore_bn_limit > -1) |
| 1149 | { | 1242 | { |
| 1150 | /* We pushed a level, but we shouldn't have. Undo that. */ | 1243 | /* We pushed a level, but we shouldn't have. Undo that. */ |
| 1151 | if (!bidi_it->invalid_rl_levels) | 1244 | if (!bidi_it->invalid_rl_levels) |
| @@ -1188,6 +1281,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 1188 | int next_char; | 1281 | int next_char; |
| 1189 | bidi_type_t type_of_next; | 1282 | bidi_type_t type_of_next; |
| 1190 | struct bidi_it saved_it; | 1283 | struct bidi_it saved_it; |
| 1284 | EMACS_INT eob = bidi_it->string.s ? bidi_it->string.schars : ZV; | ||
| 1191 | 1285 | ||
| 1192 | type = bidi_it->type; | 1286 | type = bidi_it->type; |
| 1193 | override = bidi_it->level_stack[bidi_it->stack_idx].override; | 1287 | override = bidi_it->level_stack[bidi_it->stack_idx].override; |
| @@ -1255,9 +1349,10 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 1255 | || bidi_it->prev.type_after_w1 == WEAK_AN))) | 1349 | || bidi_it->prev.type_after_w1 == WEAK_AN))) |
| 1256 | { | 1350 | { |
| 1257 | next_char = | 1351 | next_char = |
| 1258 | bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE | 1352 | bidi_it->charpos + bidi_it->nchars >= eob |
| 1259 | ? BIDI_EOB : FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1353 | ? BIDI_EOB |
| 1260 | + bidi_it->ch_len); | 1354 | : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, |
| 1355 | bidi_it->string.s); | ||
| 1261 | type_of_next = bidi_get_type (next_char, override); | 1356 | type_of_next = bidi_get_type (next_char, override); |
| 1262 | 1357 | ||
| 1263 | if (type_of_next == WEAK_BN | 1358 | if (type_of_next == WEAK_BN |
| @@ -1310,9 +1405,10 @@ bidi_resolve_weak (struct bidi_it *bidi_it) | |||
| 1310 | if (bidi_it->nchars <= 0) | 1405 | if (bidi_it->nchars <= 0) |
| 1311 | abort (); | 1406 | abort (); |
| 1312 | next_char = | 1407 | next_char = |
| 1313 | bidi_it->bytepos + bidi_it->ch_len >= ZV_BYTE | 1408 | bidi_it->charpos + bidi_it->nchars >= eob |
| 1314 | ? BIDI_EOB : FETCH_MULTIBYTE_CHAR (bidi_it->bytepos | 1409 | ? BIDI_EOB |
| 1315 | + bidi_it->ch_len); | 1410 | : bidi_char_at_pos (bidi_it->bytepos + bidi_it->ch_len, |
| 1411 | bidi_it->string.s); | ||
| 1316 | type_of_next = bidi_get_type (next_char, override); | 1412 | type_of_next = bidi_get_type (next_char, override); |
| 1317 | 1413 | ||
| 1318 | if (type_of_next == WEAK_ET | 1414 | if (type_of_next == WEAK_ET |
| @@ -1509,11 +1605,11 @@ bidi_type_of_next_char (struct bidi_it *bidi_it) | |||
| 1509 | 1605 | ||
| 1510 | /* Reset the limit until which to ignore BNs if we step out of the | 1606 | /* Reset the limit until which to ignore BNs if we step out of the |
| 1511 | area where we found only empty levels. */ | 1607 | area where we found only empty levels. */ |
| 1512 | if ((bidi_it->ignore_bn_limit > 0 | 1608 | if ((bidi_it->ignore_bn_limit > -1 |
| 1513 | && bidi_it->ignore_bn_limit <= bidi_it->charpos) | 1609 | && bidi_it->ignore_bn_limit <= bidi_it->charpos) |
| 1514 | || (bidi_it->ignore_bn_limit == -1 | 1610 | || (bidi_it->ignore_bn_limit == -2 |
| 1515 | && !bidi_explicit_dir_char (bidi_it->ch))) | 1611 | && !bidi_explicit_dir_char (bidi_it->ch))) |
| 1516 | bidi_it->ignore_bn_limit = 0; | 1612 | bidi_it->ignore_bn_limit = -1; |
| 1517 | 1613 | ||
| 1518 | type = bidi_resolve_neutral (bidi_it); | 1614 | type = bidi_resolve_neutral (bidi_it); |
| 1519 | 1615 | ||
| @@ -1530,12 +1626,12 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 1530 | bidi_type_t type; | 1626 | bidi_type_t type; |
| 1531 | int level, prev_level = -1; | 1627 | int level, prev_level = -1; |
| 1532 | struct bidi_saved_info next_for_neutral; | 1628 | struct bidi_saved_info next_for_neutral; |
| 1533 | EMACS_INT next_char_pos; | 1629 | EMACS_INT next_char_pos = -1; |
| 1534 | 1630 | ||
| 1535 | if (bidi_it->scan_dir == 1) | 1631 | if (bidi_it->scan_dir == 1) |
| 1536 | { | 1632 | { |
| 1537 | /* There's no sense in trying to advance if we hit end of text. */ | 1633 | /* There's no sense in trying to advance if we hit end of text. */ |
| 1538 | if (bidi_it->bytepos >= ZV_BYTE) | 1634 | if (bidi_it->charpos >= (bidi_it->string.s ? bidi_it->string.schars : ZV)) |
| 1539 | return bidi_it->resolved_level; | 1635 | return bidi_it->resolved_level; |
| 1540 | 1636 | ||
| 1541 | /* Record the info about the previous character. */ | 1637 | /* Record the info about the previous character. */ |
| @@ -1575,7 +1671,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 1575 | /* Perhaps the character we want is already cached. If it is, the | 1671 | /* Perhaps the character we want is already cached. If it is, the |
| 1576 | call to bidi_cache_find below will return a type other than | 1672 | call to bidi_cache_find below will return a type other than |
| 1577 | UNKNOWN_BT. */ | 1673 | UNKNOWN_BT. */ |
| 1578 | if (bidi_cache_idx && !bidi_it->first_elt) | 1674 | if (bidi_cache_idx > bidi_cache_start && !bidi_it->first_elt) |
| 1579 | { | 1675 | { |
| 1580 | if (bidi_it->scan_dir > 0) | 1676 | if (bidi_it->scan_dir > 0) |
| 1581 | { | 1677 | { |
| @@ -1583,9 +1679,12 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 1583 | abort (); | 1679 | abort (); |
| 1584 | next_char_pos = bidi_it->charpos + bidi_it->nchars; | 1680 | next_char_pos = bidi_it->charpos + bidi_it->nchars; |
| 1585 | } | 1681 | } |
| 1586 | else | 1682 | else if (bidi_it->charpos > (bidi_it->string.s ? 0 : 1)) |
| 1587 | next_char_pos = bidi_it->charpos - 1; | 1683 | next_char_pos = bidi_it->charpos - 1; |
| 1588 | type = bidi_cache_find (next_char_pos, -1, bidi_it); | 1684 | if (next_char_pos >= 0) |
| 1685 | type = bidi_cache_find (next_char_pos, -1, bidi_it); | ||
| 1686 | else | ||
| 1687 | type = UNKNOWN_BT; | ||
| 1589 | } | 1688 | } |
| 1590 | else | 1689 | else |
| 1591 | type = UNKNOWN_BT; | 1690 | type = UNKNOWN_BT; |
| @@ -1652,13 +1751,14 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) | |||
| 1652 | EMACS_INT cpos = bidi_it->charpos; | 1751 | EMACS_INT cpos = bidi_it->charpos; |
| 1653 | EMACS_INT disp_pos = bidi_it->disp_pos; | 1752 | EMACS_INT disp_pos = bidi_it->disp_pos; |
| 1654 | EMACS_INT nc = bidi_it->nchars; | 1753 | EMACS_INT nc = bidi_it->nchars; |
| 1754 | struct bidi_string_data bs = bidi_it->string; | ||
| 1655 | bidi_type_t chtype; | 1755 | bidi_type_t chtype; |
| 1656 | int fwp = bidi_it->frame_window_p; | 1756 | int fwp = bidi_it->frame_window_p; |
| 1657 | 1757 | ||
| 1658 | if (bidi_it->nchars <= 0) | 1758 | if (bidi_it->nchars <= 0) |
| 1659 | abort (); | 1759 | abort (); |
| 1660 | do { | 1760 | do { |
| 1661 | ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, fwp, | 1761 | ch = bidi_fetch_char (bpos += clen, cpos += nc, &disp_pos, &bs, fwp, |
| 1662 | &clen, &nc); | 1762 | &clen, &nc); |
| 1663 | if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */) | 1763 | if (ch == '\n' || ch == BIDI_EOB /* || ch == LINESEP_CHAR */) |
| 1664 | chtype = NEUTRAL_B; | 1764 | chtype = NEUTRAL_B; |
| @@ -1759,7 +1859,8 @@ bidi_find_other_level_edge (struct bidi_it *bidi_it, int level, int end_flag) | |||
| 1759 | int idx; | 1859 | int idx; |
| 1760 | 1860 | ||
| 1761 | /* Try the cache first. */ | 1861 | /* Try the cache first. */ |
| 1762 | if ((idx = bidi_cache_find_level_change (level, dir, end_flag)) >= 0) | 1862 | if ((idx = bidi_cache_find_level_change (level, dir, end_flag)) |
| 1863 | >= bidi_cache_start) | ||
| 1763 | bidi_cache_fetch_state (idx, bidi_it); | 1864 | bidi_cache_fetch_state (idx, bidi_it); |
| 1764 | else | 1865 | else |
| 1765 | { | 1866 | { |
| @@ -1782,6 +1883,9 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) | |||
| 1782 | int old_level, new_level, next_level; | 1883 | int old_level, new_level, next_level; |
| 1783 | struct bidi_it sentinel; | 1884 | struct bidi_it sentinel; |
| 1784 | 1885 | ||
| 1886 | if (bidi_it->charpos < 0 || bidi_it->bytepos < 0) | ||
| 1887 | abort (); | ||
| 1888 | |||
| 1785 | if (bidi_it->scan_dir == 0) | 1889 | if (bidi_it->scan_dir == 0) |
| 1786 | { | 1890 | { |
| 1787 | bidi_it->scan_dir = 1; /* default to logical order */ | 1891 | bidi_it->scan_dir = 1; /* default to logical order */ |
| @@ -1794,7 +1898,7 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) | |||
| 1794 | /* Prepare the sentinel iterator state, and cache it. When we bump | 1898 | /* Prepare the sentinel iterator state, and cache it. When we bump |
| 1795 | into it, scanning backwards, we'll know that the last non-base | 1899 | into it, scanning backwards, we'll know that the last non-base |
| 1796 | level is exhausted. */ | 1900 | level is exhausted. */ |
| 1797 | if (bidi_cache_idx == 0) | 1901 | if (bidi_cache_idx == bidi_cache_start) |
| 1798 | { | 1902 | { |
| 1799 | bidi_copy_it (&sentinel, bidi_it); | 1903 | bidi_copy_it (&sentinel, bidi_it); |
| 1800 | if (bidi_it->first_elt) | 1904 | if (bidi_it->first_elt) |
| @@ -1869,26 +1973,34 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it) | |||
| 1869 | reordering, whereas we _must_ know the paragraph base direction | 1973 | reordering, whereas we _must_ know the paragraph base direction |
| 1870 | _before_ we process the paragraph's text, since the base | 1974 | _before_ we process the paragraph's text, since the base |
| 1871 | direction affects the reordering. */ | 1975 | direction affects the reordering. */ |
| 1872 | if (bidi_it->scan_dir == 1 | 1976 | if (bidi_it->scan_dir == 1 && bidi_it->orig_type == NEUTRAL_B) |
| 1873 | && bidi_it->orig_type == NEUTRAL_B | ||
| 1874 | && bidi_it->bytepos < ZV_BYTE) | ||
| 1875 | { | 1977 | { |
| 1876 | EMACS_INT sep_len = | 1978 | /* The paragraph direction of the entire string, once |
| 1877 | bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars, | 1979 | determined, is in effect for the entire string. Setting the |
| 1878 | bidi_it->bytepos + bidi_it->ch_len); | 1980 | separator limit to the end of the string prevents |
| 1879 | if (bidi_it->nchars <= 0) | 1981 | bidi_paragraph_init from being called automatically on this |
| 1880 | abort (); | 1982 | string. */ |
| 1881 | if (sep_len >= 0) | 1983 | if (bidi_it->string.s) |
| 1984 | bidi_it->separator_limit = bidi_it->string.schars; | ||
| 1985 | else if (bidi_it->bytepos < ZV_BYTE) | ||
| 1882 | { | 1986 | { |
| 1883 | bidi_it->new_paragraph = 1; | 1987 | EMACS_INT sep_len = |
| 1884 | /* Record the buffer position of the last character of the | 1988 | bidi_at_paragraph_end (bidi_it->charpos + bidi_it->nchars, |
| 1885 | paragraph separator. */ | 1989 | bidi_it->bytepos + bidi_it->ch_len); |
| 1886 | bidi_it->separator_limit = | 1990 | if (bidi_it->nchars <= 0) |
| 1887 | bidi_it->charpos + bidi_it->nchars + sep_len; | 1991 | abort (); |
| 1992 | if (sep_len >= 0) | ||
| 1993 | { | ||
| 1994 | bidi_it->new_paragraph = 1; | ||
| 1995 | /* Record the buffer position of the last character of the | ||
| 1996 | paragraph separator. */ | ||
| 1997 | bidi_it->separator_limit = | ||
| 1998 | bidi_it->charpos + bidi_it->nchars + sep_len; | ||
| 1999 | } | ||
| 1888 | } | 2000 | } |
| 1889 | } | 2001 | } |
| 1890 | 2002 | ||
| 1891 | if (bidi_it->scan_dir == 1 && bidi_cache_idx) | 2003 | if (bidi_it->scan_dir == 1 && bidi_cache_idx > bidi_cache_start) |
| 1892 | { | 2004 | { |
| 1893 | /* If we are at paragraph's base embedding level and beyond the | 2005 | /* If we are at paragraph's base embedding level and beyond the |
| 1894 | last cached position, the cache's job is done and we can | 2006 | last cached position, the cache's job is done and we can |
diff --git a/src/dispextern.h b/src/dispextern.h index 7138c2225e8..0f7089d7916 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -1812,9 +1812,18 @@ struct bidi_stack { | |||
| 1812 | bidi_dir_t override; | 1812 | bidi_dir_t override; |
| 1813 | }; | 1813 | }; |
| 1814 | 1814 | ||
| 1815 | /* Data type for storing information about a string being iterated on. */ | ||
| 1816 | struct bidi_string_data { | ||
| 1817 | const unsigned char *s; /* the string, or NULL if reordering buffer */ | ||
| 1818 | EMACS_INT schars; /* the number of characters in the string, | ||
| 1819 | excluding the terminating null */ | ||
| 1820 | unsigned from_disp_str : 1; /* 1 means the string comes from a | ||
| 1821 | display property */ | ||
| 1822 | }; | ||
| 1823 | |||
| 1815 | /* Data type for reordering bidirectional text. */ | 1824 | /* Data type for reordering bidirectional text. */ |
| 1816 | struct bidi_it { | 1825 | struct bidi_it { |
| 1817 | EMACS_INT bytepos; /* iterator's position in buffer */ | 1826 | EMACS_INT bytepos; /* iterator's position in buffer/string */ |
| 1818 | EMACS_INT charpos; | 1827 | EMACS_INT charpos; |
| 1819 | int ch; /* character at that position, or u+FFFC | 1828 | int ch; /* character at that position, or u+FFFC |
| 1820 | ("object replacement character") for a run | 1829 | ("object replacement character") for a run |
| @@ -1844,12 +1853,13 @@ struct bidi_it { | |||
| 1844 | iterator state is saved, pushed, or popped. So only put here | 1853 | iterator state is saved, pushed, or popped. So only put here |
| 1845 | stuff that is not part of the bidi iterator's state! */ | 1854 | stuff that is not part of the bidi iterator's state! */ |
| 1846 | struct bidi_stack level_stack[BIDI_MAXLEVEL]; /* stack of embedding levels */ | 1855 | struct bidi_stack level_stack[BIDI_MAXLEVEL]; /* stack of embedding levels */ |
| 1847 | int first_elt; /* if non-zero, examine current char first */ | 1856 | struct bidi_string_data string; /* string to reorder */ |
| 1848 | bidi_dir_t paragraph_dir; /* current paragraph direction */ | 1857 | bidi_dir_t paragraph_dir; /* current paragraph direction */ |
| 1849 | int new_paragraph; /* if non-zero, we expect a new paragraph */ | ||
| 1850 | int frame_window_p; /* non-zero if displaying on a GUI frame */ | ||
| 1851 | EMACS_INT separator_limit; /* where paragraph separator should end */ | 1858 | EMACS_INT separator_limit; /* where paragraph separator should end */ |
| 1852 | EMACS_INT disp_pos; /* position of display string after ch */ | 1859 | EMACS_INT disp_pos; /* position of display string after ch */ |
| 1860 | unsigned first_elt : 1; /* if non-zero, examine current char first */ | ||
| 1861 | unsigned new_paragraph : 1; /* if non-zero, we expect a new paragraph */ | ||
| 1862 | unsigned frame_window_p : 1; /* non-zero if displaying on a GUI frame */ | ||
| 1853 | }; | 1863 | }; |
| 1854 | 1864 | ||
| 1855 | /* Value is non-zero when the bidi iterator is at base paragraph | 1865 | /* Value is non-zero when the bidi iterator is at base paragraph |
| @@ -3007,8 +3017,10 @@ extern void reseat_at_previous_visible_line_start (struct it *); | |||
| 3007 | extern Lisp_Object lookup_glyphless_char_display (int, struct it *); | 3017 | extern Lisp_Object lookup_glyphless_char_display (int, struct it *); |
| 3008 | extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, | 3018 | extern int calc_pixel_width_or_height (double *, struct it *, Lisp_Object, |
| 3009 | struct font *, int, int *); | 3019 | struct font *, int, int *); |
| 3010 | extern EMACS_INT compute_display_string_pos (EMACS_INT, int); | 3020 | extern EMACS_INT compute_display_string_pos (EMACS_INT, |
| 3011 | extern EMACS_INT compute_display_string_end (EMACS_INT); | 3021 | struct bidi_string_data *, int); |
| 3022 | extern EMACS_INT compute_display_string_end (EMACS_INT, | ||
| 3023 | struct bidi_string_data *); | ||
| 3012 | 3024 | ||
| 3013 | #ifdef HAVE_WINDOW_SYSTEM | 3025 | #ifdef HAVE_WINDOW_SYSTEM |
| 3014 | 3026 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index 23667388b56..cd62989d994 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -2342,6 +2342,7 @@ init_iterator (struct it *it, struct window *w, | |||
| 2342 | it->base_face_id = remapped_base_face_id; | 2342 | it->base_face_id = remapped_base_face_id; |
| 2343 | it->string = Qnil; | 2343 | it->string = Qnil; |
| 2344 | IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1; | 2344 | IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1; |
| 2345 | it->bidi_it.string.s = NULL; | ||
| 2345 | 2346 | ||
| 2346 | /* The window in which we iterate over current_buffer: */ | 2347 | /* The window in which we iterate over current_buffer: */ |
| 2347 | XSETWINDOW (it->window, w); | 2348 | XSETWINDOW (it->window, w); |
| @@ -3087,14 +3088,16 @@ next_overlay_change (EMACS_INT pos) | |||
| 3087 | return endpos; | 3088 | return endpos; |
| 3088 | } | 3089 | } |
| 3089 | 3090 | ||
| 3090 | /* Return the character position of a display string at or after CHARPOS. | 3091 | /* Return the character position of a display string at or after |
| 3091 | If no display string exists at or after CHARPOS, return ZV. A | 3092 | CHARPOS. If no display string exists at or after CHARPOS, return |
| 3092 | display string is either an overlay with `display' property whose | 3093 | ZV. A display string is either an overlay with `display' property |
| 3093 | value is a string, or a `display' text property whose value is a | 3094 | whose value is a string, or a `display' text property whose value |
| 3094 | string. FRAME_WINDOW_P is non-zero when we are displaying a window | 3095 | is a string. STRING is the string to iterate; if STRING->s is |
| 3095 | on a GUI frame. */ | 3096 | NULL, we are iterating a buffer. FRAME_WINDOW_P is non-zero when |
| 3097 | we are displaying a window on a GUI frame. */ | ||
| 3096 | EMACS_INT | 3098 | EMACS_INT |
| 3097 | compute_display_string_pos (EMACS_INT charpos, int frame_window_p) | 3099 | compute_display_string_pos (EMACS_INT charpos, struct bidi_string_data *string, |
| 3100 | int frame_window_p) | ||
| 3098 | { | 3101 | { |
| 3099 | /* FIXME: Support display properties on strings (object = Qnil means | 3102 | /* FIXME: Support display properties on strings (object = Qnil means |
| 3100 | current buffer). */ | 3103 | current buffer). */ |
| @@ -3143,7 +3146,7 @@ compute_display_string_pos (EMACS_INT charpos, int frame_window_p) | |||
| 3143 | `display' property whose value is a string or a `display' text | 3146 | `display' property whose value is a string or a `display' text |
| 3144 | property whose value is a string. */ | 3147 | property whose value is a string. */ |
| 3145 | EMACS_INT | 3148 | EMACS_INT |
| 3146 | compute_display_string_end (EMACS_INT charpos) | 3149 | compute_display_string_end (EMACS_INT charpos, struct bidi_string_data *string) |
| 3147 | { | 3150 | { |
| 3148 | /* FIXME: Support display properties on strings (object = Qnil means | 3151 | /* FIXME: Support display properties on strings (object = Qnil means |
| 3149 | current buffer). */ | 3152 | current buffer). */ |
| @@ -5482,6 +5485,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p) | |||
| 5482 | it->bidi_it.first_elt = 1; | 5485 | it->bidi_it.first_elt = 1; |
| 5483 | it->bidi_it.paragraph_dir = NEUTRAL_DIR; | 5486 | it->bidi_it.paragraph_dir = NEUTRAL_DIR; |
| 5484 | it->bidi_it.disp_pos = -1; | 5487 | it->bidi_it.disp_pos = -1; |
| 5488 | it->bidi_it.string.s = NULL; | ||
| 5485 | } | 5489 | } |
| 5486 | 5490 | ||
| 5487 | if (set_stop_p) | 5491 | if (set_stop_p) |
| @@ -5531,6 +5535,10 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5531 | setting of MULTIBYTE, if specified. */ | 5535 | setting of MULTIBYTE, if specified. */ |
| 5532 | if (multibyte >= 0) | 5536 | if (multibyte >= 0) |
| 5533 | it->multibyte_p = multibyte > 0; | 5537 | it->multibyte_p = multibyte > 0; |
| 5538 | #if 0 | ||
| 5539 | it->bidi_p = | ||
| 5540 | it->multibyte_p && BVAR (&buffer_defaults, bidi_display_reordering); | ||
| 5541 | #endif | ||
| 5534 | 5542 | ||
| 5535 | if (s == NULL) | 5543 | if (s == NULL) |
| 5536 | { | 5544 | { |
| @@ -5540,6 +5548,12 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5540 | it->end_charpos = it->string_nchars = SCHARS (string); | 5548 | it->end_charpos = it->string_nchars = SCHARS (string); |
| 5541 | it->method = GET_FROM_STRING; | 5549 | it->method = GET_FROM_STRING; |
| 5542 | it->current.string_pos = string_pos (charpos, string); | 5550 | it->current.string_pos = string_pos (charpos, string); |
| 5551 | #if 0 | ||
| 5552 | if (it->bidi_p) | ||
| 5553 | bidi_init_it (); | ||
| 5554 | it->bidi_it.string.s = SDATA (string); | ||
| 5555 | it->bidi_it.string.schars = it->end_charpos; | ||
| 5556 | #endif | ||
| 5543 | } | 5557 | } |
| 5544 | else | 5558 | else |
| 5545 | { | 5559 | { |
| @@ -5553,11 +5567,20 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, | |||
| 5553 | { | 5567 | { |
| 5554 | it->current.pos = c_string_pos (charpos, s, 1); | 5568 | it->current.pos = c_string_pos (charpos, s, 1); |
| 5555 | it->end_charpos = it->string_nchars = number_of_chars (s, 1); | 5569 | it->end_charpos = it->string_nchars = number_of_chars (s, 1); |
| 5570 | #if 0 | ||
| 5571 | if (it->bidi_p) | ||
| 5572 | bidi_init_it (); | ||
| 5573 | it->bidi_it.string.s = s; | ||
| 5574 | it->bidi_it.string.schars = it->end_charpos; | ||
| 5575 | #endif | ||
| 5556 | } | 5576 | } |
| 5557 | else | 5577 | else |
| 5558 | { | 5578 | { |
| 5559 | IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos; | 5579 | IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos; |
| 5560 | it->end_charpos = it->string_nchars = strlen (s); | 5580 | it->end_charpos = it->string_nchars = strlen (s); |
| 5581 | #if 0 | ||
| 5582 | it->bidi_p = 0; | ||
| 5583 | #endif | ||
| 5561 | } | 5584 | } |
| 5562 | 5585 | ||
| 5563 | it->method = GET_FROM_C_STRING; | 5586 | it->method = GET_FROM_C_STRING; |