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"
84 #error XIM_XLIB is not 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 /* Get/Set IC values for just one attribute */
94 #define XIC_Value(Get_Set, xic, name, attr, value) \
97 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
98 if ((bad_arg = X##Get_Set##ICValues (xic, name, list, NULL)) != NULL) \
99 stderr_out ("X" #Get_Set "ICValues " "bad Arg: %s\n", bad_arg); \
102 #else /* ! DEBUG_XEMACS */
103 #define XIC_Value(Get_Set, xic, name, attr, value) \
105 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
106 X##Get_Set##ICValues (xic, name, list, NULL); \
109 #endif /* DEBUG_XEMACS */
111 static char DefaultXIMStyles[] =
112 "XIMPreeditPosition|XIMStatusArea\n"
113 "XIMPreeditPosition|XIMStatusNone\n"
114 "XIMPreeditPosition|XIMStatusNothing\n"
115 "XIMPreeditNothing|XIMStatusArea\n"
116 "XIMPreeditNothing|XIMStatusNothing\n"
117 "XIMPreeditNothing|XIMStatusNone\n"
118 "XIMPreeditNone|XIMStatusArea\n"
119 "XIMPreeditNone|XIMStatusNothing\n"
120 "XIMPreeditNone|XIMStatusNone";
122 static XIMStyle best_style (XIMStyles *user, XIMStyles *xim);
124 /* This function is documented, but no prototype in the header files */
125 EXTERN_C char * XSetIMValues(XIM, ...);
128 Initialize_Locale (void)
132 /* dverna - Nov. 98: #### DON'T DO THIS !!! The default XtLanguageProc
133 routine calls setlocale(LC_ALL, lang) which fucks up our lower-level
134 locale management, and especially the value of LC_NUMERIC. Anyway, since
135 at this point, we don't know yet whether we're gonna need an X11 frame,
136 we should really do it manually and not use Xlib's dumb default routine */
137 /*XtSetLanguageProc (NULL, (XtLanguageProc) NULL, NULL);*/
138 if ((locale = setlocale (LC_ALL, "")) == NULL)
140 xim_warn ("Can't set locale.\n"
141 "Using C locale instead.\n");
144 if ((locale = setlocale (LC_ALL, "C")) == NULL)
146 xim_warn ("Can't even set locale to `C'!\n");
151 if (!XSupportsLocale ())
153 xim_warn1 ("X Windows does not support locale `%s'\n"
154 "Using C Locale instead\n", locale);
157 if ((locale = setlocale (LC_ALL, "C")) == NULL)
159 xim_warn ("Can't even set locale to `C'!\n");
162 if (!XSupportsLocale ())
164 xim_warn ("X Windows does not even support locale `C'!\n");
169 setlocale(LC_NUMERIC, "C");
171 if (XSetLocaleModifiers ("") == NULL)
173 xim_warn ("XSetLocaleModifiers(\"\") failed\n"
174 "Check the value of the XMODIFIERS environment variable.\n");
178 /* Callbacks for IM are supported from X11R6 or later. */
179 #ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK
181 static Boolean xim_initted = False;
183 /* Called from when XIM is destroying.
184 Clear all the XIC when the XIM was destroying... */
186 IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data)
188 struct device *d = (struct device *)client_data;
191 DEVICE_FRAME_LOOP (tail, d)
193 struct frame *target_frame = XFRAME (XCAR (tail));
194 if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame))
196 /* XDestroyIC (FRAME_X_XIC (target_frame)); */
197 FRAME_X_XIC (target_frame) = NULL;
201 DEVICE_X_XIM (d) = NULL;
206 /* This is registered in XIM_init_device (when DEVICE is initializing).
207 This activates XIM when XIM becomes available. */
209 IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data)
211 struct device *d = (struct device *)client_data;
214 XIMCallback ximcallback;
217 /* if no xim is presented, initialize xim ... */
218 if ( xim_initted == False )
221 XtGetApplicationNameAndClass (dpy, &name, &class);
222 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
224 /* destroy callback for im */
225 ximcallback.callback = (XIMProc) IMDestroyCallback;
226 ximcallback.client_data = (XPointer) d;
227 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL);
230 /* activate XIC on all the X frames... */
231 DEVICE_FRAME_LOOP (tail, d)
233 struct frame *target_frame = XFRAME (XCAR (tail));
234 if (FRAME_X_P (target_frame) && !FRAME_X_XIC (target_frame))
236 XIM_init_frame (target_frame);
241 #endif /* HAVE_XREGISTERIMINSTANTIATECALLBACK */
243 /* Initialize XIM for X device.
244 Register the use of XIM using XRegisterIMInstantiateCallback. */
246 XIM_init_device (struct device *d)
248 #ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK /* X11R6+ */
249 DEVICE_X_XIM (d) = NULL;
250 XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL,
251 #ifdef XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE
252 /* The sixth parameter is of type
253 XPointer in XFree86 but (XPointer *)
254 on most other X11's. */
255 (XIDProc) IMInstantiateCallback,
257 #else /* X Consortium prototype */
258 (XIMProc) IMInstantiateCallback,
260 #endif /* XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE */
263 #else /* pre-X11R6 */
264 Display *dpy = DEVICE_X_DISPLAY (d);
268 XtGetApplicationNameAndClass (dpy, &name, &class);
269 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
272 xim_warn ("XOpenIM() failed...no input server available\n");
277 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL);
280 #endif /* HAVE_XREGISTERIMINSTANTIATECALLBACK */
288 /* Callback for the deleting frame. */
290 XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data)
292 struct frame *f = (struct frame *) client_data;
293 struct device *d = XDEVICE (FRAME_DEVICE (f));
295 if (DEVICE_X_XIM (d))
299 XDestroyIC (FRAME_X_XIC (f));
300 FRAME_X_XIC (f) = NULL;
306 /* Initialize XIC for new frame.
307 Create an X input context (XIC) for this frame. */
309 XIM_init_frame (struct frame *f)
311 struct device *d = XDEVICE (FRAME_DEVICE (f));
313 Widget w = FRAME_X_TEXT_WIDGET (f);
314 Window win = XtWindow (w);
315 XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1};
318 XVaNestedList p_list, s_list;
330 #define res(name, class, representation, field, default_value) \
331 { name, class, representation, sizeof(xic_vars.field), \
332 XtOffsetOf(xic_vars_t, field), XtRString, default_value }
334 static XtResource resources[] =
336 /* name class represent'n field default value */
337 res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, (XtPointer) DefaultXIMStyles),
338 res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, (XtPointer) XtDefaultFontSet),
339 res(XtNximForeground, XtCForeground, XtRPixel, fg, (XtPointer) XtDefaultForeground),
340 res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground)
344 xim = DEVICE_X_XIM (d);
351 w = FRAME_X_TEXT_WIDGET (f);
356 if (FRAME_X_XIC (f)) return;
357 XtGetApplicationResources (w, &xic_vars,
358 resources, XtNumber (resources),
360 if (!xic_vars.fontset)
362 xim_warn ("Can't get fontset resource for Input Method\n");
363 FRAME_X_XIC (f) = NULL;
368 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES(d), NULL);
369 FRAME_X_XIC_STYLE (f) = style =
370 best_style (&xic_vars.styles, (XIMStyles *)DEVICE_X_XIM_STYLES(d));
372 p_list = XVaCreateNestedList (0,
374 XNSpotLocation, &spot,
375 XNForeground, xic_vars.fg,
376 XNBackground, xic_vars.bg,
377 XNFontSet, xic_vars.fontset,
380 s_list = XVaCreateNestedList (0,
382 XNForeground, xic_vars.fg,
383 XNBackground, xic_vars.bg,
384 XNFontSet, xic_vars.fontset,
387 FRAME_X_XIC (f) = xic =
392 XNPreeditAttributes, p_list,
393 XNStatusAttributes, s_list,
400 xim_warn ("Warning: XCreateIC failed.\n");
404 if (style & XIMPreeditPosition)
406 XPoint *frame_spot = &(FRAME_X_XIC_SPOT(f));
407 frame_spot->x = frame_spot->y = -1;
414 #ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK
415 /* when frame is going to be destroyed (closed) */
416 XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback,
417 XIM_delete_frame, (XtPointer)f);
423 XIM_SetGeometry (struct frame *f)
425 XIC xic = FRAME_X_XIC (f);
426 XIMStyle style = FRAME_X_XIC_STYLE (f);
432 if (style & XIMStatusArea)
434 /* Place Status Area in bottom right corner */
435 /* Negotiate geometry of status area */
436 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */
439 /* If input method has existing status area, use its current size */
440 /* The following at least works for Sun's htt */
441 area.x = area.y = area.width = area.height = 0;
442 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area);
443 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed);
444 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
445 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed);
447 area.width = needed->width;
448 area.height = needed->height;
449 area.x = FRAME_RIGHT_BORDER_START (f) - area.width;
450 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height;
453 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n",
454 area.x, area.y, area.width, area.height);
455 #endif /* DEBUG_XIM */
457 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area);
460 if (style & XIMPreeditPosition)
462 /* Set Preedit Area to whole frame size (sans border) */
463 /* We include the border because Preedit window might be larger
464 than display line at edge. #### FIX: we should adjust to make
465 sure that there is always room for the spot sub-window */
466 area.x = FRAME_LEFT_BORDER_START (f);
467 area.y = FRAME_TOP_BORDER_START (f);
468 area.width = FRAME_RIGHT_BORDER_END (f) - area.x;
469 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y;
470 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area);
479 XIM_SetSpotLocation (struct frame *f, int x, int y)
481 XIC xic = FRAME_X_XIC (f);
482 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
484 /* Only care if we have a valid XIC using Over the Spot in
485 * a different location */
487 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) ||
488 (spot->x == (short) x &&
489 spot->y == (short) y))
495 /* #### FIX: Must make sure spot fits within Preedit Area */
496 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
498 stderr_out ("Spot: %d %d\n", spot->x, spot->y);
503 XIM_focus_event (struct frame *f, int in_p)
505 if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */)
506 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
510 #define XIM_Composed_Text_BUFSIZE 64
511 typedef struct XIM_Composed_Text
514 wchar_t data [XIM_Composed_Text_BUFSIZE];
517 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}};
520 /* get_XIM_input -- Process results of input method composition.
522 This function copies the results of the input method composition to
523 composed_input_buf. Then for each character, a custom event of type
524 wc_atom is sent with the character as its data.
526 It is probably more efficient to copy the composition results to some
527 allocated memory and send a single event pointing to that memory.
528 That would cut down on the event processing as well as allow quick
529 insertion into the buffer of the whole string. It might require some
530 care, though, to avoid fragmenting memory through the allocation and
531 freeing of many small chunks. Maybe the existing system for
532 (single-byte) string allocation can be used, multiplying the length by
533 sizeof (wchar_t) to get the right size.
536 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy)
542 XClientMessageEvent new_event;
545 len = XwcLookupString (ic, x_key_event, composed_input_buf.data,
546 composed_input_buf.size, &keysym, &status);
549 case XBufferOverflow:
550 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */
558 new_event.type = ClientMessage;
559 new_event.display = x_key_event->display;
560 new_event.window = x_key_event->window;
561 new_event.message_type = wc_atom;
562 new_event.format = 32; /* 32-bit wide data */
563 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L;
564 new_event.data.l[0] = x_key_event->time;
565 for (i = 0; i < len; i++)
567 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i];
568 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event);
573 /* ============================================================== */
574 /* X input method style determination */
575 /* ============================================================== */
578 #define done(type, value) \
579 if (toVal->addr != NULL) { \
580 if (toVal->size < sizeof(type)) { \
581 toVal->size = sizeof(type); \
584 *(type*)toVal->addr = (value); \
586 static type static_val; \
587 static_val = (value); \
588 toVal->addr = (XPointer)&static_val; \
590 toVal->size = sizeof(type); \
591 return True /* Caller supplies `;' */
595 * This is a standard Xt type converter, except that the caller MUST
596 * supply a proper non-NULL toVal XIMStyles structure that we will
599 * fromVal points to a string like
601 "XIMPreeditPosition|XIMStatusArea,
602 XIMPreeditPosition|XIMStatusNothing
603 XIMPreeditNothing|XIMStatusNothing"
605 * This is converted in the obvious way to a XIMStyles structure.
607 * mrb: #### Fix this to handle Motif-style specifications for
608 * XIMStyles as well: overTheSpot, rootWindow, none */
610 /* XtTypeConverter */
612 EmacsXtCvtStringToXIMStyles (
618 XtPointer *converter_data)
620 #define STYLE_INFO(style) { style, #style, sizeof(#style) }
621 static struct XIMStyleInfo
623 const XIMStyle style;
624 const char * const name;
626 } emacs_XIMStyleInfo[] = {
627 STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
628 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
629 STYLE_INFO (XIMPreeditPosition|XIMStatusNone),
630 STYLE_INFO (XIMPreeditNothing|XIMStatusArea),
631 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing),
632 STYLE_INFO (XIMPreeditNothing|XIMStatusNone),
633 STYLE_INFO (XIMPreeditNone|XIMStatusArea),
634 STYLE_INFO (XIMPreeditNone|XIMStatusNothing),
635 STYLE_INFO (XIMPreeditNone|XIMStatusNone)
639 char *s = (char *) fromVal->addr;
640 char *end = s + fromVal->size;
641 XIMStyles * const p = (XIMStyles *) toVal->addr;
642 const char * const delimiter = " \t\n\r:;," ;
643 const int max_styles = XtNumber(emacs_XIMStyleInfo);
648 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n",
649 fromVal->size, (char *) fromVal->addr);
650 #endif /* DEBUG_XIM */
654 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
655 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
657 "String to XIMStyle conversion requires exactly 0 parameters",
658 (String *)NULL, (Cardinal *)NULL);
663 /* Make sure caller is giving us good data */
664 assert (fromVal->addr != NULL);
665 assert (fromVal->size == strlen(fromVal->addr)+1);
666 assert (toVal->addr != NULL);
667 assert (toVal->size == sizeof(XIMStyles));
668 #endif /* DEBUG_XEMACS */
671 p->supported_styles = xnew_array (XIMStyle, max_styles);
674 * The following routine assumes that the style name resource is
675 * identical with the programmatic name of style. For example,
676 * "XIMPreeditPosition|XIMStatusArea" means the
677 * XIMPreeditPosition|XIMStatusArea value is specified. If the
678 * style name is changed, such as "OverTheSpot|imDisplaysInClient",
679 * the parsing logic below should be modified as well. */
681 if ((c = strtok(s, delimiter)) == NULL)
686 for(i=0 ; i<max_styles ; i++)
688 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i;
689 if(!strncmp(c, rec->name, rec->namelen - 1)) {
690 p->supported_styles[p->count_styles] = rec->style;
695 if((c = strtok(NULL, delimiter)) == NULL) {
700 if (p->count_styles == 0)
701 { /* No valid styles? */
702 char *buf = (char *)alloca (strlen (fromVal->addr)
703 + strlen (DefaultXIMStyles)
706 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
708 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n"
709 "Using default string \"%s\" instead.\n",
710 fromVal->addr, DefaultXIMStyles);
711 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
713 buf, (String *)NULL, (Cardinal *)NULL);
714 new_from.addr = DefaultXIMStyles;
715 new_from.size = sizeof(DefaultXIMStyles);
716 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args,
717 &new_from, toVal, converter_data);
719 XREALLOC_ARRAY (p->supported_styles, XIMStyle, p->count_styles);
720 *converter_data = (char *) True;
729 XtPointer converter_data,
734 stderr_out ("Converter data: %x\n", converter_data);
735 stderr_out ("EmacsFreeXIMStyles called\n");
736 #endif /* DEBUG_XIM */
740 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError",
741 "Freeing an XIMStyles requires that zero arguments be passwd",
742 (String *)NULL, (Cardinal *)NULL);
748 Boolean free_p = (Boolean) (int) converter_data;
749 XIMStyles *styles = (XIMStyles *) toVal->addr;
751 XFree ( styles->supported_styles );
756 /* O'Reilly XLib Programming Manual, pg. 371 */
757 /* Much nicer implementation than O'Reilly */
758 /* Choose the more `complicated', hence nicer, XIM input style */
760 BetterStyle (XIMStyle s, XIMStyle t)
762 #define CHECK_XIMStyle_BIT(bit) \
763 if ((s ^ t) & bit) { return (s & bit) ? s : t; }
765 CHECK_XIMStyle_BIT (XIMPreeditCallbacks);
766 CHECK_XIMStyle_BIT (XIMPreeditPosition);
767 CHECK_XIMStyle_BIT (XIMPreeditArea);
768 CHECK_XIMStyle_BIT (XIMPreeditNothing);
769 CHECK_XIMStyle_BIT (XIMStatusCallbacks);
770 CHECK_XIMStyle_BIT (XIMStatusArea);
771 CHECK_XIMStyle_BIT (XIMStatusNothing);
772 #undef CHECK_XIMStyle_BIT
777 /* Choose the best style, given:
778 * - user preferences (already checked to be supported by XEmacs)
779 * - styles supported by the input method */
780 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing)
782 best_style (XIMStyles *user, XIMStyles *xim)
785 for (i=0 ; i<user->count_styles ; i++)
787 for (j=0 ; j<xim->count_styles ; j++)
789 if (user->supported_styles[i] == xim->supported_styles[j])
790 return user->supported_styles[i];
793 return DEFAULTStyle; /* Default Style */
796 /* These lisp-callable functions will be sealed until xim-leim is needed.
797 Oct 22 1999 - kazz */
800 * External callable function for XIM
802 DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /*
803 Open the XIC on the frame if XIM is available.
804 Commonly, use this as \(x-open-xim \(selected-frame)).
805 If the frame is not on X device, return signal.
806 If XIC is created successfully return t. If not return nil.
812 CHECK_LIVE_FRAME (frame);
815 return signal_simple_error ("This frame is not on X device", frame);
818 return FRAME_X_XIC (f) ? Qt : Qnil;
821 DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /*
822 Close the XIC on the frame if it exists.
823 Commonly, use this as \(x-close-xim \(selected-frame)).
824 If the frame is not on X device, return signal.
825 Otherwise, it destroys the XIC if it exists, then returns t anyway.
832 CHECK_LIVE_FRAME (frame);
835 return signal_simple_error ("This frame is not on X device", frame);
837 d = XDEVICE (FRAME_DEVICE (f));
838 if (DEVICE_X_XIM (d)) {
839 /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */
840 FRAME_X_XIC (XFRAME (f)) = NULL;
847 syms_of_input_method_xlib (void)
849 defsymbol (&Qxim_xlib, "xim-xlib");
850 #if 0 /* see above */
851 DEFSUBR (Fx_open_xim);
852 DEFSUBR (Fx_close_xim);
857 vars_of_input_method_xlib (void)
859 Fprovide (intern ("xim"));
863 /* ====================================================================== */
864 /* Internal Debugging Routines */
865 /* ====================================================================== */
869 describe_XIM (XIM xim)
873 /* Print locale of XIM */
874 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim));
876 /* List supported input method styles */
877 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
879 stderr_out ("\n%d input style(s) supported by input method.\n",
880 styles->count_styles);
885 for (i=0; i < styles->count_styles; i++)
886 describe_XIMStyle (styles->supported_styles[i]);
888 #endif /* DEBUG_XIM */
893 describe_XFontSet (XFontSet fontset)
895 XFontStruct **font_struct_list;
896 char **font_name_list;
901 stderr_out ("NULL\n");
905 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list);
906 stderr_out ( "%d font(s) available:\n", count);
907 for (i=0 ; i < count ; i++)
908 stderr_out ("Font: %s\n", *(font_name_list+i));
912 describe_Status (Status status)
914 #define DESCRIBE_STATUS(value) \
915 if (status == value) stderr_out ("Status: " #value "\n")
917 DESCRIBE_STATUS (XBufferOverflow);
918 DESCRIBE_STATUS (XLookupNone);
919 DESCRIBE_STATUS (XLookupKeySym);
920 DESCRIBE_STATUS (XLookupBoth);
921 DESCRIBE_STATUS (XLookupChars);
922 #undef DESCRIBE_STATUS
926 describe_Window (Window win)
929 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2",
930 (int) win, (int) win);
935 describe_XIC (XIC xic)
938 Window client_win=0, focus_win=0;
939 char *resourceName = NULL;
940 char *resourceClass = NULL;
941 char *bad_arg = NULL;
942 unsigned long filter_mask = NoEventMask;
943 XVaNestedList p_list, s_list;
944 XFontSet p_fontset = NULL, s_fontset = NULL;
945 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0;
946 XRectangle *p_area = NULL, *s_area = NULL;
947 XRectangle *p_needed = NULL, *s_needed = NULL;
948 XPoint *p_spot = NULL;
950 /* Check for valid input context and method */
952 stderr_out ("Input method is NULL\n");
955 stderr_out ("XIMOfIC() returns NULL\n");
957 /* Print out Input Context Attributes */
958 p_list = XVaCreateNestedList (0,
959 XNFontSet, &p_fontset,
961 XNAreaNeeded, &p_needed,
962 XNSpotLocation, &p_spot,
967 s_list = XVaCreateNestedList (0,
968 XNFontSet, &s_fontset,
970 XNAreaNeeded, &s_needed,
975 bad_arg = XGetICValues(xic,
976 XNInputStyle, &style,
977 XNFilterEvents, &filter_mask,
978 XNClientWindow, &client_win,
979 XNFocusWindow, &focus_win,
980 XNResourceName, &resourceName,
981 XNResourceClass, &resourceClass,
982 XNPreeditAttributes, p_list,
983 XNStatusAttributes, s_list,
989 stderr_out ("Couldn't get IC value: %s\n", bad_arg);
991 stderr_out ("\nInput method context attributes:\n");
992 stderr_out ("Style: "); describe_XIMStyle (style);
993 stderr_out ("Client window: %lx\n", (unsigned long int)client_win);
994 stderr_out ("Focus window: %lx\n", (unsigned long int)focus_win);
995 stderr_out ("Preedit:\n");
996 describe_XRectangle (" Area", p_area);
997 describe_XRectangle (" Area needed", p_needed);
998 stderr_out (" foreground: %lx\n", (unsigned long int)p_fg);
999 stderr_out (" background: %lx\n", (unsigned long int)p_bg);
1000 stderr_out (" fontset: "); describe_XFontSet (p_fontset);
1001 stderr_out ("Status:\n");
1002 describe_XRectangle (" Area", s_area);
1003 describe_XRectangle (" Area needed", s_needed);
1004 stderr_out (" foreground: %lx\n", (unsigned long int)s_fg);
1005 stderr_out (" background: %lx\n", (unsigned long int)s_bg);
1006 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset);
1007 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL");
1008 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL");
1009 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask);
1013 describe_XRectangle (char *name, XRectangle *r)
1016 stderr_out ("%s: NULL\n", name);
1018 stderr_out ("%s: x=%d y=%d w=%d h=%d\n",
1019 name, r->x, r->y, r->width, r->height);
1022 /* Print out elements of Event mask */
1023 /* Defines from X11/X.h */
1025 describe_event_mask (unsigned long mask)
1027 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ")
1028 DESCRIBE_EVENT_MASK (NoEventMask);
1029 DESCRIBE_EVENT_MASK (KeyPressMask);
1030 DESCRIBE_EVENT_MASK (KeyReleaseMask);
1031 DESCRIBE_EVENT_MASK (ButtonPressMask);
1032 DESCRIBE_EVENT_MASK (ButtonReleaseMask);
1033 DESCRIBE_EVENT_MASK (EnterWindowMask);
1034 DESCRIBE_EVENT_MASK (LeaveWindowMask);
1035 DESCRIBE_EVENT_MASK (PointerMotionMask);
1036 DESCRIBE_EVENT_MASK (PointerMotionHintMask);
1037 DESCRIBE_EVENT_MASK (Button1MotionMask);
1038 DESCRIBE_EVENT_MASK (Button2MotionMask);
1039 DESCRIBE_EVENT_MASK (Button3MotionMask);
1040 DESCRIBE_EVENT_MASK (Button4MotionMask);
1041 DESCRIBE_EVENT_MASK (Button5MotionMask);
1042 DESCRIBE_EVENT_MASK (ButtonMotionMask);
1043 DESCRIBE_EVENT_MASK (KeymapStateMask);
1044 DESCRIBE_EVENT_MASK (ExposureMask);
1045 DESCRIBE_EVENT_MASK (VisibilityChangeMask);
1046 DESCRIBE_EVENT_MASK (StructureNotifyMask);
1047 DESCRIBE_EVENT_MASK (ResizeRedirectMask);
1048 DESCRIBE_EVENT_MASK (SubstructureNotifyMask);
1049 DESCRIBE_EVENT_MASK (SubstructureRedirectMask);
1050 DESCRIBE_EVENT_MASK (FocusChangeMask);
1051 DESCRIBE_EVENT_MASK (PropertyChangeMask);
1052 DESCRIBE_EVENT_MASK (ColormapChangeMask);
1053 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask);
1054 #undef DESCRIBE_EVENT_MASK
1059 describe_XIMStyle (XIMStyle style)
1061 #define DESCRIBE_STYLE(bit) \
1063 stderr_out (#bit " ");
1065 DESCRIBE_STYLE (XIMPreeditArea);
1066 DESCRIBE_STYLE (XIMPreeditCallbacks);
1067 DESCRIBE_STYLE (XIMPreeditPosition);
1068 DESCRIBE_STYLE (XIMPreeditNothing);
1069 DESCRIBE_STYLE (XIMPreeditNone);
1070 DESCRIBE_STYLE (XIMStatusArea);
1071 DESCRIBE_STYLE (XIMStatusCallbacks);
1072 DESCRIBE_STYLE (XIMStatusNothing);
1073 DESCRIBE_STYLE (XIMStatusNone);
1074 #undef DESCRIBE_STYLE
1079 describe_XIMStyles (XIMStyles *p)
1082 stderr_out ("%d Style(s):\n", p->count_styles);
1083 for (i=0; i<p->count_styles ; i++)
1085 describe_XIMStyle (p->supported_styles[i]);
1089 #endif /* DEBUG_XEMACS */
1091 /* Random cruft follows */
1095 Unit_Test (struct frame *f, char * s)
1096 /* mrb unit testing */
1098 XrmValue fromVal, toVal;
1101 fromVal.size = strlen (s);
1102 toVal.addr = (XtPointer) &user_preferred_XIMStyles;
1103 toVal.size = sizeof (XIMStyles);
1105 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal,
1106 XtRXimStyles, &toVal) != False)
1108 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr);
1109 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size);
1110 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr);
1111 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size);
1112 describe_XIMStyles ((XIMStyles *) toVal.addr);
1118 /* Get a fontset for IM to use */
1120 x_init_fontset (struct device *d)
1122 Display *dpy = DEVICE_X_DISPLAY (d);
1124 char ** missing_charsets;
1125 int num_missing_charsets;
1126 char * default_string;
1127 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/
1128 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" ;
1130 DEVICE_X_FONTSET (d) = fontset =
1131 XCreateFontSet (dpy,
1134 &num_missing_charsets,
1137 if (fontset == NULL)
1139 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string);
1142 if (num_missing_charsets > 0)
1145 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string);
1146 for (i=0; i < num_missing_charsets; i++)
1148 stderr_out ("%s\n", missing_charsets[i]);
1150 XFreeStringList (missing_charsets);
1151 stderr_out ("Default string: %s\n", default_string);
1155 describe_XFontSet (fontset);