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);
130 Initialize_Locale (void)
134 /* dverna - Nov. 98: #### DON'T DO THIS !!! The default XtLanguageProc
135 routine calls setlocale(LC_ALL, lang) which fucks up our lower-level
136 locale management, and especially the value of LC_NUMERIC. Anyway, since
137 at this point, we don't know yet whether we're gonna need an X11 frame,
138 we should really do it manually and not use Xlib's dumb default routine */
139 /*XtSetLanguageProc (NULL, (XtLanguageProc) NULL, NULL);*/
140 if ((locale = setlocale (LC_ALL, "")) == NULL)
142 xim_warn ("Can't set locale.\n"
143 "Using C locale instead.\n");
146 if ((locale = setlocale (LC_ALL, "C")) == NULL)
148 xim_warn ("Can't even set locale to `C'!\n");
153 if (!XSupportsLocale ())
155 xim_warn1 ("X Windows does not support locale `%s'\n"
156 "Using C Locale instead\n", locale);
159 if ((locale = setlocale (LC_ALL, "C")) == NULL)
161 xim_warn ("Can't even set locale to `C'!\n");
164 if (!XSupportsLocale ())
166 xim_warn ("X Windows does not even support locale `C'!\n");
171 setlocale(LC_NUMERIC, "C");
173 if (XSetLocaleModifiers ("") == NULL)
175 xim_warn ("XSetLocaleModifiers(\"\") failed\n"
176 "Check the value of the XMODIFIERS environment variable.\n");
180 #ifdef THIS_IS_X11R6 /* Callbacks for IM are supported from X11R6 or later. */
181 /* Called from when XIM is destroying.
182 Clear all the XIC when the XIM was destroying... */
184 IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data)
186 struct device *d = (struct device *)client_data;
189 DEVICE_FRAME_LOOP (tail, d)
191 struct frame *target_frame = XFRAME (XCAR (tail));
192 if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame))
194 /* XDestroyIC (FRAME_X_XIC (target_frame)); */
195 FRAME_X_XIC (target_frame) = NULL;
199 DEVICE_X_XIM (d) = NULL;
204 /* This is registered in XIM_init_device (when DEVICE is initializing).
205 This activates XIM when XIM becomes available. */
207 IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data)
209 struct device *d = (struct device *)client_data;
212 XIMCallback ximcallback;
215 /* if no xim is presented, initialize xim ... */
216 if ( xim_initted == False )
219 XtGetApplicationNameAndClass (dpy, &name, &class);
220 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
222 /* destroy callback for im */
223 ximcallback.callback = IMDestroyCallback;
224 ximcallback.client_data = (XPointer) d;
225 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL);
228 /* activate XIC on all the X frames... */
229 DEVICE_FRAME_LOOP (tail, d)
231 struct frame *target_frame = XFRAME (XCAR (tail));
232 if (FRAME_X_P (target_frame) && !FRAME_X_XIC (target_frame))
234 XIM_init_frame (target_frame);
239 #endif /* if THIS_IS_X11R6 */
241 /* Initialize XIM for X device.
242 Register the use of XIM using XRegisterIMInstantiateCallback. */
244 XIM_init_device (struct device *d)
247 DEVICE_X_XIM (d) = NULL;
248 XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL,
249 IMInstantiateCallback, (XPointer) d);
252 Display *dpy = DEVICE_X_DISPLAY (d);
256 XtGetApplicationNameAndClass (dpy, &name, &class);
257 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
260 xim_warn ("XOpenIM() failed...no input server available\n");
265 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL);
276 /* Callback for the deleting frame. */
278 XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data)
280 struct frame *f = (struct frame *) client_data;
281 struct device *d = XDEVICE (FRAME_DEVICE (f));
283 if (DEVICE_X_XIM (d))
287 XDestroyIC (FRAME_X_XIC (f));
288 FRAME_X_XIC (f) = NULL;
294 /* Initialize XIC for new frame.
295 Create an X input context (XIC) for this frame. */
297 XIM_init_frame (struct frame *f)
299 struct device *d = XDEVICE (FRAME_DEVICE (f));
301 Widget w = FRAME_X_TEXT_WIDGET (f);
302 Window win = XtWindow (w);
303 XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1};
306 XVaNestedList p_list, s_list;
318 #define res(name, class, representation, field, default_value) \
319 { name, class, representation, sizeof(xic_vars.field), \
320 XtOffsetOf(xic_vars_t, field), XtRString, default_value }
322 static XtResource resources[] =
324 /* name class represent'n field default value */
325 res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, (XtPointer) DefaultXIMStyles),
326 res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, (XtPointer) XtDefaultFontSet),
327 res(XtNximForeground, XtCForeground, XtRPixel, fg, (XtPointer) XtDefaultForeground),
328 res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground)
332 xim = DEVICE_X_XIM (d);
339 w = FRAME_X_TEXT_WIDGET (f);
344 if (FRAME_X_XIC (f)) return;
345 XtGetApplicationResources (w, &xic_vars,
346 resources, XtNumber (resources),
348 if (!xic_vars.fontset)
350 xim_warn ("Can't get fontset resource for Input Method\n");
351 FRAME_X_XIC (f) = NULL;
356 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES(d), NULL);
357 FRAME_X_XIC_STYLE (f) = style =
358 best_style (&xic_vars.styles, (XIMStyles *)DEVICE_X_XIM_STYLES(d));
360 p_list = XVaCreateNestedList (0,
362 XNSpotLocation, &spot,
363 XNForeground, xic_vars.fg,
364 XNBackground, xic_vars.bg,
365 XNFontSet, xic_vars.fontset,
368 s_list = XVaCreateNestedList (0,
370 XNForeground, xic_vars.fg,
371 XNBackground, xic_vars.bg,
372 XNFontSet, xic_vars.fontset,
375 FRAME_X_XIC (f) = xic =
380 XNPreeditAttributes, p_list,
381 XNStatusAttributes, s_list,
388 xim_warn ("Warning: XCreateIC failed.\n");
392 if (style & XIMPreeditPosition)
394 XPoint *frame_spot = &(FRAME_X_XIC_SPOT(f));
395 frame_spot->x = frame_spot->y = -1;
403 /* when frame is going to be destroyed (closed) */
404 XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback,
405 XIM_delete_frame, (XtPointer)f);
411 XIM_SetGeometry (struct frame *f)
413 XIC xic = FRAME_X_XIC (f);
414 XIMStyle style = FRAME_X_XIC_STYLE (f);
420 if (style & XIMStatusArea)
422 /* Place Status Area in bottom right corner */
423 /* Negotiate geometry of status area */
424 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */
427 /* If input method has existing status area, use its current size */
428 /* The following at least works for Sun's htt */
429 area.x = area.y = area.width = area.height = 0;
430 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area);
431 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed);
432 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
433 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed);
435 area.width = needed->width;
436 area.height = needed->height;
437 area.x = FRAME_RIGHT_BORDER_START (f) - area.width;
438 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height;
441 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n",
442 area.x, area.y, area.width, area.height);
443 #endif /* DEBUG_XIM */
445 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area);
448 if (style & XIMPreeditPosition)
450 /* Set Preedit Area to whole frame size (sans border) */
451 /* We include the border because Preedit window might be larger
452 than display line at edge. #### FIX: we should adjust to make
453 sure that there is always room for the spot sub-window */
454 area.x = FRAME_LEFT_BORDER_START (f);
455 area.y = FRAME_TOP_BORDER_START (f);
456 area.width = FRAME_RIGHT_BORDER_END (f) - area.x;
457 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y;
458 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area);
467 XIM_SetSpotLocation (struct frame *f, int x, int y)
469 XIC xic = FRAME_X_XIC (f);
470 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
472 /* Only care if we have a valid XIC using Over the Spot in
473 * a different location */
475 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) ||
476 (spot->x == (short) x &&
477 spot->y == (short) y))
483 /* #### FIX: Must make sure spot fits within Preedit Area */
484 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
486 stderr_out ("Spot: %d %d\n", spot->x, spot->y);
491 XIM_focus_event (struct frame *f, int in_p)
493 if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */)
494 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
498 #define XIM_Composed_Text_BUFSIZE 64
499 typedef struct XIM_Composed_Text
502 wchar_t data [XIM_Composed_Text_BUFSIZE];
505 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}};
508 /* get_XIM_input -- Process results of input method composition.
510 This function copies the results of the input method composition to
511 composed_input_buf. Then for each character, a custom event of type
512 wc_atom is sent with the character as its data.
514 It is probably more efficient to copy the composition results to some
515 allocated memory and send a single event pointing to that memory.
516 That would cut down on the event processing as well as allow quick
517 insertion into the buffer of the whole string. It might require some
518 care, though, to avoid fragmenting memory through the allocation and
519 freeing of many small chunks. Maybe the existing system for
520 (single-byte) string allocation can be used, multiplying the length by
521 sizeof (wchar_t) to get the right size.
524 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy)
530 XClientMessageEvent new_event;
533 len = XwcLookupString (ic, x_key_event, composed_input_buf.data,
534 composed_input_buf.size, &keysym, &status);
537 case XBufferOverflow:
538 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */
546 new_event.type = ClientMessage;
547 new_event.display = x_key_event->display;
548 new_event.window = x_key_event->window;
549 new_event.message_type = wc_atom;
550 new_event.format = 32; /* 32-bit wide data */
551 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L;
552 new_event.data.l[0] = x_key_event->time;
553 for (i = 0; i < len; i++)
555 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i];
556 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event);
561 /* ============================================================== */
562 /* X input method style determination */
563 /* ============================================================== */
566 #define done(type, value) \
567 if (toVal->addr != NULL) { \
568 if (toVal->size < sizeof(type)) { \
569 toVal->size = sizeof(type); \
572 *(type*)toVal->addr = (value); \
574 static type static_val; \
575 static_val = (value); \
576 toVal->addr = (XPointer)&static_val; \
578 toVal->size = sizeof(type); \
579 return True /* Caller supplies `;' */
583 * This is a standard Xt type converter, except that the caller MUST
584 * supply a proper non-NULL toVal XIMStyles structure that we will
587 * fromVal points to a string like
589 "XIMPreeditPosition|XIMStatusArea,
590 XIMPreeditPosition|XIMStatusNothing
591 XIMPreeditNothing|XIMStatusNothing"
593 * This is converted in the obvious way to a XIMStyles structure.
595 * mrb: #### Fix this to handle Motif-style specifications for
596 * XIMStyles as well: overTheSpot, rootWindow, none */
598 /* XtTypeConverter */
600 EmacsXtCvtStringToXIMStyles (
606 XtPointer *converter_data)
608 #define STYLE_INFO(style) { style, #style, sizeof(#style) }
609 static struct XIMStyleInfo
611 const XIMStyle style;
612 const char * const name;
614 } emacs_XIMStyleInfo[] = {
615 STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
616 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
617 STYLE_INFO (XIMPreeditPosition|XIMStatusNone),
618 STYLE_INFO (XIMPreeditNothing|XIMStatusArea),
619 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing),
620 STYLE_INFO (XIMPreeditNothing|XIMStatusNone),
621 STYLE_INFO (XIMPreeditNone|XIMStatusArea),
622 STYLE_INFO (XIMPreeditNone|XIMStatusNothing),
623 STYLE_INFO (XIMPreeditNone|XIMStatusNone)
627 char *s = (char *) fromVal->addr;
628 char *end = s + fromVal->size;
629 XIMStyles * const p = (XIMStyles *) toVal->addr;
630 const char * const delimiter = " \t\n\r:;," ;
631 const int max_styles = XtNumber(emacs_XIMStyleInfo);
636 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n",
637 fromVal->size, (char *) fromVal->addr);
638 #endif /* DEBUG_XIM */
642 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
643 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
645 "String to XIMStyle conversion requires exactly 0 parameters",
646 (String *)NULL, (Cardinal *)NULL);
651 /* Make sure caller is giving us good data */
652 assert (fromVal->addr != NULL);
653 assert (fromVal->size == strlen(fromVal->addr)+1);
654 assert (toVal->addr != NULL);
655 assert (toVal->size == sizeof(XIMStyles));
656 #endif /* DEBUG_XEMACS */
659 p->supported_styles = xnew_array (XIMStyle, max_styles);
662 * The following routine assumes that the style name resource is
663 * identical with the programmatic name of style. For example,
664 * "XIMPreeditPosition|XIMStatusArea" means the
665 * XIMPreeditPosition|XIMStatusArea value is specified. If the
666 * style name is changed, such as "OverTheSpot|imDisplaysInClient",
667 * the parsing logic below should be modified as well. */
669 if ((c = strtok(s, delimiter)) == NULL)
674 for(i=0 ; i<max_styles ; i++)
676 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i;
677 if(!strncmp(c, rec->name, rec->namelen - 1)) {
678 p->supported_styles[p->count_styles] = rec->style;
683 if((c = strtok(NULL, delimiter)) == NULL) {
688 if (p->count_styles == 0)
689 { /* No valid styles? */
690 char *buf = (char *)alloca (strlen (fromVal->addr)
691 + strlen (DefaultXIMStyles)
694 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
696 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n"
697 "Using default string \"%s\" instead.\n",
698 fromVal->addr, DefaultXIMStyles);
699 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
701 buf, (String *)NULL, (Cardinal *)NULL);
702 new_from.addr = DefaultXIMStyles;
703 new_from.size = sizeof(DefaultXIMStyles);
704 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args,
705 &new_from, toVal, converter_data);
707 XREALLOC_ARRAY (p->supported_styles, XIMStyle, p->count_styles);
708 *converter_data = (char *) True;
717 XtPointer converter_data,
722 stderr_out ("Converter data: %x\n", converter_data);
723 stderr_out ("EmacsFreeXIMStyles called\n");
724 #endif /* DEBUG_XIM */
728 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError",
729 "Freeing an XIMStyles requires that zero arguments be passwd",
730 (String *)NULL, (Cardinal *)NULL);
736 Boolean free_p = (Boolean) (int) converter_data;
737 XIMStyles *styles = (XIMStyles *) toVal->addr;
739 XFree ( styles->supported_styles );
744 /* O'Reilly XLib Programming Manual, pg. 371 */
745 /* Much nicer implementation than O'Reilly */
746 /* Choose the more `complicated', hence nicer, XIM input style */
748 BetterStyle (XIMStyle s, XIMStyle t)
750 #define CHECK_XIMStyle_BIT(bit) \
751 if ((s ^ t) & bit) { return (s & bit) ? s : t; }
753 CHECK_XIMStyle_BIT (XIMPreeditCallbacks);
754 CHECK_XIMStyle_BIT (XIMPreeditPosition);
755 CHECK_XIMStyle_BIT (XIMPreeditArea);
756 CHECK_XIMStyle_BIT (XIMPreeditNothing);
757 CHECK_XIMStyle_BIT (XIMStatusCallbacks);
758 CHECK_XIMStyle_BIT (XIMStatusArea);
759 CHECK_XIMStyle_BIT (XIMStatusNothing);
760 #undef CHECK_XIMStyle_BIT
765 /* Choose the best style, given:
766 * - user preferences (already checked to be supported by XEmacs)
767 * - styles supported by the input method */
768 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing)
770 best_style (XIMStyles *user, XIMStyles *xim)
773 for (i=0 ; i<user->count_styles ; i++)
775 for (j=0 ; j<xim->count_styles ; j++)
777 if (user->supported_styles[i] == xim->supported_styles[j])
778 return user->supported_styles[i];
781 return DEFAULTStyle; /* Default Style */
784 /* These lisp-callable functions will be sealed until xim-leim is needed.
785 Oct 22 1999 - kazz */
788 * External callable function for XIM
790 DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /*
791 Open the XIC on the frame if XIM is available.
792 Commonly, use this as \(x-open-xim \(selected-frame)).
793 If the frame is not on X device, return signal.
794 If XIC is created successfully return t. If not return nil.
800 CHECK_LIVE_FRAME (frame);
803 return signal_simple_error ("This frame is not on X device", frame);
806 return FRAME_X_XIC (f) ? Qt : Qnil;
809 DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /*
810 Close the XIC on the frame if it exists.
811 Commonly, use this as \(x-close-xim \(selected-frame)).
812 If the frame is not on X device, return signal.
813 Otherwise, it destroys the XIC if it exists, then returns t anyway.
820 CHECK_LIVE_FRAME (frame);
823 return signal_simple_error ("This frame is not on X device", frame);
825 d = XDEVICE (FRAME_DEVICE (f));
826 if (DEVICE_X_XIM (d)) {
827 /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */
828 FRAME_X_XIC (XFRAME (f)) = NULL;
835 syms_of_input_method_xlib (void)
837 defsymbol (&Qxim_xlib, "xim-xlib");
838 #if 0 /* see above */
839 DEFSUBR (Fx_open_xim);
840 DEFSUBR (Fx_close_xim);
845 vars_of_input_method_xlib (void)
847 Fprovide (intern ("xim"));
851 /* ====================================================================== */
852 /* Internal Debugging Routines */
853 /* ====================================================================== */
857 describe_XIM (XIM xim)
861 /* Print locale of XIM */
862 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim));
864 /* List supported input method styles */
865 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
867 stderr_out ("\n%d input style(s) supported by input method.\n",
868 styles->count_styles);
873 for (i=0; i < styles->count_styles; i++)
874 describe_XIMStyle (styles->supported_styles[i]);
876 #endif /* DEBUG_XIM */
881 describe_XFontSet (XFontSet fontset)
883 XFontStruct **font_struct_list;
884 char **font_name_list;
889 stderr_out ("NULL\n");
893 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list);
894 stderr_out ( "%d font(s) available:\n", count);
895 for (i=0 ; i < count ; i++)
896 stderr_out ("Font: %s\n", *(font_name_list+i));
900 describe_Status (Status status)
902 #define DESCRIBE_STATUS(value) \
903 if (status == value) stderr_out ("Status: " #value "\n")
905 DESCRIBE_STATUS (XBufferOverflow);
906 DESCRIBE_STATUS (XLookupNone);
907 DESCRIBE_STATUS (XLookupKeySym);
908 DESCRIBE_STATUS (XLookupBoth);
909 DESCRIBE_STATUS (XLookupChars);
910 #undef DESCRIBE_STATUS
914 describe_Window (Window win)
917 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2",
918 (int) win, (int) win);
923 describe_XIC (XIC xic)
926 Window client_win=0, focus_win=0;
927 char *resourceName = NULL;
928 char *resourceClass = NULL;
929 char *bad_arg = NULL;
930 unsigned long filter_mask = NoEventMask;
931 XVaNestedList p_list, s_list;
932 XFontSet p_fontset = NULL, s_fontset = NULL;
933 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0;
934 XRectangle *p_area = NULL, *s_area = NULL;
935 XRectangle *p_needed = NULL, *s_needed = NULL;
936 XPoint *p_spot = NULL;
938 /* Check for valid input context and method */
940 stderr_out ("Input method is NULL\n");
943 stderr_out ("XIMOfIC() returns NULL\n");
945 /* Print out Input Context Attributes */
946 p_list = XVaCreateNestedList (0,
947 XNFontSet, &p_fontset,
949 XNAreaNeeded, &p_needed,
950 XNSpotLocation, &p_spot,
955 s_list = XVaCreateNestedList (0,
956 XNFontSet, &s_fontset,
958 XNAreaNeeded, &s_needed,
963 bad_arg = XGetICValues(xic,
964 XNInputStyle, &style,
965 XNFilterEvents, &filter_mask,
966 XNClientWindow, &client_win,
967 XNFocusWindow, &focus_win,
968 XNResourceName, &resourceName,
969 XNResourceClass, &resourceClass,
970 XNPreeditAttributes, p_list,
971 XNStatusAttributes, s_list,
977 stderr_out ("Couldn't get IC value: %s\n", bad_arg);
979 stderr_out ("\nInput method context attributes:\n");
980 stderr_out ("Style: "); describe_XIMStyle (style);
981 stderr_out ("Client window: %lx\n", (unsigned long int)client_win);
982 stderr_out ("Focus window: %lx\n", (unsigned long int)focus_win);
983 stderr_out ("Preedit:\n");
984 describe_XRectangle (" Area", p_area);
985 describe_XRectangle (" Area needed", p_needed);
986 stderr_out (" foreground: %lx\n", (unsigned long int)p_fg);
987 stderr_out (" background: %lx\n", (unsigned long int)p_bg);
988 stderr_out (" fontset: "); describe_XFontSet (p_fontset);
989 stderr_out ("Status:\n");
990 describe_XRectangle (" Area", s_area);
991 describe_XRectangle (" Area needed", s_needed);
992 stderr_out (" foreground: %lx\n", (unsigned long int)s_fg);
993 stderr_out (" background: %lx\n", (unsigned long int)s_bg);
994 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset);
995 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL");
996 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL");
997 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask);
1001 describe_XRectangle (char *name, XRectangle *r)
1004 stderr_out ("%s: NULL\n", name);
1006 stderr_out ("%s: x=%d y=%d w=%d h=%d\n",
1007 name, r->x, r->y, r->width, r->height);
1010 /* Print out elements of Event mask */
1011 /* Defines from X11/X.h */
1013 describe_event_mask (unsigned long mask)
1015 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ")
1016 DESCRIBE_EVENT_MASK (NoEventMask);
1017 DESCRIBE_EVENT_MASK (KeyPressMask);
1018 DESCRIBE_EVENT_MASK (KeyReleaseMask);
1019 DESCRIBE_EVENT_MASK (ButtonPressMask);
1020 DESCRIBE_EVENT_MASK (ButtonReleaseMask);
1021 DESCRIBE_EVENT_MASK (EnterWindowMask);
1022 DESCRIBE_EVENT_MASK (LeaveWindowMask);
1023 DESCRIBE_EVENT_MASK (PointerMotionMask);
1024 DESCRIBE_EVENT_MASK (PointerMotionHintMask);
1025 DESCRIBE_EVENT_MASK (Button1MotionMask);
1026 DESCRIBE_EVENT_MASK (Button2MotionMask);
1027 DESCRIBE_EVENT_MASK (Button3MotionMask);
1028 DESCRIBE_EVENT_MASK (Button4MotionMask);
1029 DESCRIBE_EVENT_MASK (Button5MotionMask);
1030 DESCRIBE_EVENT_MASK (ButtonMotionMask);
1031 DESCRIBE_EVENT_MASK (KeymapStateMask);
1032 DESCRIBE_EVENT_MASK (ExposureMask);
1033 DESCRIBE_EVENT_MASK (VisibilityChangeMask);
1034 DESCRIBE_EVENT_MASK (StructureNotifyMask);
1035 DESCRIBE_EVENT_MASK (ResizeRedirectMask);
1036 DESCRIBE_EVENT_MASK (SubstructureNotifyMask);
1037 DESCRIBE_EVENT_MASK (SubstructureRedirectMask);
1038 DESCRIBE_EVENT_MASK (FocusChangeMask);
1039 DESCRIBE_EVENT_MASK (PropertyChangeMask);
1040 DESCRIBE_EVENT_MASK (ColormapChangeMask);
1041 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask);
1042 #undef DESCRIBE_EVENT_MASK
1047 describe_XIMStyle (XIMStyle style)
1049 #define DESCRIBE_STYLE(bit) \
1051 stderr_out (#bit " ");
1053 DESCRIBE_STYLE (XIMPreeditArea);
1054 DESCRIBE_STYLE (XIMPreeditCallbacks);
1055 DESCRIBE_STYLE (XIMPreeditPosition);
1056 DESCRIBE_STYLE (XIMPreeditNothing);
1057 DESCRIBE_STYLE (XIMPreeditNone);
1058 DESCRIBE_STYLE (XIMStatusArea);
1059 DESCRIBE_STYLE (XIMStatusCallbacks);
1060 DESCRIBE_STYLE (XIMStatusNothing);
1061 DESCRIBE_STYLE (XIMStatusNone);
1062 #undef DESCRIBE_STYLE
1067 describe_XIMStyles (XIMStyles *p)
1070 stderr_out ("%d Style(s):\n", p->count_styles);
1071 for (i=0; i<p->count_styles ; i++)
1073 describe_XIMStyle (p->supported_styles[i]);
1077 #endif /* DEBUG_XEMACS */
1079 /* Random cruft follows */
1083 Unit_Test (struct frame *f, char * s)
1084 /* mrb unit testing */
1086 XrmValue fromVal, toVal;
1089 fromVal.size = strlen (s);
1090 toVal.addr = (XtPointer) &user_preferred_XIMStyles;
1091 toVal.size = sizeof (XIMStyles);
1093 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal,
1094 XtRXimStyles, &toVal) != False)
1096 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr);
1097 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size);
1098 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr);
1099 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size);
1100 describe_XIMStyles ((XIMStyles *) toVal.addr);
1106 /* Get a fontset for IM to use */
1108 x_init_fontset (struct device *d)
1110 Display *dpy = DEVICE_X_DISPLAY (d);
1112 char ** missing_charsets;
1113 int num_missing_charsets;
1114 char * default_string;
1115 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/
1116 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" ;
1118 DEVICE_X_FONTSET (d) = fontset =
1119 XCreateFontSet (dpy,
1122 &num_missing_charsets,
1125 if (fontset == NULL)
1127 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string);
1130 if (num_missing_charsets > 0)
1133 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string);
1134 for (i=0; i < num_missing_charsets; i++)
1136 stderr_out ("%s\n", missing_charsets[i]);
1138 XFreeStringList (missing_charsets);
1139 stderr_out ("Default string: %s\n", default_string);
1143 describe_XFontSet (fontset);