*** unix/tkUnixIm.c.orig	Sun Jan 16 17:43:02 2000
--- unix/tkUnixIm.c	Sun Jan 16 17:43:02 2000
***************
*** 0 ****
--- 1,255 ----
+ /* 
+  * 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 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
+ #ifdef I18N_IMPROVE
+ 
+ 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->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 /* I18N_IMPROVE */
+ #endif /* TK_USE_INPUT_METHODS */
