1 /* Various functions for X11R5+ input methods, using the Xlib interface.
2 Copyright (C) 1996 Sun Microsystems.
4 This file is part of XEmacs.
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Synched up with: Not in FSF. */
23 /* Written by Martin Buchholz. */
25 /* This file implements an interface to X input methods, available
26 with X11R5 and above. See O'Reilly, Xlib programmer's guide,
27 and X11 R6 release guide chapters on internationalized input,
28 for further details */
33 The XIM is of the device, by the device, for the device.
34 The XIC is of each frame, by each frame, for each frame.
36 1. Activate XICs on poor frames when the XIM is back.
37 2. Deactivate all the XICs when the XIM go down.
41 - Register a callback for an XIM when the X device is being initialized.
42 XIM_init_device (d) { XRegisterIMInstantiateCallback (); }
43 The "XRegisterIMInstantiateCallback" is called when an XIM become
44 available on the X display.
46 - Catch the XIC when the frame is being initialized if XIM was available.
47 XIM_init_frame (f) { ... XCreateIC (); ... }
49 - Release the XIC when the frame is being closed.
50 XIM_delete_frame (f) { ... FRAME_X_XIC (f) = NULL; ... }
51 "XIM_delete_frame" is a "DestroyCallback" function declared in
54 - Release all the XICs when the XIM was down accidentally.
56 DEVICE_FRAME_LOOP (...) { FRAME_X_XIC (f) = NULL; }
58 - Re-enable XIC for all the frames which doesn't have XIC when the XIM
60 In IMInstantiateCallback:
61 DEVICE_FRAME_LOOP (...) { XIM_init_frame (f); }
66 - Currently, we don't use XDestroyIC because of _XimProtoCloseIM
67 (internally registered as im->methods->close) does "Xfree (ic)".
73 #include <X11/Xlocale.h> /* More portable than <locale.h> ? */
78 #include "console-x.h"
79 #include "EmacsFrame.h"
83 #include <X11/IntrinsicP.h>
87 #error XIM_XLIB is not defined??
90 Lisp_Object Qxim_xlib;
91 #define xim_warn(str) warn_when_safe (Qxim_xlib, Qwarning, str);
92 #define xim_warn1(fmt, str) warn_when_safe (Qxim_xlib, Qwarning, fmt, str);
93 #define xim_info(str) warn_when_safe (Qxim_xlib, Qinfo, str);
95 /* Get/Set IC values for just one attribute */
97 #define XIC_Value(Get_Set, xic, name, attr, value) \
100 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
101 if ((bad_arg = X##Get_Set##ICValues (xic, name, list, NULL)) != NULL) \
102 stderr_out ("X" #Get_Set "ICValues " "bad Arg: %s\n", bad_arg); \
105 #else /* ! DEBUG_XEMACS */
106 #define XIC_Value(Get_Set, xic, name, attr, value) \
108 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
109 X##Get_Set##ICValues (xic, name, list, NULL); \
112 #endif /* DEBUG_XEMACS */
114 static char DefaultXIMStyles[] =
115 "XIMPreeditPosition|XIMStatusArea\n"
116 "XIMPreeditPosition|XIMStatusNone\n"
117 "XIMPreeditPosition|XIMStatusNothing\n"
118 "XIMPreeditNothing|XIMStatusArea\n"
119 "XIMPreeditNothing|XIMStatusNothing\n"
120 "XIMPreeditNothing|XIMStatusNone\n"
121 "XIMPreeditNone|XIMStatusArea\n"
122 "XIMPreeditNone|XIMStatusNothing\n"
123 "XIMPreeditNone|XIMStatusNone";
125 static Boolean xim_initted = False;
127 static XIMStyle best_style (XIMStyles *user, XIMStyles *xim);
129 /* #### it appears this prototype is missing from the X11R6.4 includes,
130 at least the XFree86 version ... */
131 char * XSetIMValues(XIM, ...);
134 Initialize_Locale (void)
138 /* dverna - Nov. 98: #### DON'T DO THIS !!! The default XtLanguageProc
139 routine calls setlocale(LC_ALL, lang) which fucks up our lower-level
140 locale management, and especially the value of LC_NUMERIC. Anyway, since
141 at this point, we don't know yet whether we're gonna need an X11 frame,
142 we should really do it manually and not use Xlib's dumb default routine */
143 /*XtSetLanguageProc (NULL, (XtLanguageProc) NULL, NULL);*/
144 if ((locale = setlocale (LC_ALL, "")) == NULL)
146 xim_warn ("Can't set locale.\n"
147 "Using C locale instead.\n");
150 if ((locale = setlocale (LC_ALL, "C")) == NULL)
152 xim_warn ("Can't even set locale to `C'!\n");
157 if (!XSupportsLocale ())
159 xim_warn1 ("X Windows does not support locale `%s'\n"
160 "Using C Locale instead\n", locale);
163 if ((locale = setlocale (LC_ALL, "C")) == NULL)
165 xim_warn ("Can't even set locale to `C'!\n");
168 if (!XSupportsLocale ())
170 xim_warn ("X Windows does not even support locale `C'!\n");
175 setlocale(LC_NUMERIC, "C");
177 if (XSetLocaleModifiers ("") == NULL)
179 xim_warn ("XSetLocaleModifiers(\"\") failed\n"
180 "Check the value of the XMODIFIERS environment variable.\n");
184 #ifdef THIS_IS_X11R6 /* Callbacks for IM are supported from X11R6 or later. */
185 /* Called from when XIM is destroying.
186 Clear all the XIC when the XIM was destroying... */
188 IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data)
190 struct device *d = (struct device *)client_data;
193 DEVICE_FRAME_LOOP (tail, d)
195 struct frame *target_frame = XFRAME (XCAR (tail));
196 if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame))
198 /* XDestroyIC (FRAME_X_XIC (target_frame)); */
199 FRAME_X_XIC (target_frame) = NULL;
203 DEVICE_X_XIM (d) = NULL;
208 /* This is registered in XIM_init_device (when DEVICE is initializing).
209 This activates XIM when XIM becomes available. */
211 IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data)
213 struct device *d = (struct device *)client_data;
216 XIMCallback ximcallback;
219 /* if no xim is presented, initialize xim ... */
220 if ( xim_initted == False )
223 XtGetApplicationNameAndClass (dpy, &name, &class);
224 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
226 /* destroy callback for im */
227 ximcallback.callback = IMDestroyCallback;
228 ximcallback.client_data = (XPointer) d;
229 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL);
232 /* activate XIC on all the X frames... */
233 DEVICE_FRAME_LOOP (tail, d)
235 struct frame *target_frame = XFRAME (XCAR (tail));
236 if (FRAME_X_P (target_frame) && !FRAME_X_XIC (target_frame))
238 XIM_init_frame (target_frame);
243 #endif /* if THIS_IS_X11R6 */
245 /* Initialize XIM for X device.
246 Register the use of XIM using XRegisterIMInstantiateCallback. */
248 XIM_init_device (struct device *d)
251 DEVICE_X_XIM (d) = NULL;
252 XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL,
253 IMInstantiateCallback,
254 /* The sixth parameter is of type
255 XPointer in XFree86 but (XPointer *)
256 on most other X11's. */
260 Display *dpy = DEVICE_X_DISPLAY (d);
264 XtGetApplicationNameAndClass (dpy, &name, &class);
265 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
268 xim_warn ("XOpenIM() failed...no input server available\n");
273 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL);
284 /* Callback for the deleting frame. */
286 XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data)
288 struct frame *f = (struct frame *) client_data;
289 struct device *d = XDEVICE (FRAME_DEVICE (f));
291 if (DEVICE_X_XIM (d))
295 XDestroyIC (FRAME_X_XIC (f));
296 FRAME_X_XIC (f) = NULL;
302 /* Initialize XIC for new frame.
303 Create an X input context (XIC) for this frame. */
305 XIM_init_frame (struct frame *f)
307 struct device *d = XDEVICE (FRAME_DEVICE (f));
309 Widget w = FRAME_X_TEXT_WIDGET (f);
310 Window win = XtWindow (w);
311 XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1};
314 XVaNestedList p_list, s_list;
326 #define res(name, class, representation, field, default_value) \
327 { name, class, representation, sizeof(xic_vars.field), \
328 XtOffsetOf(xic_vars_t, field), XtRString, default_value }
330 static XtResource resources[] =
332 /* name class represent'n field default value */
333 res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, (XtPointer) DefaultXIMStyles),
334 res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, (XtPointer) XtDefaultFontSet),
335 res(XtNximForeground, XtCForeground, XtRPixel, fg, (XtPointer) XtDefaultForeground),
336 res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground)
340 xim = DEVICE_X_XIM (d);
347 w = FRAME_X_TEXT_WIDGET (f);
352 if (FRAME_X_XIC (f)) return;
353 XtGetApplicationResources (w, &xic_vars,
354 resources, XtNumber (resources),
356 if (!xic_vars.fontset)
358 xim_warn ("Can't get fontset resource for Input Method\n");
359 FRAME_X_XIC (f) = NULL;
364 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES(d), NULL);
365 FRAME_X_XIC_STYLE (f) = style =
366 best_style (&xic_vars.styles, (XIMStyles *)DEVICE_X_XIM_STYLES(d));
368 p_list = XVaCreateNestedList (0,
370 XNSpotLocation, &spot,
371 XNForeground, xic_vars.fg,
372 XNBackground, xic_vars.bg,
373 XNFontSet, xic_vars.fontset,
376 s_list = XVaCreateNestedList (0,
378 XNForeground, xic_vars.fg,
379 XNBackground, xic_vars.bg,
380 XNFontSet, xic_vars.fontset,
383 FRAME_X_XIC (f) = xic =
388 XNPreeditAttributes, p_list,
389 XNStatusAttributes, s_list,
396 xim_warn ("Warning: XCreateIC failed.\n");
400 if (style & XIMPreeditPosition)
402 XPoint *frame_spot = &(FRAME_X_XIC_SPOT(f));
403 frame_spot->x = frame_spot->y = -1;
411 /* when frame is going to be destroyed (closed) */
412 XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback,
413 XIM_delete_frame, (XtPointer)f);
419 XIM_SetGeometry (struct frame *f)
421 XIC xic = FRAME_X_XIC (f);
422 XIMStyle style = FRAME_X_XIC_STYLE (f);
428 if (style & XIMStatusArea)
430 /* Place Status Area in bottom right corner */
431 /* Negotiate geometry of status area */
432 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */
435 /* If input method has existing status area, use its current size */
436 /* The following at least works for Sun's htt */
437 area.x = area.y = area.width = area.height = 0;
438 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area);
439 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed);
440 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
441 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed);
443 area.width = needed->width;
444 area.height = needed->height;
445 area.x = FRAME_RIGHT_BORDER_START (f) - area.width;
446 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height;
449 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n",
450 area.x, area.y, area.width, area.height);
451 #endif /* DEBUG_XIM */
453 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area);
456 if (style & XIMPreeditPosition)
458 /* Set Preedit Area to whole frame size (sans border) */
459 /* We include the border because Preedit window might be larger
460 than display line at edge. #### FIX: we should adjust to make
461 sure that there is always room for the spot sub-window */
462 area.x = FRAME_LEFT_BORDER_START (f);
463 area.y = FRAME_TOP_BORDER_START (f);
464 area.width = FRAME_RIGHT_BORDER_END (f) - area.x;
465 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y;
466 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area);
475 XIM_SetSpotLocation (struct frame *f, int x, int y)
477 XIC xic = FRAME_X_XIC (f);
478 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
480 /* Only care if we have a valid XIC using Over the Spot in
481 * a different location */
483 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) ||
484 (spot->x == (short) x &&
485 spot->y == (short) y))
491 /* #### FIX: Must make sure spot fits within Preedit Area */
492 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
494 stderr_out ("Spot: %d %d\n", spot->x, spot->y);
499 XIM_focus_event (struct frame *f, int in_p)
501 if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */)
502 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
506 #define XIM_Composed_Text_BUFSIZE 64
507 typedef struct XIM_Composed_Text
510 wchar_t data [XIM_Composed_Text_BUFSIZE];
513 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}};
516 /* get_XIM_input -- Process results of input method composition.
518 This function copies the results of the input method composition to
519 composed_input_buf. Then for each character, a custom event of type
520 wc_atom is sent with the character as its data.
522 It is probably more efficient to copy the composition results to some
523 allocated memory and send a single event pointing to that memory.
524 That would cut down on the event processing as well as allow quick
525 insertion into the buffer of the whole string. It might require some
526 care, though, to avoid fragmenting memory through the allocation and
527 freeing of many small chunks. Maybe the existing system for
528 (single-byte) string allocation can be used, multiplying the length by
529 sizeof (wchar_t) to get the right size.
532 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy)
538 XClientMessageEvent new_event;
541 len = XwcLookupString (ic, x_key_event, composed_input_buf.data,
542 composed_input_buf.size, &keysym, &status);
545 case XBufferOverflow:
546 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */
554 new_event.type = ClientMessage;
555 new_event.display = x_key_event->display;
556 new_event.window = x_key_event->window;
557 new_event.message_type = wc_atom;
558 new_event.format = 32; /* 32-bit wide data */
559 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L;
560 new_event.data.l[0] = x_key_event->time;
561 for (i = 0; i < len; i++)
563 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i];
564 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event);
569 /* ============================================================== */
570 /* X input method style determination */
571 /* ============================================================== */
574 #define done(type, value) \
575 if (toVal->addr != NULL) { \
576 if (toVal->size < sizeof(type)) { \
577 toVal->size = sizeof(type); \
580 *(type*)toVal->addr = (value); \
582 static type static_val; \
583 static_val = (value); \
584 toVal->addr = (XPointer)&static_val; \
586 toVal->size = sizeof(type); \
587 return True /* Caller supplies `;' */
591 * This is a standard Xt type converter, except that the caller MUST
592 * supply a proper non-NULL toVal XIMStyles structure that we will
595 * fromVal points to a string like
597 "XIMPreeditPosition|XIMStatusArea,
598 XIMPreeditPosition|XIMStatusNothing
599 XIMPreeditNothing|XIMStatusNothing"
601 * This is converted in the obvious way to a XIMStyles structure.
603 * mrb: #### Fix this to handle Motif-style specifications for
604 * XIMStyles as well: overTheSpot, rootWindow, none */
606 /* XtTypeConverter */
608 EmacsXtCvtStringToXIMStyles (
614 XtPointer *converter_data)
616 #define STYLE_INFO(style) { style, #style, sizeof(#style) }
617 static struct XIMStyleInfo
619 const XIMStyle style;
620 const char * const name;
622 } emacs_XIMStyleInfo[] = {
623 STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
624 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
625 STYLE_INFO (XIMPreeditPosition|XIMStatusNone),
626 STYLE_INFO (XIMPreeditNothing|XIMStatusArea),
627 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing),
628 STYLE_INFO (XIMPreeditNothing|XIMStatusNone),
629 STYLE_INFO (XIMPreeditNone|XIMStatusArea),
630 STYLE_INFO (XIMPreeditNone|XIMStatusNothing),
631 STYLE_INFO (XIMPreeditNone|XIMStatusNone)
635 char *s = (char *) fromVal->addr;
636 char *end = s + fromVal->size;
637 XIMStyles * const p = (XIMStyles *) toVal->addr;
638 const char * const delimiter = " \t\n\r:;," ;
639 const int max_styles = XtNumber(emacs_XIMStyleInfo);
644 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n",
645 fromVal->size, (char *) fromVal->addr);
646 #endif /* DEBUG_XIM */
650 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
651 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
653 "String to XIMStyle conversion requires exactly 0 parameters",
654 (String *)NULL, (Cardinal *)NULL);
659 /* Make sure caller is giving us good data */
660 assert (fromVal->addr != NULL);
661 assert (fromVal->size == strlen(fromVal->addr)+1);
662 assert (toVal->addr != NULL);
663 assert (toVal->size == sizeof(XIMStyles));
664 #endif /* DEBUG_XEMACS */
667 p->supported_styles = xnew_array (XIMStyle, max_styles);
670 * The following routine assumes that the style name resource is
671 * identical with the programmatic name of style. For example,
672 * "XIMPreeditPosition|XIMStatusArea" means the
673 * XIMPreeditPosition|XIMStatusArea value is specified. If the
674 * style name is changed, such as "OverTheSpot|imDisplaysInClient",
675 * the parsing logic below should be modified as well. */
677 if ((c = strtok(s, delimiter)) == NULL)
682 for(i=0 ; i<max_styles ; i++)
684 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i;
685 if(!strncmp(c, rec->name, rec->namelen - 1)) {
686 p->supported_styles[p->count_styles] = rec->style;
691 if((c = strtok(NULL, delimiter)) == NULL) {
696 if (p->count_styles == 0)
697 { /* No valid styles? */
698 char *buf = (char *)alloca (strlen (fromVal->addr)
699 + strlen (DefaultXIMStyles)
702 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
704 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n"
705 "Using default string \"%s\" instead.\n",
706 fromVal->addr, DefaultXIMStyles);
707 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
709 buf, (String *)NULL, (Cardinal *)NULL);
710 new_from.addr = DefaultXIMStyles;
711 new_from.size = sizeof(DefaultXIMStyles);
712 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args,
713 &new_from, toVal, converter_data);
715 XREALLOC_ARRAY (p->supported_styles, XIMStyle, p->count_styles);
716 *converter_data = (char *) True;
725 XtPointer converter_data,
730 stderr_out ("Converter data: %x\n", converter_data);
731 stderr_out ("EmacsFreeXIMStyles called\n");
732 #endif /* DEBUG_XIM */
736 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError",
737 "Freeing an XIMStyles requires that zero arguments be passwd",
738 (String *)NULL, (Cardinal *)NULL);
744 Boolean free_p = (Boolean) (int) converter_data;
745 XIMStyles *styles = (XIMStyles *) toVal->addr;
747 XFree ( styles->supported_styles );
752 /* O'Reilly XLib Programming Manual, pg. 371 */
753 /* Much nicer implementation than O'Reilly */
754 /* Choose the more `complicated', hence nicer, XIM input style */
756 BetterStyle (XIMStyle s, XIMStyle t)
758 #define CHECK_XIMStyle_BIT(bit) \
759 if ((s ^ t) & bit) { return (s & bit) ? s : t; }
761 CHECK_XIMStyle_BIT (XIMPreeditCallbacks);
762 CHECK_XIMStyle_BIT (XIMPreeditPosition);
763 CHECK_XIMStyle_BIT (XIMPreeditArea);
764 CHECK_XIMStyle_BIT (XIMPreeditNothing);
765 CHECK_XIMStyle_BIT (XIMStatusCallbacks);
766 CHECK_XIMStyle_BIT (XIMStatusArea);
767 CHECK_XIMStyle_BIT (XIMStatusNothing);
768 #undef CHECK_XIMStyle_BIT
773 /* Choose the best style, given:
774 * - user preferences (already checked to be supported by XEmacs)
775 * - styles supported by the input method */
776 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing)
778 best_style (XIMStyles *user, XIMStyles *xim)
781 for (i=0 ; i<user->count_styles ; i++)
783 for (j=0 ; j<xim->count_styles ; j++)
785 if (user->supported_styles[i] == xim->supported_styles[j])
786 return user->supported_styles[i];
789 return DEFAULTStyle; /* Default Style */
792 /* These lisp-callable functions will be sealed until xim-leim is needed.
793 Oct 22 1999 - kazz */
796 * External callable function for XIM
798 DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /*
799 Open the XIC on the frame if XIM is available.
800 Commonly, use this as \(x-open-xim \(selected-frame)).
801 If the frame is not on X device, return signal.
802 If XIC is created successfully return t. If not return nil.
808 CHECK_LIVE_FRAME (frame);
811 return signal_simple_error ("This frame is not on X device", frame);
814 return FRAME_X_XIC (f) ? Qt : Qnil;
817 DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /*
818 Close the XIC on the frame if it exists.
819 Commonly, use this as \(x-close-xim \(selected-frame)).
820 If the frame is not on X device, return signal.
821 Otherwise, it destroys the XIC if it exists, then returns t anyway.
828 CHECK_LIVE_FRAME (frame);
831 return signal_simple_error ("This frame is not on X device", frame);
833 d = XDEVICE (FRAME_DEVICE (f));
834 if (DEVICE_X_XIM (d)) {
835 /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */
836 FRAME_X_XIC (XFRAME (f)) = NULL;
843 syms_of_input_method_xlib (void)
845 defsymbol (&Qxim_xlib, "xim-xlib");
846 #if 0 /* see above */
847 DEFSUBR (Fx_open_xim);
848 DEFSUBR (Fx_close_xim);
853 vars_of_input_method_xlib (void)
855 Fprovide (intern ("xim"));
859 /* ====================================================================== */
860 /* Internal Debugging Routines */
861 /* ====================================================================== */
865 describe_XIM (XIM xim)
869 /* Print locale of XIM */
870 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim));
872 /* List supported input method styles */
873 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
875 stderr_out ("\n%d input style(s) supported by input method.\n",
876 styles->count_styles);
881 for (i=0; i < styles->count_styles; i++)
882 describe_XIMStyle (styles->supported_styles[i]);
884 #endif /* DEBUG_XIM */
889 describe_XFontSet (XFontSet fontset)
891 XFontStruct **font_struct_list;
892 char **font_name_list;
897 stderr_out ("NULL\n");
901 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list);
902 stderr_out ( "%d font(s) available:\n", count);
903 for (i=0 ; i < count ; i++)
904 stderr_out ("Font: %s\n", *(font_name_list+i));
908 describe_Status (Status status)
910 #define DESCRIBE_STATUS(value) \
911 if (status == value) stderr_out ("Status: " #value "\n")
913 DESCRIBE_STATUS (XBufferOverflow);
914 DESCRIBE_STATUS (XLookupNone);
915 DESCRIBE_STATUS (XLookupKeySym);
916 DESCRIBE_STATUS (XLookupBoth);
917 DESCRIBE_STATUS (XLookupChars);
918 #undef DESCRIBE_STATUS
922 describe_Window (Window win)
925 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2",
926 (int) win, (int) win);
931 describe_XIC (XIC xic)
934 Window client_win=0, focus_win=0;
935 char *resourceName = NULL;
936 char *resourceClass = NULL;
937 char *bad_arg = NULL;
938 unsigned long filter_mask = NoEventMask;
939 XVaNestedList p_list, s_list;
940 XFontSet p_fontset = NULL, s_fontset = NULL;
941 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0;
942 XRectangle *p_area = NULL, *s_area = NULL;
943 XRectangle *p_needed = NULL, *s_needed = NULL;
944 XPoint *p_spot = NULL;
946 /* Check for valid input context and method */
948 stderr_out ("Input method is NULL\n");
951 stderr_out ("XIMOfIC() returns NULL\n");
953 /* Print out Input Context Attributes */
954 p_list = XVaCreateNestedList (0,
955 XNFontSet, &p_fontset,
957 XNAreaNeeded, &p_needed,
958 XNSpotLocation, &p_spot,
963 s_list = XVaCreateNestedList (0,
964 XNFontSet, &s_fontset,
966 XNAreaNeeded, &s_needed,
971 bad_arg = XGetICValues(xic,
972 XNInputStyle, &style,
973 XNFilterEvents, &filter_mask,
974 XNClientWindow, &client_win,
975 XNFocusWindow, &focus_win,
976 XNResourceName, &resourceName,
977 XNResourceClass, &resourceClass,
978 XNPreeditAttributes, p_list,
979 XNStatusAttributes, s_list,
985 stderr_out ("Couldn't get IC value: %s\n", bad_arg);
987 stderr_out ("\nInput method context attributes:\n");
988 stderr_out ("Style: "); describe_XIMStyle (style);
989 stderr_out ("Client window: %lx\n", (unsigned long int)client_win);
990 stderr_out ("Focus window: %lx\n", (unsigned long int)focus_win);
991 stderr_out ("Preedit:\n");
992 describe_XRectangle (" Area", p_area);
993 describe_XRectangle (" Area needed", p_needed);
994 stderr_out (" foreground: %lx\n", (unsigned long int)p_fg);
995 stderr_out (" background: %lx\n", (unsigned long int)p_bg);
996 stderr_out (" fontset: "); describe_XFontSet (p_fontset);
997 stderr_out ("Status:\n");
998 describe_XRectangle (" Area", s_area);
999 describe_XRectangle (" Area needed", s_needed);
1000 stderr_out (" foreground: %lx\n", (unsigned long int)s_fg);
1001 stderr_out (" background: %lx\n", (unsigned long int)s_bg);
1002 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset);
1003 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL");
1004 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL");
1005 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask);
1009 describe_XRectangle (char *name, XRectangle *r)
1012 stderr_out ("%s: NULL\n", name);
1014 stderr_out ("%s: x=%d y=%d w=%d h=%d\n",
1015 name, r->x, r->y, r->width, r->height);
1018 /* Print out elements of Event mask */
1019 /* Defines from X11/X.h */
1021 describe_event_mask (unsigned long mask)
1023 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ")
1024 DESCRIBE_EVENT_MASK (NoEventMask);
1025 DESCRIBE_EVENT_MASK (KeyPressMask);
1026 DESCRIBE_EVENT_MASK (KeyReleaseMask);
1027 DESCRIBE_EVENT_MASK (ButtonPressMask);
1028 DESCRIBE_EVENT_MASK (ButtonReleaseMask);
1029 DESCRIBE_EVENT_MASK (EnterWindowMask);
1030 DESCRIBE_EVENT_MASK (LeaveWindowMask);
1031 DESCRIBE_EVENT_MASK (PointerMotionMask);
1032 DESCRIBE_EVENT_MASK (PointerMotionHintMask);
1033 DESCRIBE_EVENT_MASK (Button1MotionMask);
1034 DESCRIBE_EVENT_MASK (Button2MotionMask);
1035 DESCRIBE_EVENT_MASK (Button3MotionMask);
1036 DESCRIBE_EVENT_MASK (Button4MotionMask);
1037 DESCRIBE_EVENT_MASK (Button5MotionMask);
1038 DESCRIBE_EVENT_MASK (ButtonMotionMask);
1039 DESCRIBE_EVENT_MASK (KeymapStateMask);
1040 DESCRIBE_EVENT_MASK (ExposureMask);
1041 DESCRIBE_EVENT_MASK (VisibilityChangeMask);
1042 DESCRIBE_EVENT_MASK (StructureNotifyMask);
1043 DESCRIBE_EVENT_MASK (ResizeRedirectMask);
1044 DESCRIBE_EVENT_MASK (SubstructureNotifyMask);
1045 DESCRIBE_EVENT_MASK (SubstructureRedirectMask);
1046 DESCRIBE_EVENT_MASK (FocusChangeMask);
1047 DESCRIBE_EVENT_MASK (PropertyChangeMask);
1048 DESCRIBE_EVENT_MASK (ColormapChangeMask);
1049 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask);
1050 #undef DESCRIBE_EVENT_MASK
1055 describe_XIMStyle (XIMStyle style)
1057 #define DESCRIBE_STYLE(bit) \
1059 stderr_out (#bit " ");
1061 DESCRIBE_STYLE (XIMPreeditArea);
1062 DESCRIBE_STYLE (XIMPreeditCallbacks);
1063 DESCRIBE_STYLE (XIMPreeditPosition);
1064 DESCRIBE_STYLE (XIMPreeditNothing);
1065 DESCRIBE_STYLE (XIMPreeditNone);
1066 DESCRIBE_STYLE (XIMStatusArea);
1067 DESCRIBE_STYLE (XIMStatusCallbacks);
1068 DESCRIBE_STYLE (XIMStatusNothing);
1069 DESCRIBE_STYLE (XIMStatusNone);
1070 #undef DESCRIBE_STYLE
1075 describe_XIMStyles (XIMStyles *p)
1078 stderr_out ("%d Style(s):\n", p->count_styles);
1079 for (i=0; i<p->count_styles ; i++)
1081 describe_XIMStyle (p->supported_styles[i]);
1085 #endif /* DEBUG_XEMACS */
1087 /* Random cruft follows */
1091 Unit_Test (struct frame *f, char * s)
1092 /* mrb unit testing */
1094 XrmValue fromVal, toVal;
1097 fromVal.size = strlen (s);
1098 toVal.addr = (XtPointer) &user_preferred_XIMStyles;
1099 toVal.size = sizeof (XIMStyles);
1101 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal,
1102 XtRXimStyles, &toVal) != False)
1104 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr);
1105 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size);
1106 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr);
1107 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size);
1108 describe_XIMStyles ((XIMStyles *) toVal.addr);
1114 /* Get a fontset for IM to use */
1116 x_init_fontset (struct device *d)
1118 Display *dpy = DEVICE_X_DISPLAY (d);
1120 char ** missing_charsets;
1121 int num_missing_charsets;
1122 char * default_string;
1123 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/
1124 char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*, -misc-fixed-medium-r-normal--14-130-75-75-c-70-jisx0201.1976-0,-misc-fixed-medium-r-normal--14-130-75-75-c-140-jisx0208.1983-0, -misc-fixed-medium-r-normal--14-130-75-75-c-70-jisx0201.1976-0" ;
1126 DEVICE_X_FONTSET (d) = fontset =
1127 XCreateFontSet (dpy,
1130 &num_missing_charsets,
1133 if (fontset == NULL)
1135 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string);
1138 if (num_missing_charsets > 0)
1141 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string);
1142 for (i=0; i < num_missing_charsets; i++)
1144 stderr_out ("%s\n", missing_charsets[i]);
1146 XFreeStringList (missing_charsets);
1147 stderr_out ("Default string: %s\n", default_string);
1151 describe_XFontSet (fontset);