From d0234726eb4b759870dace2f272efee107024394 Mon Sep 17 00:00:00 2001 From: hobbs Date: Fri, 31 Mar 2000 09:24:26 +0000 Subject: * win/tkWinDialog.c: added unicode-aware open/save file dialogs * win/tkWinFont.c (TkpFontPkgInit): move private ref to platformId to TkWinGetPlatformId * win/tkWinMenu.c (SetDefaults): moved private use of versionInfo to TkWinGetPlatformId and removed all code for (versionInfo.dwMajorVersion < 4) (== Win32s) * win/tkWinX.c: * win/tkWin32Dll.c: moved TkWinGetPlatformId to tkWinX.c * win/tkWinInit.c: added TkWinXInit to TkpInit to ensure that its called for static Windows shells. [Bug: 3647] * win/tkWinInt.h: * win/tkWinX.c: * win/tkWinDraw.c (SetUpGraphicsPort): * win/tkWinScrlbr.c (UpdateScrollbar): removed use of tkpIsWin32s * win/tkWinInt.h (TkWinDCState struct): added bkmode value * win/tkWinDraw.c (TkWinGetDrawableDC, et al): added support for properly transparent dashed lines on Windows. [Bug: 4617] --- win/tkWin32Dll.c | 36 +----- win/tkWinDialog.c | 346 +++++++++++++++++++++++++++++++++++++++++++++++++++--- win/tkWinDraw.c | 40 ++----- win/tkWinFont.c | 24 ++-- win/tkWinInit.c | 8 +- win/tkWinInt.h | 10 +- win/tkWinMenu.c | 96 ++++----------- win/tkWinScrlbr.c | 8 +- win/tkWinX.c | 63 ++++++---- 9 files changed, 423 insertions(+), 208 deletions(-) diff --git a/win/tkWin32Dll.c b/win/tkWin32Dll.c index 7b43d99..cc77be7 100644 --- a/win/tkWin32Dll.c +++ b/win/tkWin32Dll.c @@ -8,13 +8,11 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWin32Dll.c,v 1.3 1999/04/16 01:51:48 stanton Exp $ + * RCS: @(#) $Id: tkWin32Dll.c,v 1.4 2000/03/31 09:24:26 hobbs Exp $ */ #include "tkWinInt.h" -static int tkPlatformId; - /* * The following declaration is for the VC++ DLL entry point. */ @@ -71,7 +69,6 @@ DllMain(hInstance, reason, reserved) DWORD reason; LPVOID reserved; { - OSVERSIONINFO os; /* * If we are attaching to the DLL from a new process, tell Tk about @@ -80,40 +77,9 @@ DllMain(hInstance, reason, reserved) */ if (reason == DLL_PROCESS_ATTACH) { - os.dwOSVersionInfoSize = sizeof(os); - GetVersionEx(&os); - tkPlatformId = os.dwPlatformId; - TkWinXInit(hInstance); } else if (reason == DLL_PROCESS_DETACH) { TkWinXCleanup(hInstance); } return(TRUE); } - -/* - *---------------------------------------------------------------------- - * - * TkWinGetPlatformId -- - * - * Determines whether running under NT, 95, or Win32s, to allow - * runtime conditional code. - * - * Results: - * The return value is one of: - * VER_PLATFORM_WIN32s Win32s on Windows 3.1. - * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95. - * VER_PLATFORM_WIN32_NT Win32 on Windows NT - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -int -TkWinGetPlatformId() -{ - return tkPlatformId; -} - diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index 0779b74..d7fc92a 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.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: tkWinDialog.c,v 1.7 2000/03/16 03:20:52 sven Exp $ + * RCS: @(#) $Id: tkWinDialog.c,v 1.8 2000/03/31 09:24:26 hobbs Exp $ * */ @@ -110,13 +110,18 @@ static UINT APIENTRY ChooseDirectoryHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static UINT CALLBACK ColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); -static int GetFileName(ClientData clientData, +static int GetFileNameA(ClientData clientData, + Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[], int isOpen); +static int GetFileNameW(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int isOpen); static int MakeFilter(Tcl_Interp *interp, char *string, Tcl_DString *dsPtr); static UINT APIENTRY OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static UINT APIENTRY OFNHookProcW(HWND hdlg, UINT uMsg, WPARAM wParam, + LPARAM lParam); static void SetTkDialog(ClientData clientData); static int TrySetDirectory(HWND hwnd, const TCHAR *dir); @@ -384,7 +389,11 @@ Tk_GetOpenFileObjCmd(clientData, interp, objc, objv) int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - return GetFileName(clientData, interp, objc, objv, 1); + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { + return GetFileNameW(clientData, interp, objc, objv, 1); + } else { + return GetFileNameA(clientData, interp, objc, objv, 1); + } } /* @@ -411,13 +420,17 @@ Tk_GetSaveFileObjCmd(clientData, interp, objc, objv) int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { - return GetFileName(clientData, interp, objc, objv, 0); + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { + return GetFileNameW(clientData, interp, objc, objv, 0); + } else { + return GetFileNameA(clientData, interp, objc, objv, 0); + } } /* *---------------------------------------------------------------------- * - * GetFileName -- + * GetFileNameW -- * * Calls GetOpenFileName() or GetSaveFileName(). * @@ -431,7 +444,7 @@ Tk_GetSaveFileObjCmd(clientData, interp, objc, objv) */ static int -GetFileName(clientData, interp, objc, objv, open) +GetFileNameW(clientData, interp, objc, objv, open) ClientData clientData; /* Main window associated with interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ @@ -439,8 +452,9 @@ GetFileName(clientData, interp, objc, objv, open) int open; /* 1 to call GetOpenFileName(), 0 to * call GetSaveFileName(). */ { - OPENFILENAME ofn; - TCHAR file[MAX_PATH], savePath[MAX_PATH]; + Tcl_Encoding unicodeEncoding = Tcl_GetEncoding(NULL, "unicode"); + OPENFILENAMEW ofn; + WCHAR file[MAX_PATH]; int result, winCode, oldMode, i; char *extension, *filter, *title; Tk_Window tkwin; @@ -522,7 +536,7 @@ GetFileName(clientData, interp, objc, objv, open) if (Tcl_TranslateFileName(interp, string, &ds) == NULL) { goto end; } - Tcl_UtfToExternal(NULL, NULL, Tcl_DStringValue(&ds), + Tcl_UtfToExternal(NULL, unicodeEncoding, Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL, (char *) file, sizeof(file), NULL, NULL, NULL); break; @@ -558,31 +572,327 @@ GetFileName(clientData, interp, objc, objv, open) ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 0; - ofn.lpstrFile = (LPTSTR) file; + ofn.lpstrFile = (WCHAR *) file; ofn.nMaxFile = MAX_PATH; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST - | OFN_NOCHANGEDIR; + | OFN_NOCHANGEDIR | OFN_EXPLORER; ofn.nFileOffset = 0; ofn.nFileExtension = 0; ofn.lpstrDefExt = NULL; - ofn.lpfnHook = OFNHookProc; + ofn.lpfnHook = OFNHookProcW; ofn.lCustData = (LPARAM) interp; ofn.lpTemplateName = NULL; - if (LOBYTE(LOWORD(GetVersion())) >= 4) { + if (open != 0) { + ofn.Flags |= OFN_FILEMUSTEXIST; + } else { + ofn.Flags |= OFN_OVERWRITEPROMPT; + } + + if (tsdPtr->debugFlag != 0) { + ofn.Flags |= OFN_ENABLEHOOK; + } + + if (extension != NULL) { + Tcl_UtfToExternalDString(unicodeEncoding, extension, -1, &extString); + ofn.lpstrDefExt = (WCHAR *) Tcl_DStringValue(&extString); + } + + Tcl_UtfToExternalDString(unicodeEncoding, Tcl_DStringValue(&utfFilterString), + Tcl_DStringLength(&utfFilterString), &filterString); + ofn.lpstrFilter = (WCHAR *) Tcl_DStringValue(&filterString); + + if (Tcl_DStringValue(&utfDirString)[0] != '\0') { + Tcl_UtfToExternalDString(unicodeEncoding, Tcl_DStringValue(&utfDirString), + Tcl_DStringLength(&utfDirString), &dirString); + ofn.lpstrInitialDir = (WCHAR *) Tcl_DStringValue(&dirString); + } + + if (title != NULL) { + Tcl_UtfToExternalDString(unicodeEncoding, title, -1, &titleString); + ofn.lpstrTitle = (WCHAR *) Tcl_DStringValue(&titleString); + } + + /* + * Popup the dialog. + */ + + oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + if (open != 0) { + winCode = GetOpenFileNameW(&ofn); + } else { + winCode = GetSaveFileNameW(&ofn); + } + Tcl_SetServiceMode(oldMode); + + /* + * Ensure that hWnd is enabled, because it can happen that we + * have updated the wrapper of the parent, which causes us to + * leave this child disabled (Windows loses sync). + */ + EnableWindow(hWnd, 1); + + /* + * Clear the interp result since anything may have happened during the + * modal loop. + */ + + Tcl_ResetResult(interp); + + /* + * Process the results. + */ + + if (winCode != 0) { + char *p; + Tcl_DString ds; + + Tcl_ExternalToUtfDString(unicodeEncoding, (char *) ofn.lpstrFile, -1, &ds); + for (p = Tcl_DStringValue(&ds); *p != '\0'; p++) { + /* + * Change the pathname to the Tcl "normalized" pathname, where + * back slashes are used instead of forward slashes + */ + if (*p == '\\') { + *p = '/'; + } + } + Tcl_AppendResult(interp, Tcl_DStringValue(&ds), NULL); + Tcl_DStringFree(&ds); + } + + if (ofn.lpstrTitle != NULL) { + Tcl_DStringFree(&titleString); + } + if (ofn.lpstrInitialDir != NULL) { + Tcl_DStringFree(&dirString); + } + Tcl_DStringFree(&filterString); + if (ofn.lpstrDefExt != NULL) { + Tcl_DStringFree(&extString); + } + result = TCL_OK; + + end: + Tcl_DStringFree(&utfDirString); + Tcl_DStringFree(&utfFilterString); + + return result; +} + +/* + *------------------------------------------------------------------------- + * + * OFNHookProcW -- + * + * Hook procedure called only if debugging is turned on. Sets + * the "tk_dialog" variable when the dialog is ready to receive + * messages. + * + * Results: + * Returns 0 to allow default processing of messages to occur. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static UINT APIENTRY +OFNHookProcW( + HWND hdlg, // handle to child dialog window + UINT uMsg, // message identifier + WPARAM wParam, // message parameter + LPARAM lParam) // message parameter +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + OPENFILENAMEW *ofnPtr; + + if (uMsg == WM_INITDIALOG) { + SetWindowLong(hdlg, GWL_USERDATA, lParam); + } else if (uMsg == WM_WINDOWPOSCHANGED) { /* - * Use the "explorer" style file selection box on platforms that - * support it (Win95 and NT4.0 both have a major version number - * of 4). + * This message is delivered at the right time to enable Tk + * to set the debug information. Unhooks itself so it + * won't set the debug information every time it gets a + * WM_WINDOWPOSCHANGED message. */ - ofn.Flags |= OFN_EXPLORER; + ofnPtr = (OPENFILENAMEW *) GetWindowLong(hdlg, GWL_USERDATA); + if (ofnPtr != NULL) { + hdlg = GetParent(hdlg); + tsdPtr->debugInterp = (Tcl_Interp *) ofnPtr->lCustData; + Tcl_DoWhenIdle(SetTkDialog, (ClientData) hdlg); + SetWindowLong(hdlg, GWL_USERDATA, (LPARAM) NULL); + } + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * GetFileNameA -- + * + * Calls GetOpenFileName() or GetSaveFileName(). + * + * Results: + * See user documentation. + * + * Side effects: + * See user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +GetFileNameA(clientData, interp, objc, objv, open) + ClientData clientData; /* Main window associated with interpreter. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ + int open; /* 1 to call GetOpenFileName(), 0 to + * call GetSaveFileName(). */ +{ + OPENFILENAME ofn; + TCHAR file[MAX_PATH], savePath[MAX_PATH]; + int result, winCode, oldMode, i; + char *extension, *filter, *title; + Tk_Window tkwin; + HWND hWnd; + Tcl_DString utfFilterString, utfDirString; + Tcl_DString extString, filterString, dirString, titleString; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + static char *optionStrings[] = { + "-defaultextension", "-filetypes", "-initialdir", "-initialfile", + "-parent", "-title", NULL + }; + enum options { + FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, + FILE_PARENT, FILE_TITLE + }; + + result = TCL_ERROR; + file[0] = '\0'; + + /* + * Parse the arguments. + */ + + extension = NULL; + filter = NULL; + Tcl_DStringInit(&utfFilterString); + Tcl_DStringInit(&utfDirString); + tkwin = (Tk_Window) clientData; + title = NULL; + + for (i = 1; i < objc; i += 2) { + int index; + char *string; + Tcl_Obj *optionPtr, *valuePtr; + + optionPtr = objv[i]; + valuePtr = objv[i + 1]; + + if (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings, "option", + 0, &index) != TCL_OK) { + goto end; + } + if (i + 1 == objc) { + string = Tcl_GetStringFromObj(optionPtr, NULL); + Tcl_AppendResult(interp, "value for \"", string, "\" missing", + (char *) NULL); + goto end; + } + + string = Tcl_GetStringFromObj(valuePtr, NULL); + switch ((enum options) index) { + case FILE_DEFAULT: { + if (string[0] == '.') { + string++; + } + extension = string; + break; + } + case FILE_TYPES: { + Tcl_DStringFree(&utfFilterString); + if (MakeFilter(interp, string, &utfFilterString) != TCL_OK) { + goto end; + } + filter = Tcl_DStringValue(&utfFilterString); + break; + } + case FILE_INITDIR: { + Tcl_DStringFree(&utfDirString); + if (Tcl_TranslateFileName(interp, string, + &utfDirString) == NULL) { + goto end; + } + break; + } + case FILE_INITFILE: { + Tcl_DString ds; + + if (Tcl_TranslateFileName(interp, string, &ds) == NULL) { + goto end; + } + Tcl_UtfToExternal(NULL, NULL, Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds), 0, NULL, (char *) file, + sizeof(file), NULL, NULL, NULL); + break; + } + case FILE_PARENT: { + tkwin = Tk_NameToWindow(interp, string, tkwin); + if (tkwin == NULL) { + goto end; + } + break; + } + case FILE_TITLE: { + title = string; + break; + } + } + } + + if (filter == NULL) { + if (MakeFilter(interp, "", &utfFilterString) != TCL_OK) { + goto end; + } } + Tk_MakeWindowExist(tkwin); + hWnd = Tk_GetHWND(Tk_WindowId(tkwin)); + + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = hWnd; + ofn.hInstance = (HINSTANCE) GetWindowLong(ofn.hwndOwner, + GWL_HINSTANCE); + ofn.lpstrFilter = NULL; + ofn.lpstrCustomFilter = NULL; + ofn.nMaxCustFilter = 0; + ofn.nFilterIndex = 0; + ofn.lpstrFile = (LPTSTR) file; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.lpstrTitle = NULL; + ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST + | OFN_NOCHANGEDIR | OFN_EXPLORER; + ofn.nFileOffset = 0; + ofn.nFileExtension = 0; + ofn.lpstrDefExt = NULL; + ofn.lpfnHook = OFNHookProc; + ofn.lCustData = (LPARAM) interp; + ofn.lpTemplateName = NULL; + if (open != 0) { ofn.Flags |= OFN_FILEMUSTEXIST; } else { @@ -988,7 +1298,7 @@ Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv) ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = NULL; - ofn.Flags = OFN_HIDEREADONLY + ofn.Flags = OFN_HIDEREADONLY | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE; ofn.nFileOffset = 0; ofn.nFileExtension = 0; diff --git a/win/tkWinDraw.c b/win/tkWinDraw.c index a32c45d..55c4e59 100644 --- a/win/tkWinDraw.c +++ b/win/tkWinDraw.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: tkWinDraw.c,v 1.7 1999/12/14 06:53:54 hobbs Exp $ + * RCS: @(#) $Id: tkWinDraw.c,v 1.8 2000/03/31 09:24:26 hobbs Exp $ */ #include "tkWinInt.h" @@ -173,6 +173,7 @@ TkWinGetDrawableDC(display, d, state) cmap = twdPtr->bitmap.colormap; } state->palette = TkWinSelectPalette(dc, cmap); + state->bkmode = GetBkMode(dc); return dc; } @@ -199,6 +200,7 @@ TkWinReleaseDrawableDC(d, dc, state) TkWinDCState *state; { TkWinDrawable *twdPtr = (TkWinDrawable *)d; + SetBkMode(dc, state->bkmode); SelectPalette(dc, state->palette, TRUE); RealizePalette(dc); if (twdPtr->type == TWD_WINDOW) { @@ -563,33 +565,7 @@ TkPutImage(colors, ncolors, display, d, gc, image, src_x, src_y, dest_x, infoPtr->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); infoPtr->bmiHeader.biWidth = image->width; - - /* - * The following code works around a bug in Win32s. CreateDIBitmap - * fails under Win32s for top-down images. So we have to reverse the - * order of the scanlines. If we are not running under Win32s, we can - * just declare the image to be top-down. - */ - - if (tkpIsWin32s) { - int y; - char *srcPtr, *dstPtr, *temp; - - temp = ckalloc((unsigned) image->bytes_per_line); - srcPtr = image->data; - dstPtr = image->data+(image->bytes_per_line * (image->height - 1)); - for (y = 0; y < (image->height/2); y++) { - memcpy(temp, srcPtr, image->bytes_per_line); - memcpy(srcPtr, dstPtr, image->bytes_per_line); - memcpy(dstPtr, temp, image->bytes_per_line); - srcPtr += image->bytes_per_line; - dstPtr -= image->bytes_per_line; - } - ckfree(temp); - infoPtr->bmiHeader.biHeight = image->height; /* Bottom-up order */ - } else { - infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */ - } + infoPtr->bmiHeader.biHeight = -image->height; /* Top-down order */ infoPtr->bmiHeader.biPlanes = 1; infoPtr->bmiHeader.biBitCount = image->bits_per_pixel; infoPtr->bmiHeader.biCompression = BI_RGB; @@ -890,6 +866,7 @@ XDrawLines(display, d, gc, points, npoints, mode) dc = TkWinGetDrawableDC(display, d, &state); pen = SetUpGraphicsPort(gc); + SetBkMode(dc, TRANSPARENT); RenderObject(dc, gc, points, npoints, mode, pen, Polyline); DeleteObject(pen); @@ -976,6 +953,7 @@ XDrawRectangle(display, d, gc, x, y, width, height) dc = TkWinGetDrawableDC(display, d, &state); pen = SetUpGraphicsPort(gc); + SetBkMode(dc, TRANSPARENT); oldPen = SelectObject(dc, pen); oldBrush = SelectObject(dc, GetStockObject(NULL_BRUSH)); SetROP2(dc, tkpWinRopModes[gc->function]); @@ -1146,6 +1124,7 @@ DrawOrFillArc(display, d, gc, x, y, width, height, start, extent, fill) * it's only supported under Windows NT. */ + SetBkMode(dc, TRANSPARENT); Arc(dc, x, y, x+width+1, y+height+1, xstart, ystart, xend, yend); } else { brush = CreateSolidBrush(gc->foreground); @@ -1210,10 +1189,7 @@ SetUpGraphicsPort(gc) } else { style = PS_SOLID; } - if (tkpIsWin32s || (gc->line_width < 2)) { - if (gc->line_width > 1) { - style = PS_SOLID; - } + if (gc->line_width < 2) { return CreatePen(style, gc->line_width, gc->foreground); } else { LOGBRUSH lb; diff --git a/win/tkWinFont.c b/win/tkWinFont.c index 6d13d05..1c35fc7 100644 --- a/win/tkWinFont.c +++ b/win/tkWinFont.c @@ -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: tkWinFont.c,v 1.8 2000/02/08 10:01:16 hobbs Exp $ + * RCS: @(#) $Id: tkWinFont.c,v 1.9 2000/03/31 09:24:27 hobbs Exp $ */ #include "tkWinInt.h" @@ -180,7 +180,6 @@ static Tcl_ThreadDataKey dataKey; * Information cached about the system at startup time. */ -static int platformId; static Tcl_Encoding unicodeEncoding; static Tcl_Encoding systemEncoding; @@ -233,7 +232,7 @@ static int CALLBACK WinFontFamilyEnumProc(ENUMLOGFONT *lfPtr, * * This procedure is called when an application is created. It * initializes all the structures that are used by the - * platform-dependant code on a per application basis. + * platform-dependent code on a per application basis. * * Results: * None. @@ -249,13 +248,8 @@ void TkpFontPkgInit( TkMainInfo *mainPtr) /* The application being created. */ { - OSVERSIONINFO os; - - os.dwOSVersionInfoSize = sizeof(os); - GetVersionEx(&os); - platformId = os.dwPlatformId; unicodeEncoding = Tcl_GetEncoding(NULL, "unicode"); - if (platformId == VER_PLATFORM_WIN32_NT) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { /* * If running NT, then we will be calling some Unicode functions * explictly. So, even if the Tcl system encoding isn't Unicode, @@ -493,7 +487,7 @@ TkpGetFontFamilies( * EnumFontFamilies because it only exists under NT. */ - if (platformId == VER_PLATFORM_WIN32_NT) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontFamilyEnumProc, (LPARAM) interp); } else { @@ -1051,7 +1045,7 @@ InitFont( * version of GetTextFace because it only exists under NT. */ - if (platformId == VER_PLATFORM_WIN32_NT) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf); } else { GetTextFaceA(hdc, LF_FACESIZE, (char *) buf); @@ -1228,7 +1222,7 @@ AllocFontFamily( Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); hFont = SelectObject(hdc, hFont); - if (platformId == VER_PLATFORM_WIN32_NT) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { GetTextFaceW(hdc, LF_FACESIZE, (WCHAR *) buf); } else { GetTextFaceA(hdc, LF_FACESIZE, (char *) buf); @@ -1493,7 +1487,7 @@ FindSubFontForChar( canUse.nameTriedPtr = &ds; canUse.ch = ch; canUse.subFontPtr = NULL; - if (platformId == VER_PLATFORM_WIN32_NT) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { EnumFontFamiliesW(hdc, NULL, (FONTENUMPROCW) WinFontCanUseProc, (LPARAM) &canUse); } else { @@ -1960,7 +1954,7 @@ GetScreenFont( Tcl_DStringSetLength(&ds, LF_FACESIZE); } - if (platformId == VER_PLATFORM_WIN32_NT) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { Tcl_UniChar *src, *dst; src = (Tcl_UniChar *) Tcl_DStringValue(&ds); dst = (Tcl_UniChar *) lf.lfFaceName; @@ -2030,7 +2024,7 @@ FamilyExists( * non-zero value. */ - if (platformId == VER_PLATFORM_WIN32_NT) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) { result = EnumFontFamiliesW(hdc, (WCHAR *) Tcl_DStringValue(&faceString), (FONTENUMPROCW) WinFontExistProc, 0); } else { diff --git a/win/tkWinInit.c b/win/tkWinInit.c index 93a4906..8426551 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.3 1999/04/16 01:51:52 stanton Exp $ + * RCS: @(#) $Id: tkWinInit.c,v 1.4 2000/03/31 09:24:27 hobbs Exp $ */ #include "tkWinInt.h" @@ -43,6 +43,12 @@ int TkpInit(interp) Tcl_Interp *interp; { + /* + * This is necessary for static initialization, and is ok + * otherwise because TkWinXInit flips a static bit to do + * its work just once. + */ + TkWinXInit(GetModuleHandle(NULL)); return Tcl_Eval(interp, initScript); } diff --git a/win/tkWinInt.h b/win/tkWinInt.h index 6b5e85f..339b164 100644 --- a/win/tkWinInt.h +++ b/win/tkWinInt.h @@ -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: tkWinInt.h,v 1.8 2000/03/02 23:52:37 hobbs Exp $ + * RCS: @(#) $Id: tkWinInt.h,v 1.9 2000/03/31 09:24:27 hobbs Exp $ */ #ifndef _TKWININT @@ -48,6 +48,7 @@ typedef struct TkWinDCState { HPALETTE palette; + int bkmode; } TkWinDCState; /* @@ -124,13 +125,6 @@ typedef struct { #define TK_WIN_CHILD_CLASS_NAME "TkChild" /* - * The following variable indicates whether we are restricted to Win32s - * GDI calls. - */ - -extern int tkpIsWin32s; - -/* * The following variable is a translation table between X gc functions and * Win32 raster op modes. */ diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index 92c017f..f918b71 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.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: tkWinMenu.c,v 1.6 1999/09/15 22:35:42 hobbs Exp $ + * RCS: @(#) $Id: tkWinMenu.c,v 1.7 2000/03/31 09:24:27 hobbs Exp $ */ #define OEMRESOURCE @@ -74,9 +74,6 @@ typedef struct ThreadSpecificData { } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; -static OSVERSIONINFO versionInfo; - /* So we don't have to keep doing this */ - /* * The following are default menu value strings. */ @@ -1527,8 +1524,7 @@ DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x, rect.right = mePtr->indicatorSpace + x; if ((mePtr->state == ENTRY_DISABLED) - && (menuPtr->disabledFgPtr != NULL) - && (versionInfo.dwMajorVersion >= 4)) { + && (menuPtr->disabledFgPtr != NULL)) { RECT hilightRect; COLORREF oldFgColor = whichGC->foreground; @@ -1544,13 +1540,6 @@ DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, fmPtr, x, DrawWindowsSystemBitmap(menuPtr->display, d, whichGC, &rect, OBM_CHECK, 0); - - if ((mePtr->state == ENTRY_DISABLED) - && (menuPtr->disabledImageGC != None) - && (versionInfo.dwMajorVersion < 4)) { - XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, - rect.left, rect.top, rect.right, rect.bottom); - } } } } @@ -1605,28 +1594,26 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, if ((mePtr->state == ENTRY_DISABLED) && (menuPtr->disabledFgPtr != NULL) && ((mePtr->accelPtr != NULL) - || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) { - if (versionInfo.dwMajorVersion >= 4) { - COLORREF oldFgColor = gc->foreground; - - gc->foreground = GetSysColor(COLOR_3DHILIGHT); - if (mePtr->accelPtr != NULL) { - Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, - mePtr->accelLength, leftEdge + 1, baseline + 1); - } + || ((mePtr->type == CASCADE_ENTRY) && drawArrow))) { + COLORREF oldFgColor = gc->foreground; + + gc->foreground = GetSysColor(COLOR_3DHILIGHT); + if (mePtr->accelPtr != NULL) { + Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, + mePtr->accelLength, leftEdge + 1, baseline + 1); + } - if (mePtr->type == CASCADE_ENTRY) { - RECT rect; + if (mePtr->type == CASCADE_ENTRY) { + RECT rect; - rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1; - rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1; - rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1; - rect.right = x + width; - DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, - OBM_MNARROW, ALIGN_BITMAP_RIGHT); - } - gc->foreground = oldFgColor; + rect.top = y + GetSystemMetrics(SM_CYBORDER) + 1; + rect.bottom = y + height - GetSystemMetrics(SM_CYBORDER) + 1; + rect.left = x + mePtr->indicatorSpace + mePtr->labelWidth + 1; + rect.right = x + width; + DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, + OBM_MNARROW, ALIGN_BITMAP_RIGHT); } + gc->foreground = oldFgColor; } if (mePtr->accelPtr != NULL) { @@ -1634,14 +1621,6 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, mePtr->accelLength, leftEdge, baseline); } - if ((mePtr->state == ENTRY_DISABLED) - && (menuPtr->disabledImageGC != None) - && (versionInfo.dwMajorVersion < 4)) { - XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, - leftEdge, y, width - mePtr->labelWidth - - mePtr->indicatorSpace, height); - } - if ((mePtr->type == CASCADE_ENTRY) && drawArrow) { RECT rect; @@ -1651,12 +1630,6 @@ DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, rect.right = x + width - 1; DrawWindowsSystemBitmap(menuPtr->display, d, gc, &rect, OBM_MNARROW, ALIGN_BITMAP_RIGHT); - if ((mePtr->state == ENTRY_DISABLED) - && (menuPtr->disabledImageGC != None) - && (versionInfo.dwMajorVersion < 4)) { - XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, - rect.left, rect.top, rect.right, rect.bottom); - } } } @@ -2673,19 +2646,7 @@ SetDefaults( TEXTMETRIC tm; int pointSize; HFONT menuFont; - - - versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); - - /* - * If GetVersionEx fails, it means that the version info record - * is too big for what is compiled. Should never happen, but if - * it does, we are later than Windows 95 or NT 4.0. - */ - - if (!GetVersionEx(&versionInfo)) { - versionInfo.dwMajorVersion = 4; - } + NONCLIENTMETRICS ncMetrics; /* * Set all of the default options. The loop will terminate when we run @@ -2697,23 +2658,16 @@ SetDefaults( defaultBorderWidth = GetSystemMetrics(SM_CYBORDER); } - scratchDC = CreateDC("DISPLAY", NULL, NULL, NULL); if (!firstTime) { Tcl_DStringFree(&menuFontDString); } Tcl_DStringInit(&menuFontDString); - if (versionInfo.dwMajorVersion >= 4) { - NONCLIENTMETRICS ncMetrics; - - ncMetrics.cbSize = sizeof(ncMetrics); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics), - &ncMetrics, 0); - menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont); - } else { - menuFont = GetStockObject(SYSTEM_FONT); - } + ncMetrics.cbSize = sizeof(ncMetrics); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncMetrics), + &ncMetrics, 0); + menuFont = CreateFontIndirect(&ncMetrics.lfMenuFont); SelectObject(scratchDC, menuFont); GetTextMetrics(scratchDC, &tm); GetTextFace(scratchDC, LF_FACESIZE, faceName); @@ -2757,7 +2711,7 @@ SetDefaults( * documented. */ - if (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_WINDOWS) { indicatorDimensions[0] = GetSystemMetrics(SM_CYMENUCHECK); indicatorDimensions[1] = ((GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CXBORDER) diff --git a/win/tkWinScrlbr.c b/win/tkWinScrlbr.c index f888679..a6bb09a 100644 --- a/win/tkWinScrlbr.c +++ b/win/tkWinScrlbr.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: tkWinScrlbr.c,v 1.4 2000/01/13 02:07:27 hobbs Exp $ + * RCS: @(#) $Id: tkWinScrlbr.c,v 1.5 2000/03/31 09:24:27 hobbs Exp $ */ #include "tkWinInt.h" @@ -177,11 +177,7 @@ UpdateScrollbar(scrollPtr) scrollInfo.nMin = 0; scrollInfo.nMax = MAX_SCROLL; thumbSize = (scrollPtr->info.lastFraction - scrollPtr->info.firstFraction); - if (tkpIsWin32s) { - scrollInfo.nPage = 0; - } else { - scrollInfo.nPage = ((UINT) (thumbSize * (double) MAX_SCROLL)) + 1; - } + scrollInfo.nPage = ((UINT) (thumbSize * (double) MAX_SCROLL)) + 1; if (thumbSize < 1.0) { scrollInfo.nPos = (int) ((scrollPtr->info.firstFraction / (1.0-thumbSize)) diff --git a/win/tkWinX.c b/win/tkWinX.c index e60d001..d537a7f 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.7 1999/11/19 22:00:19 hobbs Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.8 2000/03/31 09:24:27 hobbs Exp $ */ #include "tkWinInt.h" @@ -22,12 +22,6 @@ #include /* - * Definitions of extern variables supplied by this file. - */ - -int tkpIsWin32s = -1; - -/* * Declarations of static variables used in this file. */ @@ -35,6 +29,7 @@ static char winScreenName[] = ":0"; /* Default name of windows display. */ 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 */ TCL_DECLARE_MUTEX(winXMutex) @@ -84,16 +79,14 @@ TkGetServerInfo(interp, tkwin) Tk_Window tkwin; /* Token for window; this selects a * particular display and server. */ { - char buffer[50]; - OSVERSIONINFO info; - - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&info); - sprintf(buffer, "Windows %d.%d %d ", info.dwMajorVersion, - info.dwMinorVersion, info.dwBuildNumber); - Tcl_AppendResult(interp, buffer, - (info.dwPlatformId == VER_PLATFORM_WIN32s) ? "Win32s" : "Win32", - (char *) NULL); + char buffer[60]; + OSVERSIONINFO os; + + os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&os); + sprintf(buffer, "Windows %d.%d %d Win32", os.dwMajorVersion, + os.dwMinorVersion, os.dwBuildNumber); + Tcl_SetResult(interp, buffer, TCL_VOLATILE); } /* @@ -138,11 +131,7 @@ void TkWinXInit(hInstance) HINSTANCE hInstance; { - OSVERSIONINFO info; - - info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&info); - tkpIsWin32s = (info.dwPlatformId == VER_PLATFORM_WIN32s); + OSVERSIONINFO os; if (childClassInitialized != 0) { return; @@ -151,6 +140,10 @@ TkWinXInit(hInstance) tkInstance = hInstance; + os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&os); + tkPlatformId = os.dwPlatformId; + /* * When threads are enabled, we cannot use CLASSDC because * threads will then write into the same device context. @@ -225,6 +218,32 @@ TkWinXCleanup(hInstance) /* *---------------------------------------------------------------------- * + * TkWinGetPlatformId -- + * + * Determines whether running under NT, 95, or Win32s, to allow + * runtime conditional code. + * + * Results: + * The return value is one of: + * VER_PLATFORM_WIN32s Win32s on Windows 3.1. + * VER_PLATFORM_WIN32_WINDOWS Win32 on Windows 95. + * VER_PLATFORM_WIN32_NT Win32 on Windows NT + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkWinGetPlatformId() +{ + return tkPlatformId; +} + +/* + *---------------------------------------------------------------------- + * * TkGetDefaultScreenName -- * * Returns the name of the screen that Tk should use during -- cgit v0.12