From f444906e071e6d6d5f276130ab2c53ef4f67aa31 Mon Sep 17 00:00:00 2001 From: nijtmans Date: Wed, 24 Nov 2010 15:15:25 +0000 Subject: re-wrote TkpDisplayWarning such that it does not use an Tcl API calls any more, so it works even with an ill-initialized Tcl Teach WishPanic how to thread UTF-8 in it's messagebox. Both of those changes backported from Tcl 8.6. No change in functionality. --- ChangeLog | 4 +++ win/tkWinInit.c | 24 +++++++---------- win/winMain.c | 82 +++++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 75 insertions(+), 35 deletions(-) diff --git a/ChangeLog b/ChangeLog index f527e47..61d0045 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ 2010-11-24 Jan Nijtmans * win/tkWinDialog.c: [Bug #3071836]: Crash/Tcl_Panic on WinXP saving file to C:\ + * win/tkWinInit.c: re-wrote TkpDisplayWarning such that it does not use + an Tcl API calls any more, so it works even with an ill-initialized Tcl. + * win/winMain.c: Teach WishPanic how to thread UTF-8 in it's messagebox. + Both of those changes backported from Tcl 8.6. No change in functionality. 2010-11-19 Jan Nijtmans diff --git a/win/tkWinInit.c b/win/tkWinInit.c index 1a7f2be..b149996 100644 --- a/win/tkWinInit.c +++ b/win/tkWinInit.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: tkWinInit.c,v 1.14 2007/12/13 15:28:55 dgp Exp $ + * RCS: @(#) $Id: tkWinInit.c,v 1.14.2.1 2010/11/24 15:15:25 nijtmans Exp $ */ #include "tkWinInt.h" @@ -118,27 +118,21 @@ TkpDisplayWarning( CONST char *msg, /* Message to be displayed. */ CONST char *title) /* Title of warning. */ { - Tcl_DString msgString, titleString; - Tcl_Encoding unicodeEncoding = TkWinGetUnicodeEncoding(); +#define TK_MAX_WARN_LEN 1024 + WCHAR msgString[TK_MAX_WARN_LEN + 5]; + WCHAR titleString[TK_MAX_WARN_LEN + 1]; + MultiByteToWideChar(CP_UTF8, 0, msg, -1, msgString, TK_MAX_WARN_LEN); + MultiByteToWideChar(CP_UTF8, 0, title, -1, titleString, TK_MAX_WARN_LEN); /* * Truncate MessageBox string if it is too long to not overflow the screen * and cause possible oversized window error. */ - -#define TK_MAX_WARN_LEN (1024 * sizeof(WCHAR)) - Tcl_UtfToExternalDString(unicodeEncoding, msg, -1, &msgString); - Tcl_UtfToExternalDString(unicodeEncoding, title, -1, &titleString); - if (Tcl_DStringLength(&msgString) > TK_MAX_WARN_LEN) { - Tcl_DStringSetLength(&msgString, TK_MAX_WARN_LEN); - Tcl_DStringAppend(&msgString, (char *) L" ...", 4 * sizeof(WCHAR)); - } - MessageBoxW(NULL, (WCHAR *) Tcl_DStringValue(&msgString), - (WCHAR *) Tcl_DStringValue(&titleString), + memcpy(msgString + TK_MAX_WARN_LEN, L" ...", 5 * sizeof(WCHAR)); + titleString[TK_MAX_WARN_LEN] = L'\0'; + MessageBoxW(NULL, msgString, titleString, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL | MB_SETFOREGROUND | MB_TOPMOST); - Tcl_DStringFree(&msgString); - Tcl_DStringFree(&titleString); } /* diff --git a/win/winMain.c b/win/winMain.c index 273cf0f..57979f3 100644 --- a/win/winMain.c +++ b/win/winMain.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: winMain.c,v 1.26.2.1 2010/05/31 13:47:33 nijtmans Exp $ + * RCS: @(#) $Id: winMain.c,v 1.26.2.2 2010/11/24 15:15:25 nijtmans Exp $ */ #include "tkInt.h" @@ -23,15 +23,21 @@ * The following declarations refer to internal Tk routines. These interfaces * are available for use, but are not supported. */ +#ifdef TK_TEST +extern Tcl_PackageInitProc Tktest_Init; +#endif /* TK_TEST */ + +#if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES +extern Tcl_PackageInitProc Registry_Init; +extern Tcl_PackageInitProc Dde_Init; +extern Tcl_PackageInitProc Dde_SafeInit; +#endif /* * Forward declarations for procedures defined later in this file: */ static void WishPanic(CONST char *format, ...); -#ifdef TK_TEST -extern int Tktest_Init(Tcl_Interp *interp); -#endif /* TK_TEST */ #if defined(__CYGWIN__) static void setargv(int *argcPtr, char ***argvPtr); @@ -156,6 +162,9 @@ int Tcl_AppInit( Tcl_Interp *interp) /* Interpreter for application. */ { +#define TK_MAX_WARN_LEN 1024 + WCHAR msgString[TK_MAX_WARN_LEN + 5]; + if (Tcl_Init(interp) == TCL_ERROR) { goto error; } @@ -175,20 +184,15 @@ Tcl_AppInit( } } #if defined(STATIC_BUILD) && TCL_USE_STATIC_PACKAGES - { - extern Tcl_PackageInitProc Registry_Init; - extern Tcl_PackageInitProc Dde_Init; - - if (Registry_Init(interp) == TCL_ERROR) { - return TCL_ERROR; - } - Tcl_StaticPackage(interp, "registry", Registry_Init, NULL); + if (Registry_Init(interp) == TCL_ERROR) { + goto error; + } + Tcl_StaticPackage(interp, "registry", Registry_Init, NULL); - if (Dde_Init(interp) == TCL_ERROR) { - return TCL_ERROR; - } - Tcl_StaticPackage(interp, "dde", Dde_Init, NULL); - } + if (Dde_Init(interp) == TCL_ERROR) { + goto error; + } + Tcl_StaticPackage(interp, "dde", Dde_Init, NULL); #endif #ifdef TK_TEST @@ -198,12 +202,43 @@ Tcl_AppInit( Tcl_StaticPackage(interp, "Tktest", Tktest_Init, NULL); #endif /* TK_TEST */ + /* + * Call the init procedures for included packages. Each call should look + * like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. (Dynamically-loadable packages + * should have the same entry-point name.) + */ + + /* + * Call Tcl_CreateCommand for application-specific commands, if they + * weren't already created by the init procedures called above. + */ + + /* + * Specify a user-specific startup file to invoke if the application is + * run interactively. Typically the startup file is "~/.apprc" where "app" + * is the name of the application. If this line is deleted then no user- + * specific startup file will be run under any conditions. + */ + Tcl_SetVar(interp, "tcl_rcFileName", "~/wishrc.tcl", TCL_GLOBAL_ONLY); return TCL_OK; error: + MultiByteToWideChar(CP_UTF8, 0, Tcl_GetStringResult(interp), -1, + msgString, TK_MAX_WARN_LEN); + /* + * Truncate MessageBox string if it is too long to not overflow the screen + * and cause possible oversized window error. + */ + memcpy(msgString + TK_MAX_WARN_LEN, L" ...", 5 * sizeof(WCHAR)); MessageBeep(MB_ICONEXCLAMATION); - MessageBox(NULL, Tcl_GetStringResult(interp), "Error in Wish", + MessageBoxW(NULL, msgString, L"Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); ExitProcess(1); @@ -235,13 +270,20 @@ WishPanic( CONST char *format, ...) { va_list argList; - char buf[1024]; + char buf[TK_MAX_WARN_LEN]; + WCHAR msgString[TK_MAX_WARN_LEN + 5]; va_start(argList, format); vsprintf(buf, format, argList); + MultiByteToWideChar(CP_UTF8, 0, buf, -1, msgString, TK_MAX_WARN_LEN); + /* + * Truncate MessageBox string if it is too long to not overflow the screen + * and cause possible oversized window error. + */ + memcpy(msgString + TK_MAX_WARN_LEN, L" ...", 5 * sizeof(WCHAR)); MessageBeep(MB_ICONEXCLAMATION); - MessageBox(NULL, buf, "Fatal Error in Wish", + MessageBoxW(NULL, msgString, L"Fatal Error in Wish", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND); #ifdef _MSC_VER DebugBreak(); -- cgit v0.12