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
;; 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'.
;; 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'.
;; 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'.
;; 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'.
;; 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'.
;; 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.
/* 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)
raw_keybuf_count = 0;
}
+\f
+
+#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.
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:
kboard, but doing so requires throwing to wrong_kboard_jmpbuf. */
extern KBOARD *current_kboard;
\f
+
+#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;
\f
+/* 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
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;
{
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);
Vtext_conversion_face = Qunderline;
defsubr (&Sset_text_conversion_style);
+
+ postponed_buffers = Qnil;
+ staticpro (&postponed_buffers);
}
struct textconv_conversion_text text;
};
+\f
+
#define TEXTCONV_SKIP_CONVERSION_REGION (1 << 0)
extern int textconv_query (struct frame *, struct textconv_callback_struct *,
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 *);