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>
84 #include <X11/Xaw/XawImP.h>
88 #error XIM_XLIB is not defined??
91 Lisp_Object Qxim_xlib;
92 #define xim_warn(str) warn_when_safe (Qxim_xlib, Qwarning, str);
93 #define xim_warn1(fmt, str) warn_when_safe (Qxim_xlib, Qwarning, fmt, str);
94 #define xim_info(str) warn_when_safe (Qxim_xlib, Qinfo, str);
96 /* Get/Set IC values for just one attribute */
98 #define XIC_Value(Get_Set, xic, name, attr, value) \
101 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
102 if ((bad_arg = X##Get_Set##ICValues (xic, name, list, NULL)) != NULL) \
103 stderr_out ("X" #Get_Set "ICValues " "bad Arg: %s\n", bad_arg); \
106 #else /* ! DEBUG_XEMACS */
107 #define XIC_Value(Get_Set, xic, name, attr, value) \
109 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
110 X##Get_Set##ICValues (xic, name, list, NULL); \
113 #endif /* DEBUG_XEMACS */
115 static char DefaultXIMStyles[] =
116 "XIMPreeditPosition|XIMStatusArea\n"
117 "XIMPreeditPosition|XIMStatusNone\n"
118 "XIMPreeditPosition|XIMStatusNothing\n"
119 "XIMPreeditNothing|XIMStatusArea\n"
120 "XIMPreeditNothing|XIMStatusNothing\n"
121 "XIMPreeditNothing|XIMStatusNone\n"
122 "XIMPreeditNone|XIMStatusArea\n"
123 "XIMPreeditNone|XIMStatusNothing\n"
124 "XIMPreeditNone|XIMStatusNone";
126 static Boolean xim_initted = False;
128 static XIMStyle best_style (XIMStyles *user, XIMStyles *xim);
131 Initialize_Locale (void)
135 /* dverna - Nov. 98: ### DON'T DO THIS !!! The default XtLanguageProc
136 routine calls setlocale(LC_ALL, lang) which fucks up our lower-level
137 locale management, and especially the value of LC_NUMERIC. Anyway, since
138 at this point, we don't know yet whether we're gonna need an X11 frame,
139 we should really do it manually and not use Xlib's dumb default routine */
140 /*XtSetLanguageProc (NULL, (XtLanguageProc) NULL, NULL);*/
141 if ((locale = setlocale (LC_ALL, "")) == NULL)
143 xim_warn ("Can't set locale.\n"
144 "Using C locale instead.\n");
147 if ((locale = setlocale (LC_ALL, "C")) == NULL)
149 xim_warn ("Can't even set locale to `C'!\n");
154 if (!XSupportsLocale ())
156 xim_warn1 ("X Windows does not support locale `%s'\n"
157 "Using C Locale instead\n", locale);
160 if ((locale = setlocale (LC_ALL, "C")) == NULL)
162 xim_warn ("Can't even set locale to `C'!\n");
165 if (!XSupportsLocale ())
167 xim_warn ("X Windows does not even support locale `C'!\n");
172 setlocale(LC_NUMERIC, "C");
174 if (XSetLocaleModifiers ("") == NULL)
176 xim_warn ("XSetLocaleModifiers(\"\") failed\n"
177 "Check the value of the XMODIFIERS environment variable.\n");
181 #ifdef THIS_IS_X11R6 /* Callbacks for IM are supported from X11R6 or later. */
182 /* Called from when XIM is destroying.
183 Clear all the XIC when the XIM was destroying... */
185 IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data)
187 struct device *d = (struct device *)client_data;
190 DEVICE_FRAME_LOOP (tail, d)
192 struct frame *target_frame = XFRAME (XCAR (tail));
193 if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame))
195 /* XDestroyIC (FRAME_X_XIC (target_frame)); */
196 FRAME_X_XIC (target_frame) = NULL;
200 DEVICE_X_XIM (d) = NULL;
205 /* This is registered in XIM_init_device (when DEVICE is initializing).
206 This activates XIM when XIM becomes available. */
208 IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data)
210 struct device *d = (struct device *)client_data;
213 XIMCallback ximcallback;
216 /* if no xim is presented, initialize xim ... */
217 if ( xim_initted == False )
220 XtGetApplicationNameAndClass (dpy, &name, &class);
221 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
223 /* destroy callback for im */
224 ximcallback.callback = IMDestroyCallback;
225 ximcallback.client_data = (XPointer) d;
226 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL);
229 /* activate XIC on all the X frames... */
230 DEVICE_FRAME_LOOP (tail, d)
232 struct frame *target_frame = XFRAME (XCAR (tail));
233 if (FRAME_X_P (target_frame) && !FRAME_X_XIC (target_frame))
235 XIM_init_frame (target_frame);
240 #endif /* if THIS_IS_X11R6 */
242 /* Initialize XIM for X device.
243 Register the use of XIM using XRegisterIMInstantiateCallback. */
245 XIM_init_device (struct device *d)
248 DEVICE_X_XIM (d) = NULL;
249 XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL,
250 IMInstantiateCallback, (XPointer) d);
253 Display *dpy = DEVICE_X_DISPLAY (d);
257 XtGetApplicationNameAndClass (dpy, &name, &class);
258 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
261 xim_warn ("XOpenIM() failed...no input server available\n");
266 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL);
277 /* Callback for the deleting frame. */
279 XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data)
281 struct frame *f = (struct frame *) client_data;
282 struct device *d = XDEVICE (FRAME_DEVICE (f));
284 if (DEVICE_X_XIM (d))
288 XDestroyIC (FRAME_X_XIC (f));
289 FRAME_X_XIC (f) = NULL;
295 /* Initialize XIC for new frame.
296 Create an X input context (XIC) for this frame. */
298 XIM_init_frame (struct frame *f)
300 struct device *d = XDEVICE (FRAME_DEVICE (f));
302 Widget w = FRAME_X_TEXT_WIDGET (f);
303 Window win = XtWindow (w);
304 XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1};
307 XVaNestedList p_list, s_list;
319 #define res(name, class, representation, field, default_value) \
320 { name, class, representation, sizeof(xic_vars.field), \
321 XtOffsetOf(xic_vars_t, field), XtRString, default_value }
323 static XtResource resources[] =
325 /* name class represent'n field default value */
327 res(XtNinputMethod, XtCInputMethod, XtRString, inputmethod, (XtPointer) NULL),
329 res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, (XtPointer) DefaultXIMStyles),
330 res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, (XtPointer) XtDefaultFontSet),
331 res(XtNximForeground, XtCForeground, XtRPixel, fg, (XtPointer) XtDefaultForeground),
332 res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground)
336 xim = DEVICE_X_XIM (d);
340 xim_info ("X Input Method open failed. Waiting for an XIM to be enabled.\n");
344 w = FRAME_X_TEXT_WIDGET (f);
349 if (FRAME_X_XIC (f)) return;
350 XtGetApplicationResources (w, &xic_vars,
351 resources, XtNumber (resources),
353 if (!xic_vars.fontset)
355 xim_warn ("Can't get fontset resource for Input Method\n");
356 FRAME_X_XIC (f) = NULL;
361 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES(d), NULL);
362 FRAME_X_XIC_STYLE (f) = style =
363 best_style (&xic_vars.styles, (XIMStyles *)DEVICE_X_XIM_STYLES(d));
365 p_list = XVaCreateNestedList (0,
367 XNSpotLocation, &spot,
368 XNForeground, xic_vars.fg,
369 XNBackground, xic_vars.bg,
370 XNFontSet, xic_vars.fontset,
373 s_list = XVaCreateNestedList (0,
375 XNForeground, xic_vars.fg,
376 XNBackground, xic_vars.bg,
377 XNFontSet, xic_vars.fontset,
380 FRAME_X_XIC (f) = xic =
385 XNPreeditAttributes, p_list,
386 XNStatusAttributes, s_list,
393 xim_warn ("Warning: XCreateIC failed.\n");
397 if (style & XIMPreeditPosition)
399 XPoint *frame_spot = &(FRAME_X_XIC_SPOT(f));
400 frame_spot->x = frame_spot->y = -1;
408 /* when frame is going to be destroyed (closed) */
409 XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback,
410 XIM_delete_frame, (XtPointer)f);
416 XIM_SetGeometry (struct frame *f)
418 XIC xic = FRAME_X_XIC (f);
419 XIMStyle style = FRAME_X_XIC_STYLE (f);
425 if (style & XIMStatusArea)
427 /* Place Status Area in bottom right corner */
428 /* Negotiate geometry of status area */
429 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */
432 /* If input method has existing status area, use its current size */
433 /* The following at least works for Sun's htt */
434 area.x = area.y = area.width = area.height = 0;
435 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area);
436 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed);
437 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
438 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed);
440 area.width = needed->width;
441 area.height = needed->height;
442 area.x = FRAME_RIGHT_BORDER_START (f) - area.width;
443 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height;
446 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n",
447 area.x, area.y, area.width, area.height);
448 #endif /* DEBUG_XIM */
450 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area);
453 if (style & XIMPreeditPosition)
455 /* Set Preedit Area to whole frame size (sans border) */
456 /* We include the border because Preedit window might be larger
457 than display line at edge. #### FIX: we should adjust to make
458 sure that there is always room for the spot sub-window */
459 area.x = FRAME_LEFT_BORDER_START (f);
460 area.y = FRAME_TOP_BORDER_START (f);
461 area.width = FRAME_RIGHT_BORDER_END (f) - area.x;
462 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y;
463 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area);
472 XIM_SetSpotLocation (struct frame *f, int x, int y)
474 XIC xic = FRAME_X_XIC (f);
475 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
477 /* Only care if we have a valid XIC using Over the Spot in
478 * a different location */
480 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) ||
481 (spot->x == (short) x &&
482 spot->y == (short) y))
488 /* ### FIX: Must make sure spot fits within Preedit Area */
489 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
491 stderr_out ("Spot: %d %d\n", spot->x, spot->y);
496 XIM_focus_event (struct frame *f, int in_p)
498 if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */)
499 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
503 #define XIM_Composed_Text_BUFSIZE 64
504 typedef struct XIM_Composed_Text
507 wchar_t data [XIM_Composed_Text_BUFSIZE];
510 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}};
513 /* get_XIM_input -- Process results of input method composition.
515 This function copies the results of the input method composition to
516 composed_input_buf. Then for each character, a custom event of type
517 wc_atom is sent with the character as its data.
519 It is probably more efficient to copy the composition results to some
520 allocated memory and send a single event pointing to that memory.
521 That would cut down on the event processing as well as allow quick
522 insertion into the buffer of the whole string. It might require some
523 care, though, to avoid fragmenting memory through the allocation and
524 freeing of many small chunks. Maybe the existing system for
525 (single-byte) string allocation can be used, multiplying the length by
526 sizeof (wchar_t) to get the right size.
529 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy)
535 XClientMessageEvent new_event;
538 len = XwcLookupString (ic, x_key_event, composed_input_buf.data,
539 composed_input_buf.size, &keysym, &status);
542 case XBufferOverflow:
543 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */
551 new_event.type = ClientMessage;
552 new_event.display = x_key_event->display;
553 new_event.window = x_key_event->window;
554 new_event.message_type = wc_atom;
555 new_event.format = 32; /* 32-bit wide data */
556 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L;
557 new_event.data.l[0] = x_key_event->time;
558 for (i = 0; i < len; i++)
560 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i];
561 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event);
566 /* ============================================================== */
567 /* X input method style determination */
568 /* ============================================================== */
571 #define done(type, value) \
572 if (toVal->addr != NULL) { \
573 if (toVal->size < sizeof(type)) { \
574 toVal->size = sizeof(type); \
577 *(type*)toVal->addr = (value); \
579 static type static_val; \
580 static_val = (value); \
581 toVal->addr = (XPointer)&static_val; \
583 toVal->size = sizeof(type); \
584 return True /* Caller supplies `;' */
588 * This is a standard Xt type converter, except that the caller MUST
589 * supply a proper non-NULL toVal XIMStyles structure that we will
592 * fromVal points to a string like
594 "XIMPreeditPosition|XIMStatusArea,
595 XIMPreeditPosition|XIMStatusNothing
596 XIMPreeditNothing|XIMStatusNothing"
598 * This is converted in the obvious way to a XIMStyles structure.
600 * mrb: #### Fix this to handle Motif-style specifications for
601 * XIMStyles as well: overTheSpot, rootWindow, none */
603 /* XtTypeConverter */
605 EmacsXtCvtStringToXIMStyles (
611 XtPointer *converter_data)
613 #define STYLE_INFO(style) { style, #style, sizeof(#style) }
614 static struct XIMStyleInfo
616 CONST XIMStyle style;
617 CONST char * CONST name;
619 } emacs_XIMStyleInfo[] = {
620 STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
621 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
622 STYLE_INFO (XIMPreeditPosition|XIMStatusNone),
623 STYLE_INFO (XIMPreeditNothing|XIMStatusArea),
624 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing),
625 STYLE_INFO (XIMPreeditNothing|XIMStatusNone),
626 STYLE_INFO (XIMPreeditNone|XIMStatusArea),
627 STYLE_INFO (XIMPreeditNone|XIMStatusNothing),
628 STYLE_INFO (XIMPreeditNone|XIMStatusNone)
632 char *s = (char *) fromVal->addr;
633 char *end = s + fromVal->size;
634 XIMStyles * CONST p = (XIMStyles *) toVal->addr;
635 CONST char * CONST delimiter = " \t\n\r:;," ;
636 CONST int max_styles = XtNumber(emacs_XIMStyleInfo);
641 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n",
642 fromVal->size, (char *) fromVal->addr);
643 #endif /* DEBUG_XIM */
647 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
648 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
650 "String to XIMStyle conversion requires exactly 0 parameters",
651 (String *)NULL, (Cardinal *)NULL);
656 /* Make sure caller is giving us good data */
657 assert (fromVal->addr != NULL);
658 assert (fromVal->size == strlen(fromVal->addr)+1);
659 assert (toVal->addr != NULL);
660 assert (toVal->size == sizeof(XIMStyles));
661 #endif /* DEBUG_XEMACS */
664 p->supported_styles = xnew_array (XIMStyle, max_styles);
667 * The following routine assumes that the style name resource is
668 * identical with the programmatic name of style. For example,
669 * "XIMPreeditPosition|XIMStatusArea" means the
670 * XIMPreeditPosition|XIMStatusArea value is specified. If the
671 * style name is changed, such as "OverTheSpot|imDisplaysInClient",
672 * the parsing logic below should be modified as well. */
674 if ((c = strtok(s, delimiter)) == NULL)
679 for(i=0 ; i<max_styles ; i++)
681 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i;
682 if(!strncmp(c, rec->name, rec->namelen - 1)) {
683 p->supported_styles[p->count_styles] = rec->style;
688 if((c = strtok(NULL, delimiter)) == NULL) {
693 if (p->count_styles == 0)
694 { /* No valid styles? */
695 char *buf = (char *)alloca (strlen (fromVal->addr)
696 + strlen (DefaultXIMStyles)
699 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
701 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n"
702 "Using default string \"%s\" instead.\n",
703 fromVal->addr, DefaultXIMStyles);
704 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
706 buf, (String *)NULL, (Cardinal *)NULL);
707 new_from.addr = DefaultXIMStyles;
708 new_from.size = sizeof(DefaultXIMStyles);
709 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args,
710 &new_from, toVal, converter_data);
712 XREALLOC_ARRAY (p->supported_styles, XIMStyle, p->count_styles);
713 *converter_data = (char *) True;
722 XtPointer converter_data,
727 stderr_out ("Converter data: %x\n", converter_data);
728 stderr_out ("EmacsFreeXIMStyles called\n");
729 #endif /* DEBUG_XIM */
733 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError",
734 "Freeing an XIMStyles requires that zero arguments be passwd",
735 (String *)NULL, (Cardinal *)NULL);
741 Boolean free_p = (Boolean) (int) converter_data;
742 XIMStyles *styles = (XIMStyles *) toVal->addr;
744 XFree ( styles->supported_styles );
749 /* O'Reilly XLib Programming Manual, pg. 371 */
750 /* Much nicer implementation than O'Reilly */
751 /* Choose the more `complicated', hence nicer, XIM input style */
753 BetterStyle (XIMStyle s, XIMStyle t)
755 #define CHECK_XIMStyle_BIT(bit) \
756 if ((s ^ t) & bit) { return (s & bit) ? s : t; }
758 CHECK_XIMStyle_BIT (XIMPreeditCallbacks);
759 CHECK_XIMStyle_BIT (XIMPreeditPosition);
760 CHECK_XIMStyle_BIT (XIMPreeditArea);
761 CHECK_XIMStyle_BIT (XIMPreeditNothing);
762 CHECK_XIMStyle_BIT (XIMStatusCallbacks);
763 CHECK_XIMStyle_BIT (XIMStatusArea);
764 CHECK_XIMStyle_BIT (XIMStatusNothing);
765 #undef CHECK_XIMStyle_BIT
770 /* Choose the best style, given:
771 * - user preferences (already checked to be supported by XEmacs)
772 * - styles supported by the input method */
773 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing)
775 best_style (XIMStyles *user, XIMStyles *xim)
778 for (i=0 ; i<user->count_styles ; i++)
780 for (j=0 ; j<xim->count_styles ; j++)
782 if (user->supported_styles[i] == xim->supported_styles[j])
783 return user->supported_styles[i];
786 return DEFAULTStyle; /* Default Style */
789 /* These lisp-callable functions will be sealed until xim-leim is needed.
790 Oct 22 1999 - kazz */
793 * External callable function for XIM
795 DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /*
796 Open the XIC on the frame if XIM is available.
797 Commonly, use this as \(x-open-xim \(selected-frame)).
798 If the frame is not on X device, return signal.
799 If XIC is created successfully return t. If not return nil.
805 CHECK_LIVE_FRAME (frame);
808 return signal_simple_error ("This frame is not on X device", frame);
811 return FRAME_X_XIC (f) ? Qt : Qnil;
814 DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /*
815 Close the XIC on the frame if it exists.
816 Commonly, use this as \(x-close-xim \(selected-frame)).
817 If the frame is not on X device, return signal.
818 Otherwise, it destroys the XIC if it exists, then returns t anyway.
825 CHECK_LIVE_FRAME (frame);
828 return signal_simple_error ("This frame is not on X device", frame);
830 d = XDEVICE (FRAME_DEVICE (f));
831 if (DEVICE_X_XIM (d)) {
832 /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */
833 FRAME_X_XIC (XFRAME (f)) = NULL;
840 syms_of_input_method_xlib (void)
842 defsymbol (&Qxim_xlib, "xim-xlib");
843 #if 0 /* see above */
844 DEFSUBR (Fx_open_xim);
845 DEFSUBR (Fx_close_xim);
850 vars_of_input_method_xlib (void)
852 Fprovide (intern ("xim"));
856 /* ====================================================================== */
857 /* Internal Debugging Routines */
858 /* ====================================================================== */
862 describe_XIM (XIM xim)
866 /* Print locale of XIM */
867 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim));
869 /* List supported input method styles */
870 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
872 stderr_out ("\n%d input style(s) supported by input method.\n",
873 styles->count_styles);
878 for (i=0; i < styles->count_styles; i++)
879 describe_XIMStyle (styles->supported_styles[i]);
881 #endif /* DEBUG_XIM */
886 describe_XFontSet (XFontSet fontset)
888 XFontStruct **font_struct_list;
889 char **font_name_list;
894 stderr_out ("NULL\n");
898 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list);
899 stderr_out ( "%d font(s) available:\n", count);
900 for (i=0 ; i < count ; i++)
901 stderr_out ("Font: %s\n", *(font_name_list+i));
905 describe_Status (Status status)
907 #define DESCRIBE_STATUS(value) \
908 if (status == value) stderr_out ("Status: " #value "\n")
910 DESCRIBE_STATUS (XBufferOverflow);
911 DESCRIBE_STATUS (XLookupNone);
912 DESCRIBE_STATUS (XLookupKeySym);
913 DESCRIBE_STATUS (XLookupBoth);
914 DESCRIBE_STATUS (XLookupChars);
915 #undef DESCRIBE_STATUS
919 describe_Window (Window win)
922 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2",
923 (int) win, (int) win);
928 describe_XIC (XIC xic)
931 Window client_win=0, focus_win=0;
932 char *resourceName = NULL;
933 char *resourceClass = NULL;
934 char *bad_arg = NULL;
935 unsigned long filter_mask = NoEventMask;
936 XVaNestedList p_list, s_list;
937 XFontSet p_fontset = NULL, s_fontset = NULL;
938 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0;
939 XRectangle *p_area = NULL, *s_area = NULL;
940 XRectangle *p_needed = NULL, *s_needed = NULL;
941 XPoint *p_spot = NULL;
943 /* Check for valid input context and method */
945 stderr_out ("Input method is NULL\n");
948 stderr_out ("XIMOfIC() returns NULL\n");
950 /* Print out Input Context Attributes */
951 p_list = XVaCreateNestedList (0,
952 XNFontSet, &p_fontset,
954 XNAreaNeeded, &p_needed,
955 XNSpotLocation, &p_spot,
960 s_list = XVaCreateNestedList (0,
961 XNFontSet, &s_fontset,
963 XNAreaNeeded, &s_needed,
968 bad_arg = XGetICValues(xic,
969 XNInputStyle, &style,
970 XNFilterEvents, &filter_mask,
971 XNClientWindow, &client_win,
972 XNFocusWindow, &focus_win,
973 XNResourceName, &resourceName,
974 XNResourceClass, &resourceClass,
975 XNPreeditAttributes, p_list,
976 XNStatusAttributes, s_list,
982 stderr_out ("Couldn't get IC value: %s\n", bad_arg);
984 stderr_out ("\nInput method context attributes:\n");
985 stderr_out ("Style: "); describe_XIMStyle (style);
986 stderr_out ("Client window: %lx\n", (unsigned long int)client_win);
987 stderr_out ("Focus window: %lx\n", (unsigned long int)focus_win);
988 stderr_out ("Preedit:\n");
989 describe_XRectangle (" Area", p_area);
990 describe_XRectangle (" Area needed", p_needed);
991 stderr_out (" foreground: %lx\n", (unsigned long int)p_fg);
992 stderr_out (" background: %lx\n", (unsigned long int)p_bg);
993 stderr_out (" fontset: "); describe_XFontSet (p_fontset);
994 stderr_out ("Status:\n");
995 describe_XRectangle (" Area", s_area);
996 describe_XRectangle (" Area needed", s_needed);
997 stderr_out (" foreground: %lx\n", (unsigned long int)s_fg);
998 stderr_out (" background: %lx\n", (unsigned long int)s_bg);
999 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset);
1000 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL");
1001 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL");
1002 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask);
1006 describe_XRectangle (char *name, XRectangle *r)
1009 stderr_out ("%s: NULL\n", name);
1011 stderr_out ("%s: x=%d y=%d w=%d h=%d\n",
1012 name, r->x, r->y, r->width, r->height);
1015 /* Print out elements of Event mask */
1016 /* Defines from X11/X.h */
1018 describe_event_mask (unsigned long mask)
1020 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ")
1021 DESCRIBE_EVENT_MASK (NoEventMask);
1022 DESCRIBE_EVENT_MASK (KeyPressMask);
1023 DESCRIBE_EVENT_MASK (KeyReleaseMask);
1024 DESCRIBE_EVENT_MASK (ButtonPressMask);
1025 DESCRIBE_EVENT_MASK (ButtonReleaseMask);
1026 DESCRIBE_EVENT_MASK (EnterWindowMask);
1027 DESCRIBE_EVENT_MASK (LeaveWindowMask);
1028 DESCRIBE_EVENT_MASK (PointerMotionMask);
1029 DESCRIBE_EVENT_MASK (PointerMotionHintMask);
1030 DESCRIBE_EVENT_MASK (Button1MotionMask);
1031 DESCRIBE_EVENT_MASK (Button2MotionMask);
1032 DESCRIBE_EVENT_MASK (Button3MotionMask);
1033 DESCRIBE_EVENT_MASK (Button4MotionMask);
1034 DESCRIBE_EVENT_MASK (Button5MotionMask);
1035 DESCRIBE_EVENT_MASK (ButtonMotionMask);
1036 DESCRIBE_EVENT_MASK (KeymapStateMask);
1037 DESCRIBE_EVENT_MASK (ExposureMask);
1038 DESCRIBE_EVENT_MASK (VisibilityChangeMask);
1039 DESCRIBE_EVENT_MASK (StructureNotifyMask);
1040 DESCRIBE_EVENT_MASK (ResizeRedirectMask);
1041 DESCRIBE_EVENT_MASK (SubstructureNotifyMask);
1042 DESCRIBE_EVENT_MASK (SubstructureRedirectMask);
1043 DESCRIBE_EVENT_MASK (FocusChangeMask);
1044 DESCRIBE_EVENT_MASK (PropertyChangeMask);
1045 DESCRIBE_EVENT_MASK (ColormapChangeMask);
1046 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask);
1047 #undef DESCRIBE_EVENT_MASK
1052 describe_XIMStyle (XIMStyle style)
1054 #define DESCRIBE_STYLE(bit) \
1056 stderr_out (#bit " ");
1058 DESCRIBE_STYLE (XIMPreeditArea);
1059 DESCRIBE_STYLE (XIMPreeditCallbacks);
1060 DESCRIBE_STYLE (XIMPreeditPosition);
1061 DESCRIBE_STYLE (XIMPreeditNothing);
1062 DESCRIBE_STYLE (XIMPreeditNone);
1063 DESCRIBE_STYLE (XIMStatusArea);
1064 DESCRIBE_STYLE (XIMStatusCallbacks);
1065 DESCRIBE_STYLE (XIMStatusNothing);
1066 DESCRIBE_STYLE (XIMStatusNone);
1067 #undef DESCRIBE_STYLE
1072 describe_XIMStyles (XIMStyles *p)
1075 stderr_out ("%d Style(s):\n", p->count_styles);
1076 for (i=0; i<p->count_styles ; i++)
1078 describe_XIMStyle (p->supported_styles[i]);
1082 #endif /* DEBUG_XEMACS */
1084 /* Random cruft follows */
1088 Unit_Test (struct frame *f, char * s)
1089 /* mrb unit testing */
1091 XrmValue fromVal, toVal;
1094 fromVal.size = strlen (s);
1095 toVal.addr = (XtPointer) &user_preferred_XIMStyles;
1096 toVal.size = sizeof (XIMStyles);
1098 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal,
1099 XtRXimStyles, &toVal) != False)
1101 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr);
1102 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size);
1103 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr);
1104 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size);
1105 describe_XIMStyles ((XIMStyles *) toVal.addr);
1111 /* Get a fontset for IM to use */
1113 x_init_fontset (struct device *d)
1115 Display *dpy = DEVICE_X_DISPLAY (d);
1117 char ** missing_charsets;
1118 int num_missing_charsets;
1119 char * default_string;
1120 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/
1121 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" ;
1123 DEVICE_X_FONTSET (d) = fontset =
1124 XCreateFontSet (dpy,
1127 &num_missing_charsets,
1130 if (fontset == NULL)
1132 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string);
1135 if (num_missing_charsets > 0)
1138 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string);
1139 for (i=0; i < num_missing_charsets; i++)
1141 stderr_out ("%s\n", missing_charsets[i]);
1143 XFreeStringList (missing_charsets);
1144 stderr_out ("Default string: %s\n", default_string);
1148 describe_XFontSet (fontset);