diff options
Diffstat (limited to 'win/tkWinDialog.c')
-rw-r--r-- | win/tkWinDialog.c | 856 |
1 files changed, 708 insertions, 148 deletions
diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index e03862c..baebfc9 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.c @@ -8,10 +8,10 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ -#define WINVER 0x0500 /* Requires Windows 2K definitions */ -#define _WIN32_WINNT 0x0500 + #include "tkWinInt.h" #include "tkFileFilter.h" +#include "tkFont.h" #include <commdlg.h> /* includes common dialog functionality */ #ifdef _MSC_VER @@ -46,10 +46,6 @@ #endif #endif /* BFFM_VALIDATEFAILED */ -#ifndef OPENFILENAME_SIZE_VERSION_400 -#define OPENFILENAME_SIZE_VERSION_400 76 -#endif - typedef struct ThreadSpecificData { int debugFlag; /* Flags whether we should output debugging * information while displaying a builtin @@ -118,11 +114,11 @@ static const struct {int type; int btnIds[3];} allowedTypes[] = { */ #define TkWinGetHInstance(from) \ - ((HINSTANCE) GetWindowLongPtrW((from), GWLP_HINSTANCE)) + ((HINSTANCE) GetWindowLongPtr((from), GWLP_HINSTANCE)) #define TkWinGetUserData(from) \ - GetWindowLongPtrW((from), GWLP_USERDATA) + GetWindowLongPtr((from), GWLP_USERDATA) #define TkWinSetUserData(to,what) \ - SetWindowLongPtrW((to), GWLP_USERDATA, (LPARAM)(what)) + SetWindowLongPtr((to), GWLP_USERDATA, (LPARAM)(what)) /* * The value of TK_MULTI_MAX_PATH dictates how many files can be retrieved @@ -141,8 +137,8 @@ static const struct {int type; int btnIds[3];} allowedTypes[] = { */ typedef struct { - WCHAR initDir[MAX_PATH]; /* Initial folder to use */ - WCHAR retDir[MAX_PATH]; /* Returned folder to use */ + TCHAR initDir[MAX_PATH]; /* Initial folder to use */ + TCHAR retDir[MAX_PATH]; /* Returned folder to use */ Tcl_Interp *interp; int mustExist; /* True if file must exist to return from * callback */ @@ -159,7 +155,7 @@ typedef struct OFNData { int dynFileBufferSize; /* Dynamic filename buffer size, stored to * avoid shrinking and expanding the buffer * when selection changes */ - WCHAR *dynFileBuffer; /* Dynamic filename buffer */ + TCHAR *dynFileBuffer; /* Dynamic filename buffer */ } OFNData; /* @@ -180,7 +176,7 @@ static UINT APIENTRY OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam); static void SetTkDialog(ClientData clientData); -static const char *ConvertExternalFilename(WCHAR *filename, +static const char *ConvertExternalFilename(TCHAR *filename, Tcl_DString *dsPtr); /* @@ -252,7 +248,7 @@ void TkWinDialogDebug( int debug) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); tsdPtr->debugFlag = debug; @@ -284,14 +280,14 @@ Tk_ChooseColorObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tk_Window tkwin = (Tk_Window) clientData, parent; + Tk_Window tkwin = clientData, parent; HWND hWnd; int i, oldMode, winCode, result; - CHOOSECOLORW chooseColor; + CHOOSECOLOR chooseColor; static int inited = 0; static COLORREF dwCustColors[16]; static long oldColor; /* the color selected last time */ - static const char *optionStrings[] = { + static const char *const optionStrings[] = { "-initialcolor", "-parent", "-title", NULL }; enum options { @@ -315,7 +311,7 @@ Tk_ChooseColorObjCmd( } parent = tkwin; - chooseColor.lStructSize = sizeof(CHOOSECOLORW); + chooseColor.lStructSize = sizeof(CHOOSECOLOR); chooseColor.hwndOwner = NULL; chooseColor.hInstance = NULL; chooseColor.rgbResult = oldColor; @@ -323,7 +319,7 @@ Tk_ChooseColorObjCmd( chooseColor.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK; chooseColor.lCustData = (LPARAM) NULL; chooseColor.lpfnHook = (LPOFNHOOKPROC) ColorDlgHookProc; - chooseColor.lpTemplateName = (LPWSTR) interp; + chooseColor.lpTemplateName = (LPTSTR) interp; for (i = 1; i < objc; i += 2) { int index; @@ -333,14 +329,14 @@ Tk_ChooseColorObjCmd( optionPtr = objv[i]; valuePtr = objv[i + 1]; - if (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, optionPtr, optionStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } if (i + 1 == objc) { - string = Tcl_GetString(optionPtr); - Tcl_AppendResult(interp, "value for \"", string, "\" missing", - NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(optionPtr))); + Tcl_SetErrorCode(interp, "TK", "COLORDIALOG", "VALUE", NULL); return TCL_ERROR; } @@ -375,7 +371,7 @@ Tk_ChooseColorObjCmd( chooseColor.hwndOwner = hWnd; oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - winCode = ChooseColorW(&chooseColor); + winCode = ChooseColor(&chooseColor); (void) Tcl_SetServiceMode(oldMode); /* @@ -401,13 +397,11 @@ Tk_ChooseColorObjCmd( /* * User has selected a color */ - char color[100]; - sprintf(color, "#%02x%02x%02x", + Tcl_SetObjResult(interp, Tcl_ObjPrintf("#%02x%02x%02x", GetRValue(chooseColor.rgbResult), GetGValue(chooseColor.rgbResult), - GetBValue(chooseColor.rgbResult)); - Tcl_AppendResult(interp, color, NULL); + GetBValue(chooseColor.rgbResult))); oldColor = chooseColor.rgbResult; result = TCL_OK; } @@ -440,10 +434,10 @@ ColorDlgHookProc( WPARAM wParam, /* First message parameter. */ LPARAM lParam) /* Second message parameter. */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); const char *title; - CHOOSECOLORW *ccPtr; + CHOOSECOLOR *ccPtr; if (WM_INITDIALOG == uMsg) { @@ -451,18 +445,18 @@ ColorDlgHookProc( * Set the title string of the dialog. */ - ccPtr = (CHOOSECOLORW *) lParam; + ccPtr = (CHOOSECOLOR *) lParam; title = (const char *) ccPtr->lCustData; if ((title != NULL) && (title[0] != '\0')) { Tcl_DString ds; - SetWindowTextW(hDlg, (WCHAR *)Tcl_WinUtfToTChar(title,-1,&ds)); + SetWindowText(hDlg, Tcl_WinUtfToTChar(title,-1,&ds)); Tcl_DStringFree(&ds); } if (tsdPtr->debugFlag) { tsdPtr->debugInterp = (Tcl_Interp *) ccPtr->lpTemplateName; - Tcl_DoWhenIdle(SetTkDialog, (ClientData) hDlg); + Tcl_DoWhenIdle(SetTkDialog, hDlg); } return TRUE; } @@ -548,19 +542,19 @@ GetFileName( int open) /* 1 to call GetOpenFileName(), 0 to call * GetSaveFileName(). */ { - OPENFILENAMEW ofn; - WCHAR file[TK_MULTI_MAX_PATH]; + OPENFILENAME ofn; + TCHAR file[TK_MULTI_MAX_PATH]; OFNData ofnData; int cdlgerr; int filterIndex = 0, result = TCL_ERROR, winCode, oldMode, i, multi = 0; int confirmOverwrite = 1; const char *extension = NULL, *title = NULL; - Tk_Window tkwin = (Tk_Window) clientData; + Tk_Window tkwin = clientData; HWND hWnd; Tcl_Obj *filterObj = NULL, *initialTypeObj = NULL, *typeVariableObj = NULL; Tcl_DString utfFilterString, utfDirString, ds; Tcl_DString extString, filterString, dirString, titleString; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); enum options { FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, FILE_PARENT, @@ -592,7 +586,7 @@ GetFileName( {"-typevariable", FILE_TYPEVARIABLE}, {NULL, FILE_DEFAULT/*ignored*/ } }; - const struct Options *options = open ? openOptions : saveOptions; + const struct Options *const options = open ? openOptions : saveOptions; file[0] = '\0'; ZeroMemory(&ofnData, sizeof(OFNData)); @@ -612,8 +606,9 @@ GetFileName( sizeof(struct Options), "option", 0, &index) != TCL_OK) { goto end; } else if (i + 1 == objc) { - Tcl_AppendResult(interp, "value for \"", options[index].name, - "\" missing", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", options[index].name)); + Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL); goto end; } @@ -680,12 +675,8 @@ GetFileName( Tk_MakeWindowExist(tkwin); hWnd = Tk_GetHWND(Tk_WindowId(tkwin)); - ZeroMemory(&ofn, sizeof(OPENFILENAMEW)); - if (LOBYTE(LOWORD(GetVersion())) < 5) { - ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400; - } else { - ofn.lStructSize = sizeof(OPENFILENAMEW); - } + ZeroMemory(&ofn, sizeof(OPENFILENAME)); + ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWnd; ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner); ofn.lpstrFile = file; @@ -712,17 +703,17 @@ GetFileName( */ ofnData.dynFileBufferSize = 512; - ofnData.dynFileBuffer = (WCHAR *)ckalloc(512 * sizeof(WCHAR)); + ofnData.dynFileBuffer = ckalloc(512 * sizeof(TCHAR)); } if (extension != NULL) { Tcl_WinUtfToTChar(extension, -1, &extString); - ofn.lpstrDefExt = (WCHAR *) Tcl_DStringValue(&extString); + ofn.lpstrDefExt = (TCHAR *) Tcl_DStringValue(&extString); } Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString), Tcl_DStringLength(&utfFilterString), &filterString); - ofn.lpstrFilter = (WCHAR *) Tcl_DStringValue(&filterString); + ofn.lpstrFilter = (TCHAR *) Tcl_DStringValue(&filterString); ofn.nFilterIndex = filterIndex; if (Tcl_DStringValue(&utfDirString)[0] != '\0') { @@ -747,11 +738,11 @@ GetFileName( } Tcl_DStringFree(&cwd); } - ofn.lpstrInitialDir = (WCHAR *) Tcl_DStringValue(&dirString); + ofn.lpstrInitialDir = (TCHAR *) Tcl_DStringValue(&dirString); if (title != NULL) { Tcl_WinUtfToTChar(title, -1, &titleString); - ofn.lpstrTitle = (WCHAR *) Tcl_DStringValue(&titleString); + ofn.lpstrTitle = (TCHAR *) Tcl_DStringValue(&titleString); } /* @@ -760,9 +751,9 @@ GetFileName( oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); if (open != 0) { - winCode = GetOpenFileNameW(&ofn); + winCode = GetOpenFileName(&ofn); } else { - winCode = GetSaveFileNameW(&ofn); + winCode = GetSaveFileName(&ofn); } Tcl_SetServiceMode(oldMode); EatSpuriousMessageBugFix(); @@ -816,7 +807,7 @@ GetFileName( * first element is the directory path. */ - WCHAR *files = ofnData.dynFileBuffer; + TCHAR *files = ofnData.dynFileBuffer; Tcl_Obj *returnList = Tcl_NewObj(); int count = 0; @@ -862,8 +853,8 @@ GetFileName( Tcl_SetObjResult(interp, returnList); Tcl_DStringFree(&ds); } else { - Tcl_AppendResult(interp, ConvertExternalFilename( - ofn.lpstrFile, &ds), NULL); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + ConvertExternalFilename(ofn.lpstrFile, &ds), -1)); gotFilename = (Tcl_DStringLength(&ds) > 0); Tcl_DStringFree(&ds); } @@ -887,9 +878,11 @@ GetFileName( } } } else if (cdlgerr == FNERR_INVALIDFILENAME) { - Tcl_SetResult(interp, "invalid filename \"", TCL_STATIC); - Tcl_AppendResult(interp, ConvertExternalFilename( - ofn.lpstrFile, &ds), "\"", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid filename \"%s\"", + ConvertExternalFilename(ofn.lpstrFile, &ds))); + Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "INVALID_FILENAME", + NULL); Tcl_DStringFree(&ds); } else { result = TCL_OK; @@ -910,7 +903,7 @@ GetFileName( Tcl_DStringFree(&utfDirString); Tcl_DStringFree(&utfFilterString); if (ofnData.dynFileBuffer != NULL) { - ckfree((char *)ofnData.dynFileBuffer); + ckfree(ofnData.dynFileBuffer); ofnData.dynFileBuffer = NULL; } @@ -943,15 +936,15 @@ OFNHookProc( WPARAM wParam, /* Message parameter */ LPARAM lParam) /* Message parameter */ { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - OPENFILENAMEW *ofnPtr; + OPENFILENAME *ofnPtr; OFNData *ofnData; if (uMsg == WM_INITDIALOG) { TkWinSetUserData(hdlg, lParam); } else if (uMsg == WM_NOTIFY) { - OFNOTIFYW *notifyPtr = (OFNOTIFYW *) lParam; + OFNOTIFY *notifyPtr = (OFNOTIFY *) lParam; /* * This is weird... or not. The CDN_FILEOK is NOT sent when the @@ -967,7 +960,7 @@ OFNHookProc( if (notifyPtr->hdr.code == CDN_FILEOK || notifyPtr->hdr.code == CDN_SELCHANGE) { int dirsize, selsize; - WCHAR *buffer; + TCHAR *buffer; int buffersize; /* @@ -980,8 +973,8 @@ OFNHookProc( buffer = ofnData->dynFileBuffer; hdlg = GetParent(hdlg); - selsize = SendMessageW(hdlg, CDM_GETSPEC, 0, 0); - dirsize = SendMessageW(hdlg, CDM_GETFOLDERPATH, 0, 0); + selsize = SendMessage(hdlg, CDM_GETSPEC, 0, 0); + dirsize = SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0); buffersize = (selsize + dirsize + 1); /* @@ -991,15 +984,15 @@ OFNHookProc( if ((selsize > 1) && (dirsize > 0)) { if (ofnData->dynFileBufferSize < buffersize) { - buffer = (WCHAR *) ckrealloc((char *) buffer, buffersize * sizeof(WCHAR)); + buffer = ckrealloc(buffer, buffersize * sizeof(TCHAR)); ofnData->dynFileBufferSize = buffersize; ofnData->dynFileBuffer = buffer; } - SendMessageW(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer); + SendMessage(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer); buffer += dirsize; - SendMessageW(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer); + SendMessage(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer); /* * If there are multiple files, delete the quotes and change @@ -1008,7 +1001,7 @@ OFNHookProc( if (buffer[0] == '"') { BOOL findquote = TRUE; - WCHAR *tmp = buffer; + TCHAR *tmp = buffer; while (*buffer != '\0') { if (findquote) { @@ -1037,8 +1030,8 @@ OFNHookProc( if (TCL_PATH_ABSOLUTE == Tcl_GetPathType(Tcl_DStringValue(&tmpfile))) { /* re-get the full path to the start of the buffer */ - buffer = (WCHAR *) ofnData->dynFileBuffer; - SendMessageW(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer); + buffer = (TCHAR *) ofnData->dynFileBuffer; + SendMessage(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer); } else { *(buffer-1) = '\\'; } @@ -1062,7 +1055,7 @@ OFNHookProc( * information every time it gets a WM_WINDOWPOSCHANGED message. */ - ofnPtr = (OPENFILENAMEW *) TkWinGetUserData(hdlg); + ofnPtr = (OPENFILENAME *) TkWinGetUserData(hdlg); if (ofnPtr != NULL) { ofnData = (OFNData *) ofnPtr->lCustData; if (ofnData->interp != NULL) { @@ -1137,12 +1130,13 @@ MakeFilter( *p = '\0'; } else { - int len; + size_t len; if (valuePtr == NULL) { len = 0; } else { - (void) Tcl_GetStringFromObj(valuePtr, &len); + (void) Tcl_GetString(valuePtr); + len = valuePtr->length; } /* @@ -1159,7 +1153,7 @@ MakeFilter( * twice the size of the string to format the filter */ - filterStr = ckalloc((unsigned int) len * 3); + filterStr = ckalloc(len * 3); for (filterPtr = flist.filters, p = filterStr; filterPtr; filterPtr = filterPtr->next) { @@ -1229,7 +1223,7 @@ MakeFilter( } Tcl_DStringAppend(dsPtr, filterStr, (int) (p - filterStr)); - ckfree((char *) filterStr); + ckfree(filterStr); TkFreeFileFilters(&flist); return TCL_OK; @@ -1312,21 +1306,21 @@ Tk_ChooseDirectoryObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - WCHAR path[MAX_PATH]; + TCHAR path[MAX_PATH]; int oldMode, result = TCL_ERROR, i; LPCITEMIDLIST pidl; /* Returned by browser */ - BROWSEINFOW bInfo; /* Used by browser */ + BROWSEINFO bInfo; /* Used by browser */ ChooseDir cdCBData; /* Structure to pass back and forth */ LPMALLOC pMalloc; /* Used by shell */ - Tk_Window tkwin = (Tk_Window) clientData; + Tk_Window tkwin = clientData; HWND hWnd; const char *utfTitle = NULL;/* Title for window */ - WCHAR saveDir[MAX_PATH]; + TCHAR saveDir[MAX_PATH]; Tcl_DString titleString; /* Title */ Tcl_DString initDirString; /* Initial directory */ Tcl_DString tempString; /* temporary */ Tcl_Obj *objPtr; - static const char *optionStrings[] = { + static const char *const optionStrings[] = { "-initialdir", "-mustexist", "-parent", "-title", NULL }; enum options { @@ -1348,20 +1342,20 @@ Tk_ChooseDirectoryObjCmd( for (i = 1; i < objc; i += 2) { int index; const char *string; - const WCHAR *uniStr; + const TCHAR *uniStr; Tcl_Obj *optionPtr, *valuePtr; optionPtr = objv[i]; valuePtr = objv[i + 1]; - if (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings, "option", 0, - &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, optionPtr, optionStrings, + sizeof(char *), "option", 0, &index) != TCL_OK) { goto cleanup; } if (i + 1 == objc) { - string = Tcl_GetString(optionPtr); - Tcl_AppendResult(interp, "value for \"", string, "\" missing", - NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(optionPtr))); + Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "VALUE", NULL); goto cleanup; } @@ -1373,15 +1367,15 @@ Tk_ChooseDirectoryObjCmd( } Tcl_WinUtfToTChar(Tcl_DStringValue(&initDirString), -1, &tempString); - uniStr = (WCHAR *) Tcl_DStringValue(&tempString); + uniStr = (TCHAR *) Tcl_DStringValue(&tempString); /* * Convert possible relative path to full path to keep dialog * happy. */ - GetFullPathNameW(uniStr, MAX_PATH, saveDir, NULL); - wcsncpy(cdCBData.initDir, saveDir, MAX_PATH); + GetFullPathName(uniStr, MAX_PATH, saveDir, NULL); + _tcsncpy(cdCBData.initDir, saveDir, MAX_PATH); Tcl_DStringFree(&initDirString); Tcl_DStringFree(&tempString); break; @@ -1417,16 +1411,16 @@ Tk_ChooseDirectoryObjCmd( bInfo.hwndOwner = hWnd; bInfo.pszDisplayName = path; bInfo.pidlRoot = NULL; - if (wcslen(cdCBData.initDir) == 0) { - GetCurrentDirectoryW(MAX_PATH, cdCBData.initDir); + if (_tcslen(cdCBData.initDir) == 0) { + GetCurrentDirectory(MAX_PATH, cdCBData.initDir); } bInfo.lParam = (LPARAM) &cdCBData; if (utfTitle != NULL) { Tcl_WinUtfToTChar(utfTitle, -1, &titleString); - bInfo.lpszTitle = (LPWSTR) Tcl_DStringValue(&titleString); + bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString); } else { - bInfo.lpszTitle = L"Please choose a directory, then select OK."; + bInfo.lpszTitle = TEXT("Please choose a directory, then select OK."); } /* @@ -1459,9 +1453,9 @@ Tk_ChooseDirectoryObjCmd( */ oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - GetCurrentDirectoryW(MAX_PATH, saveDir); + GetCurrentDirectory(MAX_PATH, saveDir); if (SHGetMalloc(&pMalloc) == NOERROR) { - pidl = SHBrowseForFolderW(&bInfo); + pidl = SHBrowseForFolder(&bInfo); /* * This is a fix for Windows 2000, which seems to modify the folder @@ -1476,17 +1470,18 @@ Tk_ChooseDirectoryObjCmd( */ if (pidl != NULL) { - if (!SHGetPathFromIDListW(pidl, path)) { - Tcl_SetResult(interp, "Error: Not a file system folder\n", - TCL_VOLATILE); + if (!SHGetPathFromIDList(pidl, path)) { + Tcl_SetObjResult(interp, Tcl_NewStringObj( + "error: not a file system folder", -1)); + Tcl_SetErrorCode(interp, "TK", "DIRDIALOG", "PSEUDO", NULL); } pMalloc->lpVtbl->Free(pMalloc, (void *) pidl); - } else if (wcslen(cdCBData.retDir) > 0) { - wcscpy(path, cdCBData.retDir); + } else if (_tcslen(cdCBData.retDir) > 0) { + _tcscpy(path, cdCBData.retDir); } pMalloc->lpVtbl->Release(pMalloc); } - SetCurrentDirectoryW(saveDir); + SetCurrentDirectory(saveDir); Tcl_SetServiceMode(oldMode); /* @@ -1506,8 +1501,8 @@ Tk_ChooseDirectoryObjCmd( if (*path) { Tcl_DString ds; - Tcl_AppendResult(interp, ConvertExternalFilename(path, - &ds), NULL); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + ConvertExternalFilename(path, &ds), -1)); Tcl_DStringFree(&ds); } @@ -1544,17 +1539,17 @@ ChooseDirectoryValidateProc( LPARAM lParam, LPARAM lpData) { - WCHAR selDir[MAX_PATH]; + TCHAR selDir[MAX_PATH]; ChooseDir *chooseDirSharedData = (ChooseDir *) lpData; Tcl_DString tempString; Tcl_DString initDirString; - WCHAR string[MAX_PATH]; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + TCHAR string[MAX_PATH]; + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (tsdPtr->debugFlag) { tsdPtr->debugInterp = (Tcl_Interp *) chooseDirSharedData->interp; - Tcl_DoWhenIdle(SetTkDialog, (ClientData) hwnd); + Tcl_DoWhenIdle(SetTkDialog, hwnd); } chooseDirSharedData->retDir[0] = '\0'; switch (message) { @@ -1582,11 +1577,11 @@ ChooseDirectoryValidateProc( Tcl_DStringFree(&initDirString); Tcl_WinUtfToTChar(Tcl_DStringValue(&tempString), -1, &initDirString); Tcl_DStringFree(&tempString); - wcsncpy(string, (WCHAR *) Tcl_DStringValue(&initDirString), + _tcsncpy(string, (TCHAR *) Tcl_DStringValue(&initDirString), MAX_PATH); Tcl_DStringFree(&initDirString); - if (SetCurrentDirectoryW(string) == 0) { + if (SetCurrentDirectory(string) == 0) { /* * Get the full path name to the user entry, at this point it does @@ -1594,16 +1589,17 @@ ChooseDirectoryValidateProc( * it. */ - GetFullPathNameW(string, MAX_PATH, + GetFullPathName(string, MAX_PATH, chooseDirSharedData->retDir, NULL); if (chooseDirSharedData->mustExist) { /* * User HAS to select a valid directory. */ - wsprintfW(selDir, L"Directory '%.200s' does not exist,\nplease select or enter an existing directory.", + wsprintf(selDir, TEXT("Directory '%s' does not exist,\n") + TEXT("please select or enter an existing directory."), chooseDirSharedData->retDir); - MessageBoxW(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK); + MessageBox(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK); chooseDirSharedData->retDir[0] = '\0'; return 1; } @@ -1613,7 +1609,7 @@ ChooseDirectoryValidateProc( * directory in utfRetDir. */ - GetCurrentDirectoryW(MAX_PATH, chooseDirSharedData->retDir); + GetCurrentDirectory(MAX_PATH, chooseDirSharedData->retDir); return 0; } return 0; @@ -1628,13 +1624,13 @@ ChooseDirectoryValidateProc( * Not called when user changes edit box directly. */ - if (SHGetPathFromIDListW((LPITEMIDLIST) lParam, selDir)) { - SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM) selDir); + if (SHGetPathFromIDList((LPITEMIDLIST) lParam, selDir)) { + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM) selDir); // enable the OK button - SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); + SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); } else { // disable the OK button - SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0); + SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0); } UpdateWindow(hwnd); return 1; @@ -1645,9 +1641,9 @@ ChooseDirectoryValidateProc( * specified parameter. */ - WCHAR *initDir = chooseDirSharedData->initDir; + TCHAR *initDir = chooseDirSharedData->initDir; - SetCurrentDirectoryW(initDir); + SetCurrentDirectory(initDir); if (*initDir == '\\') { /* @@ -1664,10 +1660,10 @@ ChooseDirectoryValidateProc( ULONG ulCount, ulAttr; if (SUCCEEDED(psfFolder->lpVtbl->ParseDisplayName( - psfFolder, hwnd, NULL, (WCHAR *) + psfFolder, hwnd, NULL, (TCHAR *) initDir, &ulCount,&pidlMain,&ulAttr)) && (pidlMain != NULL)) { - SendMessageW(hwnd, BFFM_SETSELECTIONW, FALSE, + SendMessage(hwnd, BFFM_SETSELECTION, FALSE, (LPARAM) pidlMain); pMalloc->lpVtbl->Free(pMalloc, pidlMain); } @@ -1676,9 +1672,9 @@ ChooseDirectoryValidateProc( pMalloc->lpVtbl->Release(pMalloc); } } else { - SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) initDir); + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM) initDir); } - SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); + SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1); break; } @@ -1711,13 +1707,13 @@ Tk_MessageBoxObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - Tk_Window tkwin = (Tk_Window) clientData, parent; + Tk_Window tkwin = clientData, parent; HWND hWnd; Tcl_Obj *messageObj, *titleObj, *detailObj, *tmpObj; int defaultBtn, icon, type; int i, oldMode, winCode; UINT flags; - static const char *optionStrings[] = { + static const char *const optionStrings[] = { "-default", "-detail", "-icon", "-message", "-parent", "-title", "-type", NULL }; @@ -1725,7 +1721,7 @@ Tk_MessageBoxObjCmd( MSG_DEFAULT, MSG_DETAIL, MSG_ICON, MSG_MESSAGE, MSG_PARENT, MSG_TITLE, MSG_TYPE }; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); defaultBtn = -1; @@ -1743,14 +1739,14 @@ Tk_MessageBoxObjCmd( optionPtr = objv[i]; valuePtr = objv[i + 1]; - if (Tcl_GetIndexFromObj(interp, optionPtr, optionStrings, "option", - TCL_EXACT, &index) != TCL_OK) { + if (Tcl_GetIndexFromObjStruct(interp, optionPtr, optionStrings, + sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } if (i + 1 == objc) { - const char *string = Tcl_GetString(optionPtr); - Tcl_AppendResult(interp, "value for \"", string, "\" missing", - NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(optionPtr))); + Tcl_SetErrorCode(interp, "TK", "MSGBOX", "VALUE", NULL); return TCL_ERROR; } @@ -1819,9 +1815,10 @@ Tk_MessageBoxObjCmd( } } if (defaultBtnIdx < 0) { - Tcl_AppendResult(interp, "invalid default button \"", - TkFindStateString(buttonMap, defaultBtn), - "\"", NULL); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid default button \"%s\"", + TkFindStateString(buttonMap, defaultBtn))); + Tcl_SetErrorCode(interp, "TK", "MSGBOX", "DEFAULT", NULL); return TCL_ERROR; } break; @@ -1853,9 +1850,9 @@ Tk_MessageBoxObjCmd( tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL); tsdPtr->hBigIcon = TkWinGetIcon(parent, ICON_BIG); - tsdPtr->hMsgBoxHook = SetWindowsHookExW(WH_CBT, MsgBoxCBTProc, NULL, + tsdPtr->hMsgBoxHook = SetWindowsHookEx(WH_CBT, MsgBoxCBTProc, NULL, GetCurrentThreadId()); - winCode = MessageBoxW(hWnd, Tcl_GetUnicode(tmpObj), + winCode = MessageBox(hWnd, Tcl_GetUnicode(tmpObj), titleObj ? Tcl_GetUnicode(titleObj) : L"", flags); UnhookWindowsHookEx(tsdPtr->hMsgBoxHook); (void) Tcl_SetServiceMode(oldMode); @@ -1869,8 +1866,8 @@ Tk_MessageBoxObjCmd( EnableWindow(hWnd, 1); Tcl_DecrRefCount(tmpObj); - - Tcl_SetResult(interp, TkFindStateString(buttonMap, winCode), TCL_STATIC); + Tcl_SetObjResult(interp, Tcl_NewStringObj( + TkFindStateString(buttonMap, winCode), -1)); return TCL_OK; } @@ -1880,7 +1877,7 @@ MsgBoxCBTProc( WPARAM wParam, LPARAM lParam) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (nCode == HCBT_CREATEWND) { @@ -1897,9 +1894,9 @@ MsgBoxCBTProc( if (WC_DIALOG == lpcbtcreate->lpcs->lpszClass) { HWND hwnd = (HWND) wParam; - SendMessageW(hwnd, WM_SETICON, ICON_SMALL, + SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) tsdPtr->hSmallIcon); - SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon); + SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon); } } @@ -1927,12 +1924,12 @@ static void SetTkDialog( ClientData clientData) { - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + ThreadSpecificData *tsdPtr = Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); char buf[32]; sprintf(buf, "0x%p", (HWND) clientData); - Tcl_SetVar(tsdPtr->debugInterp, "tk_dialog", buf, TCL_GLOBAL_ONLY); + Tcl_SetVar2(tsdPtr->debugInterp, "tk_dialog", NULL, buf, TCL_GLOBAL_ONLY); } /* @@ -1941,12 +1938,12 @@ SetTkDialog( static const char * ConvertExternalFilename( - WCHAR *filename, + TCHAR *filename, Tcl_DString *dsPtr) { char *p; - Tcl_WinTCharToUtf((TCHAR *) filename, -1, dsPtr); + Tcl_WinTCharToUtf(filename, -1, dsPtr); for (p = Tcl_DStringValue(dsPtr); *p != '\0'; p++) { /* * Change the pathname to the Tcl "normalized" pathname, where back @@ -1961,6 +1958,569 @@ ConvertExternalFilename( } /* + * ---------------------------------------------------------------------- + * + * GetFontObj -- + * + * Convert a windows LOGFONT into a Tk font description. + * + * Result: + * A list containing a Tk font description. + * + * ---------------------------------------------------------------------- + */ + +static Tcl_Obj * +GetFontObj( + HDC hdc, + LOGFONT *plf) +{ + Tcl_DString ds; + Tcl_Obj *resObj; + int pt = 0; + + resObj = Tcl_NewListObj(0, NULL); + Tcl_WinTCharToUtf(plf->lfFaceName, -1, &ds); + Tcl_ListObjAppendElement(NULL, resObj, + Tcl_NewStringObj(Tcl_DStringValue(&ds), -1)); + Tcl_DStringFree(&ds); + pt = -MulDiv(plf->lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY)); + Tcl_ListObjAppendElement(NULL, resObj, Tcl_NewIntObj(pt)); + if (plf->lfWeight >= 700) { + Tcl_ListObjAppendElement(NULL, resObj, Tcl_NewStringObj("bold", -1)); + } + if (plf->lfItalic) { + Tcl_ListObjAppendElement(NULL, resObj, + Tcl_NewStringObj("italic", -1)); + } + if (plf->lfUnderline) { + Tcl_ListObjAppendElement(NULL, resObj, + Tcl_NewStringObj("underline", -1)); + } + if (plf->lfStrikeOut) { + Tcl_ListObjAppendElement(NULL, resObj, + Tcl_NewStringObj("overstrike", -1)); + } + return resObj; +} + +static void +ApplyLogfont( + Tcl_Interp *interp, + Tcl_Obj *cmdObj, + HDC hdc, + LOGFONT *logfontPtr) +{ + int objc; + Tcl_Obj **objv, **tmpv; + + Tcl_ListObjGetElements(NULL, cmdObj, &objc, &objv); + tmpv = ckalloc(sizeof(Tcl_Obj *) * (objc + 2)); + memcpy(tmpv, objv, sizeof(Tcl_Obj *) * objc); + tmpv[objc] = GetFontObj(hdc, logfontPtr); + TkBackgroundEvalObjv(interp, objc+1, tmpv, TCL_EVAL_GLOBAL); + ckfree(tmpv); +} + +/* + * ---------------------------------------------------------------------- + * + * HookProc -- + * + * Font selection hook. If the user selects Apply on the dialog, we call + * the applyProc script with the currently selected font as arguments. + * + * ---------------------------------------------------------------------- + */ + +typedef struct HookData { + Tcl_Interp *interp; + Tcl_Obj *titleObj; + Tcl_Obj *cmdObj; + Tcl_Obj *parentObj; + Tcl_Obj *fontObj; + HWND hwnd; + Tk_Window parent; +} HookData; + +static UINT_PTR CALLBACK +HookProc( + HWND hwndDlg, + UINT msg, + WPARAM wParam, + LPARAM lParam) +{ + CHOOSEFONT *pcf = (CHOOSEFONT *) lParam; + HWND hwndCtrl; + static HookData *phd = NULL; + ThreadSpecificData *tsdPtr = + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (WM_INITDIALOG == msg && lParam != 0) { + phd = (HookData *) pcf->lCustData; + phd->hwnd = hwndDlg; + if (tsdPtr->debugFlag) { + tsdPtr->debugInterp = phd->interp; + Tcl_DoWhenIdle(SetTkDialog, hwndDlg); + } + if (phd->titleObj != NULL) { + Tcl_DString title; + + Tcl_WinUtfToTChar(Tcl_GetString(phd->titleObj), -1, &title); + if (Tcl_DStringLength(&title) > 0) { + SetWindowText(hwndDlg, (LPCTSTR) Tcl_DStringValue(&title)); + } + Tcl_DStringFree(&title); + } + + /* + * Disable the colour combobox (0x473) and its label (0x443). + */ + + hwndCtrl = GetDlgItem(hwndDlg, 0x443); + if (IsWindow(hwndCtrl)) { + EnableWindow(hwndCtrl, FALSE); + } + hwndCtrl = GetDlgItem(hwndDlg, 0x473); + if (IsWindow(hwndCtrl)) { + EnableWindow(hwndCtrl, FALSE); + } + TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility"); + return 1; /* we handled the message */ + } + + if (WM_DESTROY == msg) { + phd->hwnd = NULL; + TkSendVirtualEvent(phd->parent, "TkFontchooserVisibility"); + return 0; + } + + /* + * Handle apply button by calling the provided command script as a + * background evaluation (ie: errors dont come back here). + */ + + if (WM_COMMAND == msg && LOWORD(wParam) == 1026) { + LOGFONT lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0}}; + HDC hdc = GetDC(hwndDlg); + + SendMessage(hwndDlg, WM_CHOOSEFONT_GETLOGFONT, 0, (LPARAM) &lf); + if (phd && phd->cmdObj) { + ApplyLogfont(phd->interp, phd->cmdObj, hdc, &lf); + } + if (phd && phd->parent) { + TkSendVirtualEvent(phd->parent, "TkFontchooserFontChanged"); + } + return 1; + } + return 0; /* pass on for default processing */ +} + +/* + * Helper for the FontchooserConfigure command to return the current value of + * any of the options (which may be NULL in the structure) + */ + +enum FontchooserOption { + FontchooserParent, FontchooserTitle, FontchooserFont, FontchooserCmd, + FontchooserVisible +}; + +static Tcl_Obj * +FontchooserCget( + HookData *hdPtr, + int optionIndex) +{ + Tcl_Obj *resObj = NULL; + + switch(optionIndex) { + case FontchooserParent: + if (hdPtr->parentObj) { + resObj = hdPtr->parentObj; + } else { + resObj = Tcl_NewStringObj(".", 1); + } + break; + case FontchooserTitle: + if (hdPtr->titleObj) { + resObj = hdPtr->titleObj; + } else { + resObj = Tcl_NewStringObj("", 0); + } + break; + case FontchooserFont: + if (hdPtr->fontObj) { + resObj = hdPtr->fontObj; + } else { + resObj = Tcl_NewStringObj("", 0); + } + break; + case FontchooserCmd: + if (hdPtr->cmdObj) { + resObj = hdPtr->cmdObj; + } else { + resObj = Tcl_NewStringObj("", 0); + } + break; + case FontchooserVisible: + resObj = Tcl_NewBooleanObj(hdPtr->hwnd && IsWindow(hdPtr->hwnd)); + break; + default: + resObj = Tcl_NewStringObj("", 0); + } + return resObj; +} + +/* + * ---------------------------------------------------------------------- + * + * FontchooserConfigureCmd -- + * + * Implementation of the 'tk fontchooser configure' ensemble command. See + * the user documentation for what it does. + * + * Results: + * See the user documentation. + * + * Side effects: + * Per-interp data structure may be modified + * + * ---------------------------------------------------------------------- + */ + +static int +FontchooserConfigureCmd( + ClientData clientData, /* Main window */ + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + Tk_Window tkwin = clientData; + HookData *hdPtr = NULL; + int i, r = TCL_OK; + static const char *const optionStrings[] = { + "-parent", "-title", "-font", "-command", "-visible", NULL + }; + + hdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", NULL); + + /* + * With no arguments we return all the options in a dict. + */ + + if (objc == 1) { + Tcl_Obj *keyObj, *valueObj; + Tcl_Obj *dictObj = Tcl_NewDictObj(); + + for (i = 0; r == TCL_OK && optionStrings[i] != NULL; ++i) { + keyObj = Tcl_NewStringObj(optionStrings[i], -1); + valueObj = FontchooserCget(hdPtr, i); + r = Tcl_DictObjPut(interp, dictObj, keyObj, valueObj); + } + if (r == TCL_OK) { + Tcl_SetObjResult(interp, dictObj); + } + return r; + } + + for (i = 1; i < objc; i += 2) { + int optionIndex; + + if (Tcl_GetIndexFromObjStruct(interp, objv[i], optionStrings, + sizeof(char *), "option", 0, &optionIndex) != TCL_OK) { + return TCL_ERROR; + } + if (objc == 2) { + /* + * If one option and no arg - return the current value. + */ + + Tcl_SetObjResult(interp, FontchooserCget(hdPtr, optionIndex)); + return TCL_OK; + } + if (i + 1 == objc) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "value for \"%s\" missing", Tcl_GetString(objv[i]))); + Tcl_SetErrorCode(interp, "TK", "FONTDIALOG", "VALUE", NULL); + return TCL_ERROR; + } + switch (optionIndex) { + case FontchooserVisible: { + static const char *msg = "cannot change read-only option " + "\"-visible\": use the show or hide command"; + + Tcl_SetObjResult(interp, Tcl_NewStringObj(msg, -1)); + Tcl_SetErrorCode(interp, "TK", "FONTDIALOG", "READONLY", NULL); + return TCL_ERROR; + } + case FontchooserParent: { + Tk_Window parent = Tk_NameToWindow(interp, + Tcl_GetString(objv[i+1]), tkwin); + + if (parent == None) { + return TCL_ERROR; + } + if (hdPtr->parentObj) { + Tcl_DecrRefCount(hdPtr->parentObj); + } + hdPtr->parentObj = objv[i+1]; + if (Tcl_IsShared(hdPtr->parentObj)) { + hdPtr->parentObj = Tcl_DuplicateObj(hdPtr->parentObj); + } + Tcl_IncrRefCount(hdPtr->parentObj); + break; + } + case FontchooserTitle: + if (hdPtr->titleObj) { + Tcl_DecrRefCount(hdPtr->titleObj); + } + hdPtr->titleObj = objv[i+1]; + if (Tcl_IsShared(hdPtr->titleObj)) { + hdPtr->titleObj = Tcl_DuplicateObj(hdPtr->titleObj); + } + Tcl_IncrRefCount(hdPtr->titleObj); + break; + case FontchooserFont: + if (hdPtr->fontObj) { + Tcl_DecrRefCount(hdPtr->fontObj); + } + (void)Tcl_GetString(objv[i+1]); + if (objv[i+1]->length) { + hdPtr->fontObj = objv[i+1]; + if (Tcl_IsShared(hdPtr->fontObj)) { + hdPtr->fontObj = Tcl_DuplicateObj(hdPtr->fontObj); + } + Tcl_IncrRefCount(hdPtr->fontObj); + } else { + hdPtr->fontObj = NULL; + } + break; + case FontchooserCmd: + if (hdPtr->cmdObj) { + Tcl_DecrRefCount(hdPtr->cmdObj); + } + (void)Tcl_GetString(objv[i+1]); + if (objv[i+1]->length) { + hdPtr->cmdObj = objv[i+1]; + if (Tcl_IsShared(hdPtr->cmdObj)) { + hdPtr->cmdObj = Tcl_DuplicateObj(hdPtr->cmdObj); + } + Tcl_IncrRefCount(hdPtr->cmdObj); + } else { + hdPtr->cmdObj = NULL; + } + break; + } + } + return TCL_OK; +} + +/* + * ---------------------------------------------------------------------- + * + * FontchooserShowCmd -- + * + * Implements the 'tk fontchooser show' ensemble command. The per-interp + * configuration data for the dialog is held in an interp associated + * structure. + * + * Calls the Win32 FontChooser API which provides a modal dialog. See + * HookProc where we make a few changes to the dialog and set some + * additional state. + * + * ---------------------------------------------------------------------- + */ + +static int +FontchooserShowCmd( + ClientData clientData, /* Main window */ + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + Tcl_DString ds; + Tk_Window tkwin = clientData, parent; + CHOOSEFONT cf; + LOGFONT lf; + HDC hdc; + HookData *hdPtr; + int r = TCL_OK, oldMode = 0; + + hdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", NULL); + + parent = tkwin; + if (hdPtr->parentObj) { + parent = Tk_NameToWindow(interp, Tcl_GetString(hdPtr->parentObj), + tkwin); + if (parent == None) { + return TCL_ERROR; + } + } + + Tk_MakeWindowExist(parent); + + ZeroMemory(&cf, sizeof(CHOOSEFONT)); + ZeroMemory(&lf, sizeof(LOGFONT)); + lf.lfCharSet = DEFAULT_CHARSET; + cf.lStructSize = sizeof(CHOOSEFONT); + cf.hwndOwner = Tk_GetHWND(Tk_WindowId(parent)); + cf.lpLogFont = &lf; + cf.nFontType = SCREEN_FONTTYPE; + cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_ENABLEHOOK; + cf.rgbColors = RGB(0,0,0); + cf.lpfnHook = HookProc; + cf.lCustData = (INT_PTR) hdPtr; + hdPtr->interp = interp; + hdPtr->parent = parent; + hdc = GetDC(cf.hwndOwner); + + if (hdPtr->fontObj != NULL) { + TkFont *fontPtr; + Tk_Font f = Tk_AllocFontFromObj(interp, tkwin, hdPtr->fontObj); + + if (f == NULL) { + return TCL_ERROR; + } + fontPtr = (TkFont *) f; + cf.Flags |= CF_INITTOLOGFONTSTRUCT; + Tcl_WinUtfToTChar(fontPtr->fa.family, -1, &ds); + _tcsncpy(lf.lfFaceName, (TCHAR *)Tcl_DStringValue(&ds), + LF_FACESIZE-1); + Tcl_DStringFree(&ds); + lf.lfFaceName[LF_FACESIZE-1] = 0; + lf.lfHeight = -MulDiv(TkFontGetPoints(tkwin, fontPtr->fa.size), + GetDeviceCaps(hdc, LOGPIXELSY), 72); + if (fontPtr->fa.weight == TK_FW_BOLD) { + lf.lfWeight = FW_BOLD; + } + if (fontPtr->fa.slant != TK_FS_ROMAN) { + lf.lfItalic = TRUE; + } + if (fontPtr->fa.underline) { + lf.lfUnderline = TRUE; + } + if (fontPtr->fa.overstrike) { + lf.lfStrikeOut = TRUE; + } + Tk_FreeFont(f); + } + + if (TCL_OK == r && hdPtr->cmdObj != NULL) { + int len = 0; + + r = Tcl_ListObjLength(interp, hdPtr->cmdObj, &len); + if (len > 0) { + cf.Flags |= CF_APPLY; + } + } + + if (TCL_OK == r) { + oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + if (ChooseFont(&cf)) { + if (hdPtr->cmdObj) { + ApplyLogfont(hdPtr->interp, hdPtr->cmdObj, hdc, &lf); + } + if (hdPtr->parent) { + TkSendVirtualEvent(hdPtr->parent, "TkFontchooserFontChanged"); + } + } + Tcl_SetServiceMode(oldMode); + EnableWindow(cf.hwndOwner, 1); + } + + ReleaseDC(cf.hwndOwner, hdc); + return r; +} + +/* + * ---------------------------------------------------------------------- + * + * FontchooserHideCmd -- + * + * Implementation of the 'tk fontchooser hide' ensemble. See the user + * documentation for details. + * As the Win32 FontChooser function is always modal all we do here is + * destroy the dialog + * + * ---------------------------------------------------------------------- + */ + +static int +FontchooserHideCmd( + ClientData clientData, /* Main window */ + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + HookData *hdPtr = Tcl_GetAssocData(interp, "::tk::fontchooser", NULL); + + if (hdPtr->hwnd && IsWindow(hdPtr->hwnd)) { + EndDialog(hdPtr->hwnd, 0); + } + return TCL_OK; +} + +/* + * ---------------------------------------------------------------------- + * + * DeleteHookData -- + * + * Clean up the font chooser configuration data when the interp is + * destroyed. + * + * ---------------------------------------------------------------------- + */ + +static void +DeleteHookData(ClientData clientData, Tcl_Interp *interp) +{ + HookData *hdPtr = clientData; + + if (hdPtr->parentObj) { + Tcl_DecrRefCount(hdPtr->parentObj); + } + if (hdPtr->fontObj) { + Tcl_DecrRefCount(hdPtr->fontObj); + } + if (hdPtr->titleObj) { + Tcl_DecrRefCount(hdPtr->titleObj); + } + if (hdPtr->cmdObj) { + Tcl_DecrRefCount(hdPtr->cmdObj); + } + ckfree(hdPtr); +} + +/* + * ---------------------------------------------------------------------- + * + * TkInitFontchooser -- + * + * Associate the font chooser configuration data with the Tcl + * interpreter. There is one font chooser per interp. + * + * ---------------------------------------------------------------------- + */ + +MODULE_SCOPE const TkEnsemble tkFontchooserEnsemble[]; +const TkEnsemble tkFontchooserEnsemble[] = { + { "configure", FontchooserConfigureCmd, NULL }, + { "show", FontchooserShowCmd, NULL }, + { "hide", FontchooserHideCmd, NULL }, + { NULL, NULL, NULL } +}; + +int +TkInitFontchooser(Tcl_Interp *interp, ClientData clientData) +{ + HookData *hdPtr = ckalloc(sizeof(HookData)); + + memset(hdPtr, 0, sizeof(HookData)); + Tcl_SetAssocData(interp, "::tk::fontchooser", DeleteHookData, hdPtr); + return TCL_OK; +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 |