summaryrefslogtreecommitdiffstats
path: root/win/tkWinDialog.c
diff options
context:
space:
mode:
authorJoe Mistachkin <joe@mistachkin.com>2014-11-11 22:23:34 (GMT)
committerJoe Mistachkin <joe@mistachkin.com>2014-11-11 22:23:34 (GMT)
commitb15c525eedc93a453dfea94482bc1198e27748fc (patch)
tree49a88f59bc168351fe802d8aa68da6d853b823aa /win/tkWinDialog.c
parent07f85cd3c1b4934fb746ea36516ba2944b4eea11 (diff)
parentee9722cf78769c35f57383613f570b6e797e74bf (diff)
downloadtk-b15c525eedc93a453dfea94482bc1198e27748fc.zip
tk-b15c525eedc93a453dfea94482bc1198e27748fc.tar.gz
tk-b15c525eedc93a453dfea94482bc1198e27748fc.tar.bz2
Merge updates from core 8.5 branch.
Diffstat (limited to 'win/tkWinDialog.c')
-rw-r--r--win/tkWinDialog.c946
1 files changed, 187 insertions, 759 deletions
diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c
index 069991b..e03862c 100644
--- a/win/tkWinDialog.c
+++ b/win/tkWinDialog.c
@@ -8,7 +8,6 @@
* 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"
@@ -51,19 +50,6 @@
#define OPENFILENAME_SIZE_VERSION_400 76
#endif
-/*
- * The following structure is used by the new Tk_ChooseDirectoryObjCmd to pass
- * data between it and its callback. Unqiue to Winodws platform.
- */
-
-typedef struct ChooseDirData {
- TCHAR utfInitDir[MAX_PATH]; /* Initial folder to use */
- TCHAR utfRetDir[MAX_PATH]; /* Returned folder to use */
- Tcl_Interp *interp;
- int mustExist; /* True if file must exist to return from
- * callback */
-} CHOOSEDIRDATA;
-
typedef struct ThreadSpecificData {
int debugFlag; /* Flags whether we should output debugging
* information while displaying a builtin
@@ -132,14 +118,14 @@ static const struct {int type; int btnIds[3];} allowedTypes[] = {
*/
#define TkWinGetHInstance(from) \
- ((HINSTANCE) GetWindowLongPtr((from), GWLP_HINSTANCE))
+ ((HINSTANCE) GetWindowLongPtrW((from), GWLP_HINSTANCE))
#define TkWinGetUserData(from) \
- GetWindowLongPtr((from), GWLP_USERDATA)
+ GetWindowLongPtrW((from), GWLP_USERDATA)
#define TkWinSetUserData(to,what) \
- SetWindowLongPtr((to), GWLP_USERDATA, (LPARAM)(what))
+ SetWindowLongPtrW((to), GWLP_USERDATA, (LPARAM)(what))
/*
- * The value of TK_MULTI_MAX_PATH dictactes how many files can be retrieved
+ * The value of TK_MULTI_MAX_PATH dictates how many files can be retrieved
* with tk_get*File -multiple 1. It must be allocated on the stack, so make it
* large enough but not too large. - hobbs
*
@@ -154,27 +140,17 @@ static const struct {int type; int btnIds[3];} allowedTypes[] = {
* chooser function, Tk_ChooseDirectoryObjCmd(), and its dialog hook proc.
*/
-typedef struct ChooseDir {
- Tcl_Interp *interp; /* Interp, used only if debug is turned on,
- * for setting the "tk_dialog" variable. */
- int lastCtrl; /* Used by hook proc to keep track of last
- * control that had input focus, so when OK is
- * pressed we know whether to browse a new
- * directory or return. */
- int lastIdx; /* Last item that was selected in directory
- * browser listbox. */
- TCHAR path[MAX_PATH]; /* On return from choose directory dialog,
- * holds the selected path. Cannot return
- * selected path in ofnPtr->lpstrFile because
- * the default dialog proc stores a '\0' in
- * it, since, of course, no _file_ was
- * selected. */
- OPENFILENAME *ofnPtr; /* pointer to the OFN structure */
+typedef struct {
+ WCHAR initDir[MAX_PATH]; /* Initial folder to use */
+ WCHAR retDir[MAX_PATH]; /* Returned folder to use */
+ Tcl_Interp *interp;
+ int mustExist; /* True if file must exist to return from
+ * callback */
} ChooseDir;
/*
- * The following structure is used to pass information between GetFileName/W
- * functions and OFN dialog hook procedures. [Bug 2896501, Patch 2898255]
+ * The following structure is used to pass information between GetFileName
+ * function and OFN dialog hook procedures. [Bug 2896501, Patch 2898255]
*/
typedef struct OFNData {
@@ -183,8 +159,7 @@ typedef struct OFNData {
int dynFileBufferSize; /* Dynamic filename buffer size, stored to
* avoid shrinking and expanding the buffer
* when selection changes */
- char *dynFileBuffer; /* Dynamic filename buffer, cast to WCHAR* in
- * UNICODE procedures */
+ WCHAR *dynFileBuffer; /* Dynamic filename buffer */
} OFNData;
/*
@@ -195,23 +170,18 @@ static UINT APIENTRY ChooseDirectoryValidateProc(HWND hdlg, UINT uMsg,
LPARAM wParam, LPARAM lParam);
static UINT CALLBACK ColorDlgHookProc(HWND hDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam);
-static int GetFileNameA(ClientData clientData,
- Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[], int isOpen);
-static int GetFileNameW(ClientData clientData,
+static int GetFileName(ClientData clientData,
Tcl_Interp *interp, int objc,
- Tcl_Obj *CONST objv[], int isOpen);
+ Tcl_Obj *const objv[], int isOpen);
static int MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr,
Tcl_DString *dsPtr, Tcl_Obj *initialPtr,
- int *index);
-static UINT APIENTRY OFNHookProcA(HWND hdlg, UINT uMsg, WPARAM wParam,
- LPARAM lParam);
-static UINT APIENTRY OFNHookProcW(HWND hdlg, UINT uMsg, WPARAM wParam,
+ int *indexPtr);
+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 char * ConvertExternalFilename(Tcl_Encoding encoding,
- char *filename, Tcl_DString *dsPtr);
+static const char *ConvertExternalFilename(WCHAR *filename,
+ Tcl_DString *dsPtr);
/*
*-------------------------------------------------------------------------
@@ -252,10 +222,10 @@ EatSpuriousMessageBugFix(void)
DWORD nTime = GetTickCount() + 250;
while (GetTickCount() < nTime) {
- if (PeekMessage(&msg, 0, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE)){
+ if (PeekMessageA(&msg, 0, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE)){
break;
}
- PeekMessage(&msg, 0, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE);
+ PeekMessageA(&msg, 0, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE);
}
}
@@ -312,16 +282,16 @@ Tk_ChooseColorObjCmd(
ClientData clientData, /* Main window associated with interpreter. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tk_Window tkwin = (Tk_Window) clientData, parent;
HWND hWnd;
int i, oldMode, winCode, result;
- CHOOSECOLOR chooseColor;
+ CHOOSECOLORW chooseColor;
static int inited = 0;
static COLORREF dwCustColors[16];
static long oldColor; /* the color selected last time */
- static CONST char *optionStrings[] = {
+ static const char *optionStrings[] = {
"-initialcolor", "-parent", "-title", NULL
};
enum options {
@@ -345,7 +315,7 @@ Tk_ChooseColorObjCmd(
}
parent = tkwin;
- chooseColor.lStructSize = sizeof(CHOOSECOLOR);
+ chooseColor.lStructSize = sizeof(CHOOSECOLORW);
chooseColor.hwndOwner = NULL;
chooseColor.hInstance = NULL;
chooseColor.rgbResult = oldColor;
@@ -353,11 +323,11 @@ Tk_ChooseColorObjCmd(
chooseColor.Flags = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
chooseColor.lCustData = (LPARAM) NULL;
chooseColor.lpfnHook = (LPOFNHOOKPROC) ColorDlgHookProc;
- chooseColor.lpTemplateName = (LPTSTR) interp;
+ chooseColor.lpTemplateName = (LPWSTR) interp;
for (i = 1; i < objc; i += 2) {
int index;
- char *string;
+ const char *string;
Tcl_Obj *optionPtr, *valuePtr;
optionPtr = objv[i];
@@ -405,7 +375,7 @@ Tk_ChooseColorObjCmd(
chooseColor.hwndOwner = hWnd;
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- winCode = ChooseColor(&chooseColor);
+ winCode = ChooseColorW(&chooseColor);
(void) Tcl_SetServiceMode(oldMode);
/*
@@ -473,7 +443,7 @@ ColorDlgHookProc(
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
const char *title;
- CHOOSECOLOR *ccPtr;
+ CHOOSECOLORW *ccPtr;
if (WM_INITDIALOG == uMsg) {
@@ -481,14 +451,13 @@ ColorDlgHookProc(
* Set the title string of the dialog.
*/
- ccPtr = (CHOOSECOLOR *) lParam;
+ ccPtr = (CHOOSECOLORW *) lParam;
title = (const char *) ccPtr->lCustData;
if ((title != NULL) && (title[0] != '\0')) {
Tcl_DString ds;
- (*tkWinProcs->setWindowText)(hDlg,
- Tcl_WinUtfToTChar(title, -1, &ds));
+ SetWindowTextW(hDlg, (WCHAR *)Tcl_WinUtfToTChar(title,-1,&ds));
Tcl_DStringFree(&ds);
}
if (tsdPtr->debugFlag) {
@@ -522,13 +491,9 @@ Tk_GetOpenFileObjCmd(
ClientData clientData, /* Main window associated with interpreter. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
- return GetFileNameW(clientData, interp, objc, objv, 1);
- } else {
- return GetFileNameA(clientData, interp, objc, objv, 1);
- }
+ return GetFileName(clientData, interp, objc, objv, 1);
}
/*
@@ -553,19 +518,15 @@ Tk_GetSaveFileObjCmd(
ClientData clientData, /* Main window associated with interpreter. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- if (TkWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
- return GetFileNameW(clientData, interp, objc, objv, 0);
- } else {
- return GetFileNameA(clientData, interp, objc, objv, 0);
- }
+ return GetFileName(clientData, interp, objc, objv, 0);
}
/*
*----------------------------------------------------------------------
*
- * GetFileNameW --
+ * GetFileName --
*
* Calls GetOpenFileName() or GetSaveFileName().
*
@@ -579,11 +540,11 @@ Tk_GetSaveFileObjCmd(
*/
static int
-GetFileNameW(
+GetFileName(
ClientData clientData, /* Main window associated with interpreter. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[], /* Argument objects. */
+ Tcl_Obj *const objv[], /* Argument objects. */
int open) /* 1 to call GetOpenFileName(), 0 to call
* GetSaveFileName(). */
{
@@ -593,13 +554,12 @@ GetFileNameW(
int cdlgerr;
int filterIndex = 0, result = TCL_ERROR, winCode, oldMode, i, multi = 0;
int confirmOverwrite = 1;
- char *extension = NULL, *title = NULL;
+ const char *extension = NULL, *title = NULL;
Tk_Window tkwin = (Tk_Window) clientData;
HWND hWnd;
Tcl_Obj *filterObj = NULL, *initialTypeObj = NULL, *typeVariableObj = NULL;
Tcl_DString utfFilterString, utfDirString, ds;
Tcl_DString extString, filterString, dirString, titleString;
- Tcl_Encoding unicodeEncoding = TkWinGetUnicodeEncoding();
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
enum options {
@@ -607,10 +567,10 @@ GetFileNameW(
FILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW
};
struct Options {
- CONST char *name;
+ const char *name;
enum options value;
};
- static CONST struct Options saveOptions[] = {
+ static const struct Options saveOptions[] = {
{"-confirmoverwrite", FILE_CONFIRMOW},
{"-defaultextension", FILE_DEFAULT},
{"-filetypes", FILE_TYPES},
@@ -621,7 +581,7 @@ GetFileNameW(
{"-typevariable", FILE_TYPEVARIABLE},
{NULL, FILE_DEFAULT/*ignored*/ }
};
- static CONST struct Options openOptions[] = {
+ static const struct Options openOptions[] = {
{"-defaultextension", FILE_DEFAULT},
{"-filetypes", FILE_TYPES},
{"-initialdir", FILE_INITDIR},
@@ -632,7 +592,7 @@ GetFileNameW(
{"-typevariable", FILE_TYPEVARIABLE},
{NULL, FILE_DEFAULT/*ignored*/ }
};
- CONST struct Options *options = open ? openOptions : saveOptions;
+ const struct Options *options = open ? openOptions : saveOptions;
file[0] = '\0';
ZeroMemory(&ofnData, sizeof(OFNData));
@@ -645,7 +605,7 @@ GetFileNameW(
for (i = 1; i < objc; i += 2) {
int index;
- char *string;
+ const char *string;
Tcl_Obj *valuePtr = objv[i + 1];
if (Tcl_GetIndexFromObjStruct(interp, objv[i], options,
@@ -679,9 +639,9 @@ GetFileNameW(
if (Tcl_TranslateFileName(interp, string, &ds) == NULL) {
goto end;
}
- Tcl_UtfToExternal(NULL, unicodeEncoding, Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds), 0, NULL, (char *) file,
- sizeof(file), NULL, NULL, NULL);
+ Tcl_UtfToExternal(NULL, TkWinGetUnicodeEncoding(),
+ Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL,
+ (char *) file, sizeof(file), NULL, NULL, NULL);
Tcl_DStringFree(&ds);
break;
case FILE_PARENT:
@@ -728,11 +688,11 @@ GetFileNameW(
}
ofn.hwndOwner = hWnd;
ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner);
- ofn.lpstrFile = (WCHAR *) file;
+ ofn.lpstrFile = file;
ofn.nMaxFile = TK_MULTI_MAX_PATH;
ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR
| OFN_EXPLORER | OFN_ENABLEHOOK| OFN_ENABLESIZING;
- ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProcW;
+ ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
ofn.lCustData = (LPARAM) &ofnData;
if (open != 0) {
@@ -751,24 +711,22 @@ GetFileNameW(
* procedure when necessary
*/
- ofnData.dynFileBufferSize = 1024;
- ofnData.dynFileBuffer = ckalloc(1024);
+ ofnData.dynFileBufferSize = 512;
+ ofnData.dynFileBuffer = (WCHAR *)ckalloc(512 * sizeof(WCHAR));
}
if (extension != NULL) {
- Tcl_UtfToExternalDString(unicodeEncoding, extension, -1, &extString);
+ Tcl_WinUtfToTChar(extension, -1, &extString);
ofn.lpstrDefExt = (WCHAR *) Tcl_DStringValue(&extString);
}
- Tcl_UtfToExternalDString(unicodeEncoding,
- Tcl_DStringValue(&utfFilterString),
+ Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString),
Tcl_DStringLength(&utfFilterString), &filterString);
ofn.lpstrFilter = (WCHAR *) Tcl_DStringValue(&filterString);
ofn.nFilterIndex = filterIndex;
if (Tcl_DStringValue(&utfDirString)[0] != '\0') {
- Tcl_UtfToExternalDString(unicodeEncoding,
- Tcl_DStringValue(&utfDirString),
+ Tcl_WinUtfToTChar(Tcl_DStringValue(&utfDirString),
Tcl_DStringLength(&utfDirString), &dirString);
} else {
/*
@@ -784,7 +742,7 @@ GetFileNameW(
Tcl_DStringValue(&utfDirString), &cwd) == NULL)) {
Tcl_ResetResult(interp);
} else {
- Tcl_UtfToExternalDString(unicodeEncoding, Tcl_DStringValue(&cwd),
+ Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd),
Tcl_DStringLength(&cwd), &dirString);
}
Tcl_DStringFree(&cwd);
@@ -792,7 +750,7 @@ GetFileNameW(
ofn.lpstrInitialDir = (WCHAR *) Tcl_DStringValue(&dirString);
if (title != NULL) {
- Tcl_UtfToExternalDString(unicodeEncoding, title, -1, &titleString);
+ Tcl_WinUtfToTChar(title, -1, &titleString);
ofn.lpstrTitle = (WCHAR *) Tcl_DStringValue(&titleString);
}
@@ -858,7 +816,7 @@ GetFileNameW(
* first element is the directory path.
*/
- WCHAR *files = (WCHAR *) ofnData.dynFileBuffer;
+ WCHAR *files = ofnData.dynFileBuffer;
Tcl_Obj *returnList = Tcl_NewObj();
int count = 0;
@@ -866,8 +824,7 @@ GetFileNameW(
* Get directory.
*/
- (void) ConvertExternalFilename(unicodeEncoding, (char *) files,
- &ds);
+ ConvertExternalFilename(files, &ds);
while (*files != '\0') {
while (*files != '\0') {
@@ -879,8 +836,7 @@ GetFileNameW(
Tcl_DString filenameBuf;
count++;
- (void) ConvertExternalFilename(unicodeEncoding,
- (char *) files, &filenameBuf);
+ ConvertExternalFilename(files, &filenameBuf);
fullnameObj = Tcl_NewStringObj(Tcl_DStringValue(&ds),
Tcl_DStringLength(&ds));
@@ -906,8 +862,8 @@ GetFileNameW(
Tcl_SetObjResult(interp, returnList);
Tcl_DStringFree(&ds);
} else {
- Tcl_AppendResult(interp, ConvertExternalFilename(unicodeEncoding,
- (char *) ofn.lpstrFile, &ds), NULL);
+ Tcl_AppendResult(interp, ConvertExternalFilename(
+ ofn.lpstrFile, &ds), NULL);
gotFilename = (Tcl_DStringLength(&ds) > 0);
Tcl_DStringFree(&ds);
}
@@ -932,8 +888,8 @@ GetFileNameW(
}
} else if (cdlgerr == FNERR_INVALIDFILENAME) {
Tcl_SetResult(interp, "invalid filename \"", TCL_STATIC);
- Tcl_AppendResult(interp, ConvertExternalFilename(unicodeEncoding,
- (char *) ofn.lpstrFile, &ds), "\"", NULL);
+ Tcl_AppendResult(interp, ConvertExternalFilename(
+ ofn.lpstrFile, &ds), "\"", NULL);
Tcl_DStringFree(&ds);
} else {
result = TCL_OK;
@@ -954,7 +910,7 @@ GetFileNameW(
Tcl_DStringFree(&utfDirString);
Tcl_DStringFree(&utfFilterString);
if (ofnData.dynFileBuffer != NULL) {
- ckfree(ofnData.dynFileBuffer);
+ ckfree((char *)ofnData.dynFileBuffer);
ofnData.dynFileBuffer = NULL;
}
@@ -964,7 +920,7 @@ GetFileNameW(
/*
*-------------------------------------------------------------------------
*
- * OFNHookProcW --
+ * OFNHookProc --
*
* Dialog box hook function. This is used to sets the "tk_dialog"
* variable for test/debugging when the dialog is ready to receive
@@ -981,7 +937,7 @@ GetFileNameW(
*/
static UINT APIENTRY
-OFNHookProcW(
+OFNHookProc(
HWND hdlg, /* Handle to child dialog window. */
UINT uMsg, /* Message identifier */
WPARAM wParam, /* Message parameter */
@@ -998,14 +954,16 @@ OFNHookProcW(
OFNOTIFYW *notifyPtr = (OFNOTIFYW *) lParam;
/*
- * This is weird... or not. The CDN_FILEOK is NOT sent when the selection
- * exceeds declared buffer size (the nMaxFile member of the OPENFILENAMEW
- * struct passed to GetOpenFileNameW function). So, we have to rely on
- * the most recent CDN_SELCHANGE then. Unfortunately this means, that
- * gathering the selected filenames happens twice when they fit into the
- * declared buffer. Luckily, it's not frequent operation so it should
- * not incur any noticeable delay. See [tktoolkit-Bugs-2987995]
+ * This is weird... or not. The CDN_FILEOK is NOT sent when the
+ * selection exceeds declared buffer size (the nMaxFile member of the
+ * OPENFILENAME struct passed to GetOpenFileName function). So, we
+ * have to rely on the most recent CDN_SELCHANGE then. Unfortunately
+ * this means, that gathering the selected filenames happens twice
+ * when they fit into the declared buffer. Luckily, it's not frequent
+ * operation so it should not incur any noticeable delay. See [Bug
+ * 2987995]
*/
+
if (notifyPtr->hdr.code == CDN_FILEOK ||
notifyPtr->hdr.code == CDN_SELCHANGE) {
int dirsize, selsize;
@@ -1019,21 +977,23 @@ OFNHookProcW(
ofnPtr = notifyPtr->lpOFN;
ofnData = (OFNData *) ofnPtr->lCustData;
- buffer = (WCHAR *) ofnData->dynFileBuffer;
+ buffer = ofnData->dynFileBuffer;
hdlg = GetParent(hdlg);
selsize = SendMessageW(hdlg, CDM_GETSPEC, 0, 0);
dirsize = SendMessageW(hdlg, CDM_GETFOLDERPATH, 0, 0);
- buffersize = (selsize + dirsize + 1) * 2;
+ buffersize = (selsize + dirsize + 1);
/*
- * Just empty the buffer if dirsize indicates an error [Bug 3071836]
+ * Just empty the buffer if dirsize indicates an error. [Bug
+ * 3071836]
*/
+
if ((selsize > 1) && (dirsize > 0)) {
if (ofnData->dynFileBufferSize < buffersize) {
- buffer = (WCHAR *) ckrealloc((char *) buffer, buffersize);
+ buffer = (WCHAR *) ckrealloc((char *) buffer, buffersize * sizeof(WCHAR));
ofnData->dynFileBufferSize = buffersize;
- ofnData->dynFileBuffer = (char *) buffer;
+ ofnData->dynFileBuffer = buffer;
}
SendMessageW(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer);
@@ -1050,7 +1010,7 @@ OFNHookProcW(
BOOL findquote = TRUE;
WCHAR *tmp = buffer;
- while(*buffer != '\0') {
+ while (*buffer != '\0') {
if (findquote) {
if (*buffer == '"') {
findquote = FALSE;
@@ -1066,14 +1026,24 @@ OFNHookProcW(
}
*tmp = '\0'; /* Second NULL terminator. */
} else {
- buffer[selsize] = '\0'; /* Second NULL terminator. */
- /*
- * Replace directory terminating NULL with a backslash.
+ /*
+ * Replace directory terminating NULL with a with a backslash,
+ * but only if not an absolute path.
*/
- buffer--;
- *buffer = '\\';
+ Tcl_DString tmpfile;
+ ConvertExternalFilename(buffer, &tmpfile);
+ 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);
+ } else {
+ *(buffer-1) = '\\';
+ }
+ buffer[selsize] = '\0'; /* Second NULL terminator. */
+ Tcl_DStringFree(&tmpfile);
}
} else {
/*
@@ -1109,557 +1079,6 @@ OFNHookProcW(
/*
*----------------------------------------------------------------------
*
- * GetFileNameA --
- *
- * Calls GetOpenFileName() or GetSaveFileName().
- *
- * Results:
- * See user documentation.
- *
- * Side effects:
- * See user documentation.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-GetFileNameA(
- 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[TK_MULTI_MAX_PATH], savePath[MAX_PATH];
- OFNData ofnData;
- int cdlgerr;
- int filterIndex = 0, result = TCL_ERROR, winCode, oldMode, i, multi = 0;
- char *extension = NULL, *title = NULL;
- Tk_Window tkwin = (Tk_Window) 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 *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- static CONST char *saveOptionStrings[] = {
- "-defaultextension", "-filetypes", "-initialdir", "-initialfile",
- "-parent", "-title", "-typevariable", NULL
- };
- static CONST char *openOptionStrings[] = {
- "-defaultextension", "-filetypes", "-initialdir", "-initialfile",
- "-multiple", "-parent", "-title", "-typevariable", NULL
- };
- CONST char **optionStrings;
-
- enum options {
- FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE,
- FILE_MULTIPLE, FILE_PARENT, FILE_TITLE, FILE_TYPEVARIABLE
- };
-
- file[0] = '\0';
- ZeroMemory(&ofnData, sizeof(OFNData));
- Tcl_DStringInit(&utfFilterString);
- Tcl_DStringInit(&utfDirString);
-
- /*
- * Parse the arguments.
- */
-
- if (open) {
- optionStrings = openOptionStrings;
- } else {
- optionStrings = saveOptionStrings;
- }
-
- 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;
- }
-
- /*
- * We want to maximize code sharing between the open and save file
- * dialog implementations; in particular, the switch statement below.
- * We use different sets of option strings from the GetIndexFromObj
- * call above, but a single enumeration for both. The save file dialog
- * doesn't support -multiple, but it falls in the middle of the
- * enumeration. Ultimately, this means that when the index found by
- * GetIndexFromObj is >= FILE_MULTIPLE, when doing a save file dialog,
- * we have to increment the index, so that it matches the open file
- * dialog enumeration.
- */
-
- if (!open && index >= FILE_MULTIPLE) {
- index++;
- }
- if (i + 1 == objc) {
- string = Tcl_GetString(optionPtr);
- Tcl_AppendResult(interp, "value for \"", string, "\" missing",
- NULL);
- goto end;
- }
-
- string = Tcl_GetString(valuePtr);
- switch ((enum options) index) {
- case FILE_DEFAULT:
- if (string[0] == '.') {
- string++;
- }
- extension = string;
- break;
- case FILE_TYPES:
- filterObj = valuePtr;
- break;
- case FILE_INITDIR:
- Tcl_DStringFree(&utfDirString);
- if (Tcl_TranslateFileName(interp, string, &utfDirString) == NULL) {
- goto end;
- }
- break;
- case FILE_INITFILE:
- 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);
- Tcl_DStringFree(&ds);
- break;
- case FILE_MULTIPLE:
- if (Tcl_GetBooleanFromObj(interp, valuePtr, &multi) != TCL_OK) {
- return TCL_ERROR;
- }
- break;
- case FILE_PARENT:
- tkwin = Tk_NameToWindow(interp, string, tkwin);
- if (tkwin == NULL) {
- goto end;
- }
- break;
- case FILE_TITLE:
- title = string;
- break;
- case FILE_TYPEVARIABLE:
- typeVariableObj = valuePtr;
- initialTypeObj = Tcl_ObjGetVar2(interp, typeVariableObj, NULL,
- TCL_GLOBAL_ONLY);
- break;
- }
- }
-
- if (MakeFilter(interp, filterObj, &utfFilterString, initialTypeObj,
- &filterIndex) != TCL_OK) {
- goto end;
- }
-
- Tk_MakeWindowExist(tkwin);
- hWnd = Tk_GetHWND(Tk_WindowId(tkwin));
-
- ZeroMemory(&ofn, sizeof(OPENFILENAMEA));
- if (LOBYTE(LOWORD(GetVersion())) < 5) {
- ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
- } else {
- ofn.lStructSize = sizeof(ofn);
- }
- ofn.hwndOwner = hWnd;
- ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner);
- ofn.lpstrFilter = NULL;
- ofn.lpstrCustomFilter = NULL;
- ofn.nMaxCustFilter = 0;
- ofn.lpstrFile = (LPTSTR) file;
- ofn.nMaxFile = TK_MULTI_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_ENABLEHOOK;
- ofn.nFileOffset = 0;
- ofn.nFileExtension = 0;
- ofn.lpstrDefExt = NULL;
- ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProcA;
- ofn.lCustData = (LPARAM) &ofnData;
- ofn.lpTemplateName = NULL;
-
- if (open != 0) {
- ofn.Flags |= OFN_FILEMUSTEXIST;
- } else {
- ofn.Flags |= OFN_OVERWRITEPROMPT;
- }
-
- if (tsdPtr->debugFlag != 0) {
- ofnData.interp = interp;
- }
-
- if (multi != 0) {
- ofn.Flags |= OFN_ALLOWMULTISELECT;
-
- /*
- * Starting buffer size. The buffer will be expanded by the OFN dialog
- * procedure when necessary
- */
-
- ofnData.dynFileBufferSize = 1024;
- ofnData.dynFileBuffer = ckalloc(1024);
- }
-
- if (extension != NULL) {
- Tcl_UtfToExternalDString(NULL, extension, -1, &extString);
- ofn.lpstrDefExt = (LPTSTR) Tcl_DStringValue(&extString);
- }
- Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&utfFilterString),
- Tcl_DStringLength(&utfFilterString), &filterString);
- ofn.lpstrFilter = (LPTSTR) Tcl_DStringValue(&filterString);
- ofn.nFilterIndex = filterIndex;
-
- if (Tcl_DStringValue(&utfDirString)[0] != '\0') {
- Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&utfDirString),
- Tcl_DStringLength(&utfDirString), &dirString);
- } else {
- /*
- * NT 5.0 changed the meaning of lpstrInitialDir, so we have to ensure
- * that we set the [pwd] if the user didn't specify anything else.
- */
-
- Tcl_DString cwd;
-
- Tcl_DStringFree(&utfDirString);
- if ((Tcl_GetCwd(interp, &utfDirString) == NULL) ||
- (Tcl_TranslateFileName(interp,
- Tcl_DStringValue(&utfDirString), &cwd) == NULL)) {
- Tcl_ResetResult(interp);
- } else {
- Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&cwd),
- Tcl_DStringLength(&cwd), &dirString);
- }
- Tcl_DStringFree(&cwd);
- }
- ofn.lpstrInitialDir = (LPTSTR) Tcl_DStringValue(&dirString);
-
- if (title != NULL) {
- Tcl_UtfToExternalDString(NULL, title, -1, &titleString);
- ofn.lpstrTitle = (LPTSTR) Tcl_DStringValue(&titleString);
- }
-
- /*
- * Popup the dialog.
- */
-
- GetCurrentDirectory(MAX_PATH, savePath);
- oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- if (open != 0) {
- winCode = GetOpenFileName(&ofn);
- } else {
- winCode = GetSaveFileName(&ofn);
- }
- Tcl_SetServiceMode(oldMode);
- EatSpuriousMessageBugFix();
- SetCurrentDirectory(savePath);
-
- /*
- * 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.
- *
- * Use the CommDlgExtendedError() function to retrieve the error code.
- * This function can return one of about two dozen codes; most of these
- * indicate some sort of gross system failure (insufficient memory, bad
- * window handles, etc.) Most of the error codes will be ignored; as we
- * find we want specific error messages for particular errors, we can
- * extend the code as needed.
- */
-
- cdlgerr = CommDlgExtendedError();
-
- /*
- * We now allow FNERR_BUFFERTOOSMALL when multiselection is enabled. The
- * filename buffer has been dynamically allocated by the OFN dialog
- * procedure to accomodate all selected files.
- */
-
- if ((winCode != 0)
- || ((cdlgerr == FNERR_BUFFERTOOSMALL)
- && (ofn.Flags & OFN_ALLOWMULTISELECT))) {
- if (ofn.Flags & OFN_ALLOWMULTISELECT) {
- /*
- * The result in dynFileBuffer contains many items, separated by
- * NUL characters. It is terminated with two nulls in a row. The
- * first element is the directory path (if multiple files are
- * selected) or the only returned file (if only a single file has
- * been chosen).
- */
-
- char *files = ofnData.dynFileBuffer;
- Tcl_Obj *returnList = Tcl_NewObj();
- int count = 0;
-
- /*
- * Get directory.
- */
-
- (void) ConvertExternalFilename(NULL, (char *) files, &ds);
-
- while (*files != '\0') {
- while (*files != '\0') {
- files++;
- }
- files++;
- if (*files != '\0') {
- Tcl_Obj *fullnameObj;
- Tcl_DString filename;
-
- count++;
- (void) ConvertExternalFilename(NULL, (char *) files,
- &filename);
- fullnameObj = Tcl_NewStringObj(Tcl_DStringValue(&ds),
- Tcl_DStringLength(&ds));
- Tcl_AppendToObj(fullnameObj, "/", -1);
- Tcl_AppendToObj(fullnameObj, Tcl_DStringValue(&filename),
- Tcl_DStringLength(&filename));
- Tcl_DStringFree(&filename);
- Tcl_ListObjAppendElement(NULL, returnList, fullnameObj);
- }
- }
- if (count == 0) {
- /*
- * Only one file was returned.
- */
-
- Tcl_ListObjAppendElement(NULL, returnList, Tcl_NewStringObj(
- Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
- }
- Tcl_SetObjResult(interp, returnList);
- Tcl_DStringFree(&ds);
- } else {
- Tcl_AppendResult(interp, ConvertExternalFilename(NULL,
- (char *) ofn.lpstrFile, &ds), NULL);
- Tcl_DStringFree(&ds);
- }
- result = TCL_OK;
- if ((ofn.nFilterIndex > 0) &&
- (Tcl_GetCharLength(Tcl_GetObjResult(interp)) > 0) &&
- typeVariableObj && filterObj) {
- int listObjc, count;
- Tcl_Obj **listObjv = NULL;
- Tcl_Obj **typeInfo = NULL;
-
- if (Tcl_ListObjGetElements(interp, filterObj, &listObjc,
- &listObjv) != TCL_OK) {
- result = TCL_ERROR;
- } else if (Tcl_ListObjGetElements(interp,
- listObjv[ofn.nFilterIndex - 1], &count,
- &typeInfo) != TCL_OK) {
- result = TCL_ERROR;
- } else if (Tcl_ObjSetVar2(interp, typeVariableObj, NULL,
- typeInfo[0], TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
- result = TCL_ERROR;
- }
- }
- } else if (cdlgerr == FNERR_INVALIDFILENAME) {
- Tcl_SetResult(interp, "invalid filename \"", TCL_STATIC);
- Tcl_AppendResult(interp, ConvertExternalFilename(NULL,
- (char *) ofn.lpstrFile, &ds), "\"", NULL);
- Tcl_DStringFree(&ds);
- } else {
- result = TCL_OK;
- }
-
- if (ofn.lpstrTitle != NULL) {
- Tcl_DStringFree(&titleString);
- }
- if (ofn.lpstrInitialDir != NULL) {
- Tcl_DStringFree(&dirString);
- }
- Tcl_DStringFree(&filterString);
- if (ofn.lpstrDefExt != NULL) {
- Tcl_DStringFree(&extString);
- }
-
- end:
- Tcl_DStringFree(&utfDirString);
- Tcl_DStringFree(&utfFilterString);
- if (ofnData.dynFileBuffer != NULL) {
- ckfree(ofnData.dynFileBuffer);
- ofnData.dynFileBuffer = NULL;
- }
-
- return result;
-}
-
-/*
- *-------------------------------------------------------------------------
- *
- * OFNHookProcA --
- *
- * Dialog box hook function. This is used to sets the "tk_dialog"
- * variable for test/debugging when the dialog is ready to receive
- * messages. When multiple file selection is enabled this function
- * is used to process the list of names.
- *
- * Results:
- * Returns 0 to allow default processing of messages to occur.
- *
- * Side effects:
- * None.
- *
- *-------------------------------------------------------------------------
- */
-
-static UINT APIENTRY
-OFNHookProcA(
- 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));
- OPENFILENAME *ofnPtr;
- OFNData *ofnData;
-
- if (uMsg == WM_INITDIALOG) {
- TkWinSetUserData(hdlg, lParam);
- } else if (uMsg == WM_NOTIFY) {
- OFNOTIFY *notifyPtr = (OFNOTIFY *) lParam;
-
- /*
- * This is weird... or not. The CDN_FILEOK is NOT sent when the selection
- * exceeds declared buffer size (the nMaxFile member of the OPENFILENAMEW
- * struct passed to GetOpenFileNameW function). So, we have to rely on
- * the most recent CDN_SELCHANGE then. Unfortunately this means, that
- * gathering the selected filenames happens twice when they fit into the
- * declared buffer. Luckily, it's not frequent operation so it should
- * not incur any noticeable delay. See [tktoolkit-Bugs-2987995]
- */
- if (notifyPtr->hdr.code == CDN_FILEOK ||
- notifyPtr->hdr.code == CDN_SELCHANGE) {
- int dirsize, selsize;
- char *buffer;
- int buffersize;
-
- /*
- * Change of selection. Unscramble the unholy mess that's in the
- * selection buffer, resizing it if necessary.
- */
-
- ofnPtr = notifyPtr->lpOFN;
- ofnData = (OFNData *) ofnPtr->lCustData;
- buffer = ofnData->dynFileBuffer;
- hdlg = GetParent(hdlg);
-
- selsize = SendMessage(hdlg, CDM_GETSPEC, 0, 0);
- dirsize = SendMessage(hdlg, CDM_GETFOLDERPATH, 0, 0);
- buffersize = selsize + dirsize + 1;
-
- /*
- * Just empty the buffer if dirsize indicates an error [Bug 3071836]
- */
- if ((selsize > 1) && (dirsize > 0)) {
- if (ofnData->dynFileBufferSize < buffersize) {
- buffer = ckrealloc(buffer, buffersize);
- ofnData->dynFileBufferSize = buffersize;
- ofnData->dynFileBuffer = buffer;
- }
-
- SendMessage(hdlg, CDM_GETFOLDERPATH, dirsize, (LPARAM) buffer);
- buffer += dirsize;
- SendMessage(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer);
-
- /*
- * If there are multiple files, delete the quotes and change
- * every second quote to NULL terminator.
- */
-
- if (buffer[0] == '"') {
- BOOL findquote = TRUE;
- char *tmp = buffer;
-
- while (*buffer != '\0') {
- if (findquote) {
- if (*buffer == '"') {
- findquote = FALSE;
- }
- buffer++;
- } else {
- if (*buffer == '"') {
- findquote = TRUE;
- *buffer = '\0';
- }
- *tmp++ = *buffer++;
- }
- }
- *tmp = '\0'; /* Second NULL terminator. */
- } else {
- buffer[selsize] = '\0'; /* Second NULL terminator. */
-
- /*
- * Replace directory terminating NULL with a backslash.
- */
-
- buffer--;
- *buffer = '\\';
- }
-
- } else {
- /*
- * Nothing is selected, so just empty the string.
- */
-
- if (buffer != NULL) {
- *buffer = '\0';
- }
- }
- }
- } else if (uMsg == WM_WINDOWPOSCHANGED) {
- /*
- * This message is delivered at the right time to both old-style and
- * explorer-style hook procs 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.
- */
-
- ofnPtr = (OPENFILENAME *) TkWinGetUserData(hdlg);
- if (ofnPtr != NULL) {
- ofnData = (OFNData *) ofnPtr->lCustData;
- if (ofnData->interp != NULL) {
- if (ofnPtr->Flags & OFN_EXPLORER) {
- hdlg = GetParent(hdlg);
- }
- tsdPtr->debugInterp = ofnData->interp;
- Tcl_DoWhenIdle(SetTkDialog, hdlg);
- }
- TkWinSetUserData(hdlg, NULL);
- }
- }
- return 0;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* MakeFilter --
*
* Allocate a buffer to store the filters in a format understood by
@@ -1680,18 +1099,18 @@ MakeFilter(
Tcl_Obj *valuePtr, /* Value of the -filetypes option */
Tcl_DString *dsPtr, /* Filled with windows filter string. */
Tcl_Obj *initialPtr, /* Initial type name */
- int *index) /* Index of initial type in filter string */
+ int *indexPtr) /* Index of initial type in filter string */
{
char *filterStr;
char *p;
- char *initial = NULL;
+ const char *initial = NULL;
int pass;
int ix = 0; /* index counter */
FileFilterList flist;
FileFilter *filterPtr;
if (initialPtr) {
- initial = Tcl_GetStringFromObj(initialPtr, NULL);
+ initial = Tcl_GetString(initialPtr);
}
TkInitFileFilters(&flist);
if (TkGetFileFilters(interp, &flist, valuePtr, 1) != TCL_OK) {
@@ -1702,9 +1121,9 @@ MakeFilter(
/*
* Use "All Files (*.*) as the default filter if none is specified
*/
- char *defaultFilter = "All Files (*.*)";
+ const char *defaultFilter = "All Files (*.*)";
- p = filterStr = (char*)ckalloc(30 * sizeof(char));
+ p = filterStr = ckalloc(30);
strcpy(p, defaultFilter);
p+= strlen(defaultFilter);
@@ -1744,16 +1163,18 @@ MakeFilter(
for (filterPtr = flist.filters, p = filterStr; filterPtr;
filterPtr = filterPtr->next) {
- char *sep;
+ const char *sep;
FileFilterClause *clausePtr;
/*
- * Check initial index for match, set index. Filter index is 1
+ * Check initial index for match, set *indexPtr. Filter index is 1
* based so increment first
*/
+
ix++;
- if (index && initial && (strcmp(initial, filterPtr->name) == 0)) {
- *index = ix;
+ if (indexPtr && initial
+ && (strcmp(initial, filterPtr->name) == 0)) {
+ *indexPtr = ix;
}
/*
@@ -1889,22 +1310,23 @@ Tk_ChooseDirectoryObjCmd(
ClientData clientData, /* Main window associated with interpreter. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- char path[MAX_PATH];
+ WCHAR path[MAX_PATH];
int oldMode, result = TCL_ERROR, i;
LPCITEMIDLIST pidl; /* Returned by browser */
- BROWSEINFO bInfo; /* Used by browser */
- CHOOSEDIRDATA cdCBData; /* Structure to pass back and forth */
+ BROWSEINFOW bInfo; /* Used by browser */
+ ChooseDir cdCBData; /* Structure to pass back and forth */
LPMALLOC pMalloc; /* Used by shell */
Tk_Window tkwin = (Tk_Window) clientData;
HWND hWnd;
- char *utfTitle = NULL;/* Title for window */
- TCHAR saveDir[MAX_PATH];
- Tcl_DString titleString; /* UTF Title */
+ const char *utfTitle = NULL;/* Title for window */
+ WCHAR 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 *optionStrings[] = {
"-initialdir", "-mustexist", "-parent", "-title", NULL
};
enum options {
@@ -1916,7 +1338,7 @@ Tk_ChooseDirectoryObjCmd(
*/
path[0] = '\0';
- ZeroMemory(&cdCBData, sizeof(CHOOSEDIRDATA));
+ ZeroMemory(&cdCBData, sizeof(ChooseDir));
cdCBData.interp = interp;
/*
@@ -1925,7 +1347,8 @@ Tk_ChooseDirectoryObjCmd(
for (i = 1; i < objc; i += 2) {
int index;
- char *string;
+ const char *string;
+ const WCHAR *uniStr;
Tcl_Obj *optionPtr, *valuePtr;
optionPtr = objv[i];
@@ -1948,16 +1371,19 @@ Tk_ChooseDirectoryObjCmd(
if (Tcl_TranslateFileName(interp,string,&initDirString) == NULL) {
goto cleanup;
}
- string = Tcl_DStringValue(&initDirString);
+ Tcl_WinUtfToTChar(Tcl_DStringValue(&initDirString), -1,
+ &tempString);
+ uniStr = (WCHAR *) Tcl_DStringValue(&tempString);
/*
* Convert possible relative path to full path to keep dialog
* happy.
*/
- GetFullPathName(string, MAX_PATH, saveDir, NULL);
- lstrcpyn(cdCBData.utfInitDir, saveDir, MAX_PATH);
+ GetFullPathNameW(uniStr, MAX_PATH, saveDir, NULL);
+ wcsncpy(cdCBData.initDir, saveDir, MAX_PATH);
Tcl_DStringFree(&initDirString);
+ Tcl_DStringFree(&tempString);
break;
case DIR_EXIST:
if (Tcl_GetBooleanFromObj(interp, valuePtr,
@@ -1991,16 +1417,16 @@ Tk_ChooseDirectoryObjCmd(
bInfo.hwndOwner = hWnd;
bInfo.pszDisplayName = path;
bInfo.pidlRoot = NULL;
- if (lstrlen(cdCBData.utfInitDir) == 0) {
- GetCurrentDirectory(MAX_PATH, cdCBData.utfInitDir);
+ if (wcslen(cdCBData.initDir) == 0) {
+ GetCurrentDirectoryW(MAX_PATH, cdCBData.initDir);
}
bInfo.lParam = (LPARAM) &cdCBData;
if (utfTitle != NULL) {
- Tcl_UtfToExternalDString(NULL, utfTitle, -1, &titleString);
- bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString);
+ Tcl_WinUtfToTChar(utfTitle, -1, &titleString);
+ bInfo.lpszTitle = (LPWSTR) Tcl_DStringValue(&titleString);
} else {
- bInfo.lpszTitle = "Please choose a directory, then select OK.";
+ bInfo.lpszTitle = L"Please choose a directory, then select OK.";
}
/*
@@ -2033,15 +1459,16 @@ Tk_ChooseDirectoryObjCmd(
*/
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- GetCurrentDirectory(MAX_PATH, saveDir);
+ GetCurrentDirectoryW(MAX_PATH, saveDir);
if (SHGetMalloc(&pMalloc) == NOERROR) {
- pidl = SHBrowseForFolder(&bInfo);
+ pidl = SHBrowseForFolderW(&bInfo);
/*
- * This is a fix for Windows 2000, which seems to modify the folder name
- * buffer even when the dialog is canceled (in this case the buffer
- * contains garbage). See [Bug #3002230]
+ * This is a fix for Windows 2000, which seems to modify the folder
+ * name buffer even when the dialog is canceled (in this case the
+ * buffer contains garbage). See [Bug #3002230]
*/
+
path[0] = '\0';
/*
@@ -2049,17 +1476,17 @@ Tk_ChooseDirectoryObjCmd(
*/
if (pidl != NULL) {
- if (!SHGetPathFromIDList(pidl, path)) {
+ if (!SHGetPathFromIDListW(pidl, path)) {
Tcl_SetResult(interp, "Error: Not a file system folder\n",
TCL_VOLATILE);
- };
+ }
pMalloc->lpVtbl->Free(pMalloc, (void *) pidl);
- } else if (lstrlen(cdCBData.utfRetDir) > 0) {
- lstrcpy(path, cdCBData.utfRetDir);
+ } else if (wcslen(cdCBData.retDir) > 0) {
+ wcscpy(path, cdCBData.retDir);
}
pMalloc->lpVtbl->Release(pMalloc);
}
- SetCurrentDirectory(saveDir);
+ SetCurrentDirectoryW(saveDir);
Tcl_SetServiceMode(oldMode);
/*
@@ -2079,7 +1506,7 @@ Tk_ChooseDirectoryObjCmd(
if (*path) {
Tcl_DString ds;
- Tcl_AppendResult(interp, ConvertExternalFilename(NULL, (char *) path,
+ Tcl_AppendResult(interp, ConvertExternalFilename(path,
&ds), NULL);
Tcl_DStringFree(&ds);
}
@@ -2117,10 +1544,11 @@ ChooseDirectoryValidateProc(
LPARAM lParam,
LPARAM lpData)
{
- TCHAR selDir[MAX_PATH];
- CHOOSEDIRDATA *chooseDirSharedData = (CHOOSEDIRDATA *) lpData;
+ WCHAR selDir[MAX_PATH];
+ ChooseDir *chooseDirSharedData = (ChooseDir *) lpData;
+ Tcl_DString tempString;
Tcl_DString initDirString;
- char string[MAX_PATH];
+ WCHAR string[MAX_PATH];
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
@@ -2128,7 +1556,7 @@ ChooseDirectoryValidateProc(
tsdPtr->debugInterp = (Tcl_Interp *) chooseDirSharedData->interp;
Tcl_DoWhenIdle(SetTkDialog, (ClientData) hwnd);
}
- chooseDirSharedData->utfRetDir[0] = '\0';
+ chooseDirSharedData->retDir[0] = '\0';
switch (message) {
case BFFM_VALIDATEFAILED:
/*
@@ -2140,21 +1568,25 @@ ChooseDirectoryValidateProc(
* like ~ are converted correctly.
*/
+ Tcl_WinTCharToUtf((TCHAR *) lParam, -1, &initDirString);
if (Tcl_TranslateFileName(chooseDirSharedData->interp,
- (char *) lParam, &initDirString) == NULL) {
+ Tcl_DStringValue(&initDirString), &tempString) == NULL) {
/*
* Should we expose the error (in the interp result) to the user
* at this point?
*/
- chooseDirSharedData->utfRetDir[0] = '\0';
+ chooseDirSharedData->retDir[0] = '\0';
return 1;
}
- lstrcpyn(string, Tcl_DStringValue(&initDirString), MAX_PATH);
+ Tcl_DStringFree(&initDirString);
+ Tcl_WinUtfToTChar(Tcl_DStringValue(&tempString), -1, &initDirString);
+ Tcl_DStringFree(&tempString);
+ wcsncpy(string, (WCHAR *) Tcl_DStringValue(&initDirString),
+ MAX_PATH);
Tcl_DStringFree(&initDirString);
- if (SetCurrentDirectory((char *)string) == 0) {
- LPTSTR lpFilePart[MAX_PATH];
+ if (SetCurrentDirectoryW(string) == 0) {
/*
* Get the full path name to the user entry, at this point it does
@@ -2162,16 +1594,17 @@ ChooseDirectoryValidateProc(
* it.
*/
- GetFullPathName(string, MAX_PATH,
- chooseDirSharedData->utfRetDir, /*unused*/ lpFilePart);
+ GetFullPathNameW(string, MAX_PATH,
+ chooseDirSharedData->retDir, NULL);
if (chooseDirSharedData->mustExist) {
/*
* User HAS to select a valid directory.
*/
- wsprintf(selDir, TEXT("Directory '%.200s' does not exist,\nplease select or enter an existing directory."), chooseDirSharedData->utfRetDir);
- MessageBox(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK);
- chooseDirSharedData->utfRetDir[0] = '\0';
+ wsprintfW(selDir, L"Directory '%.200s' does not exist,\nplease select or enter an existing directory.",
+ chooseDirSharedData->retDir);
+ MessageBoxW(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK);
+ chooseDirSharedData->retDir[0] = '\0';
return 1;
}
} else {
@@ -2180,7 +1613,7 @@ ChooseDirectoryValidateProc(
* directory in utfRetDir.
*/
- GetCurrentDirectory(MAX_PATH, chooseDirSharedData->utfRetDir);
+ GetCurrentDirectoryW(MAX_PATH, chooseDirSharedData->retDir);
return 0;
}
return 0;
@@ -2195,13 +1628,13 @@ ChooseDirectoryValidateProc(
* Not called when user changes edit box directly.
*/
- if (SHGetPathFromIDList((LPITEMIDLIST) lParam, selDir)) {
- SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM) selDir);
+ if (SHGetPathFromIDListW((LPITEMIDLIST) lParam, selDir)) {
+ SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM) selDir);
// enable the OK button
- SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
+ SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
} else {
// disable the OK button
- SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0);
+ SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0);
}
UpdateWindow(hwnd);
return 1;
@@ -2212,9 +1645,10 @@ ChooseDirectoryValidateProc(
* specified parameter.
*/
- char *initDir = chooseDirSharedData->utfInitDir;
+ WCHAR *initDir = chooseDirSharedData->initDir;
+
+ SetCurrentDirectoryW(initDir);
- SetCurrentDirectory(initDir);
if (*initDir == '\\') {
/*
* BFFM_SETSELECTION only understands UNC paths as pidls, so
@@ -2228,27 +1662,23 @@ ChooseDirectoryValidateProc(
if (SUCCEEDED(SHGetDesktopFolder(&psfFolder))) {
LPITEMIDLIST pidlMain;
ULONG ulCount, ulAttr;
- Tcl_DString ds;
- Tcl_UtfToExternalDString(TkWinGetUnicodeEncoding(),
- initDir, -1, &ds);
if (SUCCEEDED(psfFolder->lpVtbl->ParseDisplayName(
psfFolder, hwnd, NULL, (WCHAR *)
- Tcl_DStringValue(&ds), &ulCount,&pidlMain,&ulAttr))
+ initDir, &ulCount,&pidlMain,&ulAttr))
&& (pidlMain != NULL)) {
- SendMessage(hwnd, BFFM_SETSELECTION, FALSE,
+ SendMessageW(hwnd, BFFM_SETSELECTIONW, FALSE,
(LPARAM) pidlMain);
pMalloc->lpVtbl->Free(pMalloc, pidlMain);
}
psfFolder->lpVtbl->Release(psfFolder);
- Tcl_DStringFree(&ds);
}
pMalloc->lpVtbl->Release(pMalloc);
}
} else {
- SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM) initDir);
+ SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, (LPARAM) initDir);
}
- SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
+ SendMessageW(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
break;
}
@@ -2279,7 +1709,7 @@ Tk_MessageBoxObjCmd(
ClientData clientData, /* Main window associated with interpreter. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tk_Window tkwin = (Tk_Window) clientData, parent;
HWND hWnd;
@@ -2287,7 +1717,7 @@ Tk_MessageBoxObjCmd(
int defaultBtn, icon, type;
int i, oldMode, winCode;
UINT flags;
- static CONST char *optionStrings[] = {
+ static const char *optionStrings[] = {
"-default", "-detail", "-icon", "-message",
"-parent", "-title", "-type", NULL
};
@@ -2298,7 +1728,6 @@ Tk_MessageBoxObjCmd(
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
- (void) TkWinGetUnicodeEncoding();
defaultBtn = -1;
detailObj = NULL;
icon = MB_ICONINFORMATION;
@@ -2309,7 +1738,6 @@ Tk_MessageBoxObjCmd(
for (i = 1; i < objc; i += 2) {
int index;
- char *string;
Tcl_Obj *optionPtr, *valuePtr;
optionPtr = objv[i];
@@ -2320,7 +1748,7 @@ Tk_MessageBoxObjCmd(
return TCL_ERROR;
}
if (i + 1 == objc) {
- string = Tcl_GetString(optionPtr);
+ const char *string = Tcl_GetString(optionPtr);
Tcl_AppendResult(interp, "value for \"", string, "\" missing",
NULL);
return TCL_ERROR;
@@ -2425,7 +1853,7 @@ Tk_MessageBoxObjCmd(
tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL);
tsdPtr->hBigIcon = TkWinGetIcon(parent, ICON_BIG);
- tsdPtr->hMsgBoxHook = SetWindowsHookEx(WH_CBT, MsgBoxCBTProc, NULL,
+ tsdPtr->hMsgBoxHook = SetWindowsHookExW(WH_CBT, MsgBoxCBTProc, NULL,
GetCurrentThreadId());
winCode = MessageBoxW(hWnd, Tcl_GetUnicode(tmpObj),
titleObj ? Tcl_GetUnicode(titleObj) : L"", flags);
@@ -2453,7 +1881,7 @@ MsgBoxCBTProc(
LPARAM lParam)
{
ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
- Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
if (nCode == HCBT_CREATEWND) {
/*
@@ -2469,9 +1897,9 @@ MsgBoxCBTProc(
if (WC_DIALOG == lpcbtcreate->lpcs->lpszClass) {
HWND hwnd = (HWND) wParam;
- SendMessage(hwnd, WM_SETICON, ICON_SMALL,
+ SendMessageW(hwnd, WM_SETICON, ICON_SMALL,
(LPARAM) tsdPtr->hSmallIcon);
- SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon);
+ SendMessageW(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon);
}
}
@@ -2510,15 +1938,15 @@ SetTkDialog(
/*
* Factored out a common pattern in use in this file.
*/
-static char *
+
+static const char *
ConvertExternalFilename(
- Tcl_Encoding encoding,
- char *filename,
+ WCHAR *filename,
Tcl_DString *dsPtr)
{
char *p;
- Tcl_ExternalToUtfDString(encoding, filename, -1, dsPtr);
+ Tcl_WinTCharToUtf((TCHAR *) filename, -1, dsPtr);
for (p = Tcl_DStringValue(dsPtr); *p != '\0'; p++) {
/*
* Change the pathname to the Tcl "normalized" pathname, where back