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)
429 XIC xic = FRAME_X_XIC (f);
430 XIMStyle style = FRAME_X_XIC_STYLE (f);
436 if (style & XIMStatusArea)
438 /* Place Status Area in bottom right corner */
439 /* Negotiate geometry of status area */
440 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */
443 /* If input method has existing status area, use its current size */
444 /* The following at least works for Sun's htt */
445 area.x = area.y = area.width = area.height = 0;
446 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area);
447 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed);
448 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
449 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed);
451 area.width = needed->width;
452 area.height = needed->height;
453 area.x = FRAME_RIGHT_BORDER_START (f) - area.width;
454 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height;
457 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n",
458 area.x, area.y, area.width, area.height);
459 #endif /* DEBUG_XIM */
461 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area);
464 if (style & XIMPreeditPosition)
466 /* Set Preedit Area to whole frame size (sans border) */
467 /* We include the border because Preedit window might be larger
468 than display line at edge. #### FIX: we should adjust to make
469 sure that there is always room for the spot sub-window */
470 area.x = FRAME_LEFT_BORDER_START (f);
471 area.y = FRAME_TOP_BORDER_START (f);
472 area.width = FRAME_RIGHT_BORDER_END (f) - area.x;
473 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y;
474 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area);
483 XIM_SetSpotLocation (struct frame *f, int x, int y)
485 XIC xic = FRAME_X_XIC (f);
486 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
488 /* Only care if we have a valid XIC using Over the Spot in
489 * a different location */
491 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) ||
492 (spot->x == (short) x &&
493 spot->y == (short) y))
499 /* #### FIX: Must make sure spot fits within Preedit Area */
500 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
502 stderr_out ("Spot: %d %d\n", spot->x, spot->y);
507 XIM_focus_event (struct frame *f, int in_p)
509 if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */)
510 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
514 #define XIM_Composed_Text_BUFSIZE 64
515 typedef struct XIM_Composed_Text
518 wchar_t data [XIM_Composed_Text_BUFSIZE];
521 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}};
524 /* get_XIM_input -- Process results of input method composition.
526 This function copies the results of the input method composition to
527 composed_input_buf. Then for each character, a custom event of type
528 wc_atom is sent with the character as its data.
530 It is probably more efficient to copy the composition results to some
531 allocated memory and send a single event pointing to that memory.
532 That would cut down on the event processing as well as allow quick
533 insertion into the buffer of the whole string. It might require some
534 care, though, to avoid fragmenting memory through the allocation and
535 freeing of many small chunks. Maybe the existing system for
536 (single-byte) string allocation can be used, multiplying the length by
537 sizeof (wchar_t) to get the right size.
540 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy)
546 XClientMessageEvent new_event;
549 len = XwcLookupString (ic, x_key_event, composed_input_buf.data,
550 composed_input_buf.size, &keysym, &status);
553 case XBufferOverflow:
554 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */
562 new_event.type = ClientMessage;
563 new_event.display = x_key_event->display;
564 new_event.window = x_key_event->window;
565 new_event.message_type = wc_atom;
566 new_event.format = 32; /* 32-bit wide data */
567 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L;
568 new_event.data.l[0] = x_key_event->time;
569 for (i = 0; i < len; i++)
571 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i];
572 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event);
577 /* ============================================================== */
578 /* X input method style determination */
579 /* ============================================================== */
582 #define done(type, value) \
583 if (toVal->addr != NULL) { \
584 if (toVal->size < sizeof(type)) { \
585 toVal->size = sizeof(type); \
588 *(type*)toVal->addr = (value); \
590 static type static_val; \
591 static_val = (value); \
592 toVal->addr = (XPointer)&static_val; \
594 toVal->size = sizeof(type); \
595 return True /* Caller supplies `;' */
599 * This is a standard Xt type converter, except that the caller MUST
600 * supply a proper non-NULL toVal XIMStyles structure that we will
603 * fromVal points to a string like
605 "XIMPreeditPosition|XIMStatusArea,
606 XIMPreeditPosition|XIMStatusNothing
607 XIMPreeditNothing|XIMStatusNothing"
609 * This is converted in the obvious way to a XIMStyles structure.
611 * mrb: #### Fix this to handle Motif-style specifications for
612 * XIMStyles as well: overTheSpot, rootWindow, none */
614 /* XtTypeConverter */
616 EmacsXtCvtStringToXIMStyles (
622 XtPointer *converter_data)
624 #define STYLE_INFO(style) { style, #style, sizeof(#style) }
625 static struct XIMStyleInfo
627 const XIMStyle style;
628 const char * const name;
630 } emacs_XIMStyleInfo[] = {
631 STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
632 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
633 STYLE_INFO (XIMPreeditPosition|XIMStatusNone),
634 STYLE_INFO (XIMPreeditNothing|XIMStatusArea),
635 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing),
636 STYLE_INFO (XIMPreeditNothing|XIMStatusNone),
637 STYLE_INFO (XIMPreeditNone|XIMStatusArea),
638 STYLE_INFO (XIMPreeditNone|XIMStatusNothing),
639 STYLE_INFO (XIMPreeditNone|XIMStatusNone)
643 char *s = (char *) fromVal->addr;
644 char *end = s + fromVal->size;
645 XIMStyles * const p = (XIMStyles *) toVal->addr;
646 const char * const delimiter = " \t\n\r:;," ;
647 const int max_styles = XtNumber(emacs_XIMStyleInfo);
652 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n",
653 fromVal->size, (char *) fromVal->addr);
654 #endif /* DEBUG_XIM */
658 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
659 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
661 "String to XIMStyle conversion requires exactly 0 parameters",
662 (String *)NULL, (Cardinal *)NULL);
667 /* Make sure caller is giving us good data */
668 assert (fromVal->addr != NULL);
669 assert (fromVal->size == strlen(fromVal->addr)+1);
670 assert (toVal->addr != NULL);
671 assert (toVal->size == sizeof(XIMStyles));
672 #endif /* DEBUG_XEMACS */
675 p->supported_styles = xnew_array (XIMStyle, max_styles);
678 * The following routine assumes that the style name resource is
679 * identical with the programmatic name of style. For example,
680 * "XIMPreeditPosition|XIMStatusArea" means the
681 * XIMPreeditPosition|XIMStatusArea value is specified. If the
682 * style name is changed, such as "OverTheSpot|imDisplaysInClient",
683 * the parsing logic below should be modified as well. */
685 if ((c = strtok(s, delimiter)) == NULL)
690 for(i=0 ; i<max_styles ; i++)
692 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i;
693 if(!strncmp(c, rec->name, rec->namelen - 1)) {
694 p->supported_styles[p->count_styles] = rec->style;
699 if((c = strtok(NULL, delimiter)) == NULL) {
704 if (p->count_styles == 0)
705 { /* No valid styles? */
706 char *buf = (char *)alloca (strlen (fromVal->addr)
707 + strlen (DefaultXIMStyles)
710 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
712 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n"
713 "Using default string \"%s\" instead.\n",
714 fromVal->addr, DefaultXIMStyles);
715 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
717 buf, (String *)NULL, (Cardinal *)NULL);
718 new_from.addr = DefaultXIMStyles;
719 new_from.size = sizeof(DefaultXIMStyles);
720 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args,
721 &new_from, toVal, converter_data);
723 XREALLOC_ARRAY (p->supported_styles, XIMStyle, p->count_styles);
724 *converter_data = (char *) True;
733 XtPointer converter_data,
738 stderr_out ("Converter data: %x\n", converter_data);
739 stderr_out ("EmacsFreeXIMStyles called\n");
740 #endif /* DEBUG_XIM */
744 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError",
745 "Freeing an XIMStyles requires that zero arguments be passwd",
746 (String *)NULL, (Cardinal *)NULL);
752 Boolean free_p = (Boolean) (int) converter_data;
753 XIMStyles *styles = (XIMStyles *) toVal->addr;
755 XFree ( styles->supported_styles );
760 /* O'Reilly XLib Programming Manual, pg. 371 */
761 /* Much nicer implementation than O'Reilly */
762 /* Choose the more `complicated', hence nicer, XIM input style */
764 BetterStyle (XIMStyle s, XIMStyle t)
766 #define CHECK_XIMStyle_BIT(bit) \
767 if ((s ^ t) & bit) { return (s & bit) ? s : t; }
769 CHECK_XIMStyle_BIT (XIMPreeditCallbacks);
770 CHECK_XIMStyle_BIT (XIMPreeditPosition);
771 CHECK_XIMStyle_BIT (XIMPreeditArea);
772 CHECK_XIMStyle_BIT (XIMPreeditNothing);
773 CHECK_XIMStyle_BIT (XIMStatusCallbacks);
774 CHECK_XIMStyle_BIT (XIMStatusArea);
775 CHECK_XIMStyle_BIT (XIMStatusNothing);
776 #undef CHECK_XIMStyle_BIT
781 /* Choose the best style, given:
782 * - user preferences (already checked to be supported by XEmacs)
783 * - styles supported by the input method */
784 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing)
786 best_style (XIMStyles *user, XIMStyles *xim)
789 for (i=0 ; i<user->count_styles ; i++)
791 for (j=0 ; j<xim->count_styles ; j++)
793 if (user->supported_styles[i] == xim->supported_styles[j])
794 return user->supported_styles[i];
797 return DEFAULTStyle; /* Default Style */
800 /* These lisp-callable functions will be sealed until xim-leim is needed.
801 Oct 22 1999 - kazz */
804 * External callable function for XIM
806 DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /*
807 Open the XIC on the frame if XIM is available.
808 Commonly, use this as \(x-open-xim \(selected-frame)).
809 If the frame is not on X device, return signal.
810 If XIC is created successfully return t. If not return nil.
816 CHECK_LIVE_FRAME (frame);
819 return signal_simple_error ("This frame is not on X device", frame);
822 return FRAME_X_XIC (f) ? Qt : Qnil;
825 DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /*
826 Close the XIC on the frame if it exists.
827 Commonly, use this as \(x-close-xim \(selected-frame)).
828 If the frame is not on X device, return signal.
829 Otherwise, it destroys the XIC if it exists, then returns t anyway.
836 CHECK_LIVE_FRAME (frame);
839 return signal_simple_error ("This frame is not on X device", frame);
841 d = XDEVICE (FRAME_DEVICE (f));
842 if (DEVICE_X_XIM (d)) {
843 /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */
844 FRAME_X_XIC (XFRAME (f)) = NULL;
851 syms_of_input_method_xlib (void)
853 defsymbol (&Qxim_xlib, "xim-xlib");
854 #if 0 /* see above */
855 DEFSUBR (Fx_open_xim);
856 DEFSUBR (Fx_close_xim);
861 vars_of_input_method_xlib (void)
863 Fprovide (intern ("xim"));
867 /* ====================================================================== */
868 /* Internal Debugging Routines */
869 /* ====================================================================== */
873 describe_XIM (XIM xim)
877 /* Print locale of XIM */
878 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim));
880 /* List supported input method styles */
881 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
883 stderr_out ("\n%d input style(s) supported by input method.\n",
884 styles->count_styles);
889 for (i=0; i < styles->count_styles; i++)
890 describe_XIMStyle (styles->supported_styles[i]);
892 #endif /* DEBUG_XIM */
897 describe_XFontSet (XFontSet fontset)
899 XFontStruct **font_struct_list;
900 char **font_name_list;
905 stderr_out ("NULL\n");
909 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list);
910 stderr_out ( "%d font(s) available:\n", count);
911 for (i=0 ; i < count ; i++)
912 stderr_out ("Font: %s\n", *(font_name_list+i));
916 describe_Status (Status status)
918 #define DESCRIBE_STATUS(value) \
919 if (status == value) stderr_out ("Status: " #value "\n")
921 DESCRIBE_STATUS (XBufferOverflow);
922 DESCRIBE_STATUS (XLookupNone);
923 DESCRIBE_STATUS (XLookupKeySym);
924 DESCRIBE_STATUS (XLookupBoth);
925 DESCRIBE_STATUS (XLookupChars);
926 #undef DESCRIBE_STATUS
930 describe_Window (Window win)
933 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2",
934 (int) win, (int) win);
939 describe_XIC (XIC xic)
942 Window client_win=0, focus_win=0;
943 char *resourceName = NULL;
944 char *resourceClass = NULL;
945 char *bad_arg = NULL;
946 unsigned long filter_mask = NoEventMask;
947 XVaNestedList p_list, s_list;
948 XFontSet p_fontset = NULL, s_fontset = NULL;
949 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0;
950 XRectangle *p_area = NULL, *s_area = NULL;
951 XRectangle *p_needed = NULL, *s_needed = NULL;
952 XPoint *p_spot = NULL;
954 /* Check for valid input context and method */
956 stderr_out ("Input method is NULL\n");
959 stderr_out ("XIMOfIC() returns NULL\n");
961 /* Print out Input Context Attributes */
962 p_list = XVaCreateNestedList (0,
963 XNFontSet, &p_fontset,
965 XNAreaNeeded, &p_needed,
966 XNSpotLocation, &p_spot,
971 s_list = XVaCreateNestedList (0,
972 XNFontSet, &s_fontset,
974 XNAreaNeeded, &s_needed,
979 bad_arg = XGetICValues(xic,
980 XNInputStyle, &style,
981 XNFilterEvents, &filter_mask,
982 XNClientWindow, &client_win,
983 XNFocusWindow, &focus_win,
984 XNResourceName, &resourceName,
985 XNResourceClass, &resourceClass,
986 XNPreeditAttributes, p_list,
987 XNStatusAttributes, s_list,
993 stderr_out ("Couldn't get IC value: %s\n", bad_arg);
995 stderr_out ("\nInput method context attributes:\n");
996 stderr_out ("Style: "); describe_XIMStyle (style);
997 stderr_out ("Client window: %lx\n", (unsigned long int)client_win);
998 stderr_out ("Focus window: %lx\n", (unsigned long int)focus_win);
999 stderr_out ("Preedit:\n");
1000 describe_XRectangle (" Area", p_area);
1001 describe_XRectangle (" Area needed", p_needed);
1002 stderr_out (" foreground: %lx\n", (unsigned long int)p_fg);
1003 stderr_out (" background: %lx\n", (unsigned long int)p_bg);
1004 stderr_out (" fontset: "); describe_XFontSet (p_fontset);
1005 stderr_out ("Status:\n");
1006 describe_XRectangle (" Area", s_area);
1007 describe_XRectangle (" Area needed", s_needed);
1008 stderr_out (" foreground: %lx\n", (unsigned long int)s_fg);
1009 stderr_out (" background: %lx\n", (unsigned long int)s_bg);
1010 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset);
1011 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL");
1012 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL");
1013 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask);
1017 describe_XRectangle (char *name, XRectangle *r)
1020 stderr_out ("%s: NULL\n", name);
1022 stderr_out ("%s: x=%d y=%d w=%d h=%d\n",
1023 name, r->x, r->y, r->width, r->height);
1026 /* Print out elements of Event mask */
1027 /* Defines from X11/X.h */
1029 describe_event_mask (unsigned long mask)
1031 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ")
1032 DESCRIBE_EVENT_MASK (NoEventMask);
1033 DESCRIBE_EVENT_MASK (KeyPressMask);
1034 DESCRIBE_EVENT_MASK (KeyReleaseMask);
1035 DESCRIBE_EVENT_MASK (ButtonPressMask);
1036 DESCRIBE_EVENT_MASK (ButtonReleaseMask);
1037 DESCRIBE_EVENT_MASK (EnterWindowMask);
1038 DESCRIBE_EVENT_MASK (LeaveWindowMask);
1039 DESCRIBE_EVENT_MASK (PointerMotionMask);
1040 DESCRIBE_EVENT_MASK (PointerMotionHintMask);
1041 DESCRIBE_EVENT_MASK (Button1MotionMask);
1042 DESCRIBE_EVENT_MASK (Button2MotionMask);
1043 DESCRIBE_EVENT_MASK (Button3MotionMask);
1044 DESCRIBE_EVENT_MASK (Button4MotionMask);
1045 DESCRIBE_EVENT_MASK (Button5MotionMask);
1046 DESCRIBE_EVENT_MASK (ButtonMotionMask);
1047 DESCRIBE_EVENT_MASK (KeymapStateMask);
1048 DESCRIBE_EVENT_MASK (ExposureMask);
1049 DESCRIBE_EVENT_MASK (VisibilityChangeMask);
1050 DESCRIBE_EVENT_MASK (StructureNotifyMask);
1051 DESCRIBE_EVENT_MASK (ResizeRedirectMask);
1052 DESCRIBE_EVENT_MASK (SubstructureNotifyMask);
1053 DESCRIBE_EVENT_MASK (SubstructureRedirectMask);
1054 DESCRIBE_EVENT_MASK (FocusChangeMask);
1055 DESCRIBE_EVENT_MASK (PropertyChangeMask);
1056 DESCRIBE_EVENT_MASK (ColormapChangeMask);
1057 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask);
1058 #undef DESCRIBE_EVENT_MASK
1063 describe_XIMStyle (XIMStyle style)
1065 #define DESCRIBE_STYLE(bit) \
1067 stderr_out (#bit " ");
1069 DESCRIBE_STYLE (XIMPreeditArea);
1070 DESCRIBE_STYLE (XIMPreeditCallbacks);
1071 DESCRIBE_STYLE (XIMPreeditPosition);
1072 DESCRIBE_STYLE (XIMPreeditNothing);
1073 DESCRIBE_STYLE (XIMPreeditNone);
1074 DESCRIBE_STYLE (XIMStatusArea);
1075 DESCRIBE_STYLE (XIMStatusCallbacks);
1076 DESCRIBE_STYLE (XIMStatusNothing);
1077 DESCRIBE_STYLE (XIMStatusNone);
1078 #undef DESCRIBE_STYLE
1083 describe_XIMStyles (XIMStyles *p)
1086 stderr_out ("%d Style(s):\n", p->count_styles);
1087 for (i=0; i<p->count_styles ; i++)
1089 describe_XIMStyle (p->supported_styles[i]);
1093 #endif /* DEBUG_XEMACS */
1095 /* Random cruft follows */
1099 Unit_Test (struct frame *f, char * s)
1100 /* mrb unit testing */
1102 XrmValue fromVal, toVal;
1105 fromVal.size = strlen (s);
1106 toVal.addr = (XtPointer) &user_preferred_XIMStyles;
1107 toVal.size = sizeof (XIMStyles);
1109 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal,
1110 XtRXimStyles, &toVal) != False)
1112 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr);
1113 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size);
1114 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr);
1115 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size);
1116 describe_XIMStyles ((XIMStyles *) toVal.addr);
1120 #endif /* XIM_XLIB only */
1123 /* Get a fontset for IM to use */
1125 x_init_fontset (struct device *d)
1127 Display *dpy = DEVICE_X_DISPLAY (d);
1129 char ** missing_charsets;
1130 int num_missing_charsets;
1131 char * default_string;
1132 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/
1133 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" ;
1135 DEVICE_X_FONTSET (d) = fontset =
1136 XCreateFontSet (dpy,
1139 &num_missing_charsets,
1142 if (fontset == NULL)
1144 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string);
1147 if (num_missing_charsets > 0)
1150 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string);
1151 for (i=0; i < num_missing_charsets; i++)
1153 stderr_out ("%s\n", missing_charsets[i]);
1155 XFreeStringList (missing_charsets);
1156 stderr_out ("Default string: %s\n", default_string);
1160 describe_XFontSet (fontset);