diff options
| author | Eli Zaretskii | 2011-07-03 21:36:56 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2011-07-03 21:36:56 +0300 |
| commit | ed94e6d7bf6751592ff3dadb2b87f03ffaab3bfa (patch) | |
| tree | 0d06ed1743bb484cac818ef7ff75d68f107a6332 /src | |
| parent | 6eec759623c7d77e01370c504543a29887c28034 (diff) | |
| download | emacs-ed94e6d7bf6751592ff3dadb2b87f03ffaab3bfa.tar.gz emacs-ed94e6d7bf6751592ff3dadb2b87f03ffaab3bfa.zip | |
Save and restore bidi cache when saving and restoring the iterator.
Not tested, just compiled.
src/bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions.
src/dispextern.h (bidi_shelve_cache, bidi_unshelve_cache): Declare
prototypes.
src/xdisp.c (SAVE_IT, RESTORE_IT): New macros.
(pos_visible_p, face_before_or_after_it_pos)
(back_to_previous_visible_line_start)
(move_it_in_display_line_to, move_it_in_display_line)
(move_it_to, move_it_vertically_backward, move_it_by_lines)
(try_scrolling, redisplay_window, display_line): Use them when
saving a temporary copy of the iterator and restoring it back.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 15 | ||||
| -rw-r--r-- | src/bidi.c | 80 | ||||
| -rw-r--r-- | src/dispextern.h | 2 | ||||
| -rw-r--r-- | src/xdisp.c | 152 |
4 files changed, 204 insertions, 45 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 1a443e848a7..fdb6657e135 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | 2011-07-03 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * bidi.c (bidi_shelve_cache, bidi_unshelve_cache): New functions. | ||
| 4 | |||
| 5 | * dispextern.h (bidi_shelve_cache, bidi_unshelve_cache): Declare | ||
| 6 | prototypes. | ||
| 7 | |||
| 8 | * xdisp.c (SAVE_IT, RESTORE_IT): New macros. | ||
| 9 | (pos_visible_p, face_before_or_after_it_pos) | ||
| 10 | (back_to_previous_visible_line_start) | ||
| 11 | (move_it_in_display_line_to, move_it_in_display_line) | ||
| 12 | (move_it_to, move_it_vertically_backward, move_it_by_lines) | ||
| 13 | (try_scrolling, redisplay_window, display_line): Use them when | ||
| 14 | saving a temporary copy of the iterator and restoring it back. | ||
| 15 | |||
| 1 | 2011-07-02 Eli Zaretskii <eliz@gnu.org> | 16 | 2011-07-02 Eli Zaretskii <eliz@gnu.org> |
| 2 | 17 | ||
| 3 | * xdisp.c (reseat_1): Call bidi_init_it to resync the bidi | 18 | * xdisp.c (reseat_1): Call bidi_init_it to resync the bidi |
diff --git a/src/bidi.c b/src/bidi.c index 05c16a70f94..be34f0352de 100644 --- a/src/bidi.c +++ b/src/bidi.c | |||
| @@ -603,6 +603,86 @@ bidi_pop_it (struct bidi_it *bidi_it) | |||
| 603 | bidi_cache_last_idx = -1; | 603 | bidi_cache_last_idx = -1; |
| 604 | } | 604 | } |
| 605 | 605 | ||
| 606 | /* Stash away a copy of the cache and its control variables. */ | ||
| 607 | void * | ||
| 608 | bidi_shelve_cache (void) | ||
| 609 | { | ||
| 610 | unsigned char *databuf; | ||
| 611 | |||
| 612 | if (bidi_cache_idx == 0) | ||
| 613 | return NULL; | ||
| 614 | |||
| 615 | databuf = xmalloc (sizeof (bidi_cache_idx) | ||
| 616 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 617 | + sizeof (bidi_cache_start_stack) | ||
| 618 | + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start) | ||
| 619 | + sizeof (bidi_cache_last_idx)); | ||
| 620 | memcpy (databuf, &bidi_cache_idx, sizeof (bidi_cache_idx)); | ||
| 621 | memcpy (databuf + sizeof (bidi_cache_idx), | ||
| 622 | bidi_cache, bidi_cache_idx * sizeof (struct bidi_it)); | ||
| 623 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 624 | + bidi_cache_idx * sizeof (struct bidi_it), | ||
| 625 | bidi_cache_start_stack, sizeof (bidi_cache_start_stack)); | ||
| 626 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 627 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 628 | + sizeof (bidi_cache_start_stack), | ||
| 629 | &bidi_cache_sp, sizeof (bidi_cache_sp)); | ||
| 630 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 631 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 632 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp), | ||
| 633 | &bidi_cache_start, sizeof (bidi_cache_start)); | ||
| 634 | memcpy (databuf + sizeof (bidi_cache_idx) | ||
| 635 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 636 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) | ||
| 637 | + sizeof (bidi_cache_start), | ||
| 638 | &bidi_cache_last_idx, sizeof (bidi_cache_last_idx)); | ||
| 639 | |||
| 640 | return databuf; | ||
| 641 | } | ||
| 642 | |||
| 643 | /* Restore the cache state from a copy stashed away by bidi_shelve_cache. */ | ||
| 644 | void | ||
| 645 | bidi_unshelve_cache (void *databuf) | ||
| 646 | { | ||
| 647 | unsigned char *p = databuf; | ||
| 648 | |||
| 649 | if (!p) | ||
| 650 | { | ||
| 651 | /* A NULL pointer means an empty cache. */ | ||
| 652 | bidi_cache_start = 0; | ||
| 653 | bidi_cache_sp = 0; | ||
| 654 | bidi_cache_reset (); | ||
| 655 | } | ||
| 656 | else | ||
| 657 | { | ||
| 658 | memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx)); | ||
| 659 | memcpy (bidi_cache, p + sizeof (bidi_cache_idx), | ||
| 660 | bidi_cache_idx * sizeof (struct bidi_it)); | ||
| 661 | memcpy (bidi_cache_start_stack, | ||
| 662 | p + sizeof (bidi_cache_idx) | ||
| 663 | + bidi_cache_idx * sizeof (struct bidi_it), | ||
| 664 | sizeof (bidi_cache_start_stack)); | ||
| 665 | memcpy (&bidi_cache_sp, | ||
| 666 | p + sizeof (bidi_cache_idx) | ||
| 667 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 668 | + sizeof (bidi_cache_start_stack), | ||
| 669 | sizeof (bidi_cache_sp)); | ||
| 670 | memcpy (&bidi_cache_start, | ||
| 671 | p + sizeof (bidi_cache_idx) | ||
| 672 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 673 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp), | ||
| 674 | sizeof (bidi_cache_start)); | ||
| 675 | memcpy (&bidi_cache_last_idx, | ||
| 676 | p + sizeof (bidi_cache_idx) | ||
| 677 | + bidi_cache_idx * sizeof (struct bidi_it) | ||
| 678 | + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp) | ||
| 679 | + sizeof (bidi_cache_start), | ||
| 680 | sizeof (bidi_cache_last_idx)); | ||
| 681 | |||
| 682 | xfree (p); | ||
| 683 | } | ||
| 684 | } | ||
| 685 | |||
| 606 | 686 | ||
| 607 | /*********************************************************************** | 687 | /*********************************************************************** |
| 608 | Initialization | 688 | Initialization |
diff --git a/src/dispextern.h b/src/dispextern.h index 997ef6df088..5bb72ff7600 100644 --- a/src/dispextern.h +++ b/src/dispextern.h | |||
| @@ -2974,6 +2974,8 @@ extern void bidi_paragraph_init (bidi_dir_t, struct bidi_it *, int); | |||
| 2974 | extern int bidi_mirror_char (int); | 2974 | extern int bidi_mirror_char (int); |
| 2975 | extern void bidi_push_it (struct bidi_it *); | 2975 | extern void bidi_push_it (struct bidi_it *); |
| 2976 | extern void bidi_pop_it (struct bidi_it *); | 2976 | extern void bidi_pop_it (struct bidi_it *); |
| 2977 | extern void *bidi_shelve_cache (void); | ||
| 2978 | extern void bidi_unshelve_cache (void *); | ||
| 2977 | 2979 | ||
| 2978 | /* Defined in xdisp.c */ | 2980 | /* Defined in xdisp.c */ |
| 2979 | 2981 | ||
diff --git a/src/xdisp.c b/src/xdisp.c index c3d5fd9479b..c1f4d44dbc5 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -594,6 +594,29 @@ int current_mode_line_height, current_header_line_height; | |||
| 594 | 594 | ||
| 595 | #define TEXT_PROP_DISTANCE_LIMIT 100 | 595 | #define TEXT_PROP_DISTANCE_LIMIT 100 |
| 596 | 596 | ||
| 597 | /* SAVE_IT and RESTORE_IT are called when we save a snapshot of the | ||
| 598 | iterator state and later restore it. This is needed because the | ||
| 599 | bidi iterator on bidi.c keeps a stacked cache of its states, which | ||
| 600 | is really a singleton. When we use scratch iterator objects to | ||
| 601 | move around the buffer, we can cause the bidi cache to be pushed or | ||
| 602 | popped, and therefore we need to restore the cache state when we | ||
| 603 | return to the original iterator. */ | ||
| 604 | #define SAVE_IT(ITCOPY,ITORIG,CACHE) \ | ||
| 605 | do { \ | ||
| 606 | if (CACHE) \ | ||
| 607 | xfree (CACHE); \ | ||
| 608 | ITCOPY = ITORIG; \ | ||
| 609 | CACHE = bidi_shelve_cache(); \ | ||
| 610 | } while (0) | ||
| 611 | |||
| 612 | #define RESTORE_IT(pITORIG,pITCOPY,CACHE) \ | ||
| 613 | do { \ | ||
| 614 | if (pITORIG != pITCOPY) \ | ||
| 615 | *(pITORIG) = *(pITCOPY); \ | ||
| 616 | bidi_unshelve_cache (CACHE); \ | ||
| 617 | CACHE = NULL; \ | ||
| 618 | } while (0) | ||
| 619 | |||
| 597 | #if GLYPH_DEBUG | 620 | #if GLYPH_DEBUG |
| 598 | 621 | ||
| 599 | /* Non-zero means print traces of redisplay if compiled with | 622 | /* Non-zero means print traces of redisplay if compiled with |
| @@ -1285,14 +1308,16 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y, | |||
| 1285 | else | 1308 | else |
| 1286 | { | 1309 | { |
| 1287 | struct it it2; | 1310 | struct it it2; |
| 1311 | void *it2data = NULL; | ||
| 1288 | 1312 | ||
| 1289 | it2 = it; | 1313 | SAVE_IT (it2, it, it2data); |
| 1290 | if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n') | 1314 | if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n') |
| 1291 | move_it_by_lines (&it, 1); | 1315 | move_it_by_lines (&it, 1); |
| 1292 | if (charpos < IT_CHARPOS (it) | 1316 | if (charpos < IT_CHARPOS (it) |
| 1293 | || (it.what == IT_EOB && charpos == IT_CHARPOS (it))) | 1317 | || (it.what == IT_EOB && charpos == IT_CHARPOS (it))) |
| 1294 | { | 1318 | { |
| 1295 | visible_p = 1; | 1319 | visible_p = 1; |
| 1320 | RESTORE_IT (&it2, &it2, it2data); | ||
| 1296 | move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS); | 1321 | move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS); |
| 1297 | *x = it2.current_x; | 1322 | *x = it2.current_x; |
| 1298 | *y = it2.current_y + it2.max_ascent - it2.ascent; | 1323 | *y = it2.current_y + it2.max_ascent - it2.ascent; |
| @@ -1305,6 +1330,8 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y, | |||
| 1305 | WINDOW_HEADER_LINE_HEIGHT (w)))); | 1330 | WINDOW_HEADER_LINE_HEIGHT (w)))); |
| 1306 | *vpos = it2.vpos; | 1331 | *vpos = it2.vpos; |
| 1307 | } | 1332 | } |
| 1333 | else | ||
| 1334 | xfree (it2data); | ||
| 1308 | } | 1335 | } |
| 1309 | 1336 | ||
| 1310 | if (old_buffer) | 1337 | if (old_buffer) |
| @@ -3484,6 +3511,7 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3484 | int face_id, limit; | 3511 | int face_id, limit; |
| 3485 | EMACS_INT next_check_charpos; | 3512 | EMACS_INT next_check_charpos; |
| 3486 | struct it it_copy; | 3513 | struct it it_copy; |
| 3514 | void *it_copy_data = NULL; | ||
| 3487 | 3515 | ||
| 3488 | xassert (it->s == NULL); | 3516 | xassert (it->s == NULL); |
| 3489 | 3517 | ||
| @@ -3526,7 +3554,7 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3526 | character on this display line. */ | 3554 | character on this display line. */ |
| 3527 | if (it->current_x <= it->first_visible_x) | 3555 | if (it->current_x <= it->first_visible_x) |
| 3528 | return it->face_id; | 3556 | return it->face_id; |
| 3529 | it_copy = *it; | 3557 | SAVE_IT (it_copy, *it, it_copy_data); |
| 3530 | /* Implementation note: Since move_it_in_display_line | 3558 | /* Implementation note: Since move_it_in_display_line |
| 3531 | works in the iterator geometry, and thinks the first | 3559 | works in the iterator geometry, and thinks the first |
| 3532 | character is always the leftmost, even in R2L lines, | 3560 | character is always the leftmost, even in R2L lines, |
| @@ -3535,6 +3563,7 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3535 | move_it_in_display_line (&it_copy, SCHARS (it_copy.string), | 3563 | move_it_in_display_line (&it_copy, SCHARS (it_copy.string), |
| 3536 | it_copy.current_x - 1, MOVE_TO_X); | 3564 | it_copy.current_x - 1, MOVE_TO_X); |
| 3537 | charpos = IT_STRING_CHARPOS (it_copy); | 3565 | charpos = IT_STRING_CHARPOS (it_copy); |
| 3566 | RESTORE_IT (it, it, it_copy_data); | ||
| 3538 | } | 3567 | } |
| 3539 | else | 3568 | else |
| 3540 | { | 3569 | { |
| @@ -3624,7 +3653,7 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3624 | character on this display line. */ | 3653 | character on this display line. */ |
| 3625 | if (it->current_x <= it->first_visible_x) | 3654 | if (it->current_x <= it->first_visible_x) |
| 3626 | return it->face_id; | 3655 | return it->face_id; |
| 3627 | it_copy = *it; | 3656 | SAVE_IT (it_copy, *it, it_copy_data); |
| 3628 | /* Implementation note: Since move_it_in_display_line | 3657 | /* Implementation note: Since move_it_in_display_line |
| 3629 | works in the iterator geometry, and thinks the first | 3658 | works in the iterator geometry, and thinks the first |
| 3630 | character is always the leftmost, even in R2L lines, | 3659 | character is always the leftmost, even in R2L lines, |
| @@ -3633,6 +3662,7 @@ face_before_or_after_it_pos (struct it *it, int before_p) | |||
| 3633 | move_it_in_display_line (&it_copy, ZV, | 3662 | move_it_in_display_line (&it_copy, ZV, |
| 3634 | it_copy.current_x - 1, MOVE_TO_X); | 3663 | it_copy.current_x - 1, MOVE_TO_X); |
| 3635 | pos = it_copy.current.pos; | 3664 | pos = it_copy.current.pos; |
| 3665 | RESTORE_IT (it, it, it_copy_data); | ||
| 3636 | } | 3666 | } |
| 3637 | else | 3667 | else |
| 3638 | { | 3668 | { |
| @@ -5527,6 +5557,7 @@ back_to_previous_visible_line_start (struct it *it) | |||
| 5527 | 5557 | ||
| 5528 | { | 5558 | { |
| 5529 | struct it it2; | 5559 | struct it it2; |
| 5560 | void *it2data = NULL; | ||
| 5530 | EMACS_INT pos; | 5561 | EMACS_INT pos; |
| 5531 | EMACS_INT beg, end; | 5562 | EMACS_INT beg, end; |
| 5532 | Lisp_Object val, overlay; | 5563 | Lisp_Object val, overlay; |
| @@ -5538,7 +5569,7 @@ back_to_previous_visible_line_start (struct it *it) | |||
| 5538 | 5569 | ||
| 5539 | /* If newline is replaced by a display property, find start of overlay | 5570 | /* If newline is replaced by a display property, find start of overlay |
| 5540 | or interval and continue search from that point. */ | 5571 | or interval and continue search from that point. */ |
| 5541 | it2 = *it; | 5572 | SAVE_IT (it2, *it, it2data); |
| 5542 | pos = --IT_CHARPOS (it2); | 5573 | pos = --IT_CHARPOS (it2); |
| 5543 | --IT_BYTEPOS (it2); | 5574 | --IT_BYTEPOS (it2); |
| 5544 | it2.sp = 0; | 5575 | it2.sp = 0; |
| @@ -5551,21 +5582,12 @@ back_to_previous_visible_line_start (struct it *it) | |||
| 5551 | ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay))) | 5582 | ? (beg = OVERLAY_POSITION (OVERLAY_START (overlay))) |
| 5552 | : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil))) | 5583 | : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil))) |
| 5553 | { | 5584 | { |
| 5554 | /* If the call to handle_display_prop above pushed the | 5585 | RESTORE_IT (it, it, it2data); |
| 5555 | iterator state, that causes side effects for the bidi | ||
| 5556 | iterator by calling bidi_push_it. Undo those side | ||
| 5557 | effects. */ | ||
| 5558 | while (it2.sp > 0) | ||
| 5559 | { | ||
| 5560 | /* push_it calls bidi_push_it only if the bidi_p flag | ||
| 5561 | is set in the iterator being pushed. */ | ||
| 5562 | if (it2.stack[--it2.sp].bidi_p) | ||
| 5563 | bidi_pop_it (&it2.bidi_it); | ||
| 5564 | } | ||
| 5565 | goto replaced; | 5586 | goto replaced; |
| 5566 | } | 5587 | } |
| 5567 | 5588 | ||
| 5568 | /* Newline is not replaced by anything -- so we are done. */ | 5589 | /* Newline is not replaced by anything -- so we are done. */ |
| 5590 | RESTORE_IT (it, it, it2data); | ||
| 5569 | break; | 5591 | break; |
| 5570 | 5592 | ||
| 5571 | replaced: | 5593 | replaced: |
| @@ -7495,6 +7517,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7495 | enum move_it_result result = MOVE_UNDEFINED; | 7517 | enum move_it_result result = MOVE_UNDEFINED; |
| 7496 | struct glyph_row *saved_glyph_row; | 7518 | struct glyph_row *saved_glyph_row; |
| 7497 | struct it wrap_it, atpos_it, atx_it; | 7519 | struct it wrap_it, atpos_it, atx_it; |
| 7520 | void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL; | ||
| 7498 | int may_wrap = 0; | 7521 | int may_wrap = 0; |
| 7499 | enum it_method prev_method = it->method; | 7522 | enum it_method prev_method = it->method; |
| 7500 | EMACS_INT prev_pos = IT_CHARPOS (*it); | 7523 | EMACS_INT prev_pos = IT_CHARPOS (*it); |
| @@ -7563,7 +7586,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7563 | /* If wrap_it is valid, the current position might be in a | 7586 | /* If wrap_it is valid, the current position might be in a |
| 7564 | word that is wrapped. So, save the iterator in | 7587 | word that is wrapped. So, save the iterator in |
| 7565 | atpos_it and continue to see if wrapping happens. */ | 7588 | atpos_it and continue to see if wrapping happens. */ |
| 7566 | atpos_it = *it; | 7589 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7567 | } | 7590 | } |
| 7568 | 7591 | ||
| 7569 | prev_method = it->method; | 7592 | prev_method = it->method; |
| @@ -7600,18 +7623,18 @@ move_it_in_display_line_to (struct it *it, | |||
| 7600 | already found, we are done. */ | 7623 | already found, we are done. */ |
| 7601 | if (atpos_it.sp >= 0) | 7624 | if (atpos_it.sp >= 0) |
| 7602 | { | 7625 | { |
| 7603 | *it = atpos_it; | 7626 | RESTORE_IT (it, &atpos_it, atpos_data); |
| 7604 | result = MOVE_POS_MATCH_OR_ZV; | 7627 | result = MOVE_POS_MATCH_OR_ZV; |
| 7605 | goto done; | 7628 | goto done; |
| 7606 | } | 7629 | } |
| 7607 | if (atx_it.sp >= 0) | 7630 | if (atx_it.sp >= 0) |
| 7608 | { | 7631 | { |
| 7609 | *it = atx_it; | 7632 | RESTORE_IT (it, &atx_it, atx_data); |
| 7610 | result = MOVE_X_REACHED; | 7633 | result = MOVE_X_REACHED; |
| 7611 | goto done; | 7634 | goto done; |
| 7612 | } | 7635 | } |
| 7613 | /* Otherwise, we can wrap here. */ | 7636 | /* Otherwise, we can wrap here. */ |
| 7614 | wrap_it = *it; | 7637 | SAVE_IT (wrap_it, *it, wrap_data); |
| 7615 | may_wrap = 0; | 7638 | may_wrap = 0; |
| 7616 | } | 7639 | } |
| 7617 | } | 7640 | } |
| @@ -7679,7 +7702,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7679 | goto buffer_pos_reached; | 7702 | goto buffer_pos_reached; |
| 7680 | if (atpos_it.sp < 0) | 7703 | if (atpos_it.sp < 0) |
| 7681 | { | 7704 | { |
| 7682 | atpos_it = *it; | 7705 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7683 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); | 7706 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); |
| 7684 | } | 7707 | } |
| 7685 | } | 7708 | } |
| @@ -7693,7 +7716,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7693 | } | 7716 | } |
| 7694 | if (atx_it.sp < 0) | 7717 | if (atx_it.sp < 0) |
| 7695 | { | 7718 | { |
| 7696 | atx_it = *it; | 7719 | SAVE_IT (atx_it, *it, atx_data); |
| 7697 | IT_RESET_X_ASCENT_DESCENT (&atx_it); | 7720 | IT_RESET_X_ASCENT_DESCENT (&atx_it); |
| 7698 | } | 7721 | } |
| 7699 | } | 7722 | } |
| @@ -7737,7 +7760,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7737 | if (it->line_wrap == WORD_WRAP | 7760 | if (it->line_wrap == WORD_WRAP |
| 7738 | && atpos_it.sp < 0) | 7761 | && atpos_it.sp < 0) |
| 7739 | { | 7762 | { |
| 7740 | atpos_it = *it; | 7763 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7741 | atpos_it.current_x = x_before_this_char; | 7764 | atpos_it.current_x = x_before_this_char; |
| 7742 | atpos_it.hpos = hpos_before_this_char; | 7765 | atpos_it.hpos = hpos_before_this_char; |
| 7743 | } | 7766 | } |
| @@ -7782,7 +7805,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7782 | 7805 | ||
| 7783 | if (wrap_it.sp >= 0) | 7806 | if (wrap_it.sp >= 0) |
| 7784 | { | 7807 | { |
| 7785 | *it = wrap_it; | 7808 | RESTORE_IT (it, &wrap_it, wrap_data); |
| 7786 | atpos_it.sp = -1; | 7809 | atpos_it.sp = -1; |
| 7787 | atx_it.sp = -1; | 7810 | atx_it.sp = -1; |
| 7788 | } | 7811 | } |
| @@ -7799,7 +7822,7 @@ move_it_in_display_line_to (struct it *it, | |||
| 7799 | goto buffer_pos_reached; | 7822 | goto buffer_pos_reached; |
| 7800 | if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) | 7823 | if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0) |
| 7801 | { | 7824 | { |
| 7802 | atpos_it = *it; | 7825 | SAVE_IT (atpos_it, *it, atpos_data); |
| 7803 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); | 7826 | IT_RESET_X_ASCENT_DESCENT (&atpos_it); |
| 7804 | } | 7827 | } |
| 7805 | } | 7828 | } |
| @@ -7879,12 +7902,19 @@ move_it_in_display_line_to (struct it *it, | |||
| 7879 | /* If we scanned beyond to_pos and didn't find a point to wrap at, | 7902 | /* If we scanned beyond to_pos and didn't find a point to wrap at, |
| 7880 | restore the saved iterator. */ | 7903 | restore the saved iterator. */ |
| 7881 | if (atpos_it.sp >= 0) | 7904 | if (atpos_it.sp >= 0) |
| 7882 | *it = atpos_it; | 7905 | RESTORE_IT (it, &atpos_it, atpos_data); |
| 7883 | else if (atx_it.sp >= 0) | 7906 | else if (atx_it.sp >= 0) |
| 7884 | *it = atx_it; | 7907 | RESTORE_IT (it, &atx_it, atx_data); |
| 7885 | 7908 | ||
| 7886 | done: | 7909 | done: |
| 7887 | 7910 | ||
| 7911 | if (atpos_data) | ||
| 7912 | xfree (atpos_data); | ||
| 7913 | if (atx_data) | ||
| 7914 | xfree (atx_data); | ||
| 7915 | if (wrap_data) | ||
| 7916 | xfree (wrap_data); | ||
| 7917 | |||
| 7888 | /* Restore the iterator settings altered at the beginning of this | 7918 | /* Restore the iterator settings altered at the beginning of this |
| 7889 | function. */ | 7919 | function. */ |
| 7890 | it->glyph_row = saved_glyph_row; | 7920 | it->glyph_row = saved_glyph_row; |
| @@ -7900,8 +7930,12 @@ move_it_in_display_line (struct it *it, | |||
| 7900 | if (it->line_wrap == WORD_WRAP | 7930 | if (it->line_wrap == WORD_WRAP |
| 7901 | && (op & MOVE_TO_X)) | 7931 | && (op & MOVE_TO_X)) |
| 7902 | { | 7932 | { |
| 7903 | struct it save_it = *it; | 7933 | struct it save_it; |
| 7904 | int skip = move_it_in_display_line_to (it, to_charpos, to_x, op); | 7934 | void *save_data = NULL; |
| 7935 | int skip; | ||
| 7936 | |||
| 7937 | SAVE_IT (save_it, *it, save_data); | ||
| 7938 | skip = move_it_in_display_line_to (it, to_charpos, to_x, op); | ||
| 7905 | /* When word-wrap is on, TO_X may lie past the end | 7939 | /* When word-wrap is on, TO_X may lie past the end |
| 7906 | of a wrapped line. Then it->current is the | 7940 | of a wrapped line. Then it->current is the |
| 7907 | character on the next line, so backtrack to the | 7941 | character on the next line, so backtrack to the |
| @@ -7909,10 +7943,12 @@ move_it_in_display_line (struct it *it, | |||
| 7909 | if (skip == MOVE_LINE_CONTINUED) | 7943 | if (skip == MOVE_LINE_CONTINUED) |
| 7910 | { | 7944 | { |
| 7911 | int prev_x = max (it->current_x - 1, 0); | 7945 | int prev_x = max (it->current_x - 1, 0); |
| 7912 | *it = save_it; | 7946 | RESTORE_IT (it, &save_it, save_data); |
| 7913 | move_it_in_display_line_to | 7947 | move_it_in_display_line_to |
| 7914 | (it, -1, prev_x, MOVE_TO_X); | 7948 | (it, -1, prev_x, MOVE_TO_X); |
| 7915 | } | 7949 | } |
| 7950 | else | ||
| 7951 | xfree (save_data); | ||
| 7916 | } | 7952 | } |
| 7917 | else | 7953 | else |
| 7918 | move_it_in_display_line_to (it, to_charpos, to_x, op); | 7954 | move_it_in_display_line_to (it, to_charpos, to_x, op); |
| @@ -7935,6 +7971,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 7935 | { | 7971 | { |
| 7936 | enum move_it_result skip, skip2 = MOVE_X_REACHED; | 7972 | enum move_it_result skip, skip2 = MOVE_X_REACHED; |
| 7937 | int line_height, line_start_x = 0, reached = 0; | 7973 | int line_height, line_start_x = 0, reached = 0; |
| 7974 | void *backup_data = NULL; | ||
| 7938 | 7975 | ||
| 7939 | for (;;) | 7976 | for (;;) |
| 7940 | { | 7977 | { |
| @@ -7987,7 +8024,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 7987 | struct it it_backup; | 8024 | struct it it_backup; |
| 7988 | 8025 | ||
| 7989 | if (it->line_wrap == WORD_WRAP) | 8026 | if (it->line_wrap == WORD_WRAP) |
| 7990 | it_backup = *it; | 8027 | SAVE_IT (it_backup, *it, backup_data); |
| 7991 | 8028 | ||
| 7992 | /* TO_Y specified means stop at TO_X in the line containing | 8029 | /* TO_Y specified means stop at TO_X in the line containing |
| 7993 | TO_Y---or at TO_CHARPOS if this is reached first. The | 8030 | TO_Y---or at TO_CHARPOS if this is reached first. The |
| @@ -8021,7 +8058,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 8021 | reached = 6; | 8058 | reached = 6; |
| 8022 | break; | 8059 | break; |
| 8023 | } | 8060 | } |
| 8024 | it_backup = *it; | 8061 | SAVE_IT (it_backup, *it, backup_data); |
| 8025 | TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it))); | 8062 | TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it))); |
| 8026 | skip2 = move_it_in_display_line_to (it, to_charpos, -1, | 8063 | skip2 = move_it_in_display_line_to (it, to_charpos, -1, |
| 8027 | op & MOVE_TO_POS); | 8064 | op & MOVE_TO_POS); |
| @@ -8035,7 +8072,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 8035 | /* If TO_Y is in this line and TO_X was reached | 8072 | /* If TO_Y is in this line and TO_X was reached |
| 8036 | above, we scanned too far. We have to restore | 8073 | above, we scanned too far. We have to restore |
| 8037 | IT's settings to the ones before skipping. */ | 8074 | IT's settings to the ones before skipping. */ |
| 8038 | *it = it_backup; | 8075 | RESTORE_IT (it, &it_backup, backup_data); |
| 8039 | reached = 6; | 8076 | reached = 6; |
| 8040 | } | 8077 | } |
| 8041 | else | 8078 | else |
| @@ -8062,7 +8099,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 8062 | && it->line_wrap == WORD_WRAP) | 8099 | && it->line_wrap == WORD_WRAP) |
| 8063 | { | 8100 | { |
| 8064 | int prev_x = max (it->current_x - 1, 0); | 8101 | int prev_x = max (it->current_x - 1, 0); |
| 8065 | *it = it_backup; | 8102 | RESTORE_IT (it, &it_backup, backup_data); |
| 8066 | skip = move_it_in_display_line_to | 8103 | skip = move_it_in_display_line_to |
| 8067 | (it, -1, prev_x, MOVE_TO_X); | 8104 | (it, -1, prev_x, MOVE_TO_X); |
| 8068 | } | 8105 | } |
| @@ -8169,6 +8206,9 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos | |||
| 8169 | last_max_ascent = it->max_ascent; | 8206 | last_max_ascent = it->max_ascent; |
| 8170 | } | 8207 | } |
| 8171 | 8208 | ||
| 8209 | if (backup_data) | ||
| 8210 | xfree (backup_data); | ||
| 8211 | |||
| 8172 | TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached)); | 8212 | TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached)); |
| 8173 | } | 8213 | } |
| 8174 | 8214 | ||
| @@ -8186,6 +8226,7 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 8186 | { | 8226 | { |
| 8187 | int nlines, h; | 8227 | int nlines, h; |
| 8188 | struct it it2, it3; | 8228 | struct it it2, it3; |
| 8229 | void *it2data = NULL, *it3data = NULL; | ||
| 8189 | EMACS_INT start_pos; | 8230 | EMACS_INT start_pos; |
| 8190 | 8231 | ||
| 8191 | move_further_back: | 8232 | move_further_back: |
| @@ -8214,7 +8255,7 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 8214 | start of the next line so that we get its height. We need this | 8255 | start of the next line so that we get its height. We need this |
| 8215 | height to be able to tell whether we reached the specified | 8256 | height to be able to tell whether we reached the specified |
| 8216 | y-distance. */ | 8257 | y-distance. */ |
| 8217 | it2 = *it; | 8258 | SAVE_IT (it2, *it, it2data); |
| 8218 | it2.max_ascent = it2.max_descent = 0; | 8259 | it2.max_ascent = it2.max_descent = 0; |
| 8219 | do | 8260 | do |
| 8220 | { | 8261 | { |
| @@ -8223,7 +8264,7 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 8223 | } | 8264 | } |
| 8224 | while (!IT_POS_VALID_AFTER_MOVE_P (&it2)); | 8265 | while (!IT_POS_VALID_AFTER_MOVE_P (&it2)); |
| 8225 | xassert (IT_CHARPOS (*it) >= BEGV); | 8266 | xassert (IT_CHARPOS (*it) >= BEGV); |
| 8226 | it3 = it2; | 8267 | SAVE_IT (it3, it2, it3data); |
| 8227 | 8268 | ||
| 8228 | move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS); | 8269 | move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS); |
| 8229 | xassert (IT_CHARPOS (*it) >= BEGV); | 8270 | xassert (IT_CHARPOS (*it) >= BEGV); |
| @@ -8242,8 +8283,10 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 8242 | { | 8283 | { |
| 8243 | /* DY == 0 means move to the start of the screen line. The | 8284 | /* DY == 0 means move to the start of the screen line. The |
| 8244 | value of nlines is > 0 if continuation lines were involved. */ | 8285 | value of nlines is > 0 if continuation lines were involved. */ |
| 8286 | RESTORE_IT (it, it, it2data); | ||
| 8245 | if (nlines > 0) | 8287 | if (nlines > 0) |
| 8246 | move_it_by_lines (it, nlines); | 8288 | move_it_by_lines (it, nlines); |
| 8289 | xfree (it3data); | ||
| 8247 | } | 8290 | } |
| 8248 | else | 8291 | else |
| 8249 | { | 8292 | { |
| @@ -8251,9 +8294,13 @@ move_it_vertically_backward (struct it *it, int dy) | |||
| 8251 | Note that H has been subtracted in front of the if-statement. */ | 8294 | Note that H has been subtracted in front of the if-statement. */ |
| 8252 | int target_y = it->current_y + h - dy; | 8295 | int target_y = it->current_y + h - dy; |
| 8253 | int y0 = it3.current_y; | 8296 | int y0 = it3.current_y; |
| 8254 | int y1 = line_bottom_y (&it3); | 8297 | int y1; |
| 8255 | int line_height = y1 - y0; | 8298 | int line_height; |
| 8256 | 8299 | ||
| 8300 | RESTORE_IT (&it3, &it3, it3data); | ||
| 8301 | y1 = line_bottom_y (&it3); | ||
| 8302 | line_height = y1 - y0; | ||
| 8303 | RESTORE_IT (it, it, it2data); | ||
| 8257 | /* If we did not reach target_y, try to move further backward if | 8304 | /* If we did not reach target_y, try to move further backward if |
| 8258 | we can. If we moved too far backward, try to move forward. */ | 8305 | we can. If we moved too far backward, try to move forward. */ |
| 8259 | if (target_y < it->current_y | 8306 | if (target_y < it->current_y |
| @@ -8380,6 +8427,7 @@ move_it_by_lines (struct it *it, int dvpos) | |||
| 8380 | else | 8427 | else |
| 8381 | { | 8428 | { |
| 8382 | struct it it2; | 8429 | struct it it2; |
| 8430 | void *it2data = NULL; | ||
| 8383 | EMACS_INT start_charpos, i; | 8431 | EMACS_INT start_charpos, i; |
| 8384 | 8432 | ||
| 8385 | /* Start at the beginning of the screen line containing IT's | 8433 | /* Start at the beginning of the screen line containing IT's |
| @@ -8415,7 +8463,7 @@ move_it_by_lines (struct it *it, int dvpos) | |||
| 8415 | 8463 | ||
| 8416 | /* Above call may have moved too far if continuation lines | 8464 | /* Above call may have moved too far if continuation lines |
| 8417 | are involved. Scan forward and see if it did. */ | 8465 | are involved. Scan forward and see if it did. */ |
| 8418 | it2 = *it; | 8466 | SAVE_IT (it2, *it, it2data); |
| 8419 | it2.vpos = it2.current_y = 0; | 8467 | it2.vpos = it2.current_y = 0; |
| 8420 | move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); | 8468 | move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS); |
| 8421 | it->vpos -= it2.vpos; | 8469 | it->vpos -= it2.vpos; |
| @@ -8426,12 +8474,18 @@ move_it_by_lines (struct it *it, int dvpos) | |||
| 8426 | if (it2.vpos > -dvpos) | 8474 | if (it2.vpos > -dvpos) |
| 8427 | { | 8475 | { |
| 8428 | int delta = it2.vpos + dvpos; | 8476 | int delta = it2.vpos + dvpos; |
| 8429 | it2 = *it; | 8477 | |
| 8478 | RESTORE_IT (&it2, &it2, it2data); | ||
| 8479 | SAVE_IT (it2, *it, it2data); | ||
| 8430 | move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS); | 8480 | move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS); |
| 8431 | /* Move back again if we got too far ahead. */ | 8481 | /* Move back again if we got too far ahead. */ |
| 8432 | if (IT_CHARPOS (*it) >= start_charpos) | 8482 | if (IT_CHARPOS (*it) >= start_charpos) |
| 8433 | *it = it2; | 8483 | RESTORE_IT (it, &it2, it2data); |
| 8484 | else | ||
| 8485 | xfree (it2data); | ||
| 8434 | } | 8486 | } |
| 8487 | else | ||
| 8488 | RESTORE_IT (it, it, it2data); | ||
| 8435 | } | 8489 | } |
| 8436 | } | 8490 | } |
| 8437 | 8491 | ||
| @@ -13776,14 +13830,18 @@ try_scrolling (Lisp_Object window, int just_this_one_p, | |||
| 13776 | which was computed as distance from window bottom to | 13830 | which was computed as distance from window bottom to |
| 13777 | point. This matters when lines at window top and lines | 13831 | point. This matters when lines at window top and lines |
| 13778 | below window bottom have different height. */ | 13832 | below window bottom have different height. */ |
| 13779 | struct it it1 = it; | 13833 | struct it it1; |
| 13834 | void *it1data = NULL; | ||
| 13780 | /* We use a temporary it1 because line_bottom_y can modify | 13835 | /* We use a temporary it1 because line_bottom_y can modify |
| 13781 | its argument, if it moves one line down; see there. */ | 13836 | its argument, if it moves one line down; see there. */ |
| 13782 | int start_y = line_bottom_y (&it1); | 13837 | int start_y; |
| 13783 | 13838 | ||
| 13839 | SAVE_IT (it1, it, it1data); | ||
| 13840 | start_y = line_bottom_y (&it1); | ||
| 13784 | do { | 13841 | do { |
| 13842 | RESTORE_IT (&it, &it, it1data); | ||
| 13785 | move_it_by_lines (&it, 1); | 13843 | move_it_by_lines (&it, 1); |
| 13786 | it1 = it; | 13844 | SAVE_IT (it1, it, it1data); |
| 13787 | } while (line_bottom_y (&it1) - start_y < amount_to_scroll); | 13845 | } while (line_bottom_y (&it1) - start_y < amount_to_scroll); |
| 13788 | } | 13846 | } |
| 13789 | 13847 | ||
| @@ -14891,10 +14949,13 @@ redisplay_window (Lisp_Object window, int just_this_one_p) | |||
| 14891 | && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV) | 14949 | && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV) |
| 14892 | { | 14950 | { |
| 14893 | struct it it1; | 14951 | struct it it1; |
| 14952 | void *it1data = NULL; | ||
| 14894 | 14953 | ||
| 14954 | SAVE_IT (it1, it, it1data); | ||
| 14895 | start_display (&it1, w, startp); | 14955 | start_display (&it1, w, startp); |
| 14896 | move_it_vertically (&it1, margin); | 14956 | move_it_vertically (&it1, margin); |
| 14897 | margin_pos = IT_CHARPOS (it1); | 14957 | margin_pos = IT_CHARPOS (it1); |
| 14958 | RESTORE_IT (&it, &it, it1data); | ||
| 14898 | } | 14959 | } |
| 14899 | scrolling_up = PT > margin_pos; | 14960 | scrolling_up = PT > margin_pos; |
| 14900 | aggressive = | 14961 | aggressive = |
| @@ -17991,6 +18052,7 @@ display_line (struct it *it) | |||
| 17991 | struct glyph_row *row = it->glyph_row; | 18052 | struct glyph_row *row = it->glyph_row; |
| 17992 | Lisp_Object overlay_arrow_string; | 18053 | Lisp_Object overlay_arrow_string; |
| 17993 | struct it wrap_it; | 18054 | struct it wrap_it; |
| 18055 | void *wrap_data = NULL; | ||
| 17994 | int may_wrap = 0, wrap_x IF_LINT (= 0); | 18056 | int may_wrap = 0, wrap_x IF_LINT (= 0); |
| 17995 | int wrap_row_used = -1; | 18057 | int wrap_row_used = -1; |
| 17996 | int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0); | 18058 | int wrap_row_ascent IF_LINT (= 0), wrap_row_height IF_LINT (= 0); |
| @@ -18145,7 +18207,7 @@ display_line (struct it *it) | |||
| 18145 | may_wrap = 1; | 18207 | may_wrap = 1; |
| 18146 | else if (may_wrap) | 18208 | else if (may_wrap) |
| 18147 | { | 18209 | { |
| 18148 | wrap_it = *it; | 18210 | SAVE_IT (wrap_it, *it, wrap_data); |
| 18149 | wrap_x = x; | 18211 | wrap_x = x; |
| 18150 | wrap_row_used = row->used[TEXT_AREA]; | 18212 | wrap_row_used = row->used[TEXT_AREA]; |
| 18151 | wrap_row_ascent = row->ascent; | 18213 | wrap_row_ascent = row->ascent; |
| @@ -18315,7 +18377,7 @@ display_line (struct it *it) | |||
| 18315 | if (row->reversed_p) | 18377 | if (row->reversed_p) |
| 18316 | unproduce_glyphs (it, | 18378 | unproduce_glyphs (it, |
| 18317 | row->used[TEXT_AREA] - wrap_row_used); | 18379 | row->used[TEXT_AREA] - wrap_row_used); |
| 18318 | *it = wrap_it; | 18380 | RESTORE_IT (it, &wrap_it, wrap_data); |
| 18319 | it->continuation_lines_width += wrap_x; | 18381 | it->continuation_lines_width += wrap_x; |
| 18320 | row->used[TEXT_AREA] = wrap_row_used; | 18382 | row->used[TEXT_AREA] = wrap_row_used; |
| 18321 | row->ascent = wrap_row_ascent; | 18383 | row->ascent = wrap_row_ascent; |