summaryrefslogtreecommitdiffstats
path: root/win/tkWinDialog.c
diff options
context:
space:
mode:
Diffstat (limited to 'win/tkWinDialog.c')
-rw-r--r--win/tkWinDialog.c346
1 files changed, 328 insertions, 18 deletions
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;