From c308accc6d0f45cc64bb664fcc43a33a7ab015b3 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 3 Jun 2023 11:25:01 +0800 Subject: [PATCH] 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. --- src/textconv.c | 104 +++++++++++++++++++++++++++++++++++++------------ 1 file 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) /* Commit the given text in the composing region. If there is no composing region, then insert the text after F's selected window's - last point instead. Finally, remove the composing region. + last point instead, unless the mark is active. Finally, remove the + composing region. + + If the mark is active, delete the text between mark and point. Then, move point to POSITION relative to TEXT. If POSITION is 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, Lisp_Object text) { specpdl_ref count; - ptrdiff_t wanted, start, end; + ptrdiff_t wanted, start, end, mark; struct window *w; /* If F's old selected window is no longer live, fail. */ @@ -572,28 +575,48 @@ really_commit_text (struct frame *f, EMACS_INT position, redisplay. */ select_window (f->old_selected_window, Qt); - /* Now detect whether or not there is a composing region. + /* Now detect whether or not there is a composing or active region. If there is, then replace it with TEXT. Don't do that otherwise. */ - if (MARKERP (f->conversion.compose_region_start)) + mark = get_mark (); + if (MARKERP (f->conversion.compose_region_start) || mark != -1) { - /* Replace its contents. */ - start = marker_position (f->conversion.compose_region_start); - end = marker_position (f->conversion.compose_region_end); + /* Replace its contents. Set START and END to the start and end + of the composing region if it exists. */ + + if (MARKERP (f->conversion.compose_region_start)) + { + start = marker_position (f->conversion.compose_region_start); + end = marker_position (f->conversion.compose_region_end); + } + else + { + /* Otherwise, set it to the start and end of the region. */ + start = min (mark, PT); + end = max (mark, PT); + } + + /* Now delete whatever needs to go. */ + del_range (start, end); record_buffer_change (start, start, Qnil); - Finsert (1, &text); - record_buffer_change (start, PT, text); - /* Move to a the position specified in POSITION. If POSITION is - less than zero, it is relative to the start of the text that - was inserted. */ + /* Don't record changes if TEXT is empty. */ + + if (SCHARS (text)) + { + Finsert (1, &text); + record_buffer_change (start, PT, text); + } + + /* Move to a the position specified in POSITION. */ if (position <= 0) { - wanted - = marker_position (f->conversion.compose_region_start); + /* If POSITION is less than zero, it is relative to the + start of the text that was inserted. */ + wanted = start; if (INT_ADD_WRAPV (wanted, position, &wanted) || wanted < BEGV) @@ -608,9 +631,7 @@ really_commit_text (struct frame *f, EMACS_INT position, { /* Otherwise, it is relative to the last character in TEXT. */ - - wanted - = marker_position (f->conversion.compose_region_end); + wanted = PT; if (INT_ADD_WRAPV (wanted, position - 1, &wanted) || wanted > ZV) @@ -642,8 +663,14 @@ really_commit_text (struct frame *f, EMACS_INT position, /* Otherwise, move the text and point to an appropriate location. */ wanted = PT; - Finsert (1, &text); - record_buffer_change (wanted, PT, text); + + /* Don't record changes if TEXT is empty. */ + + if (SCHARS (text)) + { + Finsert (1, &text); + record_buffer_change (start, PT, text); + } if (position <= 0) { @@ -737,6 +764,32 @@ really_set_composing_text (struct frame *f, ptrdiff_t position, if (!MARKERP (f->conversion.compose_region_start)) { + /* Set START and END. */ + start = PT; + wanted = end = get_mark (); + + /* If END is -1, set it to start. */ + + if (end == -1) + end = start; + else + { + /* Now sort start and end. */ + start = min (start, end); + end = max (PT, wanted); + } + + /* If END is not the same as start, delete the text in + between. */ + + if (end != start) + { + del_range (start, end); + set_point (start); + record_buffer_change (start, start, Qnil); + } + + /* Now set the markers which denote the composition region. */ f->conversion.compose_region_start = build_marker (current_buffer, PT, PT_BYTE); f->conversion.compose_region_end @@ -744,8 +797,6 @@ really_set_composing_text (struct frame *f, ptrdiff_t position, Fset_marker_insertion_type (f->conversion.compose_region_end, Qt); - - start = PT; } else { @@ -1368,6 +1419,9 @@ end_batch_edit (struct frame *f, unsigned long counter) /* Insert the specified STRING into F's current buffer's composition region, and set point to POSITION relative to STRING. + If there is no composition region, use the active region instead. + If that doesn't exist either, insert STRING after point. + COUNTER means the same as in `start_batch_edit'. */ void @@ -1415,11 +1469,11 @@ finish_composing_text (struct frame *f, unsigned long counter, /* Insert the given STRING and make it the currently active composition. - If there is currently no composing region, then the new value of - point is used as the composing region. + If there is currently no composing or active region, then the new + value of point is used as the composing region. - Then, the composing region is replaced with the text in the - specified string. + Then, the composing or active region is replaced with the text in + the specified string. Finally, move point to new_point, which is relative to either the start or the end of OBJECT depending on whether or not it is less -- 2.39.2