aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-01-07 14:35:29 +0800
committerPo Lu2022-01-07 14:42:08 +0800
commit751789471cf04916bcfad358472625f382e596d8 (patch)
tree329fa13c0e4972b34a1c1b95fa398a708bb246c5 /src
parent48038cb2b2191980b3862be2c7d408e6ba6ee0d8 (diff)
downloademacs-751789471cf04916bcfad358472625f382e596d8.tar.gz
emacs-751789471cf04916bcfad358472625f382e596d8.zip
Display pre-edit information from X input methods
This also repurposes the `pgtk-preedit-text' event to be meaningful on X, renames it `preedit-text', and documents it. * doc/lispref/commands.texi (Misc Events): Document `preedit-text'. * lisp/term/pgtk-win.el (pgtk-preedit-text): Bind to `preedit-text' instead. * lisp/term/x-win.el (x-preedit-overlay): New variable. (x-preedit-text): New command, bound as a special event to `preedit-text'. * src/keyboard.c (kbd_buffer_get_event): (make_lispy_event): Rename PGTK_PREEDIT_TEXT_EVENT PREEDIT_TEXT_EVENT. (syms_of_keyboard): New defsym `preedit-text'. * src/pgtkterm.c (pgtk_enqueue_preedit): Use PREEDIT_TEXT_EVENT instead. * src/termhooks.h (enum event_kind): Rename `PGTK_PREEDIT_TEXT_EVENT' `PREEDIT_TEXT_EVENT'. * src/xfns.c (Xxic_preedit_draw_callback): (Xxic_preedit_caret_callback): (Xxic_preedit_done_callback): (Xxic_preedit_start_callback): New callback variables. (STYLE_OFFTHESPOT, STYLE_OVERTHESPOT): (STYLE_ROOT, STYLE_CALLBACK, STYLE_NONE): New macros. (supported_xim_styles): Use reasonable values. This also serves as a better fix for bug#10867. (best_xim_style): Restore code deleted as part of the original fix for bug#10867. (create_frame_xic): Add preedit callbacks. (xic_set_preeditarea): Add preedit callbacks. (x_xic_to_frame): (xic_preedit_start_callback): (xic_preedit_caret_callback): (xic_preedit_done_callback): (x_xim_text_to_utf8_unix): (xic_preedit_draw_callback): New functions. * src/xterm.c (x_detect_focus_change): Fix type of XI event. (x_free_frame_resources): Free preedit text buffer if still present. * src/xterm.h (struct x_output): New fields `preedit_size', `preedit_chars' and `preedit_active'.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c14
-rw-r--r--src/pgtkterm.c2
-rw-r--r--src/termhooks.h4
-rw-r--r--src/xfns.c335
-rw-r--r--src/xterm.c5
-rw-r--r--src/xterm.h6
6 files changed, 345 insertions, 21 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index ec1b7cd85d3..a9f3257282b 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -3973,9 +3973,7 @@ kbd_buffer_get_event (KBOARD **kbp,
3973 *used_mouse_menu = true; 3973 *used_mouse_menu = true;
3974 FALLTHROUGH; 3974 FALLTHROUGH;
3975#endif 3975#endif
3976#ifdef HAVE_PGTK 3976 case PREEDIT_TEXT_EVENT:
3977 case PGTK_PREEDIT_TEXT_EVENT:
3978#endif
3979#ifdef HAVE_NTGUI 3977#ifdef HAVE_NTGUI
3980 case END_SESSION_EVENT: 3978 case END_SESSION_EVENT:
3981 case LANGUAGE_CHANGE_EVENT: 3979 case LANGUAGE_CHANGE_EVENT:
@@ -6289,10 +6287,8 @@ make_lispy_event (struct input_event *event)
6289 return list3 (Qconfig_changed_event, 6287 return list3 (Qconfig_changed_event,
6290 event->arg, event->frame_or_window); 6288 event->arg, event->frame_or_window);
6291 6289
6292#ifdef HAVE_PGTK 6290 case PREEDIT_TEXT_EVENT:
6293 case PGTK_PREEDIT_TEXT_EVENT: 6291 return list2 (Qpreedit_text, event->arg);
6294 return list2 (intern ("pgtk-preedit-text"), event->arg);
6295#endif
6296 6292
6297 /* The 'kind' field of the event is something we don't recognize. */ 6293 /* The 'kind' field of the event is something we don't recognize. */
6298 default: 6294 default:
@@ -12003,6 +11999,8 @@ syms_of_keyboard (void)
12003 DEFSYM (Qno_record, "no-record"); 11999 DEFSYM (Qno_record, "no-record");
12004 DEFSYM (Qencoded, "encoded"); 12000 DEFSYM (Qencoded, "encoded");
12005 12001
12002 DEFSYM (Qpreedit_text, "preedit-text");
12003
12006 button_down_location = make_nil_vector (5); 12004 button_down_location = make_nil_vector (5);
12007 staticpro (&button_down_location); 12005 staticpro (&button_down_location);
12008 staticpro (&frame_relative_event_pos); 12006 staticpro (&frame_relative_event_pos);
@@ -12771,8 +12769,6 @@ keys_of_keyboard (void)
12771 "ns-put-working-text"); 12769 "ns-put-working-text");
12772 initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text", 12770 initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text",
12773 "ns-unput-working-text"); 12771 "ns-unput-working-text");
12774 initial_define_lispy_key (Vspecial_event_map, "pgtk-preedit-text",
12775 "pgtk-preedit-text");
12776 /* Here we used to use `ignore-event' which would simple set prefix-arg to 12772 /* Here we used to use `ignore-event' which would simple set prefix-arg to
12777 current-prefix-arg, as is done in `handle-switch-frame'. 12773 current-prefix-arg, as is done in `handle-switch-frame'.
12778 But `handle-switch-frame is not run from the special-map. 12774 But `handle-switch-frame is not run from the special-map.
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index 736fce09c4a..1d301d11f6f 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -5259,7 +5259,7 @@ pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit)
5259{ 5259{
5260 union buffered_input_event inev; 5260 union buffered_input_event inev;
5261 EVENT_INIT (inev.ie); 5261 EVENT_INIT (inev.ie);
5262 inev.ie.kind = PGTK_PREEDIT_TEXT_EVENT; 5262 inev.ie.kind = PREEDIT_TEXT_EVENT;
5263 inev.ie.arg = preedit; 5263 inev.ie.arg = preedit;
5264 inev.ie.code = 0; 5264 inev.ie.code = 0;
5265 XSETFRAME (inev.ie.frame_or_window, f); 5265 XSETFRAME (inev.ie.frame_or_window, f);
diff --git a/src/termhooks.h b/src/termhooks.h
index 55f7aa5d1ae..518e855eae1 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -269,10 +269,8 @@ enum event_kind
269 , FILE_NOTIFY_EVENT 269 , FILE_NOTIFY_EVENT
270#endif 270#endif
271 271
272#ifdef HAVE_PGTK
273 /* Pre-edit text was changed. */ 272 /* Pre-edit text was changed. */
274 , PGTK_PREEDIT_TEXT_EVENT 273 , PREEDIT_TEXT_EVENT
275#endif
276 274
277 /* Either the mouse wheel has been released without it being 275 /* Either the mouse wheel has been released without it being
278 clicked, or the user has lifted his finger from a touchpad. 276 clicked, or the user has lifted his finger from a touchpad.
diff --git a/src/xfns.c b/src/xfns.c
index b94fe179224..d87e67f95b1 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -24,6 +24,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
24#include <unistd.h> 24#include <unistd.h>
25 25
26#include "lisp.h" 26#include "lisp.h"
27#include "character.h"
27#include "xterm.h" 28#include "xterm.h"
28#include "frame.h" 29#include "frame.h"
29#include "window.h" 30#include "window.h"
@@ -2330,8 +2331,19 @@ hack_wm_protocols (struct frame *f, Widget widget)
2330 2331
2331#ifdef HAVE_X_I18N 2332#ifdef HAVE_X_I18N
2332 2333
2333static XFontSet xic_create_xfontset (struct frame *); 2334static void xic_preedit_draw_callback (XIC, XPointer, XIMPreeditDrawCallbackStruct *);
2334static XIMStyle best_xim_style (XIMStyles *); 2335static void xic_preedit_caret_callback (XIC, XPointer, XIMPreeditCaretCallbackStruct *);
2336static void xic_preedit_done_callback (XIC, XPointer, XPointer);
2337static int xic_preedit_start_callback (XIC, XPointer, XPointer);
2338
2339static XIMCallback Xxic_preedit_draw_callback = { NULL,
2340 (XIMProc) xic_preedit_draw_callback };
2341static XIMCallback Xxic_preedit_caret_callback = { NULL,
2342 (XIMProc) xic_preedit_caret_callback };
2343static XIMCallback Xxic_preedit_done_callback = { NULL,
2344 (XIMProc) xic_preedit_done_callback };
2345static XIMCallback Xxic_preedit_start_callback = { NULL,
2346 (void *) xic_preedit_start_callback };
2335 2347
2336#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT 2348#if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
2337/* Create an X fontset on frame F with base font name BASE_FONTNAME. */ 2349/* Create an X fontset on frame F with base font name BASE_FONTNAME. */
@@ -2608,6 +2620,23 @@ xic_free_xfontset (struct frame *f)
2608 FRAME_XIC_FONTSET (f) = NULL; 2620 FRAME_XIC_FONTSET (f) = NULL;
2609} 2621}
2610 2622
2623/* Create XIC for frame F. */
2624
2625
2626#define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea)
2627#define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing)
2628#define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing)
2629#define STYLE_CALLBACK (XIMPreeditCallbacks | XIMStatusNothing)
2630#define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing)
2631
2632static const XIMStyle supported_xim_styles[] =
2633 {
2634 STYLE_CALLBACK,
2635 STYLE_NONE,
2636 STYLE_OVERTHESPOT,
2637 STYLE_OFFTHESPOT,
2638 STYLE_ROOT
2639 };
2611 2640
2612/* Value is the best input style, given user preferences USER (already 2641/* Value is the best input style, given user preferences USER (already
2613 checked to be supported by Emacs), and styles supported by the 2642 checked to be supported by Emacs), and styles supported by the
@@ -2616,8 +2645,15 @@ xic_free_xfontset (struct frame *f)
2616static XIMStyle 2645static XIMStyle
2617best_xim_style (XIMStyles *xim) 2646best_xim_style (XIMStyles *xim)
2618{ 2647{
2619 /* Return the default style. This is what GTK3 uses and 2648 int i, j;
2620 should work fine with all modern input methods. */ 2649 int nr_supported = ARRAYELTS (supported_xim_styles);
2650
2651 for (i = 0; i < nr_supported; ++i)
2652 for (j = 0; j < xim->count_styles; ++j)
2653 if (supported_xim_styles[i] == xim->supported_styles[j])
2654 return supported_xim_styles[i];
2655
2656 /* Return the default style. */
2621 return XIMPreeditNothing | XIMStatusNothing; 2657 return XIMPreeditNothing | XIMStatusNothing;
2622} 2658}
2623 2659
@@ -2692,6 +2728,22 @@ create_frame_xic (struct frame *f)
2692 goto out; 2728 goto out;
2693 } 2729 }
2694 2730
2731 if (xic_style & XIMPreeditCallbacks)
2732 {
2733 spot.x = 0;
2734 spot.y = 0;
2735 preedit_attr = XVaCreateNestedList (0,
2736 XNSpotLocation, &spot,
2737 XNPreeditStartCallback, &Xxic_preedit_start_callback,
2738 XNPreeditDoneCallback, &Xxic_preedit_done_callback,
2739 XNPreeditDrawCallback, &Xxic_preedit_draw_callback,
2740 XNPreeditCaretCallback, &Xxic_preedit_caret_callback,
2741 NULL);
2742
2743 if (!preedit_attr)
2744 goto out;
2745 }
2746
2695 if (preedit_attr && status_attr) 2747 if (preedit_attr && status_attr)
2696 xic = XCreateIC (xim, 2748 xic = XCreateIC (xim,
2697 XNInputStyle, xic_style, 2749 XNInputStyle, xic_style,
@@ -2768,7 +2820,12 @@ xic_set_preeditarea (struct window *w, int x, int y)
2768 2820
2769 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w) + WINDOW_LEFT_MARGIN_WIDTH(w); 2821 spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w) + WINDOW_LEFT_MARGIN_WIDTH(w);
2770 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f)); 2822 spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f));
2771 attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL); 2823 attr = XVaCreateNestedList (0, XNSpotLocation, &spot,
2824 XNPreeditStartCallback, &Xxic_preedit_start_callback,
2825 XNPreeditDoneCallback, &Xxic_preedit_done_callback,
2826 XNPreeditDrawCallback, &Xxic_preedit_draw_callback,
2827 XNPreeditCaretCallback, &Xxic_preedit_caret_callback,
2828 NULL);
2772 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL); 2829 XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL);
2773 XFree (attr); 2830 XFree (attr);
2774} 2831}
@@ -2816,9 +2873,273 @@ xic_set_statusarea (struct frame *f)
2816 XFree (attr); 2873 XFree (attr);
2817} 2874}
2818 2875
2876static struct frame *
2877x_xic_to_frame (XIC xic)
2878{
2879 Lisp_Object tail, tem;
2880 struct frame *f;
2881
2882 FOR_EACH_FRAME (tail, tem)
2883 {
2884 f = XFRAME (tem);
2885
2886 if (FRAME_X_P (f) && FRAME_XIC (f) == xic)
2887 return f;
2888 }
2889
2890 return NULL;
2891}
2892
2893static int
2894xic_preedit_start_callback (XIC xic, XPointer client_data,
2895 XPointer call_data)
2896{
2897 struct frame *f = x_xic_to_frame (xic);
2898 struct x_output *output;
2899
2900 if (f)
2901 {
2902 output = FRAME_X_OUTPUT (f);
2903
2904 output->preedit_size = 0;
2905 output->preedit_active = true;
2906
2907 if (output->preedit_chars)
2908 xfree (output->preedit_chars);
2909
2910 output->preedit_chars = NULL;
2911 }
2912
2913 return -1;
2914}
2915
2916static void
2917xic_preedit_caret_callback (XIC xic, XPointer client_data,
2918 XIMPreeditCaretCallbackStruct *call_data)
2919{
2920
2921}
2922
2923
2924static void
2925xic_preedit_done_callback (XIC xic, XPointer client_data,
2926 XPointer call_data)
2927{
2928 struct frame *f = x_xic_to_frame (xic);
2929 struct x_output *output;
2930 struct input_event ie;
2931
2932 if (f)
2933 {
2934 ie.kind = PREEDIT_TEXT_EVENT;
2935 ie.arg = Qnil;
2936 XSETFRAME (ie.frame_or_window, f);
2937 XSETINT (ie.x, 0);
2938 XSETINT (ie.y, 0);
2939 kbd_buffer_store_event (&ie);
2940
2941 output = FRAME_X_OUTPUT (f);
2942
2943 if (output->preedit_chars)
2944 xfree (output->preedit_chars);
2945
2946 output->preedit_size = 0;
2947 output->preedit_active = false;
2948 output->preedit_chars = NULL;
2949 }
2950}
2951
2952/* The string returned is not null-terminated. */
2953static char *
2954x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length)
2955{
2956 unsigned char *wchar_buf;
2957 ptrdiff_t wchar_actual_length, i;
2958 ptrdiff_t nbytes;
2959 struct coding_system coding;
2960
2961 if (text->encoding_is_wchar)
2962 {
2963 wchar_buf = xmalloc ((text->length + 1) * MAX_MULTIBYTE_LENGTH);
2964 wchar_actual_length = 0;
2965
2966 for (i = 0; i < text->length; ++i)
2967 wchar_actual_length += CHAR_STRING (text->string.wide_char[i],
2968 wchar_buf + wchar_actual_length);
2969 *length = wchar_actual_length;
2970
2971 return (char *) wchar_buf;
2972 }
2973
2974 nbytes = strlen (text->string.multi_byte);
2975 setup_coding_system (Qutf_8_unix, &coding);
2976 coding.mode |= (CODING_MODE_LAST_BLOCK
2977 | CODING_MODE_SAFE_ENCODING);
2978 coding.source = (const unsigned char *) text->string.multi_byte;
2979 coding.dst_bytes = 2048;
2980 coding.destination = xmalloc (2048);
2981 decode_coding_object (&coding, Qnil, 0, 0, nbytes, nbytes, Qnil);
2982
2983 /* coding.destination has either been allocated by us, or
2984 reallocated by decode_coding_object. */
2985
2986 *length = coding.produced;
2987 return (char *) coding.destination;
2988}
2989
2990static void
2991xic_preedit_draw_callback (XIC xic, XPointer client_data,
2992 XIMPreeditDrawCallbackStruct *call_data)
2993{
2994 struct frame *f = x_xic_to_frame (xic);
2995 struct x_output *output;
2996 ptrdiff_t text_length;
2997 ptrdiff_t charpos;
2998 ptrdiff_t original_size;
2999 char *text;
3000 char *chg_start, *chg_end;
3001 struct input_event ie;
3002
3003 if (f)
3004 {
3005 output = FRAME_X_OUTPUT (f);
3006
3007 if (!output->preedit_active)
3008 return;
3009
3010 if (call_data->text)
3011 text = x_xim_text_to_utf8_unix (call_data->text, &text_length);
3012 else
3013 text = NULL;
3014
3015 original_size = output->preedit_size;
3016
3017 /* This is an ordinary insertion: reallocate the buffer to hold
3018 enough for TEXT. */
3019 if (!call_data->chg_length)
3020 {
3021 if (!text)
3022 goto im_abort;
3023
3024 if (output->preedit_chars)
3025 output->preedit_chars = xrealloc (output->preedit_chars,
3026 output->preedit_size += text_length);
3027 else
3028 output->preedit_chars = xmalloc (output->preedit_size += text_length);
3029 }
3030
3031 chg_start = output->preedit_chars;
3032
3033 /* The IM sent bad data: the buffer is empty, but the change
3034 position is more than 0. */
3035 if (!output->preedit_chars && call_data->chg_first)
3036 goto im_abort;
3037
3038 /* Find the byte position for the character position where the
3039 first change is to be made. */
3040 if (call_data->chg_first)
3041 {
3042 charpos = 0;
3043
3044 while (charpos < call_data->chg_first)
3045 {
3046 chg_start += BYTES_BY_CHAR_HEAD (*chg_start);
3047
3048 if ((chg_start - output->preedit_chars) > output->preedit_size)
3049 /* The IM sent bad data: chg_start is larger than the
3050 current buffer. */
3051 goto im_abort;
3052 ++charpos;
3053 }
3054 }
3055
3056 if (!call_data->chg_length)
3057 {
3058 if (!text)
3059 goto im_abort;
3060
3061 memmove (chg_start + text_length, chg_start,
3062 original_size - (chg_start - output->preedit_chars));
3063 memcpy (chg_start, text, text_length);
3064 }
3065 else
3066 {
3067 if (call_data->chg_length < 1)
3068 goto im_abort;
3069
3070 charpos = 0;
3071 chg_end = chg_start;
3072
3073 while (charpos < call_data->chg_length)
3074 {
3075 chg_end += BYTES_BY_CHAR_HEAD (*chg_end);
3076
3077 if ((chg_end - output->preedit_chars) > output->preedit_size)
3078 /* The IM sent bad data: chg_end ends someplace outside
3079 the current buffer. */
3080 goto im_abort;
3081 ++charpos;
3082 }
3083
3084 memmove (chg_start, chg_end, ((output->preedit_chars
3085 + output->preedit_size) - chg_end));
3086 output->preedit_size -= (chg_end - chg_start);
3087
3088 if (text)
3089 {
3090 original_size = output->preedit_size;
3091 output->preedit_chars = xrealloc (output->preedit_chars,
3092 output->preedit_size += text_length);
3093
3094 /* Find chg_start again, since preedit_chars was reallocated. */
3095
3096 chg_start = output->preedit_chars;
3097 charpos = 0;
2819 3098
2820/* Set X fontset for XIC of frame F, using base font name 3099 while (charpos < call_data->chg_first)
2821 BASE_FONTNAME. Called when a new Emacs fontset is chosen. */ 3100 {
3101 chg_start += BYTES_BY_CHAR_HEAD (*chg_start);
3102
3103 if ((chg_start - output->preedit_chars) > output->preedit_size)
3104 /* The IM sent bad data: chg_start is larger than the
3105 current buffer. */
3106 goto im_abort;
3107 ++charpos;
3108 }
3109
3110 memmove (chg_start + text_length, chg_start,
3111 original_size - (chg_start - output->preedit_chars));
3112 memcpy (chg_start, text, text_length);
3113 }
3114 }
3115
3116 if (text)
3117 xfree (text);
3118
3119 /* This is okay because this callback is called from the big XIM
3120 event filter, which runs inside XTread_socket. */
3121
3122 ie.kind = PREEDIT_TEXT_EVENT;
3123 XSETFRAME (ie.frame_or_window, f);
3124 ie.arg = make_string_from_utf8 (output->preedit_chars,
3125 output->preedit_size);
3126 XSETINT (ie.x, 0);
3127 XSETINT (ie.y, 0);
3128
3129 kbd_buffer_store_event (&ie);
3130 }
3131
3132 return;
3133
3134 im_abort:
3135 if (text)
3136 xfree (text);
3137 if (output->preedit_chars)
3138 xfree (output->preedit_chars);
3139 output->preedit_chars = NULL;
3140 output->preedit_size = 0;
3141 output->preedit_active = false;
3142}
2822 3143
2823void 3144void
2824xic_set_xfontset (struct frame *f, const char *base_fontname) 3145xic_set_xfontset (struct frame *f, const char *base_fontname)
diff --git a/src/xterm.c b/src/xterm.c
index 1d4c775753c..73c0bcf89ea 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5198,7 +5198,7 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
5198#ifdef HAVE_XINPUT2 5198#ifdef HAVE_XINPUT2
5199 case GenericEvent: 5199 case GenericEvent:
5200 { 5200 {
5201 XIEvent *xi_event = (XIEvent *) event; 5201 XIEvent *xi_event = (XIEvent *) event->xcookie.data;
5202 5202
5203 struct frame *focus_frame = dpyinfo->x_focus_event_frame; 5203 struct frame *focus_frame = dpyinfo->x_focus_event_frame;
5204 int focus_state 5204 int focus_state
@@ -14046,6 +14046,9 @@ x_free_frame_resources (struct frame *f)
14046#ifdef HAVE_X_I18N 14046#ifdef HAVE_X_I18N
14047 if (FRAME_XIC (f)) 14047 if (FRAME_XIC (f))
14048 free_frame_xic (f); 14048 free_frame_xic (f);
14049
14050 if (f->output_data.x->preedit_chars)
14051 xfree (f->output_data.x->preedit_chars);
14049#endif 14052#endif
14050 14053
14051#ifdef USE_CAIRO 14054#ifdef USE_CAIRO
diff --git a/src/xterm.h b/src/xterm.h
index d4600bdf800..dcac5732527 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -788,6 +788,12 @@ struct x_output
788 They are used when creating the cairo surface next time. */ 788 They are used when creating the cairo surface next time. */
789 int cr_surface_desired_width, cr_surface_desired_height; 789 int cr_surface_desired_width, cr_surface_desired_height;
790#endif 790#endif
791
792#ifdef HAVE_X_I18N
793 ptrdiff_t preedit_size;
794 char *preedit_chars;
795 bool preedit_active;
796#endif
791}; 797};
792 798
793enum 799enum