*** generic/tkWindow.c.orig	Wed Apr 21 23:53:28 1999
--- generic/tkWindow.c	Sun Jan 16 17:43:05 2000
***************
*** 15,27 ****
--- 15,43 ----
   * RCS: @(#) $Id: tkWindow.c,v 1.8 1999/04/21 21:53:28 rjohnson Exp $
   */
  
+ #define reserved284 tcl_SetMainLoop
+ 
  #include "tkPort.h"
  #include "tkInt.h"
  
  #if !defined(__WIN32__) && !defined(MAC_TCL)
  #include "tkUnixInt.h"
  #endif
+ #if defined(__WIN32__)
+ #include "tkWinInt.h"
+ #endif
  
+ #ifndef USE_TCL_STUBS
+ extern TclStubs tclStubs;
+ #define tclStubsPtr (&tclStubs)
+ #endif
+ 
+ /*
+  * Make sure that Tcl_SetMainLoop always references the stub pointer, not
+  * the real function.
+  */
+ #undef Tcl_SetMainLoop
+ #define Tcl_SetMainLoop ((void (*) _ANSI_ARGS_((VOID *))) ((tclStubsPtr)->tcl_SetMainLoop))
  
  typedef struct ThreadSpecificData {
      int numMainWindows;    /* Count of numver of main windows currently
***************
*** 155,160 ****
--- 171,179 ----
  #ifdef MAC_TCL
      {"unsupported1",	TkUnsupported1Cmd,	NULL,			1, 1},
  #endif
+ #if defined(TK_USE_INPUT_METHODS) && defined(I18N_IMPROVE)
+     {"imconfigure",	NULL,			Tk_ImconfigureObjCmd,	1, 1},
+ #endif /* TK_USE_INPUT_METHODS && I18N_IMPROVE */
      {(char *) NULL,	(int (*) _ANSI_ARGS_((ClientData, Tcl_Interp *, int, char **))) NULL, NULL, 0}
  };
  
***************
*** 209,214 ****
--- 228,242 ----
  			    char *name));
  static void		OpenIM _ANSI_ARGS_((TkDisplay *dispPtr));
  static void		UnlinkWindow _ANSI_ARGS_((TkWindow *winPtr));
+ #ifdef TK_USE_INPUT_METHODS
+ #ifdef I18N_IMPROVE
+ static int		CanInitiateIm _ANSI_ARGS_((Tcl_Obj *locale));
+ static void		IMInstantiateCallback _ANSI_ARGS_ ((Display *display,
+ 				XPointer clientData, XPointer callData));
+ static void		IMDestroyCallback _ANSI_ARGS_ ((XIM im, XPointer clientData, 
+ 				XPointer callData));
+ #endif /* I18N_IMPROVE */
+ #endif /* TK_USE_INPUT_METHODS */
  
  /*
   *----------------------------------------------------------------------
***************
*** 1269,1275 ****
      TkBindDeadWindow(winPtr);
  #ifdef TK_USE_INPUT_METHODS
      if (winPtr->inputContext != NULL) {
! 	XDestroyIC(winPtr->inputContext);
      }
  #endif /* TK_USE_INPUT_METHODS */
      if (winPtr->tagPtr != NULL) {
--- 1297,1307 ----
      TkBindDeadWindow(winPtr);
  #ifdef TK_USE_INPUT_METHODS
      if (winPtr->inputContext != NULL) {
! #ifdef I18N_IMPROVE
! 	TkpDestroyIC(winPtr, 1);
! #else
!   	XDestroyIC(winPtr->inputContext);
! #endif /* I18N_IMPROVE */
      }
  #endif /* TK_USE_INPUT_METHODS */
      if (winPtr->tagPtr != NULL) {
***************
*** 2422,2427 ****
--- 2454,2617 ----
  {
      return ((TkWindow *) tkwin)->mainPtr->strictMotif;
  }
+ #ifdef TK_USE_INPUT_METHODS
+ #ifdef I18N_IMPROVE
+ 
+ static int
+ CanInitiateIm(loc)
+      Tcl_Obj *loc;
+ {
+     static int inited = 0;
+     static int ret = 0;
+     char *locale = Tcl_GetString(loc);
+ 
+     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);
+ 	    }
+ 	}
+ 	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 */
+     }
+ }
+ #endif /* I18N_IMPROVE */
+ #endif /* TK_USE_INPUT_METHODS */
  
  /* 
   *--------------------------------------------------------------
***************
*** 2452,2459 ****
--- 2642,2683 ----
      unsigned short i;
      XIMStyles *stylePtr;
  
+ #ifdef I18N_IMPROVE
+     int styleFound = 0;
+     Tcl_Obj *imLocale = NULL;
+     Tcl_Obj *imEncoding = NULL;
+ 
+     dispPtr->inputMethod = NULL;
+     dispPtr->imEncoding = NULL;
+     dispPtr->lastFocusedIC = NULL;
+ 
+ #ifdef TCL_ACTIVE
+     TclpGetStartupLocaleEncoding(&imEncoding, &imLocale);
+ #endif
+     if (imEncoding == NULL || imLocale == NULL) {
+ 	return;
+     }
+     if (CanInitiateIm(imLocale) == False) {
+ 	return;
+     }
+ #endif /* I18N_IMPROVE */
      dispPtr->inputMethod = XOpenIM(dispPtr->display, NULL, NULL, NULL);
      if (dispPtr->inputMethod == NULL) {
+ #ifdef I18N_IMPROVE
+ #ifdef HAVE_XIMREGINSTCB
+ 	/*
+ 	 * Maybe no IM server is available rite now.
+ 	 * Try to register instatntiate 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 */
+ #endif /* I18N_IMPROVE */
  	return;
      }
  
