Support input method ``text conversion'' on X Windows
* configure.ac (HAVE_TEXT_CONVERSION): Define on X. * etc/NEWS: Announce new change. * src/emacs.c (main): Always call init_xterm. * src/frame.c (do_switch_frame): Use `fset_selected_window'. * src/insdel.c (struct safe_del_range_context): New structure. (safe_del_range_1, safe_del_range_2, safe_del_range): New functions. * src/lisp.h: Export new functions. * src/window.c (run_window_change_functions): Report selected window and buffer changes so that the input method can be reset. * src/xfns.c (XICCallback, Xxic_preedit_caret_callback) (Xxic_preedit_done_callback, Xxic_preedit_start_callback) (Xxic_preedit_draw_callback): Fix coding style. (Xxic_string_conversion_callback): New callback. (create_frame_xic): Register string conversion callback. (struct x_xim_text_conversion_data): New field `size'. (x_encode_xim_text_1, x_encode_xim_text): New functions. (xic_string_conversion_callback): New function. * src/xterm.c (x_reset_conversion): New function. (text_conversion_interface): New variable. (init_xterm): Initialize text conversion interface.
This commit is contained in:
parent
50140585a2
commit
ae4ff4f25f
9 changed files with 407 additions and 14 deletions
|
@ -6502,6 +6502,12 @@ if test "$window_system" != "none"; then
|
|||
AC_DEFINE([POLL_FOR_INPUT], [1],
|
||||
[Define if you poll periodically to detect C-g.])
|
||||
WINDOW_SYSTEM_OBJ="fontset.o fringe.o image.o"
|
||||
|
||||
if test "$window_system" = "x11"; then
|
||||
AC_DEFINE([HAVE_TEXT_CONVERSION], [1],
|
||||
[Define if the window system has text conversion support.])
|
||||
WINDOW_SYSTEM_OBJ="$WINDOW_SYSTEM_OBJ textconv.o"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST([WINDOW_SYSTEM_OBJ])
|
||||
|
|
7
etc/NEWS
7
etc/NEWS
|
@ -59,6 +59,13 @@ This allows the user to customize the prompt that is appended by
|
|||
|
||||
* Editing Changes in Emacs 30.1
|
||||
|
||||
---
|
||||
** On X, Emacs now supports input methods which perform "string conversion".
|
||||
This means an input method can now ask Emacs to delete text
|
||||
surrounding point and replace it with something else, as well as query
|
||||
Emacs for surrounding text. If your input method allows you to "undo"
|
||||
mistaken compositions, this will now work as well.
|
||||
|
||||
---
|
||||
** New command 'kill-matching-buffers-no-ask'.
|
||||
This works like 'kill-matching-buffers', but without asking for
|
||||
|
|
|
@ -2447,7 +2447,8 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
|||
#ifdef HAVE_DBUS
|
||||
init_dbusbind ();
|
||||
#endif
|
||||
#if defined(USE_GTK) && !defined(HAVE_PGTK)
|
||||
|
||||
#ifdef HAVE_X_WINDOWS
|
||||
init_xterm ();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1526,7 +1526,7 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord)
|
|||
|
||||
if (f->select_mini_window_flag
|
||||
&& !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt)))
|
||||
f->selected_window = f->minibuffer_window;
|
||||
fset_selected_window (f, f->minibuffer_window);
|
||||
f->select_mini_window_flag = false;
|
||||
|
||||
if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
|
||||
|
|
38
src/insdel.c
38
src/insdel.c
|
@ -1715,6 +1715,44 @@ del_range (ptrdiff_t from, ptrdiff_t to)
|
|||
del_range_1 (from, to, 1, 0);
|
||||
}
|
||||
|
||||
struct safe_del_range_context
|
||||
{
|
||||
/* From and to positions. */
|
||||
ptrdiff_t from, to;
|
||||
};
|
||||
|
||||
static Lisp_Object
|
||||
safe_del_range_1 (void *ptr)
|
||||
{
|
||||
struct safe_del_range_context *context;
|
||||
|
||||
context = ptr;
|
||||
del_range (context->from, context->to);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
safe_del_range_2 (enum nonlocal_exit type, Lisp_Object value)
|
||||
{
|
||||
return Qt;
|
||||
}
|
||||
|
||||
/* Like del_range; however, catch all non-local exits. Value is 0 if
|
||||
the buffer contents were really deleted. Otherwise, it is 1. */
|
||||
|
||||
int
|
||||
safe_del_range (ptrdiff_t from, ptrdiff_t to)
|
||||
{
|
||||
struct safe_del_range_context context;
|
||||
|
||||
context.from = from;
|
||||
context.to = to;
|
||||
|
||||
return !NILP (internal_catch_all (safe_del_range_1,
|
||||
&context,
|
||||
safe_del_range_2));
|
||||
}
|
||||
|
||||
/* Like del_range; PREPARE says whether to call prepare_to_modify_buffer.
|
||||
RET_STRING says to return the deleted text. */
|
||||
|
||||
|
|
|
@ -4116,6 +4116,7 @@ extern void del_range_byte (ptrdiff_t, ptrdiff_t);
|
|||
extern void del_range_both (ptrdiff_t, ptrdiff_t, ptrdiff_t, ptrdiff_t, bool);
|
||||
extern Lisp_Object del_range_2 (ptrdiff_t, ptrdiff_t,
|
||||
ptrdiff_t, ptrdiff_t, bool);
|
||||
extern int safe_del_range (ptrdiff_t, ptrdiff_t);
|
||||
extern void modify_text (ptrdiff_t, ptrdiff_t);
|
||||
extern void prepare_to_modify_buffer (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
|
||||
extern void prepare_to_modify_buffer_1 (ptrdiff_t, ptrdiff_t, ptrdiff_t *);
|
||||
|
@ -5212,6 +5213,11 @@ extern void syms_of_profiler (void);
|
|||
extern char *emacs_root_dir (void);
|
||||
#endif /* DOS_NT */
|
||||
|
||||
#ifdef HAVE_TEXT_CONVERSION
|
||||
/* Defined in textconv.c. */
|
||||
extern void report_selected_window_change (struct frame *);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NATIVE_COMP
|
||||
INLINE bool
|
||||
SUBR_NATIVE_COMPILEDP (Lisp_Object a)
|
||||
|
|
15
src/window.c
15
src/window.c
|
@ -3856,6 +3856,9 @@ run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer,
|
|||
*
|
||||
* This function does not save and restore match data. Any functions
|
||||
* it calls are responsible for doing that themselves.
|
||||
*
|
||||
* Additionally, report changes to each frame's selected window to the
|
||||
* input method in textconv.c.
|
||||
*/
|
||||
void
|
||||
run_window_change_functions (void)
|
||||
|
@ -4015,6 +4018,18 @@ run_window_change_functions (void)
|
|||
run_window_change_functions_1
|
||||
(Qwindow_selection_change_functions, Qnil, frame);
|
||||
|
||||
#if defined HAVE_TEXT_CONVERSION
|
||||
|
||||
/* If the buffer or selected window has changed, also reset the
|
||||
input method composition state. */
|
||||
|
||||
if ((frame_selected_window_change || frame_buffer_change)
|
||||
&& FRAME_LIVE_P (f)
|
||||
&& FRAME_WINDOW_P (f))
|
||||
report_selected_window_change (f);
|
||||
|
||||
#endif
|
||||
|
||||
/* A frame has changed state when a size or buffer change
|
||||
occurred, its selected window has changed, when it was
|
||||
(de-)selected or its window state change flag was set. */
|
||||
|
|
303
src/xfns.c
303
src/xfns.c
|
@ -37,6 +37,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "termhooks.h"
|
||||
#include "font.h"
|
||||
|
||||
#ifdef HAVE_X_I18N
|
||||
#include "textconv.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
@ -2671,24 +2675,50 @@ append_wm_protocols (struct x_display_info *dpyinfo,
|
|||
|
||||
#ifdef HAVE_X_I18N
|
||||
|
||||
static void xic_preedit_draw_callback (XIC, XPointer, XIMPreeditDrawCallbackStruct *);
|
||||
static void xic_preedit_caret_callback (XIC, XPointer, XIMPreeditCaretCallbackStruct *);
|
||||
static void xic_preedit_draw_callback (XIC, XPointer,
|
||||
XIMPreeditDrawCallbackStruct *);
|
||||
static void xic_preedit_caret_callback (XIC, XPointer,
|
||||
XIMPreeditCaretCallbackStruct *);
|
||||
static void xic_preedit_done_callback (XIC, XPointer, XPointer);
|
||||
static int xic_preedit_start_callback (XIC, XPointer, XPointer);
|
||||
static void xic_string_conversion_callback (XIC, XPointer,
|
||||
XIMStringConversionCallbackStruct *);
|
||||
|
||||
#ifndef HAVE_XICCALLBACK_CALLBACK
|
||||
#define XICCallback XIMCallback
|
||||
#define XICProc XIMProc
|
||||
#endif
|
||||
|
||||
static XIMCallback Xxic_preedit_draw_callback = { NULL,
|
||||
(XIMProc) xic_preedit_draw_callback };
|
||||
static XIMCallback Xxic_preedit_caret_callback = { NULL,
|
||||
(XIMProc) xic_preedit_caret_callback };
|
||||
static XIMCallback Xxic_preedit_done_callback = { NULL,
|
||||
(XIMProc) xic_preedit_done_callback };
|
||||
static XICCallback Xxic_preedit_start_callback = { NULL,
|
||||
(XICProc) xic_preedit_start_callback };
|
||||
static XIMCallback Xxic_preedit_draw_callback =
|
||||
{
|
||||
NULL,
|
||||
(XIMProc) xic_preedit_draw_callback,
|
||||
};
|
||||
|
||||
static XIMCallback Xxic_preedit_caret_callback =
|
||||
{
|
||||
NULL,
|
||||
(XIMProc) xic_preedit_caret_callback,
|
||||
};
|
||||
|
||||
static XIMCallback Xxic_preedit_done_callback =
|
||||
{
|
||||
NULL,
|
||||
(XIMProc) xic_preedit_done_callback,
|
||||
};
|
||||
|
||||
static XICCallback Xxic_preedit_start_callback =
|
||||
{
|
||||
NULL,
|
||||
(XICProc) xic_preedit_start_callback,
|
||||
};
|
||||
|
||||
static XIMCallback Xxic_string_conversion_callback =
|
||||
{
|
||||
/* This is actually an XICCallback! */
|
||||
NULL,
|
||||
(XIMProc) xic_string_conversion_callback,
|
||||
};
|
||||
|
||||
#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
|
||||
/* Create an X fontset on frame F with base font name BASE_FONTNAME. */
|
||||
|
@ -3094,6 +3124,8 @@ create_frame_xic (struct frame *f)
|
|||
XNFocusWindow, FRAME_X_WINDOW (f),
|
||||
XNStatusAttributes, status_attr,
|
||||
XNPreeditAttributes, preedit_attr,
|
||||
XNStringConversionCallback,
|
||||
&Xxic_string_conversion_callback,
|
||||
NULL);
|
||||
else if (preedit_attr)
|
||||
xic = XCreateIC (xim,
|
||||
|
@ -3101,6 +3133,8 @@ create_frame_xic (struct frame *f)
|
|||
XNClientWindow, FRAME_X_WINDOW (f),
|
||||
XNFocusWindow, FRAME_X_WINDOW (f),
|
||||
XNPreeditAttributes, preedit_attr,
|
||||
XNStringConversionCallback,
|
||||
&Xxic_string_conversion_callback,
|
||||
NULL);
|
||||
else if (status_attr)
|
||||
xic = XCreateIC (xim,
|
||||
|
@ -3108,12 +3142,16 @@ create_frame_xic (struct frame *f)
|
|||
XNClientWindow, FRAME_X_WINDOW (f),
|
||||
XNFocusWindow, FRAME_X_WINDOW (f),
|
||||
XNStatusAttributes, status_attr,
|
||||
XNStringConversionCallback,
|
||||
&Xxic_string_conversion_callback,
|
||||
NULL);
|
||||
else
|
||||
xic = XCreateIC (xim,
|
||||
XNInputStyle, xic_style,
|
||||
XNClientWindow, FRAME_X_WINDOW (f),
|
||||
XNFocusWindow, FRAME_X_WINDOW (f),
|
||||
XNStringConversionCallback,
|
||||
&Xxic_string_conversion_callback,
|
||||
NULL);
|
||||
|
||||
if (!xic)
|
||||
|
@ -3377,6 +3415,7 @@ struct x_xim_text_conversion_data
|
|||
struct coding_system *coding;
|
||||
char *source;
|
||||
struct x_display_info *dpyinfo;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
static Lisp_Object
|
||||
|
@ -3411,6 +3450,38 @@ x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs, Lisp_Object *args)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
x_encode_xim_text_1 (ptrdiff_t nargs, Lisp_Object *args)
|
||||
{
|
||||
struct x_xim_text_conversion_data *data;
|
||||
ptrdiff_t nbytes;
|
||||
Lisp_Object coding_system;
|
||||
|
||||
data = xmint_pointer (args[0]);
|
||||
|
||||
if (SYMBOLP (Vx_input_coding_system))
|
||||
coding_system = Vx_input_coding_system;
|
||||
else if (!NILP (data->dpyinfo->xim_coding))
|
||||
coding_system = data->dpyinfo->xim_coding;
|
||||
else
|
||||
coding_system = Vlocale_coding_system;
|
||||
|
||||
nbytes = data->size;
|
||||
|
||||
data->coding->destination = NULL;
|
||||
|
||||
setup_coding_system (coding_system, data->coding);
|
||||
data->coding->mode |= (CODING_MODE_LAST_BLOCK
|
||||
| CODING_MODE_SAFE_ENCODING);
|
||||
data->coding->source = (const unsigned char *) data->source;
|
||||
data->coding->dst_bytes = 2048;
|
||||
data->coding->destination = xmalloc (2048);
|
||||
encode_coding_object (data->coding, Qnil, 0, 0,
|
||||
nbytes, nbytes, Qnil);
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static Lisp_Object
|
||||
x_xim_text_to_utf8_unix_2 (Lisp_Object val, ptrdiff_t nargs,
|
||||
Lisp_Object *args)
|
||||
|
@ -3468,6 +3539,46 @@ x_xim_text_to_utf8_unix (struct x_display_info *dpyinfo,
|
|||
return (char *) coding.destination;
|
||||
}
|
||||
|
||||
/* Convert SIZE bytes of the specified text from Emacs's internal
|
||||
coding system to the input method coding system. Return the
|
||||
result, its byte length in *LENGTH, and its character length in
|
||||
*CHARS, or NULL.
|
||||
|
||||
The string returned is not NULL terminated. */
|
||||
|
||||
static char *
|
||||
x_encode_xim_text (struct x_display_info *dpyinfo, char *text,
|
||||
size_t size, ptrdiff_t *length,
|
||||
ptrdiff_t *chars)
|
||||
{
|
||||
struct coding_system coding;
|
||||
struct x_xim_text_conversion_data data;
|
||||
Lisp_Object arg;
|
||||
bool was_waiting_for_input_p;
|
||||
|
||||
data.coding = &coding;
|
||||
data.source = text;
|
||||
data.dpyinfo = dpyinfo;
|
||||
data.size = size;
|
||||
|
||||
was_waiting_for_input_p = waiting_for_input;
|
||||
/* Otherwise Fsignal will crash. */
|
||||
waiting_for_input = false;
|
||||
|
||||
arg = make_mint_ptr (&data);
|
||||
internal_condition_case_n (x_encode_xim_text_1, 1, &arg,
|
||||
Qt, x_xim_text_to_utf8_unix_2);
|
||||
waiting_for_input = was_waiting_for_input_p;
|
||||
|
||||
if (length)
|
||||
*length = coding.produced;
|
||||
|
||||
if (chars)
|
||||
*chars = coding.produced_char;
|
||||
|
||||
return (char *) coding.destination;
|
||||
}
|
||||
|
||||
static void
|
||||
xic_preedit_draw_callback (XIC xic, XPointer client_data,
|
||||
XIMPreeditDrawCallbackStruct *call_data)
|
||||
|
@ -3664,6 +3775,128 @@ xic_set_xfontset (struct frame *f, const char *base_fontname)
|
|||
FRAME_XIC_FONTSET (f) = xfs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* String conversion support. See textconv.c for more details. */
|
||||
|
||||
static void
|
||||
xic_string_conversion_callback (XIC ic, XPointer client_data,
|
||||
XIMStringConversionCallbackStruct *call_data)
|
||||
{
|
||||
struct textconv_callback_struct request;
|
||||
ptrdiff_t length;
|
||||
struct frame *f;
|
||||
int rc;
|
||||
|
||||
/* Find the frame associated with this IC. */
|
||||
f = x_xic_to_frame (ic);
|
||||
|
||||
if (!f)
|
||||
goto failure;
|
||||
|
||||
/* Fill in CALL_DATA as early as possible. */
|
||||
call_data->text->feedback = NULL;
|
||||
call_data->text->encoding_is_wchar = False;
|
||||
|
||||
/* Now translate the conversion request to the format understood by
|
||||
textconv.c. */
|
||||
request.position = call_data->position;
|
||||
|
||||
switch (call_data->direction)
|
||||
{
|
||||
case XIMForwardChar:
|
||||
request.direction = TEXTCONV_FORWARD_CHAR;
|
||||
break;
|
||||
|
||||
case XIMBackwardChar:
|
||||
request.direction = TEXTCONV_BACKWARD_CHAR;
|
||||
break;
|
||||
|
||||
case XIMForwardWord:
|
||||
request.direction = TEXTCONV_FORWARD_WORD;
|
||||
break;
|
||||
|
||||
case XIMBackwardWord:
|
||||
request.direction = TEXTCONV_BACKWARD_WORD;
|
||||
break;
|
||||
|
||||
case XIMCaretUp:
|
||||
request.direction = TEXTCONV_CARET_UP;
|
||||
break;
|
||||
|
||||
case XIMCaretDown:
|
||||
request.direction = TEXTCONV_CARET_DOWN;
|
||||
break;
|
||||
|
||||
case XIMNextLine:
|
||||
request.direction = TEXTCONV_NEXT_LINE;
|
||||
break;
|
||||
|
||||
case XIMPreviousLine:
|
||||
request.direction = TEXTCONV_PREVIOUS_LINE;
|
||||
break;
|
||||
|
||||
case XIMLineStart:
|
||||
request.direction = TEXTCONV_LINE_START;
|
||||
break;
|
||||
|
||||
case XIMLineEnd:
|
||||
request.direction = TEXTCONV_LINE_END;
|
||||
break;
|
||||
|
||||
case XIMAbsolutePosition:
|
||||
request.direction = TEXTCONV_ABSOLUTE_POSITION;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* factor is signed in call_data but is actually a CARD16. */
|
||||
request.factor = call_data->factor;
|
||||
|
||||
if (call_data->operation == XIMStringConversionSubstitution)
|
||||
request.operation = TEXTCONV_SUBSTITUTION;
|
||||
else
|
||||
request.operation = TEXTCONV_RETRIEVAL;
|
||||
|
||||
/* Now perform the string conversion. */
|
||||
rc = textconv_query (f, &request);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
xfree (request.text.text);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Encode the text in the locale coding system and give it back to
|
||||
the input method. */
|
||||
request.text.text = NULL;
|
||||
call_data->text->string.mbs
|
||||
= x_encode_xim_text (FRAME_DISPLAY_INFO (f),
|
||||
request.text.text,
|
||||
request.text.bytes, NULL,
|
||||
&length);
|
||||
call_data->text->length = length;
|
||||
|
||||
/* Free the encoded text. This is always set to something
|
||||
valid. */
|
||||
xfree (request.text.text);
|
||||
|
||||
/* Detect failure. */
|
||||
if (!call_data->text->string.mbs)
|
||||
goto failure;
|
||||
|
||||
return;
|
||||
|
||||
failure:
|
||||
/* Return a string of length 0 using the C library malloc. This
|
||||
assumes XFree is able to free data allocated with our malloc
|
||||
wrapper. */
|
||||
call_data->text->length = 0;
|
||||
call_data->text->string.mbs = malloc (0);
|
||||
}
|
||||
|
||||
#endif /* HAVE_X_I18N */
|
||||
|
||||
|
||||
|
@ -9771,6 +10004,53 @@ This should be called from a variable watcher for `x-gtk-use-native-input'. */)
|
|||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
DEFUN ("x-test-string-conversion", Fx_test_string_conversion,
|
||||
Sx_test_string_conversion, 5, 5, 0,
|
||||
doc: /* Perform tests on the XIM string conversion support. */)
|
||||
(Lisp_Object frame, Lisp_Object position,
|
||||
Lisp_Object direction, Lisp_Object operation, Lisp_Object factor)
|
||||
{
|
||||
struct frame *f;
|
||||
XIMStringConversionCallbackStruct call_data;
|
||||
XIMStringConversionText text;
|
||||
|
||||
f = decode_window_system_frame (frame);
|
||||
|
||||
if (!FRAME_XIC (f))
|
||||
error ("No XIC on FRAME!");
|
||||
|
||||
CHECK_FIXNUM (position);
|
||||
CHECK_FIXNUM (direction);
|
||||
CHECK_FIXNUM (operation);
|
||||
CHECK_FIXNUM (factor);
|
||||
|
||||
/* xic_string_conversion_callback (XIC ic, XPointer client_data,
|
||||
XIMStringConversionCallbackStruct *call_data) */
|
||||
|
||||
call_data.position = XFIXNUM (position);
|
||||
call_data.direction = XFIXNUM (direction);
|
||||
call_data.operation = XFIXNUM (operation);
|
||||
call_data.factor = XFIXNUM (factor);
|
||||
call_data.text = &text;
|
||||
|
||||
block_input ();
|
||||
xic_string_conversion_callback (FRAME_XIC (f), NULL,
|
||||
&call_data);
|
||||
unblock_input ();
|
||||
|
||||
/* Place a breakpoint here to inspect TEXT! */
|
||||
|
||||
while (1)
|
||||
maybe_quit ();
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
Initialization
|
||||
|
@ -10217,6 +10497,9 @@ eliminated in future versions of Emacs. */);
|
|||
defsubr (&Sx_display_set_last_user_time);
|
||||
defsubr (&Sx_translate_coordinates);
|
||||
defsubr (&Sx_get_modifier_masks);
|
||||
#if 0
|
||||
defsubr (&Sx_test_string_conversion);
|
||||
#endif
|
||||
|
||||
tip_timer = Qnil;
|
||||
staticpro (&tip_timer);
|
||||
|
|
41
src/xterm.c
41
src/xterm.c
|
@ -636,6 +636,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include "xterm.h"
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
#ifdef HAVE_X_I18N
|
||||
#include "textconv.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_XCB
|
||||
#include <xcb/xproto.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
@ -31506,7 +31510,37 @@ x_initialize (void)
|
|||
XSetIOErrorHandler (x_io_error_quitter);
|
||||
}
|
||||
|
||||
#ifdef USE_GTK
|
||||
#ifdef HAVE_X_I18N
|
||||
|
||||
/* Notice that a change has occured on F that requires its input
|
||||
method state to be reset. */
|
||||
|
||||
static void
|
||||
x_reset_conversion (struct frame *f)
|
||||
{
|
||||
char *string;
|
||||
|
||||
if (FRAME_XIC (f))
|
||||
{
|
||||
string = XmbResetIC (FRAME_XIC (f));
|
||||
|
||||
/* string is actually any string that was being composed at the
|
||||
time of the reset. */
|
||||
|
||||
if (string)
|
||||
XFree (string);
|
||||
}
|
||||
}
|
||||
|
||||
/* Interface used to control input method ``text conversion''. */
|
||||
|
||||
static struct textconv_interface text_conversion_interface =
|
||||
{
|
||||
x_reset_conversion,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
init_xterm (void)
|
||||
{
|
||||
|
@ -31520,8 +31554,11 @@ init_xterm (void)
|
|||
gdk_disable_multidevice ();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_X_I18N
|
||||
register_texconv_interface (&text_conversion_interface);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
mark_xterm (void)
|
||||
|
|
Loading…
Add table
Reference in a new issue