diff options
| author | Po Lu | 2023-06-03 11:25:01 +0800 |
|---|---|---|
| committer | Po Lu | 2023-06-03 11:25:01 +0800 |
| commit | c308accc6d0f45cc64bb664fcc43a33a7ab015b3 (patch) | |
| tree | 4326e2545a391b340322b6d4f5a02cf2b7c4a2da | |
| parent | a696ed5c30fb9a7ba2d37f0e691de17872fdab16 (diff) | |
| download | emacs-c308accc6d0f45cc64bb664fcc43a33a7ab015b3.tar.gz emacs-c308accc6d0f45cc64bb664fcc43a33a7ab015b3.zip | |
Behave correctly when IMEs commit or compose text with active mark
* src/textconv.c (really_commit_text)
(really_set_composing_text): Delete text between mark and point
if the mark is active. Don't record changes if the text is
empty.
| -rw-r--r-- | src/textconv.c | 104 |
1 files changed, 79 insertions, 25 deletions
diff --git a/src/textconv.c b/src/textconv.c index e082eb6ee22..0716cf7edbb 100644 --- a/src/textconv.c +++ b/src/textconv.c | |||
| @@ -545,7 +545,10 @@ restore_selected_window (Lisp_Object window) | |||
| 545 | 545 | ||
| 546 | /* Commit the given text in the composing region. If there is no | 546 | /* Commit the given text in the composing region. If there is no |
| 547 | composing region, then insert the text after F's selected window's | 547 | composing region, then insert the text after F's selected window's |
| 548 | last point instead. Finally, remove the composing region. | 548 | last point instead, unless the mark is active. Finally, remove the |
| 549 | composing region. | ||
| 550 | |||
| 551 | If the mark is active, delete the text between mark and point. | ||
| 549 | 552 | ||
| 550 | Then, move point to POSITION relative to TEXT. If POSITION is | 553 | Then, move point to POSITION relative to TEXT. If POSITION is |
| 551 | greater than zero, it is relative to the character at the end of | 554 | greater than zero, it is relative to the character at the end of |
| @@ -556,7 +559,7 @@ really_commit_text (struct frame *f, EMACS_INT position, | |||
| 556 | Lisp_Object text) | 559 | Lisp_Object text) |
| 557 | { | 560 | { |
| 558 | specpdl_ref count; | 561 | specpdl_ref count; |
| 559 | ptrdiff_t wanted, start, end; | 562 | ptrdiff_t wanted, start, end, mark; |
| 560 | struct window *w; | 563 | struct window *w; |
| 561 | 564 | ||
| 562 | /* If F's old selected window is no longer live, fail. */ | 565 | /* If F's old selected window is no longer live, fail. */ |
| @@ -572,28 +575,48 @@ really_commit_text (struct frame *f, EMACS_INT position, | |||
| 572 | redisplay. */ | 575 | redisplay. */ |
| 573 | select_window (f->old_selected_window, Qt); | 576 | select_window (f->old_selected_window, Qt); |
| 574 | 577 | ||
| 575 | /* Now detect whether or not there is a composing region. | 578 | /* Now detect whether or not there is a composing or active region. |
| 576 | If there is, then replace it with TEXT. Don't do that | 579 | If there is, then replace it with TEXT. Don't do that |
| 577 | otherwise. */ | 580 | otherwise. */ |
| 578 | 581 | ||
| 579 | if (MARKERP (f->conversion.compose_region_start)) | 582 | mark = get_mark (); |
| 583 | if (MARKERP (f->conversion.compose_region_start) || mark != -1) | ||
| 580 | { | 584 | { |
| 581 | /* Replace its contents. */ | 585 | /* Replace its contents. Set START and END to the start and end |
| 582 | start = marker_position (f->conversion.compose_region_start); | 586 | of the composing region if it exists. */ |
| 583 | end = marker_position (f->conversion.compose_region_end); | 587 | |
| 588 | if (MARKERP (f->conversion.compose_region_start)) | ||
| 589 | { | ||
| 590 | start = marker_position (f->conversion.compose_region_start); | ||
| 591 | end = marker_position (f->conversion.compose_region_end); | ||
| 592 | } | ||
| 593 | else | ||
| 594 | { | ||
| 595 | /* Otherwise, set it to the start and end of the region. */ | ||
| 596 | start = min (mark, PT); | ||
| 597 | end = max (mark, PT); | ||
| 598 | } | ||
| 599 | |||
| 600 | /* Now delete whatever needs to go. */ | ||
| 601 | |||
| 584 | del_range (start, end); | 602 | del_range (start, end); |
| 585 | record_buffer_change (start, start, Qnil); | 603 | record_buffer_change (start, start, Qnil); |
| 586 | Finsert (1, &text); | ||
| 587 | record_buffer_change (start, PT, text); | ||
| 588 | 604 | ||
| 589 | /* Move to a the position specified in POSITION. If POSITION is | 605 | /* Don't record changes if TEXT is empty. */ |
| 590 | less than zero, it is relative to the start of the text that | 606 | |
| 591 | was inserted. */ | 607 | if (SCHARS (text)) |
| 608 | { | ||
| 609 | Finsert (1, &text); | ||
| 610 | record_buffer_change (start, PT, text); | ||
| 611 | } | ||
| 612 | |||
| 613 | /* Move to a the position specified in POSITION. */ | ||
| 592 | 614 | ||
| 593 | if (position <= 0) | 615 | if (position <= 0) |
| 594 | { | 616 | { |
| 595 | wanted | 617 | /* If POSITION is less than zero, it is relative to the |
| 596 | = marker_position (f->conversion.compose_region_start); | 618 | start of the text that was inserted. */ |
| 619 | wanted = start; | ||
| 597 | 620 | ||
| 598 | if (INT_ADD_WRAPV (wanted, position, &wanted) | 621 | if (INT_ADD_WRAPV (wanted, position, &wanted) |
| 599 | || wanted < BEGV) | 622 | || wanted < BEGV) |
| @@ -608,9 +631,7 @@ really_commit_text (struct frame *f, EMACS_INT position, | |||
| 608 | { | 631 | { |
| 609 | /* Otherwise, it is relative to the last character in | 632 | /* Otherwise, it is relative to the last character in |
| 610 | TEXT. */ | 633 | TEXT. */ |
| 611 | 634 | wanted = PT; | |
| 612 | wanted | ||
| 613 | = marker_position (f->conversion.compose_region_end); | ||
| 614 | 635 | ||
| 615 | if (INT_ADD_WRAPV (wanted, position - 1, &wanted) | 636 | if (INT_ADD_WRAPV (wanted, position - 1, &wanted) |
| 616 | || wanted > ZV) | 637 | || wanted > ZV) |
| @@ -642,8 +663,14 @@ really_commit_text (struct frame *f, EMACS_INT position, | |||
| 642 | /* Otherwise, move the text and point to an appropriate | 663 | /* Otherwise, move the text and point to an appropriate |
| 643 | location. */ | 664 | location. */ |
| 644 | wanted = PT; | 665 | wanted = PT; |
| 645 | Finsert (1, &text); | 666 | |
| 646 | record_buffer_change (wanted, PT, text); | 667 | /* Don't record changes if TEXT is empty. */ |
| 668 | |||
| 669 | if (SCHARS (text)) | ||
| 670 | { | ||
| 671 | Finsert (1, &text); | ||
| 672 | record_buffer_change (start, PT, text); | ||
| 673 | } | ||
| 647 | 674 | ||
| 648 | if (position <= 0) | 675 | if (position <= 0) |
| 649 | { | 676 | { |
| @@ -737,6 +764,32 @@ really_set_composing_text (struct frame *f, ptrdiff_t position, | |||
| 737 | 764 | ||
| 738 | if (!MARKERP (f->conversion.compose_region_start)) | 765 | if (!MARKERP (f->conversion.compose_region_start)) |
| 739 | { | 766 | { |
| 767 | /* Set START and END. */ | ||
| 768 | start = PT; | ||
| 769 | wanted = end = get_mark (); | ||
| 770 | |||
| 771 | /* If END is -1, set it to start. */ | ||
| 772 | |||
| 773 | if (end == -1) | ||
| 774 | end = start; | ||
| 775 | else | ||
| 776 | { | ||
| 777 | /* Now sort start and end. */ | ||
| 778 | start = min (start, end); | ||
| 779 | end = max (PT, wanted); | ||
| 780 | } | ||
| 781 | |||
| 782 | /* If END is not the same as start, delete the text in | ||
| 783 | between. */ | ||
| 784 | |||
| 785 | if (end != start) | ||
| 786 | { | ||
| 787 | del_range (start, end); | ||
| 788 | set_point (start); | ||
| 789 | record_buffer_change (start, start, Qnil); | ||
| 790 | } | ||
| 791 | |||
| 792 | /* Now set the markers which denote the composition region. */ | ||
| 740 | f->conversion.compose_region_start | 793 | f->conversion.compose_region_start |
| 741 | = build_marker (current_buffer, PT, PT_BYTE); | 794 | = build_marker (current_buffer, PT, PT_BYTE); |
| 742 | f->conversion.compose_region_end | 795 | f->conversion.compose_region_end |
| @@ -744,8 +797,6 @@ really_set_composing_text (struct frame *f, ptrdiff_t position, | |||
| 744 | 797 | ||
| 745 | Fset_marker_insertion_type (f->conversion.compose_region_end, | 798 | Fset_marker_insertion_type (f->conversion.compose_region_end, |
| 746 | Qt); | 799 | Qt); |
| 747 | |||
| 748 | start = PT; | ||
| 749 | } | 800 | } |
| 750 | else | 801 | else |
| 751 | { | 802 | { |
| @@ -1368,6 +1419,9 @@ end_batch_edit (struct frame *f, unsigned long counter) | |||
| 1368 | /* Insert the specified STRING into F's current buffer's composition | 1419 | /* Insert the specified STRING into F's current buffer's composition |
| 1369 | region, and set point to POSITION relative to STRING. | 1420 | region, and set point to POSITION relative to STRING. |
| 1370 | 1421 | ||
| 1422 | If there is no composition region, use the active region instead. | ||
| 1423 | If that doesn't exist either, insert STRING after point. | ||
| 1424 | |||
| 1371 | COUNTER means the same as in `start_batch_edit'. */ | 1425 | COUNTER means the same as in `start_batch_edit'. */ |
| 1372 | 1426 | ||
| 1373 | void | 1427 | void |
| @@ -1415,11 +1469,11 @@ finish_composing_text (struct frame *f, unsigned long counter, | |||
| 1415 | /* Insert the given STRING and make it the currently active | 1469 | /* Insert the given STRING and make it the currently active |
| 1416 | composition. | 1470 | composition. |
| 1417 | 1471 | ||
| 1418 | If there is currently no composing region, then the new value of | 1472 | If there is currently no composing or active region, then the new |
| 1419 | point is used as the composing region. | 1473 | value of point is used as the composing region. |
| 1420 | 1474 | ||
| 1421 | Then, the composing region is replaced with the text in the | 1475 | Then, the composing or active region is replaced with the text in |
| 1422 | specified string. | 1476 | the specified string. |
| 1423 | 1477 | ||
| 1424 | Finally, move point to new_point, which is relative to either the | 1478 | Finally, move point to new_point, which is relative to either the |
| 1425 | start or the end of OBJECT depending on whether or not it is less | 1479 | start or the end of OBJECT depending on whether or not it is less |