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 goes 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 don'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> ? */
79 #include "console-x.h"
80 #include "EmacsFrame.h"
83 #if !defined (XIM_XLIB) && !defined (USE_XFONTSET)
84 #error neither XIM_XLIB nor USE_XFONTSET is defined??
87 Lisp_Object Qxim_xlib;
88 #define xim_warn(str) warn_when_safe (Qxim_xlib, Qwarning, str);
89 #define xim_warn1(fmt, str) warn_when_safe (Qxim_xlib, Qwarning, fmt, str);
90 #define xim_info(str) warn_when_safe (Qxim_xlib, Qinfo, str);
92 #ifdef XIM_XLIB /* XIM_XLIB specific */
93 /* Get/Set IC values for just one attribute */
95 #define XIC_Value(Get_Set, xic, name, attr, value) \
98 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
99 if ((bad_arg = X##Get_Set##ICValues (xic, name, list, NULL)) != NULL) \
100 stderr_out ("X" #Get_Set "ICValues " "bad Arg: %s\n", bad_arg); \
103 #else /* ! DEBUG_XEMACS */
104 #define XIC_Value(Get_Set, xic, name, attr, value) \
106 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
107 X##Get_Set##ICValues (xic, name, list, NULL); \
110 #endif /* DEBUG_XEMACS */
112 static char DefaultXIMStyles[] =
113 "XIMPreeditPosition|XIMStatusArea\n"
114 "XIMPreeditPosition|XIMStatusNone\n"
115 "XIMPreeditPosition|XIMStatusNothing\n"
116 "XIMPreeditNothing|XIMStatusArea\n"
117 "XIMPreeditNothing|XIMStatusNothing\n"
118 "XIMPreeditNothing|XIMStatusNone\n"
119 "XIMPreeditNone|XIMStatusArea\n"
120 "XIMPreeditNone|XIMStatusNothing\n"
121 "XIMPreeditNone|XIMStatusNone";
123 static XIMStyle best_style (XIMStyles *user, XIMStyles *xim);
124 #endif /* XIM_XLIB only */
126 /* This function is documented, but no prototype in the header files */
127 EXTERN_C char * XSetIMValues(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 XIM_XLIB /* starting XIM specific codes */
182 /* Callbacks for IM are supported from X11R6 or later. */
183 #ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK
185 static Boolean xim_initted = False;
187 /* Called from when XIM is destroying.
188 Clear all the XIC when the XIM was destroying... */
190 IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data)
192 struct device *d = (struct device *)client_data;
195 DEVICE_FRAME_LOOP (tail, d)
197 struct frame *target_frame = XFRAME (XCAR (tail));
198 if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame))
200 /* XDestroyIC (FRAME_X_XIC (target_frame)); */
201 FRAME_X_XIC (target_frame) = NULL;
205 DEVICE_X_XIM (d) = NULL;
210 /* This is registered in XIM_init_device (when DEVICE is initializing).
211 This activates XIM when XIM becomes available. */
213 IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data)
215 struct device *d = (struct device *)client_data;
218 XIMCallback ximcallback;
221 /* if no xim is presented, initialize xim ... */
222 if ( xim_initted == False )
225 XtGetApplicationNameAndClass (dpy, &name, &class);
226 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
228 /* destroy callback for im */
229 ximcallback.callback = (XIMProc) IMDestroyCallback;
230 ximcallback.client_data = (XPointer) d;
231 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL);
234 /* activate XIC on all the X frames... */
235 DEVICE_FRAME_LOOP (tail, d)
237 struct frame *target_frame = XFRAME (XCAR (tail));
238 if (FRAME_X_P (target_frame) && !FRAME_X_XIC (target_frame))
240 XIM_init_frame (target_frame);
245 #endif /* HAVE_XREGISTERIMINSTANTIATECALLBACK */
247 /* Initialize XIM for X device.
248 Register the use of XIM using XRegisterIMInstantiateCallback. */
250 XIM_init_device (struct device *d)
252 #ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK /* X11R6+ */
253 DEVICE_X_XIM (d) = NULL;
254 XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL,
255 #ifdef XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE
256 /* The sixth parameter is of type
257 XPointer in XFree86 but (XPointer *)
258 on most other X11's. */
259 (XIDProc) IMInstantiateCallback,
261 #else /* X Consortium prototype */
262 (XIMProc) IMInstantiateCallback,
264 #endif /* XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE */
267 #else /* pre-X11R6 */
268 Display *dpy = DEVICE_X_DISPLAY (d);
272 XtGetApplicationNameAndClass (dpy, &name, &class);
273 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
276 xim_warn ("XOpenIM() failed...no input server available\n");
281 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL);
284 #endif /* HAVE_XREGISTERIMINSTANTIATECALLBACK */
292 /* Callback for the deleting frame. */
294 XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data)
296 struct frame *f = (struct frame *) client_data;
297 struct device *d = XDEVICE (FRAME_DEVICE (f));
299 if (DEVICE_X_XIM (d))
303 XDestroyIC (FRAME_X_XIC (f));
304 FRAME_X_XIC (f) = NULL;
310 /* Initialize XIC for new frame.
311 Create an X input context (XIC) for this frame. */
313 XIM_init_frame (struct frame *f)
315 struct device *d = XDEVICE (FRAME_DEVICE (f));
317 Widget w = FRAME_X_TEXT_WIDGET (f);
318 Window win = XtWindow (w);
319 XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1};
322 XVaNestedList p_list, s_list;
334 #define res(name, class, representation, field, default_value) \
335 { name, class, representation, sizeof(xic_vars.field), \
336 XtOffsetOf(xic_vars_t, field), XtRString, default_value }
338 static XtResource resources[] =
340 /* name class represent'n field default value */
341 res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, (XtPointer) DefaultXIMStyles),
342 res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, (XtPointer) XtDefaultFontSet),
343 res(XtNximForeground, XtCForeground, XtRPixel, fg, (XtPointer) XtDefaultForeground),
344 res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground)
348 xim = DEVICE_X_XIM (d);
355 w = FRAME_X_TEXT_WIDGET (f);
360 if (FRAME_X_XIC (f)) return;
361 XtGetApplicationResources (w, &xic_vars,
362 resources, XtNumber (resources),
364 if (!xic_vars.fontset)
366 xim_warn ("Can't get fontset resource for Input Method\n");
367 FRAME_X_XIC (f) = NULL;
372 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES(d), NULL);
373 FRAME_X_XIC_STYLE (f) = style =
374 best_style (&xic_vars.styles, (XIMStyles *)DEVICE_X_XIM_STYLES(d));
376 p_list = XVaCreateNestedList (0,
378 XNSpotLocation, &spot,
379 XNForeground, xic_vars.fg,
380 XNBackground, xic_vars.bg,
381 XNFontSet, xic_vars.fontset,
384 s_list = XVaCreateNestedList (0,
386 XNForeground, xic_vars.fg,
387 XNBackground, xic_vars.bg,
388 XNFontSet, xic_vars.fontset,
391 FRAME_X_XIC (f) = xic =
396 XNPreeditAttributes, p_list,
397 XNStatusAttributes, s_list,
404 xim_warn ("Warning: XCreateIC failed.\n");
408 if (style & XIMPreeditPosition)
410 XPoint *frame_spot = &(FRAME_X_XIC_SPOT(f));
411 frame_spot->x = frame_spot->y = -1;
418 #ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK
419 /* when frame is going to be destroyed (closed) */
420 XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback,
421 XIM_delete_frame, (XtPointer)f);
427 XIM_SetGeometry (struct frame *f)
436 xic = FRAME_X_XIC (f);
440 style = FRAME_X_XIC_STYLE (f);
441 if (style & XIMStatusArea)
443 /* Place Status Area in bottom right corner */
444 /* Negotiate geometry of status area */
445 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */
448 /* If input method has existing status area, use its current size */
449 /* The following at least works for Sun's htt */
450 area.x = area.y = area.width = area.height = 0;
451 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area);
452 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed);
453 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
454 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed);
456 area.width = needed->width;
457 area.height = needed->height;
458 area.x = FRAME_RIGHT_BORDER_START (f) - area.width;
459 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height;
462 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n",
463 area.x, area.y, area.width, area.height);
464 #endif /* DEBUG_XIM */
466 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area);
469 if (style & XIMPreeditPosition)
471 /* Set Preedit Area to whole frame size (sans border) */
472 /* We include the border because Preedit window might be larger
473 than display line at edge. #### FIX: we should adjust to make
474 sure that there is always room for the spot sub-window */
475 area.x = FRAME_LEFT_BORDER_START (f);
476 area.y = FRAME_TOP_BORDER_START (f);
477 area.width = FRAME_RIGHT_BORDER_END (f) - area.x;
478 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y;
479 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area);
488 XIM_SetSpotLocation (struct frame *f, int x, int y)
490 XIC xic = FRAME_X_XIC (f);
491 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
493 /* Only care if we have a valid XIC using Over the Spot in
494 * a different location */
496 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) ||
497 (spot->x == (short) x &&
498 spot->y == (short) y))
504 /* #### FIX: Must make sure spot fits within Preedit Area */
505 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
507 stderr_out ("Spot: %d %d\n", spot->x, spot->y);
512 XIM_focus_event (struct frame *f, int in_p)
514 if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */)
515 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
519 #define XIM_Composed_Text_BUFSIZE 64
520 typedef struct XIM_Composed_Text
523 wchar_t data [XIM_Composed_Text_BUFSIZE];
526 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}};
529 /* get_XIM_input -- Process results of input method composition.
531 This function copies the results of the input method composition to
532 composed_input_buf. Then for each character, a custom event of type
533 wc_atom is sent with the character as its data.
535 It is probably more efficient to copy the composition results to some
536 allocated memory and send a single event pointing to that memory.
537 That would cut down on the event processing as well as allow quick
538 insertion into the buffer of the whole string. It might require some
539 care, though, to avoid fragmenting memory through the allocation and
540 freeing of many small chunks. Maybe the existing system for
541 (single-byte) string allocation can be used, multiplying the length by
542 sizeof (wchar_t) to get the right size.
545 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy)
551 XClientMessageEvent new_event;
554 len = XwcLookupString (ic, x_key_event, composed_input_buf.data,
555 composed_input_buf.size, &keysym, &status);
558 case XBufferOverflow:
559 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */
567 new_event.type = ClientMessage;
568 new_event.display = x_key_event->display;
569 new_event.window = x_key_event->window;
570 new_event.message_type = wc_atom;
571 new_event.format = 32; /* 32-bit wide data */
572 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L;
573 new_event.data.l[0] = x_key_event->time;
574 for (i = 0; i < len; i++)
576 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i];
577 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event);
582 /* ============================================================== */
583 /* X input method style determination */
584 /* ============================================================== */
587 #define done(type, value) \
588 if (toVal->addr != NULL) { \
589 if (toVal->size < sizeof(type)) { \
590 toVal->size = sizeof(type); \
593 *(type*)toVal->addr = (value); \
595 static type static_val; \
596 static_val = (value); \
597 toVal->addr = (XPointer)&static_val; \
599 toVal->size = sizeof(type); \
600 return True /* Caller supplies `;' */
604 * This is a standard Xt type converter, except that the caller MUST
605 * supply a proper non-NULL toVal XIMStyles structure that we will
608 * fromVal points to a string like
610 "XIMPreeditPosition|XIMStatusArea,
611 XIMPreeditPosition|XIMStatusNothing
612 XIMPreeditNothing|XIMStatusNothing"
614 * This is converted in the obvious way to a XIMStyles structure.
616 * mrb: #### Fix this to handle Motif-style specifications for
617 * XIMStyles as well: overTheSpot, rootWindow, none */
619 /* XtTypeConverter */
621 EmacsXtCvtStringToXIMStyles (
627 XtPointer *converter_data)
629 #define STYLE_INFO(style) { style, #style, sizeof(#style) }
630 static struct XIMStyleInfo
632 const XIMStyle style;
633 const char * const name;
635 } emacs_XIMStyleInfo[] = {
636 STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
637 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
638 STYLE_INFO (XIMPreeditPosition|XIMStatusNone),
639 STYLE_INFO (XIMPreeditNothing|XIMStatusArea),
640 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing),
641 STYLE_INFO (XIMPreeditNothing|XIMStatusNone),
642 STYLE_INFO (XIMPreeditNone|XIMStatusArea),
643 STYLE_INFO (XIMPreeditNone|XIMStatusNothing),
644 STYLE_INFO (XIMPreeditNone|XIMStatusNone)
648 char *s = (char *) fromVal->addr;
649 char *end = s + fromVal->size;
650 XIMStyles * const p = (XIMStyles *) toVal->addr;
651 const char * const delimiter = " \t\n\r:;," ;
652 const int max_styles = XtNumber(emacs_XIMStyleInfo);
657 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n",
658 fromVal->size, (char *) fromVal->addr);
659 #endif /* DEBUG_XIM */
663 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
664 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
666 "String to XIMStyle conversion requires exactly 0 parameters",
667 (String *)NULL, (Cardinal *)NULL);
672 /* Make sure caller is giving us good data */
673 assert (fromVal->addr != NULL);
674 assert (fromVal->size == strlen(fromVal->addr)+1);
675 assert (toVal->addr != NULL);
676 assert (toVal->size == sizeof(XIMStyles));
677 #endif /* DEBUG_XEMACS */
680 p->supported_styles = xnew_array (XIMStyle, max_styles);
683 * The following routine assumes that the style name resource is
684 * identical with the programmatic name of style. For example,
685 * "XIMPreeditPosition|XIMStatusArea" means the
686 * XIMPreeditPosition|XIMStatusArea value is specified. If the
687 * style name is changed, such as "OverTheSpot|imDisplaysInClient",
688 * the parsing logic below should be modified as well. */
690 if ((c = strtok(s, delimiter)) == NULL)
695 for(i=0 ; i<max_styles ; i++)
697 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i;
698 if(!strncmp(c, rec->name, rec->namelen - 1)) {
699 p->supported_styles[p->count_styles] = rec->style;
704 if((c = strtok(NULL, delimiter)) == NULL) {
709 if (p->count_styles == 0)
710 { /* No valid styles? */
711 char *buf = (char *)alloca (strlen (fromVal->addr)
712 + strlen (DefaultXIMStyles)
715 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
717 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n"
718 "Using default string \"%s\" instead.\n",
719 fromVal->addr, DefaultXIMStyles);
720 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
722 buf, (String *)NULL, (Cardinal *)NULL);
723 new_from.addr = DefaultXIMStyles;
724 new_from.size = sizeof(DefaultXIMStyles);
725 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args,
726 &new_from, toVal, converter_data);
728 XREALLOC_ARRAY (p->supported_styles, XIMStyle, p->count_styles);
729 *converter_data = (char *) True;
738 XtPointer converter_data,
743 stderr_out ("Converter data: %x\n", converter_data);
744 stderr_out ("EmacsFreeXIMStyles called\n");
745 #endif /* DEBUG_XIM */
749 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError",
750 "Freeing an XIMStyles requires that zero arguments be passwd",
751 (String *)NULL, (Cardinal *)NULL);
757 Boolean free_p = (Boolean) (int) converter_data;
758 XIMStyles *styles = (XIMStyles *) toVal->addr;
760 XFree ( styles->supported_styles );
765 /* O'Reilly XLib Programming Manual, pg. 371 */
766 /* Much nicer implementation than O'Reilly */
767 /* Choose the more `complicated', hence nicer, XIM input style */
769 BetterStyle (XIMStyle s, XIMStyle t)
771 #define CHECK_XIMStyle_BIT(bit) \
772 if ((s ^ t) & bit) { return (s & bit) ? s : t; }
774 CHECK_XIMStyle_BIT (XIMPreeditCallbacks);
775 CHECK_XIMStyle_BIT (XIMPreeditPosition);
776 CHECK_XIMStyle_BIT (XIMPreeditArea);
777 CHECK_XIMStyle_BIT (XIMPreeditNothing);
778 CHECK_XIMStyle_BIT (XIMStatusCallbacks);
779 CHECK_XIMStyle_BIT (XIMStatusArea);
780 CHECK_XIMStyle_BIT (XIMStatusNothing);
781 #undef CHECK_XIMStyle_BIT
786 /* Choose the best style, given:
787 * - user preferences (already checked to be supported by XEmacs)
788 * - styles supported by the input method */
789 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing)
791 best_style (XIMStyles *user, XIMStyles *xim)
794 for (i=0 ; i<user->count_styles ; i++)
796 for (j=0 ; j<xim->count_styles ; j++)
798 if (user->supported_styles[i] == xim->supported_styles[j])
799 return user->supported_styles[i];
802 return DEFAULTStyle; /* Default Style */
805 /* These lisp-callable functions will be sealed until xim-leim is needed.
806 Oct 22 1999 - kazz */
809 * External callable function for XIM
811 DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /*
812 Open the XIC on the frame if XIM is available.
813 Commonly, use this as \(x-open-xim \(selected-frame)).
814 If the frame is not on X device, return signal.
815 If XIC is created successfully return t. If not return nil.
821 CHECK_LIVE_FRAME (frame);
824 return signal_simple_error ("This frame is not on X device", frame);
827 return FRAME_X_XIC (f) ? Qt : Qnil;
830 DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /*
831 Close the XIC on the frame if it exists.
832 Commonly, use this as \(x-close-xim \(selected-frame)).
833 If the frame is not on X device, return signal.
834 Otherwise, it destroys the XIC if it exists, then returns t anyway.
841 CHECK_LIVE_FRAME (frame);
844 return signal_simple_error ("This frame is not on X device", frame);
846 d = XDEVICE (FRAME_DEVICE (f));
847 if (DEVICE_X_XIM (d)) {
848 /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */
849 FRAME_X_XIC (XFRAME (f)) = NULL;
856 syms_of_input_method_xlib (void)
858 defsymbol (&Qxim_xlib, "xim-xlib");
859 #if 0 /* see above */
860 DEFSUBR (Fx_open_xim);
861 DEFSUBR (Fx_close_xim);
866 vars_of_input_method_xlib (void)
868 Fprovide (intern ("xim"));
872 /* ====================================================================== */
873 /* Internal Debugging Routines */
874 /* ====================================================================== */
878 describe_XIM (XIM xim)
882 /* Print locale of XIM */
883 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim));
885 /* List supported input method styles */
886 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
888 stderr_out ("\n%d input style(s) supported by input method.\n",
889 styles->count_styles);
894 for (i=0; i < styles->count_styles; i++)
895 describe_XIMStyle (styles->supported_styles[i]);
897 #endif /* DEBUG_XIM */
902 describe_XFontSet (XFontSet fontset)
904 XFontStruct **font_struct_list;
905 char **font_name_list;
910 stderr_out ("NULL\n");
914 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list);
915 stderr_out ( "%d font(s) available:\n", count);
916 for (i=0 ; i < count ; i++)
917 stderr_out ("Font: %s\n", *(font_name_list+i));
921 describe_Status (Status status)
923 #define DESCRIBE_STATUS(value) \
924 if (status == value) stderr_out ("Status: " #value "\n")
926 DESCRIBE_STATUS (XBufferOverflow);
927 DESCRIBE_STATUS (XLookupNone);
928 DESCRIBE_STATUS (XLookupKeySym);
929 DESCRIBE_STATUS (XLookupBoth);
930 DESCRIBE_STATUS (XLookupChars);
931 #undef DESCRIBE_STATUS
935 describe_Window (Window win)
938 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2",
939 (int) win, (int) win);
944 describe_XIC (XIC xic)
947 Window client_win=0, focus_win=0;
948 char *resourceName = NULL;
949 char *resourceClass = NULL;
950 char *bad_arg = NULL;
951 unsigned long filter_mask = NoEventMask;
952 XVaNestedList p_list, s_list;
953 XFontSet p_fontset = NULL, s_fontset = NULL;
954 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0;
955 XRectangle *p_area = NULL, *s_area = NULL;
956 XRectangle *p_needed = NULL, *s_needed = NULL;
957 XPoint *p_spot = NULL;
959 /* Check for valid input context and method */
961 stderr_out ("Input method is NULL\n");
964 stderr_out ("XIMOfIC() returns NULL\n");
966 /* Print out Input Context Attributes */
967 p_list = XVaCreateNestedList (0,
968 XNFontSet, &p_fontset,
970 XNAreaNeeded, &p_needed,
971 XNSpotLocation, &p_spot,
976 s_list = XVaCreateNestedList (0,
977 XNFontSet, &s_fontset,
979 XNAreaNeeded, &s_needed,
984 bad_arg = XGetICValues(xic,
985 XNInputStyle, &style,
986 XNFilterEvents, &filter_mask,
987 XNClientWindow, &client_win,
988 XNFocusWindow, &focus_win,
989 XNResourceName, &resourceName,
990 XNResourceClass, &resourceClass,
991 XNPreeditAttributes, p_list,
992 XNStatusAttributes, s_list,
998 stderr_out ("Couldn't get IC value: %s\n", bad_arg);
1000 stderr_out ("\nInput method context attributes:\n");
1001 stderr_out ("Style: "); describe_XIMStyle (style);
1002 stderr_out ("Client window: %lx\n", (unsigned long int)client_win);
1003 stderr_out ("Focus window: %lx\n", (unsigned long int)focus_win);
1004 stderr_out ("Preedit:\n");
1005 describe_XRectangle (" Area", p_area);
1006 describe_XRectangle (" Area needed", p_needed);
1007 stderr_out (" foreground: %lx\n", (unsigned long int)p_fg);
1008 stderr_out (" background: %lx\n", (unsigned long int)p_bg);
1009 stderr_out (" fontset: "); describe_XFontSet (p_fontset);
1010 stderr_out ("Status:\n");
1011 describe_XRectangle (" Area", s_area);
1012 describe_XRectangle (" Area needed", s_needed);
1013 stderr_out (" foreground: %lx\n", (unsigned long int)s_fg);
1014 stderr_out (" background: %lx\n", (unsigned long int)s_bg);
1015 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset);
1016 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL");
1017 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL");
1018 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask);
1022 describe_XRectangle (char *name, XRectangle *r)
1025 stderr_out ("%s: NULL\n", name);
1027 stderr_out ("%s: x=%d y=%d w=%d h=%d\n",
1028 name, r->x, r->y, r->width, r->height);
1031 /* Print out elements of Event mask */
1032 /* Defines from X11/X.h */
1034 describe_event_mask (unsigned long mask)
1036 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ")
1037 DESCRIBE_EVENT_MASK (NoEventMask);
1038 DESCRIBE_EVENT_MASK (KeyPressMask);
1039 DESCRIBE_EVENT_MASK (KeyReleaseMask);
1040 DESCRIBE_EVENT_MASK (ButtonPressMask);
1041 DESCRIBE_EVENT_MASK (ButtonReleaseMask);
1042 DESCRIBE_EVENT_MASK (EnterWindowMask);
1043 DESCRIBE_EVENT_MASK (LeaveWindowMask);
1044 DESCRIBE_EVENT_MASK (PointerMotionMask);
1045 DESCRIBE_EVENT_MASK (PointerMotionHintMask);
1046 DESCRIBE_EVENT_MASK (Button1MotionMask);
1047 DESCRIBE_EVENT_MASK (Button2MotionMask);
1048 DESCRIBE_EVENT_MASK (Button3MotionMask);
1049 DESCRIBE_EVENT_MASK (Button4MotionMask);
1050 DESCRIBE_EVENT_MASK (Button5MotionMask);
1051 DESCRIBE_EVENT_MASK (ButtonMotionMask);
1052 DESCRIBE_EVENT_MASK (KeymapStateMask);
1053 DESCRIBE_EVENT_MASK (ExposureMask);
1054 DESCRIBE_EVENT_MASK (VisibilityChangeMask);
1055 DESCRIBE_EVENT_MASK (StructureNotifyMask);
1056 DESCRIBE_EVENT_MASK (ResizeRedirectMask);
1057 DESCRIBE_EVENT_MASK (SubstructureNotifyMask);
1058 DESCRIBE_EVENT_MASK (SubstructureRedirectMask);
1059 DESCRIBE_EVENT_MASK (FocusChangeMask);
1060 DESCRIBE_EVENT_MASK (PropertyChangeMask);
1061 DESCRIBE_EVENT_MASK (ColormapChangeMask);
1062 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask);
1063 #undef DESCRIBE_EVENT_MASK
1068 describe_XIMStyle (XIMStyle style)
1070 #define DESCRIBE_STYLE(bit) \
1072 stderr_out (#bit " ");
1074 DESCRIBE_STYLE (XIMPreeditArea);
1075 DESCRIBE_STYLE (XIMPreeditCallbacks);
1076 DESCRIBE_STYLE (XIMPreeditPosition);
1077 DESCRIBE_STYLE (XIMPreeditNothing);
1078 DESCRIBE_STYLE (XIMPreeditNone);
1079 DESCRIBE_STYLE (XIMStatusArea);
1080 DESCRIBE_STYLE (XIMStatusCallbacks);
1081 DESCRIBE_STYLE (XIMStatusNothing);
1082 DESCRIBE_STYLE (XIMStatusNone);
1083 #undef DESCRIBE_STYLE
1088 describe_XIMStyles (XIMStyles *p)
1091 stderr_out ("%d Style(s):\n", p->count_styles);
1092 for (i=0; i<p->count_styles ; i++)
1094 describe_XIMStyle (p->supported_styles[i]);
1098 #endif /* DEBUG_XEMACS */
1100 /* Random cruft follows */
1104 Unit_Test (struct frame *f, char * s)
1105 /* mrb unit testing */
1107 XrmValue fromVal, toVal;
1110 fromVal.size = strlen (s);
1111 toVal.addr = (XtPointer) &user_preferred_XIMStyles;
1112 toVal.size = sizeof (XIMStyles);
1114 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal,
1115 XtRXimStyles, &toVal) != False)
1117 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr);
1118 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size);
1119 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr);
1120 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size);
1121 describe_XIMStyles ((XIMStyles *) toVal.addr);
1125 #endif /* XIM_XLIB only */
1128 /* Get a fontset for IM to use */
1130 x_init_fontset (struct device *d)
1132 Display *dpy = DEVICE_X_DISPLAY (d);
1134 char ** missing_charsets;
1135 int num_missing_charsets;
1136 char * default_string;
1137 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/
1138 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" ;
1140 DEVICE_X_FONTSET (d) = fontset =
1141 XCreateFontSet (dpy,
1144 &num_missing_charsets,
1147 if (fontset == NULL)
1149 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string);
1152 if (num_missing_charsets > 0)
1155 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string);
1156 for (i=0; i < num_missing_charsets; i++)
1158 stderr_out ("%s\n", missing_charsets[i]);
1160 XFreeStringList (missing_charsets);
1161 stderr_out ("Default string: %s\n", default_string);
1165 describe_XFontSet (fontset);