aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-10-03 20:18:22 +0800
committerPo Lu2022-10-03 20:18:37 +0800
commitda02b9edadbc809b25ac83eccf64089f1cf3b160 (patch)
tree084641cd35e268b195b51ba7d09352207c52eb16
parente245c4f226979ccb717cccc8f82b2b0a0f96bdac (diff)
downloademacs-da02b9edadbc809b25ac83eccf64089f1cf3b160.tar.gz
emacs-da02b9edadbc809b25ac83eccf64089f1cf3b160.zip
Fix coding systems used for X input methods
* doc/emacs/mule.texi (International): Refer to X Coding as well. (Communication Coding): Document that locale-coding-system is not always used on X to decode keyboard input. (X Coding): New node. * etc/NEWS: Announce change to input method coding resolution. * lisp/term/x-win.el (x-get-input-coding-system): New function. * src/coding.c (syms_of_coding): Update doc string of locale-coding-system. * src/xfns.c (struct x_xim_text_conversion_data) (x_xim_text_to_utf8_unix_1, x_xim_text_to_utf8_unix_2) (x_xim_text_to_utf8_unix): Accept dpyinfo. Use the coding system specified inside if possible. (xic_preedit_draw_callback): Pass dpyinfo. * src/xterm.c (handle_one_xevent): Use XIM coding system for IM input. (xim_open_dpy): Try to determine the input method coding system. (mark_xterm): Mark `xim_coding'. (syms_of_xterm): New variable `x-input-coding-system'. * src/xterm.h (struct x_display_info): New field `xim_coding'. (FRAME_X_XIM_CODING): New macro.
-rw-r--r--doc/emacs/mule.texi40
-rw-r--r--etc/NEWS13
-rw-r--r--lisp/term/x-win.el22
-rw-r--r--src/coding.c6
-rw-r--r--src/xfns.c33
-rw-r--r--src/xterm.c34
-rw-r--r--src/xterm.h9
7 files changed, 130 insertions, 27 deletions
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 5f303418383..1bbd7440f3e 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -61,7 +61,7 @@ can also be input by using the @kbd{C-x 8} prefix, see @ref{Unibyte Mode}.
61 61
62With the X Window System, your locale should be set to an appropriate 62With the X Window System, your locale should be set to an appropriate
63value to make sure Emacs interprets keyboard input correctly; see 63value to make sure Emacs interprets keyboard input correctly; see
64@ref{Language Environments, locales}. 64@ref{Language Environments, locales}, and @ref{X Coding}.
65@end itemize 65@end itemize
66 66
67 The rest of this chapter describes these issues in detail. 67 The rest of this chapter describes these issues in detail.
@@ -79,6 +79,7 @@ value to make sure Emacs interprets keyboard input correctly; see
79* Text Coding:: Choosing conversion to use for file text. 79* Text Coding:: Choosing conversion to use for file text.
80* Communication Coding:: Coding systems for interprocess communication. 80* Communication Coding:: Coding systems for interprocess communication.
81* File Name Coding:: Coding systems for file @emph{names}. 81* File Name Coding:: Coding systems for file @emph{names}.
82* X Coding:: Coding systems for X input methods.
82* Terminal Coding:: Specifying coding systems for converting 83* Terminal Coding:: Specifying coding systems for converting
83 terminal input and output. 84 terminal input and output.
84* Fontsets:: Fontsets are collections of fonts 85* Fontsets:: Fontsets are collections of fonts
@@ -1241,15 +1242,14 @@ current language environment.
1241 The variable @code{locale-coding-system} specifies a coding system 1242 The variable @code{locale-coding-system} specifies a coding system
1242to use when encoding and decoding system strings such as system error 1243to use when encoding and decoding system strings such as system error
1243messages and @code{format-time-string} formats and time stamps. That 1244messages and @code{format-time-string} formats and time stamps. That
1244coding system is also used for decoding non-@acronym{ASCII} keyboard 1245coding system might also be used for decoding non-@acronym{ASCII}
1245input on the X Window System and for encoding text sent to the 1246keyboard input on the X Window System and will also be used to encode
1246standard output and error streams when in batch mode. You should 1247text sent to the standard output and error streams in batch mode. You
1247choose a coding system that is compatible 1248should choose a coding system that is compatible with the underlying
1248with the underlying system's text representation, which is normally 1249system's text representation, which is normally specified by one of
1249specified by one of the environment variables @env{LC_ALL}, 1250the environment variables @env{LC_ALL}, @env{LC_CTYPE}, and
1250@env{LC_CTYPE}, and @env{LANG}. (The first one, in the order 1251@env{LANG}. (The first one, in the order specified above, whose value
1251specified above, whose value is nonempty is the one that determines 1252is nonempty is the one that determines the text representation.)
1252the text representation.)
1253 1253
1254@node File Name Coding 1254@node File Name Coding
1255@section Coding Systems for File Names 1255@section Coding Systems for File Names
@@ -1311,6 +1311,26 @@ C-w} to specify a new file name for that buffer.
1311system. This prompts for an existing file name, its old coding 1311system. This prompts for an existing file name, its old coding
1312system, and the coding system to which you wish to convert. 1312system, and the coding system to which you wish to convert.
1313 1313
1314@node X Coding
1315@section Coding Systems for X Keyboard Input
1316@cindex X input method coding systems
1317 Input methods under the X Window System specify their own coding
1318systems that must be used to decode keyboard input. By default, Emacs
1319determines the coding system used for each input method automatically
1320upon establishing the connection to the input method server, and uses
1321that specific coding system to decode keyboard input. However, that
1322determination can sometimes fail; in that situation, the locale coding
1323system (@pxref{Communication Coding}) is used instead.
1324
1325@cindex X input method coding systems, overriding
1326@vindex x-input-coding-system
1327 If the input method does not correctly announce the coding system it
1328uses to encode text, then the coding system used by Emacs to decode
1329text from input methods must be manually specified. The value of the
1330variable @code{x-input-coding-system}, when set to a symbol, is
1331unconditionally used as the coding system used to decode keyboard
1332input from input methods.
1333
1314@node Terminal Coding 1334@node Terminal Coding
1315@section Coding Systems for Terminal I/O 1335@section Coding Systems for Terminal I/O
1316 1336
diff --git a/etc/NEWS b/etc/NEWS
index db7c675edb5..d7bc4b0e0c2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -187,6 +187,19 @@ of 'user-emacs-directory'.
187* Incompatible changes in Emacs 29.1 187* Incompatible changes in Emacs 29.1
188 188
189+++ 189+++
190*** Emacs now picks the correct coding system for X input methods.
191Previously, Emacs would use the locale coding system for input
192methods, which could in some circumstances be incorrect, especially
193when the input method chose to fall back to some other coding system.
194
195Now, Emacs automatically detects the coding system used by input
196methods, and uses that to decode input in preference to the value of
197'locale-coding-system'. This unfortunately means that users who have
198changed the coding system used to decode X keyboard input must adjust
199their customizations to 'locale-coding-system' to the variable
200'x-input-coding-system' instead.
201
202+++
190*** Bookmarks no longer include context for encrypted files. 203*** Bookmarks no longer include context for encrypted files.
191If you're visiting an encrypted file, setting a bookmark no longer 204If you're visiting an encrypted file, setting a bookmark no longer
192includes excerpts from that buffer in the bookmarks file. This is 205includes excerpts from that buffer in the bookmarks file. This is
diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el
index 9d3e7803650..57c6b785e73 100644
--- a/lisp/term/x-win.el
+++ b/lisp/term/x-win.el
@@ -1613,6 +1613,28 @@ Users should not call this function; see `device-class' instead."
1613(setq x-dnd-movement-function #'x-dnd-movement) 1613(setq x-dnd-movement-function #'x-dnd-movement)
1614(setq x-dnd-unsupported-drop-function #'x-dnd-handle-unsupported-drop) 1614(setq x-dnd-unsupported-drop-function #'x-dnd-handle-unsupported-drop)
1615 1615
1616(defvar x-input-coding-function)
1617
1618(defun x-get-input-coding-system (x-locale)
1619 "Return a coding system for the locale X-LOCALE.
1620Return a coding system that is able to decode text sent with the
1621X input method locale X-LOCALE, or nil if no coding system was
1622found."
1623 (if (equal x-locale "C")
1624 ;; Treat the C locale specially, as it means "ascii" under X.
1625 'ascii
1626 (let ((locale (downcase x-locale)))
1627 (or (locale-name-match locale locale-preferred-coding-systems)
1628 (when locale
1629 (if (string-match "\\.\\([^@]+\\)" locale)
1630 (locale-charset-to-coding-system
1631 (match-string 1 locale))))
1632 (let ((language-name
1633 (locale-name-match locale locale-language-names)))
1634 (and (consp language-name) (cdr language-name)))))))
1635
1636(setq x-input-coding-function #'x-get-input-coding-system)
1637
1616(provide 'x-win) 1638(provide 'x-win)
1617(provide 'term/x-win) 1639(provide 'term/x-win)
1618 1640
diff --git a/src/coding.c b/src/coding.c
index 0ae8eb3282b..ab73bda8440 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -12014,9 +12014,9 @@ See also the function `find-operation-coding-system'. */);
12014 Vnetwork_coding_system_alist = Qnil; 12014 Vnetwork_coding_system_alist = Qnil;
12015 12015
12016 DEFVAR_LISP ("locale-coding-system", Vlocale_coding_system, 12016 DEFVAR_LISP ("locale-coding-system", Vlocale_coding_system,
12017 doc: /* Coding system to use with system messages. 12017 doc: /* Coding system to use with system messages.
12018Also used for decoding keyboard input on X Window system, and for 12018Potentially also used for decoding keyboard input on X Windows, and is
12019encoding standard output and error streams. */); 12019used for encoding standard output and error streams. */);
12020 Vlocale_coding_system = Qnil; 12020 Vlocale_coding_system = Qnil;
12021 12021
12022 /* The eol mnemonics are reset in startup.el system-dependently. */ 12022 /* The eol mnemonics are reset in startup.el system-dependently. */
diff --git a/src/xfns.c b/src/xfns.c
index bb75ca5ad1c..8cea93c6698 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3354,22 +3354,30 @@ struct x_xim_text_conversion_data
3354{ 3354{
3355 struct coding_system *coding; 3355 struct coding_system *coding;
3356 char *source; 3356 char *source;
3357 struct x_display_info *dpyinfo;
3357}; 3358};
3358 3359
3359static Lisp_Object 3360static Lisp_Object
3360x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs, 3361x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs, Lisp_Object *args)
3361 Lisp_Object *args)
3362{ 3362{
3363 struct x_xim_text_conversion_data *data; 3363 struct x_xim_text_conversion_data *data;
3364 ptrdiff_t nbytes; 3364 ptrdiff_t nbytes;
3365 Lisp_Object coding_system;
3365 3366
3366 data = xmint_pointer (args[0]); 3367 data = xmint_pointer (args[0]);
3368
3369 if (SYMBOLP (Vx_input_coding_system))
3370 coding_system = Vx_input_coding_system;
3371 else if (!NILP (data->dpyinfo->xim_coding))
3372 coding_system = data->dpyinfo->xim_coding;
3373 else
3374 coding_system = Vlocale_coding_system;
3375
3367 nbytes = strlen (data->source); 3376 nbytes = strlen (data->source);
3368 3377
3369 data->coding->destination = NULL; 3378 data->coding->destination = NULL;
3370 3379
3371 setup_coding_system (Vlocale_coding_system, 3380 setup_coding_system (coding_system, data->coding);
3372 data->coding);
3373 data->coding->mode |= (CODING_MODE_LAST_BLOCK 3381 data->coding->mode |= (CODING_MODE_LAST_BLOCK
3374 | CODING_MODE_SAFE_ENCODING); 3382 | CODING_MODE_SAFE_ENCODING);
3375 data->coding->source = (const unsigned char *) data->source; 3383 data->coding->source = (const unsigned char *) data->source;
@@ -3382,8 +3390,7 @@ x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs,
3382} 3390}
3383 3391
3384static Lisp_Object 3392static Lisp_Object
3385x_xim_text_to_utf8_unix_2 (Lisp_Object val, 3393x_xim_text_to_utf8_unix_2 (Lisp_Object val, ptrdiff_t nargs,
3386 ptrdiff_t nargs,
3387 Lisp_Object *args) 3394 Lisp_Object *args)
3388{ 3395{
3389 struct x_xim_text_conversion_data *data; 3396 struct x_xim_text_conversion_data *data;
@@ -3400,7 +3407,8 @@ x_xim_text_to_utf8_unix_2 (Lisp_Object val,
3400 3407
3401/* The string returned is not null-terminated. */ 3408/* The string returned is not null-terminated. */
3402static char * 3409static char *
3403x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length) 3410x_xim_text_to_utf8_unix (struct x_display_info *dpyinfo,
3411 XIMText *text, ptrdiff_t *length)
3404{ 3412{
3405 unsigned char *wchar_buf; 3413 unsigned char *wchar_buf;
3406 ptrdiff_t wchar_actual_length, i; 3414 ptrdiff_t wchar_actual_length, i;
@@ -3424,6 +3432,7 @@ x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length)
3424 3432
3425 data.coding = &coding; 3433 data.coding = &coding;
3426 data.source = text->string.multi_byte; 3434 data.source = text->string.multi_byte;
3435 data.dpyinfo = dpyinfo;
3427 3436
3428 was_waiting_for_input_p = waiting_for_input; 3437 was_waiting_for_input_p = waiting_for_input;
3429 /* Otherwise Fsignal will crash. */ 3438 /* Otherwise Fsignal will crash. */
@@ -3441,18 +3450,21 @@ static void
3441xic_preedit_draw_callback (XIC xic, XPointer client_data, 3450xic_preedit_draw_callback (XIC xic, XPointer client_data,
3442 XIMPreeditDrawCallbackStruct *call_data) 3451 XIMPreeditDrawCallbackStruct *call_data)
3443{ 3452{
3444 struct frame *f = x_xic_to_frame (xic); 3453 struct frame *f;
3445 struct x_output *output; 3454 struct x_output *output;
3446 ptrdiff_t text_length = 0; 3455 ptrdiff_t text_length;
3447 ptrdiff_t charpos; 3456 ptrdiff_t charpos;
3448 ptrdiff_t original_size; 3457 ptrdiff_t original_size;
3449 char *text; 3458 char *text;
3450 char *chg_start, *chg_end; 3459 char *chg_start, *chg_end;
3451 struct input_event ie; 3460 struct input_event ie;
3461
3462 f = x_xic_to_frame (xic);
3452 EVENT_INIT (ie); 3463 EVENT_INIT (ie);
3453 3464
3454 if (f) 3465 if (f)
3455 { 3466 {
3467 text_length = 0;
3456 output = FRAME_X_OUTPUT (f); 3468 output = FRAME_X_OUTPUT (f);
3457 3469
3458 if (!output->preedit_active) 3470 if (!output->preedit_active)
@@ -3460,7 +3472,8 @@ xic_preedit_draw_callback (XIC xic, XPointer client_data,
3460 3472
3461 if (call_data->text) 3473 if (call_data->text)
3462 { 3474 {
3463 text = x_xim_text_to_utf8_unix (call_data->text, &text_length); 3475 text = x_xim_text_to_utf8_unix (FRAME_DISPLAY_INFO (f),
3476 call_data->text, &text_length);
3464 3477
3465 if (!text) 3478 if (!text)
3466 /* Decoding the IM text failed. */ 3479 /* Decoding the IM text failed. */
diff --git a/src/xterm.c b/src/xterm.c
index d83b03d1ca6..42335f0de0e 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -19139,7 +19139,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
19139 &xkey, (char *) copy_bufptr, 19139 &xkey, (char *) copy_bufptr,
19140 copy_bufsiz, &keysym, 19140 copy_bufsiz, &keysym,
19141 &status_return); 19141 &status_return);
19142 coding = Qnil; 19142 coding = FRAME_X_XIM_CODING (f);
19143 if (status_return == XBufferOverflow) 19143 if (status_return == XBufferOverflow)
19144 { 19144 {
19145 copy_bufsiz = nbytes + 1; 19145 copy_bufsiz = nbytes + 1;
@@ -22828,7 +22828,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
22828 &xkey, (char *) copy_bufptr, 22828 &xkey, (char *) copy_bufptr,
22829 copy_bufsiz, &keysym, 22829 copy_bufsiz, &keysym,
22830 &status_return); 22830 &status_return);
22831 coding = Qnil; 22831 coding = FRAME_X_XIM_CODING (f);
22832 22832
22833 if (status_return == XBufferOverflow) 22833 if (status_return == XBufferOverflow)
22834 { 22834 {
@@ -25488,9 +25488,10 @@ xim_destroy_callback (XIM xim, XPointer client_data, XPointer call_data)
25488static void 25488static void
25489xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name) 25489xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
25490{ 25490{
25491#ifdef HAVE_XIM
25491 XIM xim; 25492 XIM xim;
25493 const char *locale;
25492 25494
25493#ifdef HAVE_XIM
25494 if (use_xim) 25495 if (use_xim)
25495 { 25496 {
25496 if (dpyinfo->xim) 25497 if (dpyinfo->xim)
@@ -25513,6 +25514,14 @@ xim_open_dpy (struct x_display_info *dpyinfo, char *resource_name)
25513 destroy.client_data = (XPointer)dpyinfo; 25514 destroy.client_data = (XPointer)dpyinfo;
25514 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL); 25515 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
25515#endif 25516#endif
25517
25518 locale = XLocaleOfIM (xim);
25519
25520 /* Now try to determine the coding system that should be
25521 used. locale is in Host Portable Character Encoding, and
25522 as such can be passed to build_string as is. */
25523 dpyinfo->xim_coding = safe_call1 (Vx_input_coding_function,
25524 build_string (locale));
25516 } 25525 }
25517 } 25526 }
25518 25527
@@ -29843,7 +29852,7 @@ mark_xterm (void)
29843 } 29852 }
29844 29853
29845#if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \ 29854#if defined HAVE_XINPUT2 || defined USE_TOOLKIT_SCROLL_BARS \
29846 || defined HAVE_XRANDR || defined USE_GTK 29855 || defined HAVE_XRANDR || defined USE_GTK || defined HAVE_X_I18N
29847 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) 29856 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
29848 { 29857 {
29849#ifdef HAVE_XINPUT2 29858#ifdef HAVE_XINPUT2
@@ -29857,6 +29866,9 @@ mark_xterm (void)
29857#if defined HAVE_XRANDR || defined USE_GTK 29866#if defined HAVE_XRANDR || defined USE_GTK
29858 mark_object (dpyinfo->last_monitor_attributes_list); 29867 mark_object (dpyinfo->last_monitor_attributes_list);
29859#endif 29868#endif
29869#if defined HAVE_X_I18N
29870 mark_object (dpyinfo->xim_coding);
29871#endif
29860 } 29872 }
29861#endif 29873#endif
29862} 29874}
@@ -30385,4 +30397,18 @@ on the same display.
30385In addition, when this variable is a list, only preserve the 30397In addition, when this variable is a list, only preserve the
30386selections whose names are contained within. */); 30398selections whose names are contained within. */);
30387 Vx_auto_preserve_selections = list2 (QCLIPBOARD, QPRIMARY); 30399 Vx_auto_preserve_selections = list2 (QCLIPBOARD, QPRIMARY);
30400
30401 DEFVAR_LISP ("x-input-coding-system", Vx_input_coding_system,
30402 doc: /* Coding system used for input from X input methods.
30403If a symbol and non-nil, this is the coding system that will be used
30404to decode input from X input methods. It does not affect input from
30405GTK native input methods enabled through `x-gtk-use-native-input'. */);
30406 Vx_input_coding_system = Qnil;
30407
30408 DEFVAR_LISP ("x-input-coding-function", Vx_input_coding_function,
30409 doc: /* Function used to determine the coding system used by input methods.
30410It should accept a single argument, a string describing the locale of
30411the input method, and return a coding system that can decode keyboard
30412input generated by said input method. */);
30413 Vx_input_coding_function = Qnil;
30388} 30414}
diff --git a/src/xterm.h b/src/xterm.h
index f3791aa8df9..b68a234faa5 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -580,6 +580,9 @@ struct x_display_info
580 XIMStyles *xim_styles; 580 XIMStyles *xim_styles;
581 struct xim_inst_t *xim_callback_data; 581 struct xim_inst_t *xim_callback_data;
582 XIMStyle preferred_xim_style; 582 XIMStyle preferred_xim_style;
583
584 /* The named coding system to use for this input method. */
585 Lisp_Object xim_coding;
583#endif 586#endif
584 587
585 /* A cache mapping color names to RGB values. */ 588 /* A cache mapping color names to RGB values. */
@@ -1348,6 +1351,12 @@ extern void x_mark_frame_dirty (struct frame *f);
1348#define FRAME_X_XIM_STYLES(f) (FRAME_DISPLAY_INFO (f)->xim_styles) 1351#define FRAME_X_XIM_STYLES(f) (FRAME_DISPLAY_INFO (f)->xim_styles)
1349#define FRAME_XIC_STYLE(f) ((f)->output_data.x->xic_style) 1352#define FRAME_XIC_STYLE(f) ((f)->output_data.x->xic_style)
1350#define FRAME_XIC_FONTSET(f) ((f)->output_data.x->xic_xfs) 1353#define FRAME_XIC_FONTSET(f) ((f)->output_data.x->xic_xfs)
1354#define FRAME_X_XIM_CODING(f) \
1355 (SYMBOLP (Vx_input_coding_system) \
1356 ? Vx_input_coding_system \
1357 : (!NILP (FRAME_DISPLAY_INFO (f)->xim_coding) \
1358 ? FRAME_DISPLAY_INFO(f)->xim_coding \
1359 : Vlocale_coding_system))
1351 1360
1352/* X-specific scroll bar stuff. */ 1361/* X-specific scroll bar stuff. */
1353 1362