summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhobbs <hobbs>2001-03-30 23:50:17 (GMT)
committerhobbs <hobbs>2001-03-30 23:50:17 (GMT)
commit739d4321a3b8dd6e1073ecb19aa5b09eb5893571 (patch)
treeaf9d10c78323c178cd299b0ebd3b034ee96b1b25
parent0dcaafd32b3ba64d04c60046ecbc7d774e60de66 (diff)
downloadtk-739d4321a3b8dd6e1073ecb19aa5b09eb5893571.zip
tk-739d4321a3b8dd6e1073ecb19aa5b09eb5893571.tar.gz
tk-739d4321a3b8dd6e1073ecb19aa5b09eb5893571.tar.bz2
* win/makefile.vc:
* win/configure: * win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support. * win/tkWinInt.h: * win/tkWinKey.c: * win/tkWinX.c: added support for changing IME on the fly in Windows (2000). (lam) [Patch #402993]
-rw-r--r--ChangeLog24
-rwxr-xr-xwin/configure2
-rw-r--r--win/makefile.vc5
-rw-r--r--win/tcl.m42
-rw-r--r--win/tkWinInt.h4
-rw-r--r--win/tkWinKey.c29
-rw-r--r--win/tkWinX.c240
7 files changed, 288 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index c282062..829de88 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2001-03-30 Jeff Hobbs <jeffh@ActiveState.com>
+
+ * win/makefile.vc:
+ * win/configure:
+ * win/tcl.m4: added imm32.lib to LIBS_GUI for Tk IME support.
+ * win/tkWinInt.h:
+ * win/tkWinKey.c:
+ * win/tkWinX.c: added support for changing IME on the fly in
+ Windows (2000). (lam) [Patch #402993]
+
+ * tests/bind.test (bind-22.18):
+ * generic/tkBind.c (NameToWindow): handled the error case where a
+ valid-looking but invalid identifier could be passed in certain
+ event generate options causing a crash. [Bug #411307]
+
+ * win/tkWinWm.c (UpdateWrapper): ensured that the passed in winPtr
+ had an existent window to operate on. [Bug #409172]
+
+ * win/Makefile.in (install-*): improved install-* targets to use
+ their base build dependency.
+
+ * generic/tkImage.c (Tk_ImageObjCmd, EventuallyDeleteImage):
+ added casts to allow compiling on Windows with debbuging.
+
2001-03-29 Jeff Hobbs <jeffh@ActiveState.com>
* library/msgs/de.msg: fixed translations. [Patch #403525]
diff --git a/win/configure b/win/configure
index dcfce43..ecaed2e 100755
--- a/win/configure
+++ b/win/configure
@@ -1234,7 +1234,7 @@ echo "configure:1192: checking whether $ld_prog supports -shared option" >&5
SHLIB_LD="link -dll -nologo"
SHLIB_LD_LIBS="user32.lib advapi32.lib"
LIBS="user32.lib advapi32.lib"
- LIBS_GUI="gdi32.lib comdlg32.lib"
+ LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib"
AR="lib -nologo"
STLIB_LD="lib -nologo"
RC="rc"
diff --git a/win/makefile.vc b/win/makefile.vc
index 3171c87..2c4ebd6 100644
--- a/win/makefile.vc
+++ b/win/makefile.vc
@@ -6,7 +6,7 @@
# Copyright (c) 1995-1997 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
#
-# RCS: @(#) $Id: makefile.vc,v 1.39 2000/11/03 01:16:30 hobbs Exp $
+# RCS: @(#) $Id: makefile.vc,v 1.40 2001/03/30 23:50:17 hobbs Exp $
# Does not depend on the presence of any environment variables in
# order to compile tcl; all needed information is derived from
@@ -317,7 +317,8 @@ libcdll = msvcrt$(DBGX).lib oldnames.lib
!ENDIF
baselibs = kernel32.lib $(optlibs) advapi32.lib
-winlibs = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib
+winlibs = $(baselibs) user32.lib gdi32.lib comdlg32.lib winspool.lib \
+ imm32.lib
guilibs = $(libc) $(winlibs)
conlibs = $(libc) $(baselibs)
guilibsdll = $(libcdll) $(winlibs)
diff --git a/win/tcl.m4 b/win/tcl.m4
index 29e64fc..e25a999 100644
--- a/win/tcl.m4
+++ b/win/tcl.m4
@@ -444,7 +444,7 @@ AC_DEFUN(SC_CONFIG_CFLAGS, [
SHLIB_LD="link -dll -nologo"
SHLIB_LD_LIBS="user32.lib advapi32.lib"
LIBS="user32.lib advapi32.lib"
- LIBS_GUI="gdi32.lib comdlg32.lib"
+ LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib"
AR="lib -nologo"
STLIB_LD="lib -nologo"
RC="rc"
diff --git a/win/tkWinInt.h b/win/tkWinInt.h
index 710779a..57eef8d 100644
--- a/win/tkWinInt.h
+++ b/win/tkWinInt.h
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinInt.h,v 1.10 2000/04/12 18:51:11 hobbs Exp $
+ * RCS: @(#) $Id: tkWinInt.h,v 1.11 2001/03/30 23:50:17 hobbs Exp $
*/
#ifndef _TKWININT
@@ -167,5 +167,7 @@ EXTERN void TkWinUpdatingClipboard(int mode);
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
+extern Tcl_Encoding TkWinGetKeyInputEncoding _ANSI_ARGS_((void));
+
#endif /* _TKWININT */
diff --git a/win/tkWinKey.c b/win/tkWinKey.c
index bb61d23..e2b67dd 100644
--- a/win/tkWinKey.c
+++ b/win/tkWinKey.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinKey.c,v 1.12 2000/04/15 17:41:20 hobbs Exp $
+ * RCS: @(#) $Id: tkWinKey.c,v 1.13 2001/03/30 23:50:17 hobbs Exp $
*/
#include "tkWinInt.h"
@@ -90,7 +90,29 @@ TkpGetString(winPtr, eventPtr, dsPtr)
XKeyEvent* keyEv = &eventPtr->xkey;
Tcl_DStringInit(dsPtr);
- if (eventPtr->xkey.send_event != -1) {
+ if (eventPtr->xkey.send_event == -1) {
+ if (eventPtr->xkey.nbytes > 0) {
+ Tcl_ExternalToUtfDString(TkWinGetKeyInputEncoding(),
+ eventPtr->xkey.trans_chars, eventPtr->xkey.nbytes, dsPtr);
+ }
+ } else if (eventPtr->xkey.send_event == -2) {
+ /*
+ * Special case for win2000 multi-lingal IME input.
+ * xkey.trans_chars[] already contains a UNICODE char.
+ */
+
+ int unichar;
+ char buf[TCL_UTF_MAX];
+ int len;
+
+ unichar = (eventPtr->xkey.trans_chars[1] & 0xff);
+ unichar <<= 8;
+ unichar |= (eventPtr->xkey.trans_chars[0] & 0xff);
+
+ len = Tcl_UniCharToUtf((Tcl_UniChar) unichar, buf);
+
+ Tcl_DStringAppend(dsPtr, buf, len);
+ } else {
/*
* This is an event generated from generic code. It has no
* nchars or trans_chars members.
@@ -105,9 +127,6 @@ TkpGetString(winPtr, eventPtr, dsPtr)
int len = Tcl_UniCharToUtf((Tcl_UniChar) (keysym & 255), buf);
Tcl_DStringAppend(dsPtr, buf, len);
}
- } else if (eventPtr->xkey.nbytes > 0) {
- Tcl_ExternalToUtfDString(NULL, eventPtr->xkey.trans_chars,
- eventPtr->xkey.nbytes, dsPtr);
}
return Tcl_DStringValue(dsPtr);
}
diff --git a/win/tkWinX.c b/win/tkWinX.c
index 0325df7..1b2c0e7 100644
--- a/win/tkWinX.c
+++ b/win/tkWinX.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkWinX.c,v 1.11 2000/07/06 03:17:45 mo Exp $
+ * RCS: @(#) $Id: tkWinX.c,v 1.12 2001/03/30 23:50:18 hobbs Exp $
*/
#include "tkWinInt.h"
@@ -30,6 +30,10 @@ static HINSTANCE tkInstance; /* Application instance handle. */
static int childClassInitialized; /* Registered child class? */
static WNDCLASS childClass; /* Window class for child windows. */
static int tkPlatformId; /* version of Windows platform */
+static Tcl_Encoding keyInputEncoding = NULL;/* The current character
+ * encoding for keyboard input */
+static int keyInputCharset = -1; /* The Win32 CHARSET for the keyboard
+ * encoding */
/*
* Thread local storage. Notice that now each thread must have its
@@ -52,6 +56,9 @@ static void GenerateXEvent _ANSI_ARGS_((HWND hwnd, UINT message,
static unsigned int GetState _ANSI_ARGS_((UINT message, WPARAM wParam,
LPARAM lParam));
static void GetTranslatedKey _ANSI_ARGS_((XKeyEvent *xkey));
+static void UpdateInputLanguage _ANSI_ARGS_((int charset));
+static int HandleIMEComposition _ANSI_ARGS_((HWND hwnd,
+ LPARAM lParam));
/*
*----------------------------------------------------------------------
@@ -524,6 +531,18 @@ TkWinChildProc(hwnd, message, wParam, lParam)
LRESULT result;
switch (message) {
+ case WM_INPUTLANGCHANGE:
+ UpdateInputLanguage(wParam);
+ result = 1;
+ break;
+
+ case WM_IME_COMPOSITION:
+ result = 0;
+ if (HandleIMEComposition(hwnd, lParam) == 0) {
+ result = DefWindowProc(hwnd, message, wParam, lParam);
+ }
+ break;
+
case WM_SETCURSOR:
/*
* Short circuit the WM_SETCURSOR message since we set
@@ -826,13 +845,11 @@ GenerateXEvent(hwnd, message, wParam, lParam)
/*
* Check for translated characters in the event queue.
* Setting xany.send_event to -1 indicates to the
- * Windows implementation of XLookupString that this
+ * Windows implementation of TkpGetString() that this
* event was generated by windows and that the Windows
* extension xkey.trans_chars is filled with the
- * characters that came from the TranslateMessage
- * call. If it is not -1, xkey.keycode is the
- * virtual key being sent programmatically by generic
- * code.
+ * MBCS characters that came from the TranslateMessage
+ * call.
*/
event.type = KeyPress;
@@ -1017,7 +1034,6 @@ GetTranslatedKey(xkey)
XKeyEvent *xkey;
{
MSG msg;
- char buf[XMaxTransChars];
xkey->nbytes = 0;
@@ -1037,9 +1053,21 @@ GetTranslatedKey(xkey)
if ((msg.message == WM_CHAR) && (msg.lParam & 0x20000000)) {
xkey->state = 0;
}
- buf[xkey->nbytes] = (char) msg.wParam;
xkey->trans_chars[xkey->nbytes] = (char) msg.wParam;
xkey->nbytes++;
+
+ if (((unsigned short) msg.wParam) > ((unsigned short) 0xff)) {
+ /*
+ * Some "addon" input devices, such as the popular
+ * PenPower Chinese writing pad, generate 16 bit
+ * values in WM_CHAR messages (instead of passing them
+ * in two separate WM_CHAR messages containing two
+ * 8-bit values.
+ */
+
+ xkey->trans_chars[xkey->nbytes] = (char) (msg.wParam >> 8);
+ xkey->nbytes ++;
+ }
} else {
break;
}
@@ -1049,6 +1077,202 @@ GetTranslatedKey(xkey)
/*
*----------------------------------------------------------------------
*
+ * UpdateInputLanguage --
+ *
+ * Gets called when a WM_INPUTLANGCHANGE message is received
+ * by the TK child window procedure. This message is sent
+ * by the Input Method Editor system when the user chooses
+ * a different input method. All subsequent WM_CHAR
+ * messages will contain characters in the new encoding. We record
+ * the new encoding so that TkpGetString() knows how to
+ * correctly translate the WM_CHAR into unicode.
+ *
+ * Results:
+ * Records the new encoding in keyInputEncoding.
+ *
+ * Side effects:
+ * Old value of keyInputEncoding is freed.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateInputLanguage(charset)
+ int charset;
+{
+ CHARSETINFO charsetInfo;
+ Tcl_Encoding encoding;
+ char codepage[4 + TCL_INTEGER_SPACE];
+
+ if (keyInputCharset == charset) {
+ return;
+ }
+ if (TranslateCharsetInfo((DWORD*)charset, &charsetInfo, TCI_SRCCHARSET)
+ == 0) {
+ /*
+ * Some mysterious failure.
+ */
+
+ return;
+ }
+
+ wsprintfA(codepage, "cp%d", charsetInfo.ciACP);
+
+ if ((encoding = Tcl_GetEncoding(NULL, codepage)) == NULL) {
+ /*
+ * The encoding is not supported by Tcl.
+ */
+
+ return;
+ }
+
+ if (keyInputEncoding != NULL) {
+ Tcl_FreeEncoding(keyInputEncoding);
+ }
+
+ keyInputEncoding = encoding;
+ keyInputCharset = charset;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkWinGetKeyInputEncoding --
+ *
+ * Returns the current keyboard input encoding selected by the
+ * user (with WM_INPUTLANGCHANGE events).
+ *
+ * Results:
+ * The current keyboard input encoding.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Encoding
+TkWinGetKeyInputEncoding()
+{
+ return keyInputEncoding;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * HandleIMEComposition --
+ *
+ * This function works around a definciency in some versions
+ * of Windows 2000 to make it possible to entry multi-lingual
+ * characters under all versions of Windows 2000.
+ *
+ * When an Input Method Editor (IME) is ready to send input
+ * characters to an application, it sends a WM_IME_COMPOSITION
+ * message with the GCS_RESULTSTR. However, The DefWindowProc()
+ * on English Windows 2000 arbitrarily converts all non-Latin-1
+ * characters in the composition to "?".
+ *
+ * This function correctly processes the composition data and
+ * sends the UNICODE values of the composed characters to
+ * TK's event queue.
+ *
+ * Results:
+ * If this function has processed the composition data, returns 1.
+ * Otherwise returns 0.
+ *
+ * Side effects:
+ * Key events are put into the TK event queue.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+HandleIMEComposition(hwnd, lParam)
+ HWND hwnd; /* Window receiving the message. */
+ LPARAM lParam; /* Flags for the WM_IME_COMPOSITION
+ * message */
+{
+ HIMC hIMC;
+ int i, n;
+ XEvent event;
+ char * buff;
+ TkWindow *winPtr;
+
+ if (tkPlatformId != VER_PLATFORM_WIN32_NT) {
+ /*
+ * The ImmGetCompositionStringW function works only on WinNT.
+ */
+
+ return 0;
+ }
+
+ if ((lParam & GCS_RESULTSTR) == 0) {
+ /*
+ * Composition is not finished yet.
+ */
+
+ return 0;
+ }
+
+ hIMC = ImmGetContext(hwnd);
+ if (hIMC) {
+ n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
+
+ if (n > 0) {
+ buff = (char*)ckalloc(n);
+ n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n);
+
+ /*
+ * Set up the fields pertinent to key event.
+ *
+ * We set send_event to the special value of -2, so that
+ * TkpGetString() in tkWinKey.c knows that trans_chars[]
+ * already contains a UNICODE char and there's no need to
+ * do encoding conversion.
+ */
+
+ winPtr = (TkWindow *)Tk_HWNDToWindow(hwnd);
+
+ event.xkey.serial = winPtr->display->request++;
+ event.xkey.send_event = -2;
+ event.xkey.display = winPtr->display;
+ event.xkey.window = winPtr->window;
+ event.xkey.root = RootWindow(winPtr->display, winPtr->screenNum);
+ event.xkey.subwindow = None;
+ event.xkey.state = TkWinGetModifierState();
+ event.xkey.time = TkpGetMS();
+ event.xkey.same_screen = True;
+ event.xkey.keycode = 0;
+ event.xkey.nbytes = 2;
+
+ for (i=0; i<n;) {
+ /*
+ * Simulate a pair of KeyPress and KeyRelease events
+ * for each UNICODE character in the composition.
+ */
+
+ event.xkey.trans_chars[0] = (char) buff[i++];
+ event.xkey.trans_chars[1] = (char) buff[i++];
+
+ event.type = KeyPress;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+
+ event.type = KeyRelease;
+ Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
+ }
+
+ ckfree(buff);
+ }
+ ImmReleaseContext(hwnd, hIMC);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tk_FreeXId --
*
* This inteface is not needed under Windows.