X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Finput-method-xlib.c;h=8a1f3cad6c42db5709c878ea128c68a0e1e3d533;hb=3f711eea68ce5fd586297b43c8d9936cd2ba916f;hp=08e0135de641ec86052c04943426c3a9fcdb2afb;hpb=da416a1945940b3f952144475eb1a1357430527d;p=chise%2Fxemacs-chise.git.1 diff --git a/src/input-method-xlib.c b/src/input-method-xlib.c index 08e0135..8a1f3ca 100644 --- a/src/input-method-xlib.c +++ b/src/input-method-xlib.c @@ -27,9 +27,51 @@ Boston, MA 02111-1307, USA. */ 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 goes down. + + Implementation: + + - 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 don'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 #include "lisp.h" #include /* More portable than ? */ +#include #include "frame.h" #include "device.h" #include "window.h" @@ -38,13 +80,16 @@ Boston, MA 02111-1307, USA. */ #include "EmacsFrame.h" #include "events.h" -#include -#include - -#ifndef XIM_XLIB -#error XIM_XLIB is not defined?? +#if !defined (XIM_XLIB) && !defined (USE_XFONTSET) +#error neither XIM_XLIB nor USE_XFONTSET is 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); + +#ifdef XIM_XLIB /* XIM_XLIB specific */ /* Get/Set IC values for just one attribute */ #ifdef DEBUG_XEMACS #define XIC_Value(Get_Set, xic, name, attr, value) \ @@ -75,16 +120,18 @@ static char DefaultXIMStyles[] = "XIMPreeditNone|XIMStatusNothing\n" "XIMPreeditNone|XIMStatusNone"; -static Boolean xim_initted = False; - static XIMStyle best_style (XIMStyles *user, XIMStyles *xim); +#endif /* XIM_XLIB only */ + +/* This function is documented, but no prototype in the header files */ +EXTERN_C char * XSetIMValues(XIM, ...); void Initialize_Locale (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, @@ -92,31 +139,31 @@ Initialize_Locale (void) /*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; } } @@ -125,67 +172,154 @@ Initialize_Locale (void) 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"); } } -/******************************************************************/ -/* Input method using xlib */ -/******************************************************************/ +#ifdef XIM_XLIB /* starting XIM specific codes */ -/* - * called from when XIM is destroying - */ +/* Callbacks for IM are supported from X11R6 or later. */ +#ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK + +static Boolean xim_initted = False; + +/* 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 frame *f = (struct frame *)client_data; - struct device *d = XDEVICE (FRAME_DEVICE ((struct frame *)client_data)); - Lisp_Object frame_list = DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f))); + struct device *d = (struct device *)client_data; Lisp_Object tail; - struct frame *target_frame = NULL; - LIST_LOOP (tail, frame_list) + DEVICE_FRAME_LOOP (tail, d) { - if (target_frame = XFRAME (XCAR (tail))) + struct frame *target_frame = XFRAME (XCAR (tail)); + if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame)) { - if ( FRAME_X_XIC(target_frame) ) - { - XDestroyIC (FRAME_X_XIC(target_frame)); - FRAME_X_XIC (target_frame) = NULL; - } + /* XDestroyIC (FRAME_X_XIC (target_frame)); */ + FRAME_X_XIC (target_frame) = NULL; } } -#if 0 - if ( DEVICE_X_XIM (d) ) + 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 ) { - stderr_out ("NULLing d->xim...\n"); - /* DEVICE_X_XIM (d) = NULL; */ + xim_initted = True; + XtGetApplicationNameAndClass (dpy, &name, &class); + DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class); + + /* destroy callback for im */ + ximcallback.callback = (XIMProc) IMDestroyCallback; + ximcallback.client_data = (XPointer) d; + XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); } -#endif - xim_initted = False; + /* 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 /* HAVE_XREGISTERIMINSTANTIATECALLBACK */ + +/* Initialize XIM for X device. + Register the use of XIM using XRegisterIMInstantiateCallback. */ +void +XIM_init_device (struct device *d) +{ +#ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK /* X11R6+ */ + DEVICE_X_XIM (d) = NULL; + XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL, +#ifdef XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE + /* The sixth parameter is of type + XPointer in XFree86 but (XPointer *) + on most other X11's. */ + (XIDProc) IMInstantiateCallback, + (XPointer) d +#else /* X Consortium prototype */ + (XIMProc) IMInstantiateCallback, + (XPointer *) d +#endif /* XREGISTERIMINSTANTIATECALLBACK_NONSTANDARD_PROTOTYPE */ + ); + return; +#else /* pre-X11R6 */ + 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) + { + xim_warn ("XOpenIM() failed...no input server available\n"); + return; + } + else + { + XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL); + return; + } +#endif /* HAVE_XREGISTERIMINSTANTIATECALLBACK */ +} + /* - * called from when FRAME is initializing + * For the frames */ + +/* Callback for the deleting frame. */ static void -IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) +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; +} + +/* Initialize XIC for new frame. + Create an X input context (XIC) for this frame. */ +void +XIM_init_frame (struct frame *f) { - struct frame *f = (struct frame *)client_data; - struct device *d = XDEVICE (FRAME_DEVICE ((struct frame *)client_data)); + struct device *d = XDEVICE (FRAME_DEVICE (f)); XIM xim; - Widget w = FRAME_X_TEXT_WIDGET ((struct frame *)client_data); + Widget w = FRAME_X_TEXT_WIDGET (f); Window win = XtWindow (w); XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1}; XPoint spot = {0,0}; XIMStyle style; XVaNestedList p_list, s_list; - char *name, *class; typedef struct { XIMStyles styles; @@ -195,7 +329,6 @@ IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) char *inputmethod; } xic_vars_t; xic_vars_t xic_vars; - XIMCallback ximcallback; XIC xic; #define res(name, class, representation, field, default_value) \ @@ -208,29 +341,15 @@ IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, (XtPointer) DefaultXIMStyles), res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, (XtPointer) XtDefaultFontSet), res(XtNximForeground, XtCForeground, XtRPixel, fg, (XtPointer) XtDefaultForeground), - res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground), - res(XtNinputMethod, XtCInputMethod, XtRString, inputmethod, (XtPointer) NULL) + res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground) }; - /* ---------- beginning of the action ---------- */ - /* - * 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); + xim = DEVICE_X_XIM (d); - /* destroy callback for im */ - ximcallback.callback = IMDestroyCallback; - ximcallback.client_data = (XPointer)f; - XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); - } - else + if (!xim) { - xim = DEVICE_X_XIM (d); + return; } w = FRAME_X_TEXT_WIDGET (f); @@ -238,13 +357,13 @@ IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) /* * initialize XIC */ - if ( FRAME_X_XIC (f) ) return; + 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; } @@ -282,7 +401,7 @@ IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) if (!xic) { - stderr_out ("Warning: XCreateIC failed.\n"); + xim_warn ("Warning: XCreateIC failed.\n"); return; } @@ -296,73 +415,29 @@ IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) XSetICFocus (xic); - return; -} - -/* Create X input method for device */ -void -XIM_init_device (struct device *d) -{ - /* do nothing here */ - return; -} - -/* Callback for when the frame was deleted (closed) */ -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 ((struct frame *)client_data)); - Display *dpy = DEVICE_X_DISPLAY (d); - - XUnregisterIMInstantiateCallback (dpy, NULL, NULL, NULL, - IMInstantiateCallback, (XtPointer)f); - - if ( FRAME_X_XIC (f) ) - { - XDestroyIC (FRAME_X_XIC(f)); - FRAME_X_XIC (f) = NULL; - } - return; -} - -/* Create an X input context for this frame. - - Register the IM to be initiated later using XRegisterIMInstantiateCallback - */ -void -XIM_init_frame (struct frame *f) -{ - struct device *d = XDEVICE (FRAME_DEVICE (f)); - - XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL, - IMInstantiateCallback, (XtPointer)f); - -#if 0 - if ( FRAME_X_XIC (f) ) - return; -#endif - if ( ! DEVICE_X_XIM (d) ) - { - stderr_out ("X Input Method open failed. Waiting IM to be enabled.\n"); - } - +#ifdef HAVE_XREGISTERIMINSTANTIATECALLBACK /* when frame is going to be destroyed (closed) */ XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback, XIM_delete_frame, (XtPointer)f); - return; +#endif } void XIM_SetGeometry (struct frame *f) { - XIC xic = FRAME_X_XIC (f); - XIMStyle style = FRAME_X_XIC_STYLE (f); + XIC xic; + XIMStyle style; XRectangle area; - if (!xic || !f) + if (!f) return; + xic = FRAME_X_XIC (f); + if (!xic) + return; + + style = FRAME_X_XIC_STYLE (f); if (style & XIMStatusArea) { /* Place Status Area in bottom right corner */ @@ -426,7 +501,7 @@ XIM_SetSpotLocation (struct frame *f, int x, int y) 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); @@ -486,7 +561,7 @@ retry: case XLookupChars: break; default: - abort (); + ABORT (); } new_event.type = ClientMessage; @@ -554,9 +629,9 @@ EmacsXtCvtStringToXIMStyles ( #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), @@ -572,9 +647,9 @@ EmacsXtCvtStringToXIMStyles ( 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; @@ -727,6 +802,65 @@ best_style (XIMStyles *user, XIMStyles *xim) 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) @@ -988,6 +1122,7 @@ Unit_Test (struct frame *f, char * s) } } #endif +#endif /* XIM_XLIB only */ #if 0 /* Get a fontset for IM to use */