***************
*** 2464,2474 ****
      for (i = 0; i < stylePtr->count_styles; i++) {
  	if (stylePtr->supported_styles[i]
  		== (XIMPreeditNothing|XIMStatusNothing)) {
! 	    XFree(stylePtr);
! 	    return;
  	}
      }
      XFree(stylePtr);
  
      error:
  
--- 2688,2717 ----
      for (i = 0; i < stylePtr->count_styles; i++) {
  	if (stylePtr->supported_styles[i]
  		== (XIMPreeditNothing|XIMStatusNothing)) {
! #ifdef I18N_IMPROVE
! 	    styleFound = 1;
! #else
!   	    XFree(stylePtr);
!   	    return;
! #endif /* I18N_IMPROVE */
  	}
      }
      XFree(stylePtr);
+ #ifdef I18N_IMPROVE
+     if (styleFound == 1) {
+ 	/*
+ 	 * Create a Tcl_Encoding for XmbLookupString() conversion.
+ 	 */
+ 	dispPtr->imEncoding = Tcl_GetEncoding(NULL, Tcl_GetString(imEncoding));
+ #ifdef XNDestroyCallback
+ 	dispPtr->destroyCallback.client_data = (XPointer)dispPtr;
+ 	dispPtr->destroyCallback.callback = (XIMProc)IMDestroyCallback;
+ 	(void)XSetIMValues(dispPtr->inputMethod,
+ 			   XNDestroyCallback, &(dispPtr->destroyCallback), NULL);
+ #endif /* XNDestroyCallback */	
+ 	return;
+     }
+ #endif /* I18N_IMPROVE */
  
      error:
  
***************
*** 2709,2714 ****
--- 2952,2967 ----
      Tcl_DString class;
      ThreadSpecificData *tsdPtr;
      
+ #if defined(__WIN32__) && defined(STATIC_BUILD) && !defined(NO_STATIC_INIT)
+     /*
+      * If we are in a statically linked executable, then we need to
+      * explicitly initialize the Windows function tables here since
+      * DllMain() will not be invoked.
+      */
+ 
+     TkWinXInit(GetModuleHandle(NULL));
+ #endif
+ 
      /*
       * Ensure that we are getting the matching version of Tcl.  This is
       * really only an issue when Tk is loaded dynamically.
***************
*** 2935,2941 ****
      }
      Tcl_MutexUnlock(&windowMutex);
  
!     if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) {
  	code = TCL_ERROR;
  	goto done;
      }
--- 3188,3194 ----
      }
      Tcl_MutexUnlock(&windowMutex);
  
!     if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 0) == NULL) {
  	code = TCL_ERROR;
  	goto done;
      }
***************
*** 2949,2959 ****
--- 3202,3214 ----
  	goto done;
      }
  
+ #ifndef __WIN32__
  #ifdef Tk_InitStubs
  #undef Tk_InitStubs
  #endif
  
      Tk_InitStubs(interp, TK_VERSION, 1);
+ #endif
  
      /*
       * Invoke platform-specific initialization.
***************
*** 2961,2969 ****
--- 3216,3231 ----
  
      code = TkpInit(interp);
  
+     if (Tcl_SetMainLoop) {
+ 	Tcl_SetMainLoop(Tk_GetNumMainWindows);
+     }
+ 
      done:
      if (argv != NULL) {
  	ckfree((char *) argv);
+     }
+     if (code != TCL_ERROR) {
+ 	code = TCL_OK;
      }
      return code;
  }
