and X11 R6 release guide chapters on internationalized input,
for further details */
+/*
+ Policy:
+
+ The XIM is of the device, by the device, for the device.
+ The XIC is of each frame, by each frame, for each frame.
+ The exceptions are:
+ 1. Activate XICs on poor frames when the XIM is back.
+ 2. Deactivate all the XICs when the XIM go down.
+
+ Methods:
+
+ - Register a callback for an XIM when the X device is being initialized.
+ XIM_init_device (d) { XRegisterIMInstantiateCallback (); }
+ The "XRegisterIMInstantiateCallback" is called when an XIM become
+ available on the X display.
+
+ - Catch the XIC when the frame is being initialized if XIM was available.
+ XIM_init_frame (f) { ... XCreateIC (); ... }
+
+ - Release the XIC when the frame is being closed.
+ XIM_delete_frame (f) { ... FRAME_X_XIC (f) = NULL; ... }
+ "XIM_delete_frame" is a "DestroyCallback" function declared in
+ XIM_init_frame ();
+
+ - Release all the XICs when the XIM was down accidentally.
+ In IMDestroyCallback:
+ DEVICE_FRAME_LOOP (...) { FRAME_X_XIC (f) = NULL; }
+
+ - Re-enable XIC for all the frames which doesn't have XIC when the XIM
+ is back.
+ In IMInstantiateCallback:
+ DEVICE_FRAME_LOOP (...) { XIM_init_frame (f); }
+
+
+ Note:
+
+ - Currently, we don't use XDestroyIC because of _XimProtoCloseIM
+ (internally registered as im->methods->close) does "Xfree (ic)".
+
+ */
+
#include <config.h>
#include "lisp.h"
#include <X11/Xlocale.h> /* More portable than <locale.h> ? */
#include "EmacsFrame.h"
#include "events.h"
+#ifdef THIS_IS_X11R6
+#include <X11/IntrinsicP.h>
+#endif
+
#ifndef XIM_XLIB
#error XIM_XLIB is not defined??
#endif
+Lisp_Object Qxim_xlib;
+#define xim_warn(str) warn_when_safe (Qxim_xlib, Qwarning, str);
+#define xim_warn1(fmt, str) warn_when_safe (Qxim_xlib, Qwarning, fmt, str);
+#define xim_info(str) warn_when_safe (Qxim_xlib, Qinfo, str);
+
/* Get/Set IC values for just one attribute */
#ifdef DEBUG_XEMACS
#define XIC_Value(Get_Set, xic, name, attr, value) \
"XIMPreeditNone|XIMStatusNothing\n"
"XIMPreeditNone|XIMStatusNone";
+static Boolean xim_initted = False;
+
static XIMStyle best_style (XIMStyles *user, XIMStyles *xim);
void
{
char *locale;
- /* dverna - Nov. 98: ### DON'T DO THIS !!! The default XtLanguageProc
+ /* dverna - Nov. 98: #### DON'T DO THIS !!! The default XtLanguageProc
routine calls setlocale(LC_ALL, lang) which fucks up our lower-level
locale management, and especially the value of LC_NUMERIC. Anyway, since
at this point, we don't know yet whether we're gonna need an X11 frame,
/*XtSetLanguageProc (NULL, (XtLanguageProc) NULL, NULL);*/
if ((locale = setlocale (LC_ALL, "")) == NULL)
{
- stderr_out ("Can't set locale.\n");
- stderr_out ("Using C locale instead.\n");
+ xim_warn ("Can't set locale.\n"
+ "Using C locale instead.\n");
putenv ("LANG=C");
putenv ("LC_ALL=C");
if ((locale = setlocale (LC_ALL, "C")) == NULL)
{
- stderr_out ("Can't even set locale to `C'!\n");
+ xim_warn ("Can't even set locale to `C'!\n");
return;
}
}
if (!XSupportsLocale ())
{
- stderr_out ("X Windows does not support locale `%s'\n", locale);
- stderr_out ("Using C Locale instead\n");
+ xim_warn1 ("X Windows does not support locale `%s'\n"
+ "Using C Locale instead\n", locale);
putenv ("LANG=C");
putenv ("LC_ALL=C");
if ((locale = setlocale (LC_ALL, "C")) == NULL)
{
- stderr_out ("Can't even set locale to `C'!\n");
+ xim_warn ("Can't even set locale to `C'!\n");
return;
}
if (!XSupportsLocale ())
{
- stderr_out ("X Windows does not even support locale `C'!\n");
+ xim_warn ("X Windows does not even support locale `C'!\n");
return;
}
}
if (XSetLocaleModifiers ("") == NULL)
{
- stderr_out ("XSetLocaleModifiers(\"\") failed\n");
- stderr_out ("Check the value of the XMODIFIERS environment variable.\n");
+ xim_warn ("XSetLocaleModifiers(\"\") failed\n"
+ "Check the value of the XMODIFIERS environment variable.\n");
+ }
+}
+
+#ifdef THIS_IS_X11R6 /* Callbacks for IM are supported from X11R6 or later. */
+/* Called from when XIM is destroying.
+ Clear all the XIC when the XIM was destroying... */
+static void
+IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data)
+{
+ struct device *d = (struct device *)client_data;
+ Lisp_Object tail;
+
+ DEVICE_FRAME_LOOP (tail, d)
+ {
+ struct frame *target_frame = XFRAME (XCAR (tail));
+ if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame))
+ {
+ /* XDestroyIC (FRAME_X_XIC (target_frame)); */
+ FRAME_X_XIC (target_frame) = NULL;
+ }
+ }
+
+ DEVICE_X_XIM (d) = NULL;
+ xim_initted = False;
+ return;
+}
+
+/* This is registered in XIM_init_device (when DEVICE is initializing).
+ This activates XIM when XIM becomes available. */
+static void
+IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data)
+{
+ struct device *d = (struct device *)client_data;
+ XIM xim;
+ char *name, *class;
+ XIMCallback ximcallback;
+ Lisp_Object tail;
+
+ /* if no xim is presented, initialize xim ... */
+ if ( xim_initted == False )
+ {
+ xim_initted = True;
+ XtGetApplicationNameAndClass (dpy, &name, &class);
+ DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
+
+ /* destroy callback for im */
+ ximcallback.callback = IMDestroyCallback;
+ ximcallback.client_data = (XPointer) d;
+ XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL);
}
+
+ /* activate XIC on all the X frames... */
+ DEVICE_FRAME_LOOP (tail, d)
+ {
+ struct frame *target_frame = XFRAME (XCAR (tail));
+ if (FRAME_X_P (target_frame) && !FRAME_X_XIC (target_frame))
+ {
+ XIM_init_frame (target_frame);
+ }
+ }
+ return;
}
+#endif /* if THIS_IS_X11R6 */
-/* Create X input method for device */
+/* Initialize XIM for X device.
+ Register the use of XIM using XRegisterIMInstantiateCallback. */
void
XIM_init_device (struct device *d)
{
+#ifdef THIS_IS_X11R6
+ DEVICE_X_XIM (d) = NULL;
+ XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL,
+ IMInstantiateCallback, (XPointer) d);
+ return;
+#else
Display *dpy = DEVICE_X_DISPLAY (d);
char *name, *class;
XIM xim;
XtGetApplicationNameAndClass (dpy, &name, &class);
-
DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
-
if (xim == NULL)
{
- stderr_out ("Warning: XOpenIM() failed...no input server available\n");
+ xim_warn ("XOpenIM() failed...no input server available\n");
return;
}
else
{
- /* Get supported styles */
XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL);
-#ifdef DEBUG_XIM
- describe_XIM (xim);
+ return;
+ }
#endif
+}
+
+
+/*
+ * For the frames
+ */
+
+/* Callback for the deleting frame. */
+static void
+XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data)
+{
+ struct frame *f = (struct frame *) client_data;
+ struct device *d = XDEVICE (FRAME_DEVICE (f));
+
+ if (DEVICE_X_XIM (d))
+ {
+ if (FRAME_X_XIC (f))
+ {
+ XDestroyIC (FRAME_X_XIC (f));
+ FRAME_X_XIC (f) = NULL;
+ }
}
+ return;
}
-/* Create an X input context for this frame. */
+/* Initialize XIC for new frame.
+ Create an X input context (XIC) for this frame. */
void
XIM_init_frame (struct frame *f)
{
struct device *d = XDEVICE (FRAME_DEVICE (f));
- XIM xim = DEVICE_X_XIM (d);
- XIC xic;
+ XIM xim;
Widget w = FRAME_X_TEXT_WIDGET (f);
Window win = XtWindow (w);
- XRectangle p_area = {0,0,1,1}, s_area={0,0,1,1};
+ XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1};
XPoint spot = {0,0};
XIMStyle style;
XVaNestedList p_list, s_list;
-
typedef struct
{
XIMStyles styles;
XFontSet fontset;
Pixel fg;
Pixel bg;
+ char *inputmethod;
} xic_vars_t;
-
xic_vars_t xic_vars;
-
- /* mrb: #### Fix so that background and foreground is set from
- default face, rather than foreground and background resources, or
- that the user can use set-frame-parameters to set xic attributes */
+ XIC xic;
#define res(name, class, representation, field, default_value) \
{ name, class, representation, sizeof(xic_vars.field), \
res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground)
};
- assert (win != 0 && w != NULL && d != NULL);
+
+ xim = DEVICE_X_XIM (d);
if (!xim)
- { /* No input method? */
- FRAME_X_XIC (f) = NULL;
+ {
return;
}
+ w = FRAME_X_TEXT_WIDGET (f);
+
+ /*
+ * initialize XIC
+ */
+ if (FRAME_X_XIC (f)) return;
XtGetApplicationResources (w, &xic_vars,
resources, XtNumber (resources),
NULL, 0);
-
if (!xic_vars.fontset)
{
- stderr_out ("Can't get fontset resource for Input Method\n");
+ xim_warn ("Can't get fontset resource for Input Method\n");
FRAME_X_XIC (f) = NULL;
return;
}
+ /* construct xic */
+ XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES(d), NULL);
FRAME_X_XIC_STYLE (f) = style =
- best_style (&xic_vars.styles, DEVICE_X_XIM_STYLES (d));
+ best_style (&xic_vars.styles, (XIMStyles *)DEVICE_X_XIM_STYLES(d));
- /* Hopefully we don't have to conditionalize the following based on
- style; the IM should ignore values it doesn't use */
p_list = XVaCreateNestedList (0,
- XNArea, &p_area,
- XNSpotLocation, &spot,
- XNForeground, xic_vars.fg,
- XNBackground, xic_vars.bg,
- XNFontSet, xic_vars.fontset,
- NULL);
+ XNArea, &p_area,
+ XNSpotLocation, &spot,
+ XNForeground, xic_vars.fg,
+ XNBackground, xic_vars.bg,
+ XNFontSet, xic_vars.fontset,
+ NULL);
s_list = XVaCreateNestedList (0,
- XNArea, &s_area,
- XNForeground, xic_vars.fg,
- XNBackground, xic_vars.bg,
- XNFontSet, xic_vars.fontset,
- NULL);
+ XNArea, &s_area,
+ XNForeground, xic_vars.fg,
+ XNBackground, xic_vars.bg,
+ XNFontSet, xic_vars.fontset,
+ NULL);
+
FRAME_X_XIC (f) = xic =
XCreateIC (xim,
- XNInputStyle, style,
- XNClientWindow, win,
- XNFocusWindow, win,
- XNPreeditAttributes, p_list,
- XNStatusAttributes, s_list,
- NULL);
+ XNInputStyle, style,
+ XNClientWindow, win,
+ XNFocusWindow, win,
+ XNPreeditAttributes, p_list,
+ XNStatusAttributes, s_list,
+ NULL);
XFree (p_list);
XFree (s_list);
if (!xic)
{
- stderr_out ("Warning: XCreateIC failed\n");
+ xim_warn ("Warning: XCreateIC failed.\n");
return;
}
if (style & XIMPreeditPosition)
- { /* Init spot to invalid values */
- XPoint *frame_spot = &(FRAME_X_XIC_SPOT (f));
+ {
+ XPoint *frame_spot = &(FRAME_X_XIC_SPOT(f));
frame_spot->x = frame_spot->y = -1;
}
XSetICFocus (xic);
-#ifdef DEBUG_XIM
- describe_XIC (xic);
+#ifdef THIS_IS_X11R6
+ /* when frame is going to be destroyed (closed) */
+ XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback,
+ XIM_delete_frame, (XtPointer)f);
#endif
}
+
void
XIM_SetGeometry (struct frame *f)
{
spot->x = (short) x;
spot->y = (short) y;
- /* ### FIX: Must make sure spot fits within Preedit Area */
+ /* #### FIX: Must make sure spot fits within Preedit Area */
XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
#ifdef DEBUG_XIM
stderr_out ("Spot: %d %d\n", spot->x, spot->y);
void
XIM_focus_event (struct frame *f, int in_p)
{
- if (FRAME_X_XIC (f))
+ if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */)
(in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
}
#define STYLE_INFO(style) { style, #style, sizeof(#style) }
static struct XIMStyleInfo
{
- CONST XIMStyle style;
- CONST char * CONST name;
- CONST int namelen;
+ const XIMStyle style;
+ const char * const name;
+ const int namelen;
} emacs_XIMStyleInfo[] = {
STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
char *s = (char *) fromVal->addr;
char *end = s + fromVal->size;
- XIMStyles * CONST p = (XIMStyles *) toVal->addr;
- CONST char * CONST delimiter = " \t\n\r:;," ;
- CONST int max_styles = XtNumber(emacs_XIMStyleInfo);
+ XIMStyles * const p = (XIMStyles *) toVal->addr;
+ const char * const delimiter = " \t\n\r:;," ;
+ const int max_styles = XtNumber(emacs_XIMStyleInfo);
int i;
char *c;
return DEFAULTStyle; /* Default Style */
}
+/* These lisp-callable functions will be sealed until xim-leim is needed.
+ Oct 22 1999 - kazz */
+#if 0
+/*
+ * External callable function for XIM
+ */
+DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /*
+Open the XIC on the frame if XIM is available.
+Commonly, use this as \(x-open-xim \(selected-frame)).
+If the frame is not on X device, return signal.
+If XIC is created successfully return t. If not return nil.
+*/
+ (frame))
+{
+ struct frame *f;
+
+ CHECK_LIVE_FRAME (frame);
+ f = XFRAME (frame);
+ if (!FRAME_X_P (f))
+ return signal_simple_error ("This frame is not on X device", frame);
+
+ XIM_init_frame (f);
+ return FRAME_X_XIC (f) ? Qt : Qnil;
+}
+
+DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /*
+Close the XIC on the frame if it exists.
+Commonly, use this as \(x-close-xim \(selected-frame)).
+If the frame is not on X device, return signal.
+Otherwise, it destroys the XIC if it exists, then returns t anyway.
+*/
+ (frame))
+{
+ struct frame *f;
+ struct device *d;
+
+ CHECK_LIVE_FRAME (frame);
+ f = XFRAME (frame);
+ if (!FRAME_X_P (f))
+ return signal_simple_error ("This frame is not on X device", frame);
+
+ d = XDEVICE (FRAME_DEVICE (f));
+ if (DEVICE_X_XIM (d)) {
+ /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */
+ FRAME_X_XIC (XFRAME (f)) = NULL;
+ }
+ return Qt;
+}
+#endif /* if 0 */
+
+void
+syms_of_input_method_xlib (void)
+{
+ defsymbol (&Qxim_xlib, "xim-xlib");
+#if 0 /* see above */
+ DEFSUBR (Fx_open_xim);
+ DEFSUBR (Fx_close_xim);
+#endif
+}
void
vars_of_input_method_xlib (void)