From 9e9142249725b4785a01734a8c0f50301fccdea7 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 5 Jul 2023 11:39:45 +0800 Subject: [PATCH] Update Android port * doc/lispref/commands.texi (Misc Events): Correctly index `set-text-conversion-style'. * lisp/tool-bar.el (tool-bar-event-apply-alt-modifier) (tool-bar-event-apply-super-modifier) (tool-bar-event-apply-hyper-modifier) (tool-bar-event-apply-shift-modifier) (tool-bar-event-apply-control-modifier) (tool-bar-event-apply-meta-modifier): Pass t when restoring text conversion style. * src/keyboard.c (restore_reading_key_sequence): New function. (read_key_sequence): Set `reading_key_sequence' where necessary. * src/keyboard.h: Declare variable. * src/textconv.c (check_postponed_buffers): New function. (Fset_text_conversion_style): New argument. If set, and a key sequence is being read, postpone resetting the IME until the key sequence is read. (syms_of_textconv): Clear new variable and add staticpro. * src/textconv.h: Update prototypes. --- doc/lispref/commands.texi | 2 +- lisp/tool-bar.el | 12 +++--- src/keyboard.c | 35 +++++++++++++++ src/keyboard.h | 8 ++++ src/textconv.c | 89 +++++++++++++++++++++++++++++++++++++-- src/textconv.h | 3 ++ 6 files changed, 139 insertions(+), 10 deletions(-) diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index eaf6f3e451b..7a076406bed 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2251,7 +2251,7 @@ This, or any other value, means that the input method will be enabled and make edits followed by @code{text-conversion} events. @end table -@findex disable-text-conversion +@findex set-text-conversion-style Changes to the value of this variable will only take effect upon the next redisplay after the buffer becomes the selected buffer of a frame. If you need to disable text conversion in a way that takes diff --git a/lisp/tool-bar.el b/lisp/tool-bar.el index aeab21f61a0..1ede5c45971 100644 --- a/lisp/tool-bar.el +++ b/lisp/tool-bar.el @@ -444,7 +444,7 @@ apply any extra modifiers bound to subsequent `tool-bar' events." ;; Re-enable text conversion if necessary. (unless (or (not (fboundp 'set-text-conversion-style)) (eq old-text-conversion-style text-conversion-style)) - (set-text-conversion-style old-text-conversion-style))))) + (set-text-conversion-style old-text-conversion-style t))))) (defun tool-bar-event-apply-super-modifier (_ignore-prompt) "Like `event-apply-super-modifier'. @@ -480,7 +480,7 @@ apply any extra modifiers bound to subsequent `tool-bar' events." ;; Re-enable text conversion if necessary. (unless (or (not (fboundp 'set-text-conversion-style)) (eq old-text-conversion-style text-conversion-style)) - (set-text-conversion-style old-text-conversion-style))))) + (set-text-conversion-style old-text-conversion-style t))))) (defun tool-bar-event-apply-hyper-modifier (_ignore-prompt) "Like `event-apply-hyper-modifier'. @@ -516,7 +516,7 @@ apply any extra modifiers bound to subsequent `tool-bar' events." ;; Re-enable text conversion if necessary. (unless (or (not (fboundp 'set-text-conversion-style)) (eq old-text-conversion-style text-conversion-style)) - (set-text-conversion-style old-text-conversion-style))))) + (set-text-conversion-style old-text-conversion-style t))))) (defun tool-bar-event-apply-shift-modifier (_ignore-prompt) "Like `event-apply-shift-modifier'. @@ -552,7 +552,7 @@ apply any extra modifiers bound to subsequent `tool-bar' events." ;; Re-enable text conversion if necessary. (unless (or (not (fboundp 'set-text-conversion-style)) (eq old-text-conversion-style text-conversion-style)) - (set-text-conversion-style old-text-conversion-style))))) + (set-text-conversion-style old-text-conversion-style t))))) (defun tool-bar-event-apply-control-modifier (_ignore-prompt) "Like `event-apply-control-modifier'. @@ -588,7 +588,7 @@ apply any extra modifiers bound to subsequent `tool-bar' events." ;; Re-enable text conversion if necessary. (unless (or (not (fboundp 'set-text-conversion-style)) (eq old-text-conversion-style text-conversion-style)) - (set-text-conversion-style old-text-conversion-style))))) + (set-text-conversion-style old-text-conversion-style t))))) (defun tool-bar-event-apply-meta-modifier (_ignore-prompt) "Like `event-apply-meta-modifier'. @@ -624,7 +624,7 @@ apply any extra modifiers bound to subsequent `tool-bar' events." ;; Re-enable text conversion if necessary. (unless (or (not (fboundp 'set-text-conversion-style)) (eq old-text-conversion-style text-conversion-style)) - (set-text-conversion-style old-text-conversion-style))))) + (set-text-conversion-style old-text-conversion-style t))))) (define-minor-mode modifier-bar-mode "Toggle display of the modifier bar. diff --git a/src/keyboard.c b/src/keyboard.c index b33fbf8f155..ea07c538aa2 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -115,6 +115,13 @@ static KBOARD *all_kboards; /* True in the single-kboard state, false in the any-kboard state. */ static bool single_kboard; +#ifdef HAVE_TEXT_CONVERSION + +/* True if a key sequence is currently being read. */ +bool reading_key_sequence; + +#endif /* HAVE_TEXT_CONVERSION */ + /* Minimum allowed size of the recent_keys vector. */ #define MIN_NUM_RECENT_KEYS (100) @@ -10102,6 +10109,24 @@ void init_raw_keybuf_count (void) raw_keybuf_count = 0; } + + +#ifdef HAVE_TEXT_CONVERSION + +static void +restore_reading_key_sequence (int old_reading_key_sequence) +{ + reading_key_sequence = old_reading_key_sequence; + + /* If a key sequence is no longer being read, reset input methods + whose state changes were postponed. */ + + if (!old_reading_key_sequence) + check_postponed_buffers (); +} + +#endif /* HAVE_TEXT_CONVERSION */ + /* Read a sequence of keys that ends with a non prefix character, storing it in KEYBUF, a buffer of size READ_KEY_ELTS. Prompt with PROMPT. @@ -10261,6 +10286,16 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt, keys_start = this_command_key_count; this_single_command_key_start = keys_start; +#ifdef HAVE_TEXT_CONVERSION + /* Set `reading_key_sequence' to true. This variable is used by + Fset_text_conversion_style to determine if it should postpone + resetting the input method until this function completes. */ + + record_unwind_protect_int (restore_reading_key_sequence, + reading_key_sequence); + reading_key_sequence = true; +#endif /* HAVE_TEXT_CONVERSION */ + /* We jump here when we need to reinitialize fkey and keytran; this happens if we switch keyboards between rescans. */ replay_entire_sequence: diff --git a/src/keyboard.h b/src/keyboard.h index 26eecd48b00..9f6e65f9a09 100644 --- a/src/keyboard.h +++ b/src/keyboard.h @@ -246,6 +246,14 @@ extern KBOARD *initial_kboard; kboard, but doing so requires throwing to wrong_kboard_jmpbuf. */ extern KBOARD *current_kboard; + +#ifdef HAVE_TEXT_CONVERSION + +/* True if a key sequence is currently being read. */ +extern bool reading_key_sequence; + +#endif /* HAVE_TEXT_CONVERSION */ + /* Total number of times read_char has returned, modulo UINTMAX_MAX + 1. */ extern uintmax_t num_input_events; diff --git a/src/textconv.c b/src/textconv.c index 6718568ac98..60f3ba80577 100644 --- a/src/textconv.c +++ b/src/textconv.c @@ -2020,10 +2020,67 @@ register_textconv_interface (struct textconv_interface *interface) +/* List of buffers whose text conversion state will be reset after a + key sequence is read. */ +static Lisp_Object postponed_buffers; + +/* Reset the text conversion style of each frame whose selected buffer + is contained inside `postponed_buffers'. Set `postponed_buffers' + to nil. */ + +void +check_postponed_buffers (void) +{ + Lisp_Object buffer, tail, frame; + struct buffer *b; + struct frame *f; + + buffer = postponed_buffers; + postponed_buffers = Qnil; + + if (!text_interface->reset) + return; + + FOR_EACH_TAIL (buffer) + { + b = XBUFFER (XCAR (buffer)); + + /* Continue if this is a dead buffer. */ + + if (!BUFFER_LIVE_P (b)) + continue; + + /* If no windows are displaying B anymore, continue. */ + + if (!buffer_window_count (b)) + continue; + + /* Look for frames which have B selected. */ + + FOR_EACH_FRAME (tail, frame) + { + f = XFRAME (frame); + + if (WINDOW_LIVE_P (f->old_selected_window) + && FRAME_WINDOW_P (f) + /* N.B. that the same frame can't be reset twice as long + as the list of buffers remains unique. */ + && EQ (XWINDOW (f->old_selected_window)->contents, + XCAR (buffer))) + { + block_input (); + reset_frame_state (f); + text_interface->reset (f); + unblock_input (); + } + } + } +} + /* Lisp interface. */ DEFUN ("set-text-conversion-style", Fset_text_conversion_style, - Sset_text_conversion_style, 1, 1, 0, + Sset_text_conversion_style, 1, 2, 0, doc: /* Set the text conversion style in the current buffer. Set `text-conversion-style' to VALUE, then force any input method @@ -2032,8 +2089,17 @@ editing frame displaying this buffer to stop itself. This can lead to a significant amount of time being taken by the input method resetting itself, so you should not use this function lightly; instead, set `text-conversion-style' before your buffer is displayed, -and let redisplay manage the input method appropriately. */) - (Lisp_Object value) +and let redisplay manage the input method appropriately. + +If a key sequence is currently being read (either through the command +loop or by a call to `read-key-sequence') and AFTER-KEY-SEQUENCE is +non-nil, don't perform changes to the input method until the key +sequence is read. This is useful within a function bound to +`input-decode-map' or `local-function-key-map', as it prevents the +input method from being redundantly enabled according to VALUE if the +replacement key sequence returned starts a new key sequence and makes +`read-key-sequence' disable text conversion again. */) + (Lisp_Object value, Lisp_Object after_key_sequence) { Lisp_Object tail, frame; struct frame *f; @@ -2051,6 +2117,20 @@ and let redisplay manage the input method appropriately. */) { buffer = Fcurrent_buffer (); + /* Postpone changes to the actual text conversion state if + AFTER_KEY_SEQUENCE is non-nil and a key sequence is being + read. */ + + if (reading_key_sequence && !NILP (after_key_sequence)) + { + if (NILP (Fmemq (buffer, postponed_buffers))) + /* `check_postponed_buffers' will hopefully be called soon + enough to avoid postponed_buffers growing + indefinitely. */ + postponed_buffers = Fcons (buffer, postponed_buffers); + return Qnil; + } + FOR_EACH_FRAME (tail, frame) { f = XFRAME (frame); @@ -2126,4 +2206,7 @@ nil means to display no indication of a temporary edit. */); Vtext_conversion_face = Qunderline; defsubr (&Sset_text_conversion_style); + + postponed_buffers = Qnil; + staticpro (&postponed_buffers); } diff --git a/src/textconv.h b/src/textconv.h index 7550388a723..feac5b805af 100644 --- a/src/textconv.h +++ b/src/textconv.h @@ -118,6 +118,8 @@ struct textconv_callback_struct struct textconv_conversion_text text; }; + + #define TEXTCONV_SKIP_CONVERSION_REGION (1 << 0) extern int textconv_query (struct frame *, struct textconv_callback_struct *, @@ -148,6 +150,7 @@ extern char *get_surrounding_text (struct frame *, ptrdiff_t, ptrdiff_t *, ptrdiff_t *, ptrdiff_t *, ptrdiff_t *); extern bool conversion_disabled_p (void); +extern void check_postponed_buffers (void); extern void register_textconv_interface (struct textconv_interface *); -- 2.39.2