Bugzilla – Attachment 48662 Details for
Bug 77424
tcl/tk 8.4.11 doesn't support XIM very well.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
IDP Log In
|
Forgot Password
[patch]
First attempt of a patch to make Tk work with SCIM
tk-scim.patch (text/plain), 27.51 KB, created by
Reinhard Max
on 2005-09-02 21:01:12 UTC
(
hide
)
Description:
First attempt of a patch to make Tk work with SCIM
Filename:
MIME Type:
Creator:
Reinhard Max
Created:
2005-09-02 21:01:12 UTC
Size:
27.51 KB
patch
obsolete
>--- generic/tk.h >+++ generic/tk.h >@@ -808,6 +808,9 @@ > int internalBorderBottom; > int minReqWidth; > int minReqHeight; >+#ifdef TK_USE_INPUT_METHODS >+ Tcl_DString dummy20; /* composedDStr */; >+#endif /* TK_USE_INPUT_METHODS */ > } Tk_FakeWin; > > /* >--- generic/tkBind.c >+++ generic/tkBind.c >@@ -1465,6 +1465,9 @@ > */ > > if (winPtr->pathName == NULL) { >+#ifdef TK_USE_INPUT_METHODS >+ winPtr->dispPtr->isComposed = 0; >+#endif /* TK_USE_INPUT_METHODS */ > return; > } > >@@ -1700,10 +1703,13 @@ > Tcl_DStringAppend(&scripts, "", 1); > } > } >+#ifdef TK_USE_INPUT_METHODS >+ winPtr->dispPtr->isComposed = 0; >+#endif /* TK_USE_INPUT_METHODS */ > if (Tcl_DStringLength(&scripts) == 0) { > return; > } >- >+ > /* > * Now go back through and evaluate the binding for each object, > * in order, dealing with "break" and "continue" exceptions >--- generic/tkEvent.c >+++ generic/tkEvent.c >@@ -872,6 +872,7 @@ > } > } > >+#if 0 > #ifdef TK_USE_INPUT_METHODS > /* > * Pass the event to the input method(s), if there are any, and >@@ -953,6 +954,7 @@ > } > } > #endif /* TK_USE_INPUT_METHODS */ >+#endif /* 0 */ > > /* > * For events where it hasn't already been done, update the current >@@ -1291,6 +1293,18 @@ > } > } > >+#ifdef TK_USE_INPUT_METHODS >+ if (eventPtr->type == KeyPress && eventPtr->xkey.keycode == 0) { >+ /* >+ * No doubt this is a composed message from IM server. >+ * Tk can handle KeyPress event with zero keycode value >+ * if state of the event is zero. >+ */ >+ eventPtr->xkey.state = 0; >+ dispPtr->isComposed = 1; >+ } >+#endif /* TK_USE_INPUT_METHODS */ >+ > /* > * Don't filter motion events if the user > * defaulting to true (1), which could be set to false (0) when the >--- generic/tkInt.h >+++ generic/tkInt.h >@@ -509,6 +509,23 @@ > > int iconDataSize; /* size of default iconphoto image data */ > unsigned char *iconDataPtr; /* default iconphoto image data, if set */ >+ >+#ifdef TK_USE_INPUT_METHODS >+ Tcl_Encoding imEncoding; /* Tcl encoding when the first Tcl >+ * interp was created. >+ * For encoding conversion from >+ * XmbLookupString() to UTF. >+ */ >+ XIC lastFocusedIC; /* The last focused input context on >+ * the display. >+ */ >+ int isComposed; /* 1 if the latest KeyPress event is a >+ * "Compose message" from IM server, >+ * otherwise 0. */ >+#ifdef XNDestroyCallback >+ XIMCallback destroyCallback; >+#endif /* XNDestroyCallback */ >+#endif /* TK_USE_INPUT_METHODS */ > } TkDisplay; > > /* >@@ -833,6 +850,12 @@ > > int minReqWidth; /* Minimum requested width. */ > int minReqHeight; /* Minimum requested height. */ >+ >+#ifdef TK_USE_INPUT_METHODS >+ Tcl_DString composedDStr; /* To prepare successive "%A" in bind >+ * script, save a string from IM >+ * server. */ >+#endif /* TK_USE_INPUT_METHODS */ > } TkWindow; > > /* >@@ -1089,6 +1112,7 @@ > Tcl_Interp *interp, int objc, > Tcl_Obj *CONST objv[])); > >+EXTERN int TkConsoleInit _ANSI_ARGS_((Tcl_Interp *interp)); > EXTERN void TkConsolePrint _ANSI_ARGS_((Tcl_Interp *interp, > int devId, CONST char *buffer, long size)); > >@@ -1183,6 +1207,13 @@ > EXTERN int TkUnsupported1Cmd _ANSI_ARGS_((ClientData clientData, > Tcl_Interp *interp, int argc, CONST char **argv)); > >+#ifdef TK_USE_INPUT_METHODS >+EXTERN XIC TkpCreateIC _ANSI_ARGS_((TkWindow *winPtr)); >+EXTERN void TkpDestroyIC _ANSI_ARGS_((TkWindow *winPtr, int needDestroy)); >+EXTERN int Tk_ImconfigureObjCmd _ANSI_ARGS_((ClientData clientData, >+ Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); >+#endif /* TK_USE_INPUT_METHODS */ >+ > # undef TCL_STORAGE_CLASS > # define TCL_STORAGE_CLASS DLLIMPORT > >--- generic/tkWindow.c >+++ generic/tkWindow.c >@@ -179,6 +179,10 @@ > {"::tk::unsupported::MacWindowStyle", > TkUnsupported1Cmd, NULL, 1, 1}, > #endif >+#ifdef TK_USE_INPUT_METHODS >+ {"::tk::unsupported::imconfigure", NULL, >+ Tk_ImconfigureObjCmd, 1, 1}, >+#endif > {(char *) NULL, (int (*) _ANSI_ARGS_((ClientData, Tcl_Interp *, int, CONST char **))) NULL, NULL, 0} > }; > >@@ -233,6 +237,7 @@ > TkWindow *winPtr, TkWindow *parentPtr, > CONST char *name)); > static void UnlinkWindow _ANSI_ARGS_((TkWindow *winPtr)); >+ > > /* > *---------------------------------------------------------------------- >@@ -679,6 +684,7 @@ > winPtr->handlerList = NULL; > #ifdef TK_USE_INPUT_METHODS > winPtr->inputContext = NULL; >+ Tcl_DStringInit(&(winPtr->composedDStr)); > #endif /* TK_USE_INPUT_METHODS */ > winPtr->tagPtr = NULL; > winPtr->numTags = 0; >@@ -1471,9 +1477,11 @@ > TkBindDeadWindow(winPtr); > #ifdef TK_USE_INPUT_METHODS > if (winPtr->inputContext != NULL) { >- XDestroyIC(winPtr->inputContext); >+ TkpDestroyIC(winPtr, 1); > winPtr->inputContext = NULL; > } >+ Tcl_DStringFree(&(winPtr->composedDStr)); >+ Tcl_DStringInit(&(winPtr->composedDStr)); > #endif /* TK_USE_INPUT_METHODS */ > if (winPtr->tagPtr != NULL) { > TkFreeBindingTags(winPtr); >--- library/entry.tcl >+++ library/entry.tcl >@@ -217,6 +217,13 @@ > } > } > >+# input method configuration binding (unix only) >+if {![string compare $tcl_platform(platform) "unix"]} { >+ if {[string compare [info commands ::tk::unsupported::imconfigure] {}]} { >+ bind Entry <FocusIn> {catch {::tk::unsupported::imconfigure %W}} >+ } >+} >+ > # Additional emacs-like bindings: > > bind Entry <Control-a> { >--- library/text.tcl >+++ library/text.tcl >@@ -391,6 +391,13 @@ > } > } > >+# UNIX only bindings: >+ >+if {[string equal $tcl_platform(platform) "unix"] && >+ [string compare [info commands ::tk::unsupported::imconfigure] {}]} { >+ bind Text <FocusIn> {catch {::tk::unsupported::imconfigure %W}} >+} >+ > # Macintosh only bindings: > > # if text black & highlight black -> text white, other text the same >--- unix/Makefile.in >+++ unix/Makefile.in >@@ -280,7 +280,7 @@ > # modify any of this stuff by hand. > #---------------------------------------------------------------- > >-AC_FLAGS = @DEFS@ >+AC_FLAGS = @DEFS@ @CPPFLAGS@ @X11_IMAKE_FLAGS@ > AR = @AR@ > RANLIB = @RANLIB@ > SRC_DIR = @srcdir@ >@@ -349,7 +349,7 @@ > tkUnixCursor.o tkUnixDraw.o tkUnixEmbed.o tkUnixEvent.o \ > tkUnixFocus.o tkUnixFont.o tkUnixInit.o tkUnixKey.o tkUnixMenu.o \ > tkUnixMenubu.o tkUnixScale.o tkUnixScrlbr.o tkUnixSelect.o \ >- tkUnixSend.o tkUnixWm.o tkUnixXId.o >+ tkUnixSend.o tkUnixWm.o tkUnixXId.o tkUnixIm.o > > AQUA_OBJS = tkMacOSXBitmap.o tkMacOSXButton.o tkMacOSXClipboard.o \ > tkMacOSXColor.o tkMacOSXConfig.o tkMacOSXCursor.o tkMacOSXDebug.o \ >@@ -420,6 +420,7 @@ > $(UNIX_DIR)/tkUnixEmbed.c $(UNIX_DIR)/tkUnixEvent.c \ > $(UNIX_DIR)/tkUnixFocus.c \ > $(UNIX_DIR)/tkUnixFont.c $(UNIX_DIR)/tkUnixInit.c \ >+ $(UNIX_DIR)/tkUnixIm.c \ > $(UNIX_DIR)/tkUnixKey.c \ > $(UNIX_DIR)/tkUnixMenu.c $(UNIX_DIR)/tkUnixMenubu.c \ > $(UNIX_DIR)/tkUnixScale.c $(UNIX_DIR)/tkUnixScrlbr.c \ >@@ -1073,6 +1074,9 @@ > $(CC) -c $(CC_SWITCHES) -DTK_LIBRARY=\"${TK_LIBRARY}\" \ > $(UNIX_DIR)/tkUnixInit.c > >+tkUnixIm.o: $(UNIX_DIR)/tkUnixIm.c >+ $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixIm.c >+ > tkUnixKey.o: $(UNIX_DIR)/tkUnixKey.c > $(CC) -c $(CC_SWITCHES) $(UNIX_DIR)/tkUnixKey.c > >--- unix/configure.in >+++ unix/configure.in >@@ -528,6 +528,113 @@ > > TK_SHARED_BUILD=${SHARED_BUILD} > >+#-------------------------------------------------------------------- >+# Checking X lib for i18n related things. >+#-------------------------------------------------------------------- >+ >+X11_IMAKE_FLAGS="" >+tk_oldCflags=$CFLAGS >+tk_oldLibs=$LIBS >+CFLAGS="$CFLAGS $XINCLUDES" >+LIBS="$XLIBSW $LIBS" >+ >+AC_MSG_CHECKING([XRegisterIMInstantiateCallback]) >+AC_TRY_LINK([ >+#include <X11/Xlib.h> >+], [ >+XRegisterIMInstantiateCallback(0, 0, 0, 0, 0, 0); >+], [ >+AC_MSG_RESULT(yes) >+X11_IMAKE_FLAGS="-DHAVE_XIMREGINSTCB" >+], [ >+AC_MSG_RESULT(no) >+]) >+ >+AC_MSG_CHECKING([XIDProc]) >+AC_TRY_COMPILE([ >+#include <X11/Xlib.h> >+], [ >+XIDProc *a; >+], [ >+AC_MSG_RESULT(yes) >+], [ >+AC_MSG_RESULT(no) >+X11_IMAKE_FLAGS="$X11_IMAKE_FLAGS -DNO_XIDPROC" >+]) >+ >+HAVE_XMKMF="" >+AC_PATH_PROG(HAVE_XMKMF, xmkmf, "", ${PATH}:/usr/X11R6/bin:/usr/X11R5/bin:/usr/local/X11R6/bin:/usr/local/X11R5/bi:/usr/openwin/bin:/usr/X11/bin:/usr/X386/bin:/usr/sww/bin:/usr/unsupported/bin) >+if test "X$HAVE_XMKMF" != "X"; then >+ IMAKE_FLAGS="" >+ if test -d ImakeCheck; then >+ rm -rf ImakeCheck >+ fi >+ mkdir ImakeCheck >+ cat << EOF > ImakeCheck/Imakefile >+SRCS = dummy.c >+OBJS = dummy.o >+ >+ComplexProgramTarget(dummy) >+EOF >+ cat << EOF > ImakeCheck/dummy.c >+static int justAnInt = 0; >+EOF >+ (cd ./ImakeCheck; rm -f Makefile Makefile.*; eval $HAVE_XMKMF) > /dev/null 2>&1 >+ for i in `(cd ./ImakeCheck; make -n dummy.o)` >+ do >+ case $i in -D*) IMAKE_FLAGS="$IMAKE_FLAGS $i";; esac >+ done >+ if test "X$IMAKE_FLAGS" != "X"; then >+ AC_MSG_RESULT(Add these flags for proper compile: $IMAKE_FLAGS) >+ X11_IMAKE_FLAGS="$X11_IMAKE_FLAGS $IMAKE_FLAGS" >+ fi >+ rm -rf ImakeCheck >+fi >+ >+# At last check FreeBSD and have -lxpg4. >+AC_MSG_CHECKING([system version (for additional locale library)]) >+if test -f /usr/lib/NextStep/software_version; then >+ system=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` >+else >+ system=`uname -s`-`uname -r` >+ if test "$?" -ne 0 ; then >+ system=unknown >+ else >+ # Special check for weird MP-RAS system (uname returns weird >+ # results, and the version is kept in special file). >+ >+ if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then >+ system=MP-RAS-`awk '{print $3}' /etc/.relid'` >+ fi >+ if test "`uname -s`" = "AIX" ; then >+ system=AIX-`uname -v`.`uname -r` >+ fi >+ fi >+fi >+ >+case $system in >+ FreeBSD-*) >+ LIBS="$XLIBSW -lxpg4 $tk_oldLibs" >+ CFLAGS="$CFLAGS $X11_IMAKE_FLAGS" >+ AC_TRY_COMPILE([ >+#include <locale.h> >+], [ >+(void)setlocale(LC_ALL, ""); >+], [ >+AC_MSG_RESULT(use xpg4 library.) >+XLIBSW="$XLIBSW -lxpg4" >+], [ >+AC_MSG_RESULT(no need other libraries.) >+]) >+ ;; >+ *) >+ AC_MSG_RESULT(No additional library is needed.) >+ ;; >+esac >+ >+CFLAGS=$tk_oldCflags >+LIBS=$tk_oldLibs >+ > AC_SUBST(TK_VERSION) > AC_SUBST(TK_MAJOR_VERSION) > AC_SUBST(TK_MINOR_VERSION) >@@ -548,6 +655,7 @@ > AC_SUBST(TK_DBGX) > > AC_SUBST(TK_SHARED_BUILD) >+AC_SUBST(X11_IMAKE_FLAGS) > AC_SUBST(LD_LIBRARY_PATH_VAR) > > AC_SUBST(TK_BUILD_LIB_SPEC) >--- unix/tkConfig.sh.in >+++ unix/tkConfig.sh.in >@@ -20,7 +20,7 @@ > TK_PATCH_LEVEL='@TK_PATCH_LEVEL@' > > # -D flags for use with the C compiler. >-TK_DEFS='@DEFS@' >+TK_DEFS='@DEFS@ @X11_IMAKE_FLAGS@' > > # Flag, 1: we built a shared lib, 0 we didn't > TK_SHARED_BUILD=@TK_SHARED_BUILD@ >--- unix/tkUnixEvent.c >+++ unix/tkUnixEvent.c >@@ -200,7 +200,7 @@ > * not be run for with these new releases. > */ > >-#if defined(TK_USE_INPUT_METHODS) && defined(PEEK_XCLOSEIM) >+#ifdef PEEK_XCLOSEIM > int do_peek = 0; > struct XIMPeek *peek; > >@@ -229,6 +229,9 @@ > #endif > XCloseIM(dispPtr->inputMethod); > } >+ if (dispPtr->imEncoding != NULL) { >+ Tcl_FreeEncoding(dispPtr->imEncoding); >+ } > #endif > > if (dispPtr->display != 0) { >@@ -354,6 +357,16 @@ > > while (numFound > 0) { > XNextEvent(display, &event); >+ /* >+ * To avoid Tk freezing by IM server's protocol bugs, >+ * Re-check queued event after an event is filterd. >+ * >+ * m-hirano >+ */ >+ if (XFilterEvent(&event, None) == True) { >+ numFound = XEventsQueued(display, QueuedAlready); >+ continue; >+ } > Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); > numFound--; > } >@@ -623,7 +636,177 @@ > */ > TransferXEventsToTcl(display); > } >+ > #ifdef TK_USE_INPUT_METHODS >+static int >+CanInitiateIm() >+{ >+ static int inited = 0; >+ static int ret = 0; >+ char *locale; >+ >+ /* >+ * Determine the current encoding from the LC_* or LANG environment >+ * variables. We previously used setlocale() to determine the locale, >+ * but this does not work on some systems (e.g. Linux/i386 RH 5.0). >+ */ >+ locale = getenv("LC_ALL"); >+ >+ if (locale == NULL || locale[0] == '\0') { >+ locale = getenv("LC_CTYPE"); >+ } >+ if (locale == NULL || locale[0] == '\0') { >+ locale = getenv("LANG"); >+ } >+ if (locale == NULL || locale[0] == '\0') { >+ return False; >+ } >+ >+ if (inited == 0) { >+ char *curSpec = setlocale(LC_ALL, NULL); >+ >+ inited = 1; >+ >+ if (strcmp(locale, "C") == 0 || >+ strcmp(locale, "POSIX") == 0) { >+ goto Checked; >+ } >+ >+ /* >+ * Ok I know, everyone of core Tcl/Tk developer hates this. >+ * believe it or not, it must be needed to call >+ * setlocale(3)/_Xsetlocale() VERY HERE. This is what the X >+ * input method wants. >+ * Note that X11's i18n implementation should be ONLY governed >+ * by LC_CTYPE. This is clearly/explicitly specified in X11 >+ * documente Chapter 13. Thus, If there are some X11 >+ * implementation that need using LC_ALL to initialize i18n >+ * subsystem, I won't care about such a X library. >+ * But, we are still on edge of darkside. ctype(3) routines >+ * are governed by LC_CTYPE.... Need to create "Locale >+ * independent ctype libraries" for Tcl/Tk... >+ * >+ * m-hirano >+ */ >+ >+ /* >+ * OK, First of all, setting WHOLE locale to "C". >+ */ >+ (void)setlocale(LC_ALL, "C"); >+ if (setlocale(LC_CTYPE, locale) == NULL) { >+ /* >+ * Reset to old locale. >+ */ >+ if (setlocale(LC_ALL, curSpec) == NULL) { >+ (void)setlocale(LC_ALL, "C"); >+ } >+ goto Checked; >+ } else { >+ /* >+ * For insurance, reset LC_NUMERIC to "C" for Tcl numeric parsing. >+ */ >+ (void)setlocale(LC_NUMERIC, "C"); >+ } >+ if (XSupportsLocale() != True) { >+ goto Checked; >+ } >+ ret = True; >+ /* >+ * At last, Setting the locale modifiers. >+ */ >+ (void)XSetLocaleModifiers(""); >+ } >+ >+Checked: >+ return ret; >+} >+ >+/* >+ *---------------------------------------------------------------------- >+ * >+ * IMInstantiateCallback >+ * >+ * Whenever IM server become available, this function will be called. >+ * >+ * Results: >+ * OpenIM() is called. >+ * >+ * Side effects: >+ * None. >+ * >+ *---------------------------------------------------------------------- >+ */ >+void >+IMInstantiateCallback(display, clientData, callData) >+Display *display; >+XPointer clientData; >+XPointer callData; >+{ >+ TkDisplay *dispPtr = (TkDisplay *)clientData; >+ >+ if (display == dispPtr->display && >+ dispPtr->inputMethod == NULL) { >+ OpenIM(dispPtr); >+ } >+} >+ >+/* >+ *---------------------------------------------------------------------- >+ * >+ * IMDestroyCallback >+ * >+ * Whenever IM server stops the service, this function will be called. >+ * >+ * Results: >+ * the XIM opened before is marked as unusable. >+ * >+ * Side effects: >+ * XIC using this XIM will be useless. >+ * >+ *---------------------------------------------------------------------- >+ */ >+void >+IMDestroyCallback(im, clientData, callData) >+XIM im; >+XPointer clientData; >+XPointer callData; >+{ >+ TkDisplay *dispPtr = (TkDisplay *)clientData; >+ if (im == dispPtr->inputMethod) { >+ Tcl_HashTable winTable = dispPtr->winTable; >+ Tcl_HashEntry *entry = NULL; >+ Tcl_HashSearch search; >+ TkWindow *winPtr; >+ >+ /* >+ * We must not call XCloseIM() or XDestroyIC(). >+ * because the XIM and XIC are destroyed by Xlib >+ * automatically. >+ */ >+ for (entry = Tcl_FirstHashEntry(&winTable, &search); entry != NULL; >+ entry = Tcl_NextHashEntry(&search)) { >+ winPtr = (TkWindow *)Tcl_GetHashValue(entry); >+ if (winPtr->dispPtr->display == dispPtr->display && >+ winPtr->dispPtr->inputMethod == im && >+ winPtr->inputContext != NULL) { >+ TkpDestroyIC(winPtr, 0); >+ } >+ Tcl_DStringFree(&(winPtr->composedDStr)); >+ Tcl_DStringInit(&(winPtr->composedDStr)); >+ } >+ dispPtr->inputMethod = NULL; >+ dispPtr->lastFocusedIC = NULL; >+#ifdef HAVE_XIMREGINSTCB >+#ifdef NO_XIDPROC >+ XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, >+ (XIMProc)IMInstantiateCallback, (XPointer *)dispPtr); >+#else >+ XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, >+ (XIDProc)IMInstantiateCallback, (XPointer)dispPtr); >+#endif /* NO_XIDPROC */ >+#endif /* HAVE_XIMREGINSTCB */ >+ } >+} > > /* > *-------------------------------------------------------------- >@@ -650,13 +833,32 @@ > { > unsigned short i; > XIMStyles *stylePtr; >+ int styleFound = 0; > >- if (XSetLocaleModifiers("") == NULL) { >- goto error; >+ dispPtr->inputMethod = NULL; >+ dispPtr->imEncoding = NULL; >+ dispPtr->lastFocusedIC = NULL; >+ dispPtr->isComposed = 0; >+ >+ if (CanInitiateIm() == False) { >+ return; > } > > dispPtr->inputMethod = XOpenIM(dispPtr->display, NULL, NULL, NULL); > if (dispPtr->inputMethod == NULL) { >+#ifdef HAVE_XIMREGINSTCB >+ /* >+ * Maybe no IM server is available right now. >+ * Try to register instantiate callback. >+ */ >+#ifdef NO_XIDPROC >+ XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, >+ (XIMProc)IMInstantiateCallback, (XPointer *)dispPtr); >+#else >+ XRegisterIMInstantiateCallback(dispPtr->display, NULL, NULL, NULL, >+ (XIDProc)IMInstantiateCallback, (XPointer)dispPtr); >+#endif /* NO_XIDPROC */ >+#endif /* HAVE_XIMREGINSTCB */ > return; > } > >@@ -681,12 +883,25 @@ > for (i = 0; i < stylePtr->count_styles; i++) { > if (stylePtr->supported_styles[i] > == (XIMPreeditNothing | XIMStatusNothing)) { >- XFree(stylePtr); >- return; >+ styleFound = 1; > } > } > XFree(stylePtr); > >+ if (styleFound == 1) { >+ /* >+ * Create a Tcl_Encoding for XmbLookupString() conversion. >+ */ >+ dispPtr->imEncoding = Tcl_GetEncoding(NULL, Tcl_GetEncodingName(NULL)); >+#ifdef XNDestroyCallback >+ dispPtr->destroyCallback.client_data = (XPointer)dispPtr; >+ dispPtr->destroyCallback.callback = (XIMProc)IMDestroyCallback; >+ (void)XSetIMValues(dispPtr->inputMethod, >+ XNDestroyCallback, &(dispPtr->destroyCallback), NULL); >+#endif /* XNDestroyCallback */ >+ return; >+ } >+ > error: > > if (dispPtr->inputMethod) { >--- unix/tkUnixIm.c >+++ unix/tkUnixIm.c >@@ -0,0 +1,261 @@ >+/* >+ * tkUnixIm.c -- >+ * >+ * This file contains modules to implement the XIM protocol session. >+ * This is the shrinked version of tkXIM.c, worte for tk8.0jp. >+ * >+ * Author: m-hirano@sra.co.jp >+ * >+ * Copyright 1999, 2000 Software Research Associates, Inc. >+ * >+ * Permission to use, copy, modify, and distribute this software and its >+ * documentation for any purpose and without fee is hereby granted, provided >+ * that the above copyright notice appear in all copies and that both that >+ * copyright notice and this permission notice appear in supporting >+ * documentation, and that the name of Software Research Associates not be >+ * used in advertising or publicity pertaining to distribution of the >+ * software without specific, written prior permission. Software Research >+ * Associates makes no representations about the suitability of this software >+ * for any purpose. It is provided "as is" without express or implied >+ * warranty. >+ */ >+ >+#if 0 >+static char rcsid[] = "$Header: /home/m-hirano/cvsroot/tcltk/tk8.1/unix/tkUnixIm.c,v 1.1 1999/05/10 00:39:16 m-hirano Exp $"; >+#endif >+ >+#include "tkPort.h" >+#include "tkInt.h" >+ >+#ifdef TK_USE_INPUT_METHODS >+ >+static void TkpIMGenericHandler _ANSI_ARGS_((ClientData clientData, XEvent *eventPtr)); >+static TkWindow * GetToplevel _ANSI_ARGS_((TkWindow *winPtr)); >+static void TkpCreateIMGenericHandler _ANSI_ARGS_((Tk_Window tkwin)); >+static void TkpDeleteIMGenericHandler _ANSI_ARGS_((Tk_Window tkwin)); >+ >+static TkWindow * >+GetToplevel(winPtr) >+ TkWindow *winPtr; >+{ >+ while (!(winPtr->flags & TK_TOP_LEVEL)) { >+ winPtr = winPtr->parentPtr; >+ if (winPtr == NULL) { >+ return NULL; >+ } >+ } >+ return winPtr; >+} >+ >+ >+static void >+TkpIMGenericHandler(clientData, eventPtr) >+ ClientData clientData; >+ XEvent *eventPtr; >+{ >+ Tk_Window tkwin = (Tk_Window)clientData; >+ TkWindow *winPtr = (TkWindow *)clientData; >+ >+ if (eventPtr->xany.window != Tk_WindowId(tkwin) || >+ winPtr->inputContext == NULL || >+ !(winPtr->flags & TK_CHECKED_IC)) { >+ /* >+ * Why ME ??? >+ */ >+ return; >+ } >+ >+ /* >+ * Well, should I care about Enter/Leave ? >+ */ >+ >+ switch (eventPtr->type) { >+ case KeyPress: >+ case FocusIn: { >+ Window root, child; >+ int rootX, rootY; >+ int wX, wY; >+ unsigned int mask; >+ >+ /* >+ * Care about case mouse pointer is not on winPtr->window. >+ * In such a case, IM server can't fetch any events from Tk. >+ */ >+ >+ if (XQueryPointer(winPtr->display, >+ RootWindow(winPtr->display, winPtr->screenNum), >+ &root, &child, &rootX, &rootY, &wX, &wY, &mask) == True) { >+ TkWindow *pWin = (TkWindow *)Tk_CoordsToWindow(rootX, rootY, >+ (Tk_Window)winPtr); >+ if (pWin != NULL && (pWin->window != winPtr->window)) { >+#if 0 >+ /* >+ * Code belows are what I REALLY want to do. But, >+ * in XIMPreeditPosition mode, IM server use the >+ * focus window as key event source window and as >+ * PreeditArea window by X11 specification. I want >+ * IM server to use this focus window ONLY as key >+ * event source. Means: >+ * >+ * o PreeditArea and PreeditPosition take place >+ * within client window (winPtr->window). >+ * o KeyPress event source is the window in which >+ * mouse pointer is (pWin->window). >+ */ >+ >+ if (XSetICValues(winPtr->inputContext, XNFocusWindow, >+ pWin->window, NULL) != NULL) { >+ fprintf(stderr, "debugIC: can't set IC focus to pointer window 0x%08x\n", >+ pWin->window); >+ } else { >+ fprintf(stderr, "debugIC: set IC focus to pointer window 0x%08x\n", >+ pWin->window); >+ } >+#endif >+ /* >+ * Check pWin and winPtr are in same toplevel. >+ * If they are NOT, don't change focus. >+ */ >+ TkWindow *pTop = GetToplevel(pWin); >+ TkWindow *wTop = GetToplevel(winPtr); >+ if (pTop == wTop) { >+ TkpChangeFocus(winPtr, 1); >+ } >+ } >+ } >+ /* >+ * Get current focused window. >+ */ >+ if (winPtr->dispPtr->lastFocusedIC != winPtr->inputContext) { >+ winPtr->dispPtr->lastFocusedIC = winPtr->inputContext; >+ XSetICFocus(winPtr->inputContext); >+ } >+ break; >+ } >+ >+ case FocusOut: { >+ winPtr->dispPtr->lastFocusedIC = None; >+ XUnsetICFocus(winPtr->inputContext); >+ break; >+ } >+ >+ case DestroyNotify: { >+ winPtr->dispPtr->lastFocusedIC = NULL; >+ XUnsetICFocus(winPtr->inputContext); >+ TkpDeleteIMGenericHandler(tkwin); >+ break; >+ } >+ } >+} >+ >+ >+static void >+TkpCreateIMGenericHandler(tkwin) >+ Tk_Window tkwin; >+{ >+ Tk_CreateEventHandler(tkwin, FocusChangeMask|StructureNotifyMask|KeyPressMask >+#if 0 >+ EnterWindowMask|LeaveWindowMask, >+#else >+ , >+#endif >+ (Tk_EventProc *)TkpIMGenericHandler, >+ (ClientData)tkwin); >+} >+ >+ >+static void >+TkpDeleteIMGenericHandler(tkwin) >+ Tk_Window tkwin; >+{ >+ Tk_DeleteEventHandler(tkwin, FocusChangeMask|StructureNotifyMask|KeyPressMask >+#if 0 >+ EnterWindowMask|LeaveWindowMask, >+#else >+ , >+#endif >+ (Tk_EventProc *)TkpIMGenericHandler, >+ (ClientData)tkwin); >+} >+ >+ >+XIC >+TkpCreateIC(winPtr) >+ TkWindow *winPtr; >+{ >+ if (winPtr->dispPtr->inputMethod != NULL && >+ !(winPtr->flags & TK_CHECKED_IC)) { >+ winPtr->inputContext = >+ XCreateIC(winPtr->dispPtr->inputMethod, >+ XNInputStyle, XIMPreeditNothing|XIMStatusNothing, >+ XNClientWindow, winPtr->window, >+ XNFocusWindow, winPtr->window, >+ NULL); >+ if (winPtr->inputContext != NULL) { >+ TkpCreateIMGenericHandler((Tk_Window)winPtr); >+ } >+ } >+ winPtr->flags |= TK_CHECKED_IC; >+ return winPtr->inputContext; >+} >+ >+ >+void >+TkpDestroyIC(winPtr, needDestroy) >+ TkWindow *winPtr; >+ int needDestroy; >+{ >+ TkpDeleteIMGenericHandler((Tk_Window)winPtr); >+ if (winPtr->inputContext == winPtr->dispPtr->lastFocusedIC) { >+ winPtr->dispPtr->lastFocusedIC = None; >+ } >+ if (needDestroy == 1 && >+ winPtr->inputContext != NULL) { >+ XDestroyIC(winPtr->inputContext); >+ } >+ winPtr->flags &= ~(TK_CHECKED_IC); >+ winPtr->inputContext = NULL; >+} >+ >+ >+int >+Tk_ImconfigureObjCmd(clientData, interp, objc, objv) >+ ClientData clientData; /* Main window associated with >+ * interpreter. */ >+ Tcl_Interp *interp; /* Current interpreter. */ >+ int objc; /* Number of arguments. */ >+ Tcl_Obj *CONST objv[]; /* Argument objects. */ >+{ >+ Tk_Window tkwin = (Tk_Window)clientData; >+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); >+ >+ if (objc < 2) { >+ Tcl_WrongNumArgs(interp, 1, objv, "path ?option? ?arg? ..."); >+ return TCL_ERROR; >+ } >+ >+ tkwin = Tk_NameToWindow(interp, Tcl_GetStringFromObj(objv[1], NULL), tkwin); >+ if (tkwin == NULL) { >+ return TCL_ERROR; >+ } >+ >+ if ((((TkWindow *)tkwin)->dispPtr->flags & TK_DISPLAY_USE_IM) == 0) { >+ /* >+ * Destroy XIC and leave. >+ */ >+ TkpDestroyIC((TkWindow *)tkwin, 1); >+ return TCL_OK; >+ } >+ >+ if (((TkWindow *)tkwin)->dispPtr->inputMethod == NULL) { >+ Tcl_AppendStringsToObj(resultPtr, "No IM server is available.", NULL); >+ return TCL_ERROR; >+ } >+ >+ Tcl_AppendStringsToObj(resultPtr, >+ (TkpCreateIC((TkWindow *)tkwin) != NULL) ? "1" : "0", >+ NULL); >+ return TCL_OK; >+} >+ >+#endif /* TK_USE_INPUT_METHODS */ >--- unix/tkUnixKey.c >+++ unix/tkUnixKey.c >@@ -88,6 +88,8 @@ > Status status; > #ifdef TK_USE_INPUT_METHODS > TkDisplay *dispPtr = winPtr->dispPtr; >+ Bool validString = False; >+ Bool usePreviousComposed = False; > #endif > > /* >@@ -98,8 +100,7 @@ > Tcl_DStringSetLength(&buf, TCL_DSTRING_STATIC_SIZE-1); > > #ifdef TK_USE_INPUT_METHODS >- if ((dispPtr->flags & TK_DISPLAY_USE_IM) >- && (winPtr->inputContext != NULL) >+ if ((winPtr->inputContext != NULL) > && (eventPtr->type == KeyPress)) { > #if TK_XIM_SPOT > XVaNestedList preedit_attr; >@@ -119,6 +120,11 @@ > Tcl_DStringValue(&buf), len, (KeySym *) NULL, &status); > } > if ((status != XLookupChars) && (status != XLookupBoth)) { >+ if (dispPtr->isComposed == 1 && >+ Tcl_DStringLength(&(winPtr->composedDStr)) > 0 && >+ dispPtr->flags & TK_DISPLAY_USE_IM) { >+ usePreviousComposed = True; >+ } > len = 0; > } > >@@ -136,10 +142,14 @@ > XFree(preedit_attr); > } > #endif >+ if (dispPtr->flags & TK_DISPLAY_USE_IM) { >+ validString = True; >+ } > } else { > len = XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf), > Tcl_DStringLength(&buf), (KeySym *) NULL, > (XComposeStatus *) NULL); >+ validString = True; > } > #else /* TK_USE_INPUT_METHODS */ > len = XLookupString(&eventPtr->xkey, Tcl_DStringValue(&buf), >@@ -147,10 +157,32 @@ > (XComposeStatus *) NULL); > #endif /* TK_USE_INPUT_METHODS */ > Tcl_DStringSetLength(&buf, len); >- >+#ifdef TK_USE_INPUT_METHODS >+ if (validString == True) { >+ if (usePreviousComposed == False) { >+ Tcl_ExternalToUtfDString(dispPtr->imEncoding, >+ Tcl_DStringValue(&buf), len, dsPtr); >+ Tcl_DStringFree(&(winPtr->composedDStr)); >+ Tcl_DStringInit(&(winPtr->composedDStr)); >+ Tcl_DStringAppend(&(winPtr->composedDStr), >+ Tcl_DStringValue(dsPtr), >+ Tcl_DStringLength(dsPtr)); >+ } else { >+ Tcl_DStringFree(dsPtr); >+ Tcl_DStringInit(dsPtr); >+ Tcl_DStringAppend(dsPtr, >+ Tcl_DStringValue(&(winPtr->composedDStr)), >+ Tcl_DStringLength(&(winPtr->composedDStr))); >+ } >+ } else { >+ Tcl_DStringFree(dsPtr); >+ Tcl_DStringInit(dsPtr); >+ } >+#else > Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&buf), len, dsPtr); >+#endif > Tcl_DStringFree(&buf); >- >+ > return Tcl_DStringValue(dsPtr); > } > >--- unix/tkUnixPort.h >+++ unix/tkUnixPort.h >@@ -81,6 +81,7 @@ > #include <X11/Xproto.h> > #include <X11/Xresource.h> > #include <X11/Xutil.h> >+#include <X11/Xlocale.h> > > /* > * The following macro defines the type of the mask arguments to
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
Actions:
View
|
Diff
Attachments on
bug 77424
: 48662 |
61935