OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.4 / win / tkWinDialog.c
diff --git a/util/src/TclTk/tk8.6.4/win/tkWinDialog.c b/util/src/TclTk/tk8.6.4/win/tkWinDialog.c
deleted file mode 100644 (file)
index c137111..0000000
+++ /dev/null
@@ -1,3570 +0,0 @@
-/*
- * tkWinDialog.c --
- *
- *     Contains the Windows implementation of the common dialog boxes.
- *
- * Copyright (c) 1996-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution of
- * this file, and for a DISCLAIMER OF ALL WARRANTIES.
- */
-
-#include "tkWinInt.h"
-#include "tkFileFilter.h"
-#include "tkFont.h"
-
-#include <commdlg.h>           /* includes common dialog functionality */
-#include <dlgs.h>              /* includes common dialog template defines */
-#include <cderr.h>             /* includes the common dialog error codes */
-
-#include <shlobj.h>            /* includes SHBrowseForFolder */
-#include <shobjidl.h>
-
-#ifdef _MSC_VER
-#   pragma comment (lib, "shell32.lib")
-#   pragma comment (lib, "comdlg32.lib")
-#   pragma comment (lib, "uuid.lib")
-#endif
-
-/* These needed for compilation with VC++ 5.2 */
-/* XXX - remove these since need at least VC 6 */
-#ifndef BIF_EDITBOX
-#define BIF_EDITBOX 0x10
-#endif
-
-#ifndef BIF_VALIDATE
-#define BIF_VALIDATE 0x0020
-#endif
-
-/* This "new" dialog style is now actually the "old" dialog style post-Vista */
-#ifndef BIF_NEWDIALOGSTYLE
-#define BIF_NEWDIALOGSTYLE 0x0040
-#endif
-
-#ifndef BFFM_VALIDATEFAILED
-#ifdef UNICODE
-#define BFFM_VALIDATEFAILED 4
-#else
-#define BFFM_VALIDATEFAILED 3
-#endif
-#endif /* BFFM_VALIDATEFAILED */
-
-typedef struct ThreadSpecificData {
-    int debugFlag;             /* Flags whether we should output debugging
-                                * information while displaying a builtin
-                                * dialog. */
-    Tcl_Interp *debugInterp;   /* Interpreter to used for debugging. */
-    UINT WM_LBSELCHANGED;      /* Holds a registered windows event used for
-                                * communicating between the Directory Chooser
-                                * dialog and its hook proc. */
-    HHOOK hMsgBoxHook;         /* Hook proc for tk_messageBox and the */
-    HICON hSmallIcon;          /* icons used by a parent to be used in */
-    HICON hBigIcon;            /* the message box */
-    int   newFileDialogsState;
-#define FDLG_STATE_INIT 0       /* Uninitialized */
-#define FDLG_STATE_USE_NEW 1    /* Use the new dialogs */
-#define FDLG_STATE_USE_OLD 2    /* Use the old dialogs */
-} ThreadSpecificData;
-static Tcl_ThreadDataKey dataKey;
-
-/*
- * The following structures are used by Tk_MessageBoxCmd() to parse arguments
- * and return results.
- */
-
-static const TkStateMap iconMap[] = {
-    {MB_ICONERROR,             "error"},
-    {MB_ICONINFORMATION,       "info"},
-    {MB_ICONQUESTION,          "question"},
-    {MB_ICONWARNING,           "warning"},
-    {-1,                       NULL}
-};
-
-static const TkStateMap typeMap[] = {
-    {MB_ABORTRETRYIGNORE,      "abortretryignore"},
-    {MB_OK,                    "ok"},
-    {MB_OKCANCEL,              "okcancel"},
-    {MB_RETRYCANCEL,           "retrycancel"},
-    {MB_YESNO,                 "yesno"},
-    {MB_YESNOCANCEL,           "yesnocancel"},
-    {-1,                       NULL}
-};
-
-static const TkStateMap buttonMap[] = {
-    {IDABORT,                  "abort"},
-    {IDRETRY,                  "retry"},
-    {IDIGNORE,                 "ignore"},
-    {IDOK,                     "ok"},
-    {IDCANCEL,                 "cancel"},
-    {IDNO,                     "no"},
-    {IDYES,                    "yes"},
-    {-1,                       NULL}
-};
-
-static const int buttonFlagMap[] = {
-    MB_DEFBUTTON1, MB_DEFBUTTON2, MB_DEFBUTTON3, MB_DEFBUTTON4
-};
-
-static const struct {int type; int btnIds[3];} allowedTypes[] = {
-    {MB_ABORTRETRYIGNORE,      {IDABORT, IDRETRY,  IDIGNORE}},
-    {MB_OK,                    {IDOK,    -1,       -1      }},
-    {MB_OKCANCEL,              {IDOK,    IDCANCEL, -1      }},
-    {MB_RETRYCANCEL,           {IDRETRY, IDCANCEL, -1      }},
-    {MB_YESNO,                 {IDYES,   IDNO,     -1      }},
-    {MB_YESNOCANCEL,           {IDYES,   IDNO,     IDCANCEL}}
-};
-
-#define NUM_TYPES (sizeof(allowedTypes) / sizeof(allowedTypes[0]))
-
-/*
- * Abstract trivial differences between Win32 and Win64.
- */
-
-#define TkWinGetHInstance(from) \
-       ((HINSTANCE) GetWindowLongPtr((from), GWLP_HINSTANCE))
-#define TkWinGetUserData(from) \
-       GetWindowLongPtr((from), GWLP_USERDATA)
-#define TkWinSetUserData(to,what) \
-       SetWindowLongPtr((to), GWLP_USERDATA, (LPARAM)(what))
-
-/*
- * 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
- *
- * The data is stored as <dir>\0<file1>\0<file2>\0...<fileN>\0\0. Since
- * MAX_PATH == 260 on Win2K/NT, *40 is ~10Kbytes.
- */
-
-#define TK_MULTI_MAX_PATH      (MAX_PATH*40)
-
-/*
- * The following structure is used to pass information between the directory
- * chooser function, Tk_ChooseDirectoryObjCmd(), and its dialog hook proc.
- */
-
-typedef struct {
-   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 */
-} ChooseDir;
-
-/*
- * The following structure is used to pass information between GetFileName
- * function and OFN dialog hook procedures. [Bug 2896501, Patch 2898255]
- */
-
-typedef struct OFNData {
-    Tcl_Interp *interp;                /* Interp, used only if debug is turned on,
-                                * for setting the "tk_dialog" variable. */
-    int dynFileBufferSize;     /* Dynamic filename buffer size, stored to
-                                * avoid shrinking and expanding the buffer
-                                * when selection changes */
-    TCHAR *dynFileBuffer;      /* Dynamic filename buffer */
-} OFNData;
-
-/*
- * The following structure is used to gather options used by various
- * file dialogs
- */
-typedef struct OFNOpts {
-    Tk_Window tkwin;            /* Owner window for dialog */
-    Tcl_Obj *extObj;            /* Default extension */
-    Tcl_Obj *titleObj;          /* Title for dialog */
-    Tcl_Obj *filterObj;         /* File type filter list */
-    Tcl_Obj *typeVariableObj;   /* Variable in which to store type selected */
-    Tcl_Obj *initialTypeObj;    /* Initial value of above, or NULL */
-    Tcl_DString utfDirString;   /* Initial dir */
-    int multi;                  /* Multiple selection enabled */
-    int confirmOverwrite;       /* Confirm before overwriting */
-    int mustExist;              /* Used only for  */
-    int forceXPStyle;          /* XXX - Force XP style even on newer systems */
-    TCHAR file[TK_MULTI_MAX_PATH]; /* File name
-                                      XXX - fixed size because it was so
-                                      historically. Why not malloc'ed ?
-                                      XXX - also, TCHAR should really be WCHAR
-                                      because TkWinGetUnicodeEncoding is always
-                                      UCS2.
-                                   */
-} OFNOpts;
-
-/* Define the operation for which option parsing is to be done. */
-enum OFNOper {
-    OFN_FILE_SAVE,              /* tk_getOpenFile */
-    OFN_FILE_OPEN,              /* tk_getSaveFile */
-    OFN_DIR_CHOOSE              /* tk_chooseDirectory */
-};
-
-
-/*
- * The following definitions are required when using older versions of
- * Visual C++ (like 6.0) and possibly MingW. Those headers do not contain
- * required definitions for interfaces new to Vista that we need for
- * the new file dialogs. Duplicating definitions is OK because they
- * should forever remain unchanged.
- *
- * XXX - is there a better/easier way to use new data definitions with
- * older compilers? Should we prefix definitions with Tcl_ instead
- * of using the same names as in the SDK?
- */
-#ifndef __IShellItem_INTERFACE_DEFINED__
-#  define __IShellItem_INTERFACE_DEFINED__
-#ifdef __MSVCRT__
-typedef struct IShellItem IShellItem;
-
-typedef enum __MIDL_IShellItem_0001 {
-    SIGDN_NORMALDISPLAY = 0,SIGDN_PARENTRELATIVEPARSING = 0x80018001,SIGDN_PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
-    SIGDN_DESKTOPABSOLUTEPARSING = 0x80028000,SIGDN_PARENTRELATIVEEDITING = 0x80031001,SIGDN_DESKTOPABSOLUTEEDITING = 0x8004c000,
-    SIGDN_FILESYSPATH = 0x80058000,SIGDN_URL = 0x80068000
-} SIGDN;
-
-typedef DWORD SICHINTF;
-
-typedef struct IShellItemVtbl
-{
-    BEGIN_INTERFACE
-
-    HRESULT (STDMETHODCALLTYPE *QueryInterface)(IShellItem *, REFIID, void **);
-    ULONG (STDMETHODCALLTYPE *AddRef)(IShellItem *);
-    ULONG (STDMETHODCALLTYPE *Release)(IShellItem *);
-    HRESULT (STDMETHODCALLTYPE *BindToHandler)(IShellItem *, IBindCtx *, REFGUID, REFIID, void **);
-    HRESULT (STDMETHODCALLTYPE *GetParent)(IShellItem *, IShellItem **);
-    HRESULT (STDMETHODCALLTYPE *GetDisplayName)(IShellItem *, SIGDN, LPOLESTR *);
-    HRESULT (STDMETHODCALLTYPE *GetAttributes)(IShellItem *, SFGAOF, SFGAOF *);
-    HRESULT (STDMETHODCALLTYPE *Compare)(IShellItem *, IShellItem *, SICHINTF, int *);
-
-    END_INTERFACE
-} IShellItemVtbl;
-struct IShellItem {
-    CONST_VTBL struct IShellItemVtbl *lpVtbl;
-};
-#endif
-#endif
-
-#ifndef __IShellItemArray_INTERFACE_DEFINED__
-#define __IShellItemArray_INTERFACE_DEFINED__
-
-typedef enum SIATTRIBFLAGS {
-    SIATTRIBFLAGS_AND  = 0x1,
-    SIATTRIBFLAGS_OR   = 0x2,
-    SIATTRIBFLAGS_APPCOMPAT    = 0x3,
-    SIATTRIBFLAGS_MASK = 0x3,
-    SIATTRIBFLAGS_ALLITEMS     = 0x4000
-} SIATTRIBFLAGS;
-#ifdef __MSVCRT__
-typedef ULONG SFGAOF;
-#endif /* __MSVCRT__ */
-typedef struct IShellItemArray IShellItemArray;
-typedef struct IShellItemArrayVtbl
-{
-    BEGIN_INTERFACE
-
-    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
-        IShellItemArray *, REFIID riid,void **ppvObject);
-    ULONG ( STDMETHODCALLTYPE *AddRef )(IShellItemArray *);
-    ULONG ( STDMETHODCALLTYPE *Release )(IShellItemArray *);
-    HRESULT ( STDMETHODCALLTYPE *BindToHandler )(IShellItemArray *,
-        IBindCtx *, REFGUID, REFIID, void **);
-    /* flags is actually is enum GETPROPERTYSTOREFLAGS */
-    HRESULT ( STDMETHODCALLTYPE *GetPropertyStore )(
-        IShellItemArray *, int,  REFIID, void **);
-    /* keyType actually REFPROPERTYKEY */
-    HRESULT ( STDMETHODCALLTYPE *GetPropertyDescriptionList )(
-         IShellItemArray *, void *, REFIID, void **);
-    HRESULT ( STDMETHODCALLTYPE *GetAttributes )(IShellItemArray *,
-        SIATTRIBFLAGS, SFGAOF, SFGAOF *);
-    HRESULT ( STDMETHODCALLTYPE *GetCount )(
-        IShellItemArray *, DWORD *);
-    HRESULT ( STDMETHODCALLTYPE *GetItemAt )(
-        IShellItemArray *, DWORD, IShellItem **);
-    /* ppenumShellItems actually (IEnumShellItems **) */
-    HRESULT ( STDMETHODCALLTYPE *EnumItems )(
-        IShellItemArray *, void **);
-
-    END_INTERFACE
-} IShellItemArrayVtbl;
-
-struct IShellItemArray {
-    CONST_VTBL struct IShellItemArrayVtbl *lpVtbl;
-};
-
-#endif /* __IShellItemArray_INTERFACE_DEFINED__ */
-
-/*
- * Older compilers do not define these CLSIDs so we do so here under
- * a slightly different name so as to not clash with the definitions
- * in new compilers
- */
-static const CLSID ClsidFileOpenDialog = {
-    0xDC1C5A9C, 0xE88A, 0X4DDE, {0xA5, 0xA1, 0x60, 0xF8, 0x2A, 0x20, 0xAE, 0xF7}
-};
-static const CLSID ClsidFileSaveDialog = {
-    0xC0B4E2F3, 0xBA21, 0x4773, {0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B}
-};
-static const IID IIDIFileOpenDialog = {
-    0xD57C7288, 0xD4AD, 0x4768, {0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60}
-};
-static const IID IIDIFileSaveDialog = {
-    0x84BCCD23, 0x5FDE, 0x4CDB, {0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB}
-};
-static const IID IIDIShellItem = {
-       0x43826D1E, 0xE718, 0x42EE, {0xBC, 0x55, 0xA1, 0xE2, 0x61, 0xC3, 0x7B, 0xFE}
-};
-
-#ifdef __IFileDialog_INTERFACE_DEFINED__
-# define TCLCOMDLG_FILTERSPEC COMDLG_FILTERSPEC
-#else
-
-/* Forward declarations for structs that are referenced but not used */
-typedef struct IPropertyStore IPropertyStore;
-typedef struct IPropertyDescriptionList IPropertyDescriptionList;
-typedef struct IFileOperationProgressSink IFileOperationProgressSink;
-typedef enum FDAP {
-    FDAP_BOTTOM        = 0,
-    FDAP_TOP   = 1
-} FDAP;
-
-typedef struct {
-    LPCWSTR pszName;
-    LPCWSTR pszSpec;
-} TCLCOMDLG_FILTERSPEC;
-
-enum _FILEOPENDIALOGOPTIONS {
-    FOS_OVERWRITEPROMPT        = 0x2,
-    FOS_STRICTFILETYPES        = 0x4,
-    FOS_NOCHANGEDIR    = 0x8,
-    FOS_PICKFOLDERS    = 0x20,
-    FOS_FORCEFILESYSTEM        = 0x40,
-    FOS_ALLNONSTORAGEITEMS     = 0x80,
-    FOS_NOVALIDATE     = 0x100,
-    FOS_ALLOWMULTISELECT       = 0x200,
-    FOS_PATHMUSTEXIST  = 0x800,
-    FOS_FILEMUSTEXIST  = 0x1000,
-    FOS_CREATEPROMPT   = 0x2000,
-    FOS_SHAREAWARE     = 0x4000,
-    FOS_NOREADONLYRETURN       = 0x8000,
-    FOS_NOTESTFILECREATE       = 0x10000,
-    FOS_HIDEMRUPLACES  = 0x20000,
-    FOS_HIDEPINNEDPLACES       = 0x40000,
-    FOS_NODEREFERENCELINKS     = 0x100000,
-    FOS_DONTADDTORECENT        = 0x2000000,
-    FOS_FORCESHOWHIDDEN        = 0x10000000,
-    FOS_DEFAULTNOMINIMODE      = 0x20000000,
-    FOS_FORCEPREVIEWPANEON     = 0x40000000
-} ;
-typedef DWORD FILEOPENDIALOGOPTIONS;
-
-typedef struct IFileDialog IFileDialog;
-typedef struct IFileDialogVtbl
-{
-    BEGIN_INTERFACE
-
-    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
-         IFileDialog *, REFIID, void **);
-    ULONG ( STDMETHODCALLTYPE *AddRef )( IFileDialog *);
-    ULONG ( STDMETHODCALLTYPE *Release )( IFileDialog *);
-    HRESULT ( STDMETHODCALLTYPE *Show )( IFileDialog *, HWND);
-    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileDialog *,
-        UINT, const TCLCOMDLG_FILTERSPEC *);
-    HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(IFileDialog *, UINT);
-    HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(IFileDialog *, UINT *);
-    /* XXX - Actually pfde is IFileDialogEvents* but we do not use
-       this call and do not want to define IFileDialogEvents as that
-       pulls in a whole bunch of other stuff. */
-    HRESULT ( STDMETHODCALLTYPE *Advise )(
-        IFileDialog *, void *, DWORD *);
-    HRESULT ( STDMETHODCALLTYPE *Unadvise )(IFileDialog *, DWORD);
-    HRESULT ( STDMETHODCALLTYPE *SetOptions )(
-        IFileDialog *, FILEOPENDIALOGOPTIONS);
-    HRESULT ( STDMETHODCALLTYPE *GetOptions )(
-        IFileDialog *, FILEOPENDIALOGOPTIONS *);
-    HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )(
-        IFileDialog *, IShellItem *);
-    HRESULT ( STDMETHODCALLTYPE *SetFolder )(
-        IFileDialog *, IShellItem *);
-    HRESULT ( STDMETHODCALLTYPE *GetFolder )(
-        IFileDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )(
-        IFileDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *SetFileName )(
-        IFileDialog *,  LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *GetFileName )(
-        IFileDialog *,  LPWSTR *);
-    HRESULT ( STDMETHODCALLTYPE *SetTitle )(
-        IFileDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )(
-        IFileDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )(
-        IFileDialog *,  LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *GetResult )(
-        IFileDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *AddPlace )(
-        IFileDialog *, IShellItem *, FDAP);
-    HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )(
-         IFileDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *Close )( IFileDialog *, HRESULT);
-    HRESULT ( STDMETHODCALLTYPE *SetClientGuid )(
-        IFileDialog *, REFGUID);
-    HRESULT ( STDMETHODCALLTYPE *ClearClientData )( IFileDialog *);
-    /* pFilter actually IShellItemFilter. But deprecated in Win7 AND we do
-       not use it anyways. So define as void* */
-    HRESULT ( STDMETHODCALLTYPE *SetFilter )(
-         IFileDialog *, void *);
-
-    END_INTERFACE
-} IFileDialogVtbl;
-
-struct IFileDialog {
-    CONST_VTBL struct IFileDialogVtbl *lpVtbl;
-};
-
-
-typedef struct IFileSaveDialog IFileSaveDialog;
-typedef struct IFileSaveDialogVtbl {
-    BEGIN_INTERFACE
-
-    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
-        IFileSaveDialog *, REFIID, void **);
-    ULONG ( STDMETHODCALLTYPE *AddRef )( IFileSaveDialog *);
-    ULONG ( STDMETHODCALLTYPE *Release )( IFileSaveDialog *);
-    HRESULT ( STDMETHODCALLTYPE *Show )(
-        IFileSaveDialog *, HWND);
-    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileSaveDialog * this,
-        UINT, const TCLCOMDLG_FILTERSPEC *);
-    HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(
-        IFileSaveDialog *, UINT);
-    HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(
-         IFileSaveDialog *, UINT *);
-    /* Actually pfde is IFileSaveDialogEvents* */
-    HRESULT ( STDMETHODCALLTYPE *Advise )(
-         IFileSaveDialog *, void *, DWORD *);
-    HRESULT ( STDMETHODCALLTYPE *Unadvise )( IFileSaveDialog *, DWORD);
-    HRESULT ( STDMETHODCALLTYPE *SetOptions )(
-         IFileSaveDialog *, FILEOPENDIALOGOPTIONS);
-    HRESULT ( STDMETHODCALLTYPE *GetOptions )(
-         IFileSaveDialog *, FILEOPENDIALOGOPTIONS *);
-    HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )(
-         IFileSaveDialog *, IShellItem *);
-    HRESULT ( STDMETHODCALLTYPE *SetFolder )(
-        IFileSaveDialog *, IShellItem *);
-    HRESULT ( STDMETHODCALLTYPE *GetFolder )(
-         IFileSaveDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )(
-         IFileSaveDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *SetFileName )(
-         IFileSaveDialog *,  LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *GetFileName )(
-         IFileSaveDialog *,  LPWSTR *);
-    HRESULT ( STDMETHODCALLTYPE *SetTitle )(
-         IFileSaveDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )(
-         IFileSaveDialog *,  LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )(
-         IFileSaveDialog *,  LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *GetResult )(
-         IFileSaveDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *AddPlace )(
-         IFileSaveDialog *, IShellItem *, FDAP);
-    HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )(
-         IFileSaveDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *Close )( IFileSaveDialog *, HRESULT);
-    HRESULT ( STDMETHODCALLTYPE *SetClientGuid )(
-        IFileSaveDialog *, REFGUID);
-    HRESULT ( STDMETHODCALLTYPE *ClearClientData )( IFileSaveDialog *);
-    /* pFilter Actually IShellItemFilter* */
-    HRESULT ( STDMETHODCALLTYPE *SetFilter )(
-        IFileSaveDialog *, void *);
-    HRESULT ( STDMETHODCALLTYPE *SetSaveAsItem )(
-        IFileSaveDialog *, IShellItem *);
-    HRESULT ( STDMETHODCALLTYPE *SetProperties )(
-        IFileSaveDialog *, IPropertyStore *);
-    HRESULT ( STDMETHODCALLTYPE *SetCollectedProperties )(
-        IFileSaveDialog *, IPropertyDescriptionList *, BOOL);
-    HRESULT ( STDMETHODCALLTYPE *GetProperties )(
-        IFileSaveDialog *, IPropertyStore **);
-    HRESULT ( STDMETHODCALLTYPE *ApplyProperties )(
-        IFileSaveDialog *, IShellItem *, IPropertyStore *,
-        HWND, IFileOperationProgressSink *);
-
-    END_INTERFACE
-
-} IFileSaveDialogVtbl;
-
-struct IFileSaveDialog {
-    CONST_VTBL struct IFileSaveDialogVtbl *lpVtbl;
-};
-
-typedef struct IFileOpenDialog IFileOpenDialog;
-typedef struct IFileOpenDialogVtbl {
-    BEGIN_INTERFACE
-
-    HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
-        IFileOpenDialog *, REFIID, void **);
-    ULONG ( STDMETHODCALLTYPE *AddRef )( IFileOpenDialog *);
-    ULONG ( STDMETHODCALLTYPE *Release )( IFileOpenDialog *);
-    HRESULT ( STDMETHODCALLTYPE *Show )( IFileOpenDialog *, HWND);
-    HRESULT ( STDMETHODCALLTYPE *SetFileTypes )( IFileOpenDialog *,
-        UINT, const TCLCOMDLG_FILTERSPEC *);
-    HRESULT ( STDMETHODCALLTYPE *SetFileTypeIndex )(
-        IFileOpenDialog *, UINT);
-    HRESULT ( STDMETHODCALLTYPE *GetFileTypeIndex )(
-        IFileOpenDialog *, UINT *);
-    /* Actually pfde is IFileDialogEvents* */
-    HRESULT ( STDMETHODCALLTYPE *Advise )(
-        IFileOpenDialog *, void *, DWORD *);
-    HRESULT ( STDMETHODCALLTYPE *Unadvise )( IFileOpenDialog *, DWORD);
-    HRESULT ( STDMETHODCALLTYPE *SetOptions )(
-        IFileOpenDialog *, FILEOPENDIALOGOPTIONS);
-    HRESULT ( STDMETHODCALLTYPE *GetOptions )(
-        IFileOpenDialog *, FILEOPENDIALOGOPTIONS *);
-    HRESULT ( STDMETHODCALLTYPE *SetDefaultFolder )(
-        IFileOpenDialog *, IShellItem *);
-    HRESULT ( STDMETHODCALLTYPE *SetFolder )(
-        IFileOpenDialog *, IShellItem *);
-    HRESULT ( STDMETHODCALLTYPE *GetFolder )(
-        IFileOpenDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *GetCurrentSelection )(
-        IFileOpenDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *SetFileName )(
-        IFileOpenDialog *,  LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *GetFileName )(
-        IFileOpenDialog *, LPWSTR *);
-    HRESULT ( STDMETHODCALLTYPE *SetTitle )(
-        IFileOpenDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *SetOkButtonLabel )(
-        IFileOpenDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *SetFileNameLabel )(
-        IFileOpenDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *GetResult )(
-        IFileOpenDialog *, IShellItem **);
-    HRESULT ( STDMETHODCALLTYPE *AddPlace )(
-        IFileOpenDialog *, IShellItem *, FDAP);
-    HRESULT ( STDMETHODCALLTYPE *SetDefaultExtension )(
-        IFileOpenDialog *, LPCWSTR);
-    HRESULT ( STDMETHODCALLTYPE *Close )( IFileOpenDialog *, HRESULT);
-    HRESULT ( STDMETHODCALLTYPE *SetClientGuid )(
-        IFileOpenDialog *, REFGUID);
-    HRESULT ( STDMETHODCALLTYPE *ClearClientData )(
-        IFileOpenDialog *);
-    HRESULT ( STDMETHODCALLTYPE *SetFilter )(
-        IFileOpenDialog *,
-        /* pFilter is actually IShellItemFilter */
-        void *);
-    HRESULT ( STDMETHODCALLTYPE *GetResults )(
-        IFileOpenDialog *, IShellItemArray **);
-    HRESULT ( STDMETHODCALLTYPE *GetSelectedItems )(
-        IFileOpenDialog *, IShellItemArray **);
-
-    END_INTERFACE
-} IFileOpenDialogVtbl;
-
-struct IFileOpenDialog
-{
-    CONST_VTBL struct IFileOpenDialogVtbl *lpVtbl;
-};
-
-#endif /* __IFileDialog_INTERFACE_DEFINED__ */
-
-/*
- * Definitions of functions used only in this file.
- */
-
-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 void             CleanupOFNOptions(OFNOpts *optsPtr);
-static int              ParseOFNOptions(ClientData clientData,
-                            Tcl_Interp *interp, int objc,
-                            Tcl_Obj *const objv[], enum OFNOper oper, OFNOpts *optsPtr);
-static int GetFileNameXP(Tcl_Interp *interp, OFNOpts *optsPtr,
-                         enum OFNOper oper);
-static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr,
-                            enum OFNOper oper);
-static int             GetFileName(ClientData clientData,
-                                    Tcl_Interp *interp, int objc,
-                                    Tcl_Obj *const objv[], enum OFNOper oper);
-static int MakeFilterVista(Tcl_Interp *interp, OFNOpts *optsPtr,
-               DWORD *countPtr, TCLCOMDLG_FILTERSPEC **dlgFilterPtrPtr,
-               DWORD *defaultFilterIndexPtr);
-static void FreeFilterVista(DWORD count, TCLCOMDLG_FILTERSPEC *dlgFilterPtr);
-static int             MakeFilter(Tcl_Interp *interp, Tcl_Obj *valuePtr,
-                           Tcl_DString *dsPtr, Tcl_Obj *initialPtr,
-                           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 const char *ConvertExternalFilename(TCHAR *filename,
-                           Tcl_DString *dsPtr);
-static void             LoadShellProcs(void);
-
-
-/* Definitions of dynamically loaded Win32 calls */
-typedef HRESULT (STDAPICALLTYPE SHCreateItemFromParsingNameProc)(
-    PCWSTR pszPath, IBindCtx *pbc, REFIID riid, void **ppv);
-struct ShellProcPointers {
-    SHCreateItemFromParsingNameProc *SHCreateItemFromParsingName;
-} ShellProcs;
-
-\f
-/*
- *-------------------------------------------------------------------------
- *
- * LoadShellProcs --
- *
- *     Some shell functions are not available on older versions of
- *     Windows. This function dynamically loads them and stores pointers
- *     to them in ShellProcs. Any function that is not available has
- *     the corresponding pointer set to NULL.
- *
- *     Note this call never fails. Unavailability of a function is not
- *     a reason for failure. Caller should check whether a particular
- *     function pointer is NULL or not. Once loaded a function stays
- *     forever loaded.
- *
- *     XXX - we load the function pointers into global memory. This implies
- *     there is a potential (however small) for race conditions between
- *     threads. However, Tk is in any case meant to be loaded in exactly
- *     one thread so this should not be an issue and saves us from
- *     unnecessary bookkeeping.
- *
- * Return value:
- *     None.
- *
- * Side effects:
- *     ShellProcs is populated.
- *-------------------------------------------------------------------------
- */
-static void LoadShellProcs()
-{
-    static HMODULE shell32_handle = NULL;
-
-    if (shell32_handle != NULL)
-        return; /* We have already been through here. */
-
-    /*
-     * XXX - Note we never call FreeLibrary. There is no point because
-     * shell32.dll is loaded at startup anyways and stays for the duration
-     * of the process so why bother with keeping track of when to unload
-     */
-    shell32_handle = LoadLibrary(TEXT("shell32.dll"));
-    if (shell32_handle == NULL) /* Should never happen but check anyways. */
-        return;
-
-    ShellProcs.SHCreateItemFromParsingName =
-        (SHCreateItemFromParsingNameProc*) GetProcAddress(shell32_handle,
-                                                         "SHCreateItemFromParsingName");
-}
-
-\f
-/*
- *-------------------------------------------------------------------------
- *
- * EatSpuriousMessageBugFix --
- *
- *     In the file open/save dialog, double clicking on a list item causes
- *     the dialog box to close, but an unwanted WM_LBUTTONUP message is sent
- *     to the window underneath. If the window underneath happens to be a
- *     windows control (eg a button) then it will be activated by accident.
- *
- *     This problem does not occur in dialog boxes, because windows must do
- *     some special processing to solve the problem. (separate message
- *     processing functions are used to cope with keyboard navigation of
- *     controls.)
- *
- *     Here is one solution. After returning, we poll the message queue for
- *     1/4s looking for WM_LBUTTON up messages. If we see one it's consumed.
- *     If we get a WM_LBUTTONDOWN message, then we exit early, since the user
- *     must be doing something new. This fix only works for the current
- *     application, so the problem will still occur if the open dialog
- *     happens to be over another applications button. However this is a
- *     fairly rare occurrance.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     Consumes an unwanted BUTTON messages.
- *
- *-------------------------------------------------------------------------
- */
-
-static void
-EatSpuriousMessageBugFix(void)
-{
-    MSG msg;
-    DWORD nTime = GetTickCount() + 250;
-
-    while (GetTickCount() < nTime) {
-       if (PeekMessageA(&msg, 0, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE)){
-           break;
-       }
-       PeekMessageA(&msg, 0, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE);
-    }
-}
-\f
-/*
- *-------------------------------------------------------------------------
- *
- * TkWinDialogDebug --
- *
- *     Function to turn on/off debugging support for common dialogs under
- *     windows. The variable "tk_debug" is set to the identifier of the
- *     dialog window when the modal dialog window pops up and it is safe to
- *     send messages to the dialog.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     This variable only makes sense if just one dialog is up at a time.
- *
- *-------------------------------------------------------------------------
- */
-
-void
-TkWinDialogDebug(
-    int debug)
-{
-    ThreadSpecificData *tsdPtr =
-           Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
-    tsdPtr->debugFlag = debug;
-}
-\f
-/*
- *-------------------------------------------------------------------------
- *
- * Tk_ChooseColorObjCmd --
- *
- *     This function implements the color dialog box for the Windows
- *     platform. See the user documentation for details on what it does.
- *
- * Results:
- *     See user documentation.
- *
- * Side effects:
- *     A dialog window is created the first time this function is called.
- *     This window is not destroyed and will be reused the next time the
- *     application invokes the "tk_chooseColor" command.
- *
- *-------------------------------------------------------------------------
- */
-
-int
-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. */
-{
-    Tk_Window tkwin = clientData, parent;
-    HWND hWnd;
-    int i, oldMode, winCode, result;
-    CHOOSECOLOR chooseColor;
-    static int inited = 0;
-    static COLORREF dwCustColors[16];
-    static long oldColor;              /* the color selected last time */
-    static const char *const optionStrings[] = {
-       "-initialcolor", "-parent", "-title", NULL
-    };
-    enum options {
-       COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE
-    };
-
-    result = TCL_OK;
-    if (inited == 0) {
-       /*
-        * dwCustColors stores the custom color which the user can modify. We
-        * store these colors in a static array so that the next time the
-        * color dialog pops up, the same set of custom colors remain in the
-        * dialog.
-        */
-
-       for (i = 0; i < 16; i++) {
-           dwCustColors[i] = RGB(255-i * 10, i, i * 10);
-       }
-       oldColor = RGB(0xa0, 0xa0, 0xa0);
-       inited = 1;
-    }
-
-    parent                     = tkwin;
-    chooseColor.lStructSize    = sizeof(CHOOSECOLOR);
-    chooseColor.hwndOwner      = NULL;
-    chooseColor.hInstance      = NULL;
-    chooseColor.rgbResult      = oldColor;
-    chooseColor.lpCustColors   = dwCustColors;
-    chooseColor.Flags          = CC_RGBINIT | CC_FULLOPEN | CC_ENABLEHOOK;
-    chooseColor.lCustData      = (LPARAM) NULL;
-    chooseColor.lpfnHook       = (LPOFNHOOKPROC) ColorDlgHookProc;
-    chooseColor.lpTemplateName = (LPTSTR) interp;
-
-    for (i = 1; i < objc; i += 2) {
-       int index;
-       const char *string;
-       Tcl_Obj *optionPtr, *valuePtr;
-
-       optionPtr = objv[i];
-       valuePtr = objv[i + 1];
-
-       if (Tcl_GetIndexFromObjStruct(interp, optionPtr, optionStrings,
-               sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       if (i + 1 == objc) {
-           Tcl_SetObjResult(interp, Tcl_ObjPrintf(
-                   "value for \"%s\" missing", Tcl_GetString(optionPtr)));
-           Tcl_SetErrorCode(interp, "TK", "COLORDIALOG", "VALUE", NULL);
-           return TCL_ERROR;
-       }
-
-       string = Tcl_GetString(valuePtr);
-       switch ((enum options) index) {
-       case COLOR_INITIAL: {
-           XColor *colorPtr;
-
-           colorPtr = Tk_GetColor(interp, tkwin, string);
-           if (colorPtr == NULL) {
-               return TCL_ERROR;
-           }
-           chooseColor.rgbResult = RGB(colorPtr->red / 0x100,
-                   colorPtr->green / 0x100, colorPtr->blue / 0x100);
-           break;
-       }
-       case COLOR_PARENT:
-           parent = Tk_NameToWindow(interp, string, tkwin);
-           if (parent == NULL) {
-               return TCL_ERROR;
-           }
-           break;
-       case COLOR_TITLE:
-           chooseColor.lCustData = (LPARAM) string;
-           break;
-       }
-    }
-
-    Tk_MakeWindowExist(parent);
-    chooseColor.hwndOwner = NULL;
-    hWnd = Tk_GetHWND(Tk_WindowId(parent));
-    chooseColor.hwndOwner = hWnd;
-
-    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
-    winCode = ChooseColor(&chooseColor);
-    (void) 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);
-
-    /*
-     * 3. Process the result of the dialog
-     */
-
-    if (winCode) {
-       /*
-        * User has selected a color
-        */
-
-       Tcl_SetObjResult(interp, Tcl_ObjPrintf("#%02x%02x%02x",
-               GetRValue(chooseColor.rgbResult),
-               GetGValue(chooseColor.rgbResult),
-               GetBValue(chooseColor.rgbResult)));
-       oldColor = chooseColor.rgbResult;
-       result = TCL_OK;
-    }
-
-    return result;
-}
-\f
-/*
- *-------------------------------------------------------------------------
- *
- * ColorDlgHookProc --
- *
- *     Provides special handling of messages for the Color common dialog box.
- *     Used to set the title when the dialog first appears.
- *
- * Results:
- *     The return value is 0 if the default dialog box function should handle
- *     the message, non-zero otherwise.
- *
- * Side effects:
- *     Changes the title of the dialog window.
- *
- *----------------------------------------------------------------------
- */
-
-static UINT CALLBACK
-ColorDlgHookProc(
-    HWND hDlg,                 /* Handle to the color dialog. */
-    UINT uMsg,                 /* Type of message. */
-    WPARAM wParam,             /* First message parameter. */
-    LPARAM lParam)             /* Second message parameter. */
-{
-    ThreadSpecificData *tsdPtr =
-           Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-    const char *title;
-    CHOOSECOLOR *ccPtr;
-
-    if (WM_INITDIALOG == uMsg) {
-
-       /*
-        * Set the title string of the dialog.
-        */
-
-       ccPtr = (CHOOSECOLOR *) lParam;
-       title = (const char *) ccPtr->lCustData;
-
-       if ((title != NULL) && (title[0] != '\0')) {
-           Tcl_DString ds;
-
-           SetWindowText(hDlg, Tcl_WinUtfToTChar(title,-1,&ds));
-           Tcl_DStringFree(&ds);
-       }
-       if (tsdPtr->debugFlag) {
-           tsdPtr->debugInterp = (Tcl_Interp *) ccPtr->lpTemplateName;
-           Tcl_DoWhenIdle(SetTkDialog, hDlg);
-       }
-       return TRUE;
-    }
-    return FALSE;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * Tk_GetOpenFileCmd --
- *
- *     This function implements the "open file" dialog box for the Windows
- *     platform. See the user documentation for details on what it does.
- *
- * Results:
- *     See user documentation.
- *
- * Side effects:
- *     A dialog window is created the first this function is called.
- *
- *----------------------------------------------------------------------
- */
-
-int
-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. */
-{
-    return GetFileName(clientData, interp, objc, objv, OFN_FILE_OPEN);
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * Tk_GetSaveFileCmd --
- *
- *     Same as Tk_GetOpenFileCmd but opens a "save file" dialog box
- *     instead
- *
- * Results:
- *     Same as Tk_GetOpenFileCmd.
- *
- * Side effects:
- *     Same as Tk_GetOpenFileCmd.
- *
- *----------------------------------------------------------------------
- */
-
-int
-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. */
-{
-    return GetFileName(clientData, interp, objc, objv, OFN_FILE_SAVE);
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * CleanupOFNOptions --
- *
- *     Cleans up any storage allocated by ParseOFNOptions
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     Releases resources held by *optsPtr
- *----------------------------------------------------------------------
- */
-static void CleanupOFNOptions(OFNOpts *optsPtr)
-{
-    Tcl_DStringFree(&optsPtr->utfDirString);
-}
-
-
-\f
-/*
- *----------------------------------------------------------------------
- *
- * ParseOFNOptions --
- *
- *     Option parsing for tk_get{Open,Save}File
- *
- * Results:
- *     TCL_OK on success, TCL_ERROR otherwise
- *
- * Side effects:
- *     Returns option values in *optsPtr. Note these may include string
- *      pointers into objv[]
- *----------------------------------------------------------------------
- */
-
-static int
-ParseOFNOptions(
-    ClientData clientData,     /* Main window associated with interpreter. */
-    Tcl_Interp *interp,                /* Current interpreter. */
-    int objc,                  /* Number of arguments. */
-    Tcl_Obj *const objv[],     /* Argument objects. */
-    enum OFNOper oper,                 /* 1 for Open, 0 for Save */
-    OFNOpts *optsPtr)           /* Output, uninitialized on entry */
-{
-    int i;
-    Tcl_DString ds;
-    enum options {
-       FILE_DEFAULT, FILE_TYPES, FILE_INITDIR, FILE_INITFILE, FILE_PARENT,
-       FILE_TITLE, FILE_TYPEVARIABLE, FILE_MULTIPLE, FILE_CONFIRMOW,
-        FILE_MUSTEXIST,
-    };
-    struct Options {
-       const char *name;
-       enum options value;
-    };
-    static const struct Options saveOptions[] = {
-       {"-confirmoverwrite",   FILE_CONFIRMOW},
-       {"-defaultextension",   FILE_DEFAULT},
-       {"-filetypes",          FILE_TYPES},
-       {"-initialdir",         FILE_INITDIR},
-       {"-initialfile",        FILE_INITFILE},
-       {"-parent",             FILE_PARENT},
-       {"-title",              FILE_TITLE},
-       {"-typevariable",       FILE_TYPEVARIABLE},
-       {NULL,                  FILE_DEFAULT/*ignored*/ }
-    };
-    static const struct Options openOptions[] = {
-       {"-defaultextension",   FILE_DEFAULT},
-       {"-filetypes",          FILE_TYPES},
-       {"-initialdir",         FILE_INITDIR},
-       {"-initialfile",        FILE_INITFILE},
-       {"-multiple",           FILE_MULTIPLE},
-       {"-parent",             FILE_PARENT},
-       {"-title",              FILE_TITLE},
-       {"-typevariable",       FILE_TYPEVARIABLE},
-       {NULL,                  FILE_DEFAULT/*ignored*/ }
-    };
-    static const struct Options dirOptions[] = {
-       {"-initialdir", FILE_INITDIR},
-        {"-mustexist",  FILE_MUSTEXIST},
-       {"-parent",     FILE_PARENT},
-       {"-title",      FILE_TITLE},
-       {NULL,          FILE_DEFAULT/*ignored*/ }
-    };
-
-    const struct Options *options = NULL;
-
-    switch (oper) {
-    case OFN_FILE_SAVE: options = saveOptions; break;
-    case OFN_DIR_CHOOSE: options = dirOptions; break;
-    case OFN_FILE_OPEN: options = openOptions; break;
-    }
-
-    ZeroMemory(optsPtr, sizeof(*optsPtr));
-    // optsPtr->forceXPStyle = 1;
-    optsPtr->tkwin = clientData;
-    optsPtr->confirmOverwrite = 1; /* By default we ask for confirmation */
-    Tcl_DStringInit(&optsPtr->utfDirString);
-    optsPtr->file[0] = 0;
-
-    for (i = 1; i < objc; i += 2) {
-       int index;
-       const char *string;
-       Tcl_Obj *valuePtr = objv[i + 1];
-
-       if (Tcl_GetIndexFromObjStruct(interp, objv[i], options,
-               sizeof(struct Options), "option", 0, &index) != TCL_OK) {
-            /*
-             * XXX -xpstyle is explicitly checked for as it is undocumented
-             * and we do not want it to show in option error messages.
-             */
-            if (strcmp(Tcl_GetString(objv[i]), "-xpstyle"))
-                goto error_return;
-           if (Tcl_GetBooleanFromObj(interp, valuePtr,
-                                      &optsPtr->forceXPStyle) != TCL_OK)
-                goto error_return;
-
-            continue;
-
-       } else if (i + 1 == objc) {
-           Tcl_SetObjResult(interp, Tcl_ObjPrintf(
-                   "value for \"%s\" missing", options[index].name));
-           Tcl_SetErrorCode(interp, "TK", "FILEDIALOG", "VALUE", NULL);
-           goto error_return;
-       }
-
-       string = Tcl_GetString(valuePtr);
-       switch (options[index].value) {
-       case FILE_DEFAULT:
-           optsPtr->extObj = valuePtr;
-           break;
-       case FILE_TYPES:
-           optsPtr->filterObj = valuePtr;
-           break;
-       case FILE_INITDIR:
-           Tcl_DStringFree(&optsPtr->utfDirString);
-           if (Tcl_TranslateFileName(interp, string,
-                                      &optsPtr->utfDirString) == NULL)
-               goto error_return;
-           break;
-       case FILE_INITFILE:
-           if (Tcl_TranslateFileName(interp, string, &ds) == NULL)
-               goto error_return;
-           Tcl_UtfToExternal(NULL, TkWinGetUnicodeEncoding(),
-                              Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), 0, NULL,
-                              (char *) &optsPtr->file[0], sizeof(optsPtr->file),
-                              NULL, NULL, NULL);
-           Tcl_DStringFree(&ds);
-           break;
-       case FILE_PARENT:
-           optsPtr->tkwin = Tk_NameToWindow(interp, string, clientData);
-           if (optsPtr->tkwin == NULL)
-               goto error_return;
-           break;
-       case FILE_TITLE:
-           optsPtr->titleObj = valuePtr;
-           break;
-       case FILE_TYPEVARIABLE:
-           optsPtr->typeVariableObj = valuePtr;
-           optsPtr->initialTypeObj = Tcl_ObjGetVar2(interp, valuePtr,
-                                                     NULL, TCL_GLOBAL_ONLY);
-           break;
-       case FILE_MULTIPLE:
-           if (Tcl_GetBooleanFromObj(interp, valuePtr,
-                                      &optsPtr->multi) != TCL_OK)
-                goto error_return;
-           break;
-       case FILE_CONFIRMOW:
-           if (Tcl_GetBooleanFromObj(interp, valuePtr,
-                                      &optsPtr->confirmOverwrite) != TCL_OK)
-                goto error_return;
-           break;
-        case FILE_MUSTEXIST:
-           if (Tcl_GetBooleanFromObj(interp, valuePtr,
-                                      &optsPtr->mustExist) != TCL_OK)
-                goto error_return;
-            break;
-       }
-    }
-
-    return TCL_OK;
-
-error_return:                   /* interp should already hold error */
-    /* On error, we need to clean up anything we might have allocated */
-    CleanupOFNOptions(optsPtr);
-    return TCL_ERROR;
-}
-
-\f
-/*
- *----------------------------------------------------------------------
- * VistaFileDialogsAvailable
- *
- *      Checks whether the new (Vista) file dialogs can be used on
- *      the system.
- *
- * Returns:
- *      1 if new dialogs are available, 0 otherwise
- *
- * Side effects:
- *      Loads required procedures dynamically if available.
- *      If new dialogs are available, COM is also initialized.
- *----------------------------------------------------------------------
- */
-static int VistaFileDialogsAvailable()
-{
-    HRESULT hr;
-    IFileDialog *fdlgPtr = NULL;
-    ThreadSpecificData *tsdPtr =
-        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
-    if (tsdPtr->newFileDialogsState == FDLG_STATE_INIT) {
-        tsdPtr->newFileDialogsState = FDLG_STATE_USE_OLD;
-        LoadShellProcs();
-        if (ShellProcs.SHCreateItemFromParsingName != NULL) {
-            hr = CoInitialize(0);
-            /* XXX - need we schedule CoUninitialize at thread shutdown ? */
-
-            /* Ensure all COM interfaces we use are available */
-            if (SUCCEEDED(hr)) {
-                hr = CoCreateInstance(&ClsidFileOpenDialog, NULL,
-                                      CLSCTX_INPROC_SERVER, &IIDIFileOpenDialog, (void **) &fdlgPtr);
-                if (SUCCEEDED(hr)) {
-                    fdlgPtr->lpVtbl->Release(fdlgPtr);
-                    hr = CoCreateInstance(&ClsidFileSaveDialog, NULL,
-                             CLSCTX_INPROC_SERVER, &IIDIFileSaveDialog,
-                                          (void **) &fdlgPtr);
-                    if (SUCCEEDED(hr)) {
-                        fdlgPtr->lpVtbl->Release(fdlgPtr);
-
-                        /* Looks like we have all we need */
-                        tsdPtr->newFileDialogsState = FDLG_STATE_USE_NEW;
-                    }
-                }
-            }
-        }
-    }
-
-    return (tsdPtr->newFileDialogsState == FDLG_STATE_USE_NEW);
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * GetFileNameVista --
- *
- *     Displays the new file dialogs on Vista and later.
- *      This function must generally not be called unless the
- *      tsdPtr->newFileDialogsState is FDLG_STATE_USE_NEW but if
- *      it is, it will just pass the call to the older GetFileNameXP
- *
- * Results:
- *     TCL_OK - dialog was successfully displayed, results returned in interp
- *      TCL_ERROR - error return
- *
- * Side effects:
- *      Dialogs is displayed
- *----------------------------------------------------------------------
- */
-static int GetFileNameVista(Tcl_Interp *interp, OFNOpts *optsPtr,
-                            enum OFNOper oper)
-{
-    HRESULT hr;
-    HWND hWnd;
-    DWORD flags, nfilters, defaultFilterIndex;
-    TCLCOMDLG_FILTERSPEC *filterPtr = NULL;
-    IFileDialog *fdlgIf = NULL;
-    IShellItem *dirIf = NULL;
-    LPWSTR wstr;
-    Tcl_Obj *resultObj = NULL;
-    ThreadSpecificData *tsdPtr =
-           Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-    int oldMode;
-
-    if (tsdPtr->newFileDialogsState != FDLG_STATE_USE_NEW) {
-        /* XXX - should be an assert but Tcl does not seem to have one? */
-        Tcl_SetResult(interp, "Internal error: GetFileNameVista: IFileDialog API not available", TCL_STATIC);
-        return TCL_ERROR;
-    }
-
-    /*
-     * At this point new interfaces are supposed to be available.
-     * fdlgIf is actually a IFileOpenDialog or IFileSaveDialog
-     * both of which inherit from IFileDialog. We use the common
-     * IFileDialog interface for the most part, casting only for
-     * type-specific calls.
-     */
-    Tk_MakeWindowExist(optsPtr->tkwin);
-    hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin));
-
-    /*
-     * The only validation we need to do w.r.t caller supplied data
-     * is the filter specification so do that before creating
-     */
-    if (MakeFilterVista(interp, optsPtr, &nfilters, &filterPtr,
-                        &defaultFilterIndex) != TCL_OK)
-        return TCL_ERROR;
-
-    /*
-     * Beyond this point, do not just return on error as there will be
-     * resources that need to be released/freed.
-     */
-
-    if (oper == OFN_FILE_OPEN || oper == OFN_DIR_CHOOSE)
-        hr = CoCreateInstance(&ClsidFileOpenDialog, NULL,
-                              CLSCTX_INPROC_SERVER, &IIDIFileOpenDialog, (void **) &fdlgIf);
-    else
-        hr = CoCreateInstance(&ClsidFileSaveDialog, NULL,
-                              CLSCTX_INPROC_SERVER, &IIDIFileSaveDialog, (void **) &fdlgIf);
-
-    if (FAILED(hr))
-        goto vamoose;
-
-    /*
-     * Get current settings first because we want to preserve existing
-     * settings like whether to show hidden files etc. based on the
-     * user's existing preference
-     */
-    hr = fdlgIf->lpVtbl->GetOptions(fdlgIf, &flags);
-    if (FAILED(hr))
-        goto vamoose;
-
-    if (filterPtr) {
-        flags |= FOS_STRICTFILETYPES;
-        hr = fdlgIf->lpVtbl->SetFileTypes(fdlgIf, nfilters, filterPtr);
-        if (FAILED(hr))
-            goto vamoose;
-        hr = fdlgIf->lpVtbl->SetFileTypeIndex(fdlgIf, defaultFilterIndex);
-        if (FAILED(hr))
-            goto vamoose;
-    }
-
-    /* Flags are equivalent to those we used in the older API */
-
-    /*
-     * Following flags must be set irrespective of original setting
-     * XXX - should FOS_NOVALIDATE be there ? Note FOS_NOVALIDATE has different
-     * semantics than OFN_NOVALIDATE in the old API.
-     */
-    flags |=
-        FOS_FORCEFILESYSTEM | /* Only want files, not other shell items */
-        FOS_NOVALIDATE |           /* Don't check for access denied etc. */
-        FOS_PATHMUSTEXIST;           /* The *directory* path must exist */
-
-
-    if (oper == OFN_DIR_CHOOSE) {
-        flags |= FOS_PICKFOLDERS;
-        if (optsPtr->mustExist)
-            flags |= FOS_FILEMUSTEXIST; /* XXX - check working */
-    } else
-        flags &= ~ FOS_PICKFOLDERS;
-
-    if (optsPtr->multi)
-        flags |= FOS_ALLOWMULTISELECT;
-    else
-        flags &= ~FOS_ALLOWMULTISELECT;
-
-    if (optsPtr->confirmOverwrite)
-        flags |= FOS_OVERWRITEPROMPT;
-    else
-        flags &= ~FOS_OVERWRITEPROMPT;
-
-    hr = fdlgIf->lpVtbl->SetOptions(fdlgIf, flags);
-    if (FAILED(hr))
-        goto vamoose;
-
-    if (optsPtr->extObj != NULL) {
-        wstr = Tcl_GetUnicode(optsPtr->extObj);
-        if (wstr[0] == L'.')
-            ++wstr;
-        hr = fdlgIf->lpVtbl->SetDefaultExtension(fdlgIf, wstr);
-        if (FAILED(hr))
-            goto vamoose;
-    }
-
-    if (optsPtr->titleObj != NULL) {
-        hr = fdlgIf->lpVtbl->SetTitle(fdlgIf,
-                                       Tcl_GetUnicode(optsPtr->titleObj));
-        if (FAILED(hr))
-            goto vamoose;
-    }
-
-    if (optsPtr->file[0]) {
-        hr = fdlgIf->lpVtbl->SetFileName(fdlgIf, optsPtr->file);
-        if (FAILED(hr))
-            goto vamoose;
-    }
-
-    if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') {
-        Tcl_DString dirString;
-       Tcl_WinUtfToTChar(Tcl_DStringValue(&optsPtr->utfDirString),
-               Tcl_DStringLength(&optsPtr->utfDirString), &dirString);
-        hr = ShellProcs.SHCreateItemFromParsingName(
-            (TCHAR *) Tcl_DStringValue(&dirString), NULL,
-            &IIDIShellItem, (void **) &dirIf);
-        /* XXX - Note on failure we do not raise error, simply ignore ini dir */
-        if (SUCCEEDED(hr)) {
-            /* Note we use SetFolder, not SetDefaultFolder - see MSDN docs */
-            fdlgIf->lpVtbl->SetFolder(fdlgIf, dirIf); /* Ignore errors */
-        }
-        Tcl_DStringFree(&dirString);
-    }
-
-    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
-    hr = fdlgIf->lpVtbl->Show(fdlgIf, hWnd);
-    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).
-     */
-
-    if (hWnd)
-        EnableWindow(hWnd, 1);
-
-    /*
-     * Clear interp result since it might have been set during the modal loop.
-     * http://core.tcl.tk/tk/tktview/4a0451f5291b3c9168cc560747dae9264e1d2ef6
-     */
-    Tcl_ResetResult(interp);
-
-    if (SUCCEEDED(hr)) {
-        if ((oper == OFN_FILE_OPEN) && optsPtr->multi) {
-            IShellItemArray *multiIf;
-            DWORD dw, count;
-            IFileOpenDialog *fodIf = (IFileOpenDialog *) fdlgIf;
-            hr = fodIf->lpVtbl->GetResults(fodIf, &multiIf);
-            if (SUCCEEDED(hr)) {
-                Tcl_Obj *multiObj;
-                hr = multiIf->lpVtbl->GetCount(multiIf, &count);
-                multiObj = Tcl_NewListObj(count, NULL);
-                if (SUCCEEDED(hr)) {
-                    IShellItem *itemIf;
-                    for (dw = 0; dw < count; ++dw) {
-                        hr = multiIf->lpVtbl->GetItemAt(multiIf, dw, &itemIf);
-                        if (FAILED(hr))
-                            break;
-                        hr = itemIf->lpVtbl->GetDisplayName(itemIf,
-                                        SIGDN_FILESYSPATH, &wstr);
-                        if (SUCCEEDED(hr)) {
-                            Tcl_DString fnds;
-                            ConvertExternalFilename(wstr, &fnds);
-                            CoTaskMemFree(wstr);
-                            Tcl_ListObjAppendElement(
-                                interp, multiObj,
-                                Tcl_NewStringObj(Tcl_DStringValue(&fnds),
-                                                 Tcl_DStringLength(&fnds)));
-                        }
-                        itemIf->lpVtbl->Release(itemIf);
-                        if (FAILED(hr))
-                            break;
-                    }
-                }
-                multiIf->lpVtbl->Release(multiIf);
-                if (SUCCEEDED(hr))
-                    resultObj = multiObj;
-                else
-                    Tcl_DecrRefCount(multiObj);
-            }
-        } else {
-            IShellItem *resultIf;
-            hr = fdlgIf->lpVtbl->GetResult(fdlgIf, &resultIf);
-            if (SUCCEEDED(hr)) {
-                hr = resultIf->lpVtbl->GetDisplayName(resultIf, SIGDN_FILESYSPATH,
-                                                      &wstr);
-                if (SUCCEEDED(hr)) {
-                    Tcl_DString fnds;
-                    ConvertExternalFilename(wstr, &fnds);
-                    resultObj = Tcl_NewStringObj(Tcl_DStringValue(&fnds),
-                                                 Tcl_DStringLength(&fnds));
-                    CoTaskMemFree(wstr);
-                }
-                resultIf->lpVtbl->Release(resultIf);
-            }
-        }
-        if (SUCCEEDED(hr)) {
-            if (filterPtr && optsPtr->typeVariableObj) {
-                UINT ftix;
-                hr = fdlgIf->lpVtbl->GetFileTypeIndex(fdlgIf, &ftix);
-                if (SUCCEEDED(hr)) {
-                    /* Note ftix is a 1-based index */
-                    if (ftix > 0 && ftix <= nfilters) {
-                        Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL,
-                               Tcl_NewUnicodeObj(filterPtr[ftix-1].pszName, -1),
-                               TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
-                    }
-                }
-            }
-        }
-    } else {
-        if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
-            hr = 0;             /* User cancelled, return empty string */
-    }
-
-vamoose: /* (hr != 0) => error */
-    if (dirIf)
-        dirIf->lpVtbl->Release(dirIf);
-    if (fdlgIf)
-        fdlgIf->lpVtbl->Release(fdlgIf);
-
-    if (filterPtr)
-        FreeFilterVista(nfilters, filterPtr);
-
-    if (hr == 0) {
-        if (resultObj)          /* May be NULL if user cancelled */
-            Tcl_SetObjResult(interp, resultObj);
-        return TCL_OK;
-    } else {
-        if (resultObj)
-            Tcl_DecrRefCount(resultObj);
-        Tcl_SetObjResult(interp, TkWin32ErrorObj(hr));
-        return TCL_ERROR;
-    }
-}
-
-\f
-/*
- *----------------------------------------------------------------------
- *
- * GetFileNameXP --
- *
- *     Displays the old pre-Vista file dialogs.
- *
- * Results:
- *     TCL_OK - if dialog was successfully displayed
- *      TCL_ERROR - error return
- *
- * Side effects:
- *      See user documentation.
- *----------------------------------------------------------------------
- */
-static int GetFileNameXP(Tcl_Interp *interp, OFNOpts *optsPtr, enum OFNOper oper)
-{
-    OPENFILENAME ofn;
-    OFNData ofnData;
-    int cdlgerr;
-    int filterIndex = 0, result = TCL_ERROR, winCode, oldMode;
-    HWND hWnd;
-    Tcl_DString utfFilterString, ds;
-    Tcl_DString extString, filterString, dirString, titleString;
-    const char *str;
-    ThreadSpecificData *tsdPtr =
-        Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
-    ZeroMemory(&ofnData, sizeof(OFNData));
-    Tcl_DStringInit(&utfFilterString);
-    Tcl_DStringInit(&dirString); /* XXX - original code was missing this
-                                    leaving dirString uninitialized for
-                                    the unlikely code path where cwd failed */
-
-    if (MakeFilter(interp, optsPtr->filterObj, &utfFilterString,
-                   optsPtr->initialTypeObj, &filterIndex) != TCL_OK) {
-       goto end;
-    }
-
-    Tk_MakeWindowExist(optsPtr->tkwin);
-    hWnd = Tk_GetHWND(Tk_WindowId(optsPtr->tkwin));
-
-    ZeroMemory(&ofn, sizeof(OPENFILENAME));
-    ofn.lStructSize = sizeof(OPENFILENAME);
-    ofn.hwndOwner = hWnd;
-    ofn.hInstance = TkWinGetHInstance(ofn.hwndOwner);
-    ofn.lpstrFile = optsPtr->file;
-    ofn.nMaxFile = TK_MULTI_MAX_PATH;
-    ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_NOCHANGEDIR
-           | OFN_EXPLORER| OFN_ENABLEHOOK| OFN_ENABLESIZING;
-    ofn.lpfnHook = (LPOFNHOOKPROC) OFNHookProc;
-    ofn.lCustData = (LPARAM) &ofnData;
-
-    if (oper != OFN_FILE_SAVE) {
-       ofn.Flags |= OFN_FILEMUSTEXIST;
-    } else if (optsPtr->confirmOverwrite) {
-       ofn.Flags |= OFN_OVERWRITEPROMPT;
-    }
-    if (tsdPtr->debugFlag != 0) {
-       ofnData.interp = interp;
-    }
-    if (optsPtr->multi != 0) {
-       ofn.Flags |= OFN_ALLOWMULTISELECT;
-
-       /*
-        * Starting buffer size. The buffer will be expanded by the OFN dialog
-        * procedure when necessary
-        */
-
-       ofnData.dynFileBufferSize = 512;
-       ofnData.dynFileBuffer = ckalloc(512 * sizeof(TCHAR));
-    }
-
-    if (optsPtr->extObj != NULL) {
-        str = Tcl_GetString(optsPtr->extObj);
-        if (str[0] == '.')
-            ++str;
-       Tcl_WinUtfToTChar(str, -1, &extString);
-       ofn.lpstrDefExt = (TCHAR *) Tcl_DStringValue(&extString);
-    }
-
-    Tcl_WinUtfToTChar(Tcl_DStringValue(&utfFilterString),
-           Tcl_DStringLength(&utfFilterString), &filterString);
-    ofn.lpstrFilter = (TCHAR *) Tcl_DStringValue(&filterString);
-    ofn.nFilterIndex = filterIndex;
-
-    if (Tcl_DStringValue(&optsPtr->utfDirString)[0] != '\0') {
-       Tcl_WinUtfToTChar(Tcl_DStringValue(&optsPtr->utfDirString),
-               Tcl_DStringLength(&optsPtr->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(&optsPtr->utfDirString);
-       if ((Tcl_GetCwd(interp, &optsPtr->utfDirString) == NULL) ||
-               (Tcl_TranslateFileName(interp,
-                     Tcl_DStringValue(&optsPtr->utfDirString), &cwd) == NULL)) {
-           Tcl_ResetResult(interp);
-       } else {
-           Tcl_WinUtfToTChar(Tcl_DStringValue(&cwd),
-                   Tcl_DStringLength(&cwd), &dirString);
-       }
-       Tcl_DStringFree(&cwd);
-    }
-    ofn.lpstrInitialDir = (TCHAR *) Tcl_DStringValue(&dirString);
-
-    if (optsPtr->titleObj != NULL) {
-       Tcl_WinUtfToTChar(Tcl_GetString(optsPtr->titleObj), -1, &titleString);
-       ofn.lpstrTitle = (TCHAR *) Tcl_DStringValue(&titleString);
-    }
-
-    /*
-     * Popup the dialog.
-     */
-
-    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
-    if (oper != OFN_FILE_SAVE) {
-       winCode = GetOpenFileName(&ofn);
-    } else {
-       winCode = GetSaveFileName(&ofn);
-    }
-    Tcl_SetServiceMode(oldMode);
-    EatSpuriousMessageBugFix();
-
-    /*
-     * 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 more 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))) {
-       int gotFilename = 0;    /* Flag for tracking whether we have any
-                                * filename at all. For details, see
-                                * http://stackoverflow.com/q/9227859/301832
-                                */
-
-       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.
-            */
-
-           TCHAR *files = ofnData.dynFileBuffer;
-           Tcl_Obj *returnList = Tcl_NewObj();
-           int count = 0;
-
-           /*
-            * Get directory.
-            */
-
-           ConvertExternalFilename(files, &ds);
-
-           while (*files != '\0') {
-               while (*files != '\0') {
-                   files++;
-               }
-               files++;
-               if (*files != '\0') {
-                   Tcl_Obj *fullnameObj;
-                   Tcl_DString filenameBuf;
-
-                   count++;
-                   ConvertExternalFilename(files, &filenameBuf);
-
-                   fullnameObj = Tcl_NewStringObj(Tcl_DStringValue(&ds),
-                           Tcl_DStringLength(&ds));
-                   Tcl_AppendToObj(fullnameObj, "/", -1);
-                   Tcl_AppendToObj(fullnameObj, Tcl_DStringValue(&filenameBuf),
-                           Tcl_DStringLength(&filenameBuf));
-                   gotFilename = 1;
-                   Tcl_DStringFree(&filenameBuf);
-                   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)));
-               gotFilename |= (Tcl_DStringLength(&ds) > 0);
-           }
-           Tcl_SetObjResult(interp, returnList);
-           Tcl_DStringFree(&ds);
-       } else {
-           Tcl_SetObjResult(interp, Tcl_NewStringObj(
-                   ConvertExternalFilename(ofn.lpstrFile, &ds), -1));
-           gotFilename = (Tcl_DStringLength(&ds) > 0);
-           Tcl_DStringFree(&ds);
-       }
-       result = TCL_OK;
-       if ((ofn.nFilterIndex > 0) && gotFilename && optsPtr->typeVariableObj
-               && optsPtr->filterObj) {
-           int listObjc, count;
-           Tcl_Obj **listObjv = NULL;
-           Tcl_Obj **typeInfo = NULL;
-
-           if (Tcl_ListObjGetElements(interp, optsPtr->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 {
-                /*
-                 * BUGFIX for d43a10ce2fed950e00890049f3c273f2cdd12583
-                 * The original code was broken because it passed typeinfo[0]
-                 * directly into Tcl_ObjSetVar2. In the case of typeInfo[0]
-                 * pointing into a list which is also referenced by
-                 * typeVariableObj, TOSV2 shimmers the object into
-                 * variable intrep which loses the list representation.
-                 * This invalidates typeInfo[0] which is freed but
-                 * nevertheless stored as the value of the variable.
-                 */
-                Tcl_Obj *selFilterObj = typeInfo[0];
-                Tcl_IncrRefCount(selFilterObj);
-                if (Tcl_ObjSetVar2(interp, optsPtr->typeVariableObj, NULL,
-                                   selFilterObj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG) == NULL) {
-                    result = TCL_ERROR;
-                }
-                Tcl_DecrRefCount(selFilterObj);
-           }
-       }
-    } else if (cdlgerr == FNERR_INVALIDFILENAME) {
-       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;
-    }
-
-    if (ofn.lpstrTitle != NULL) {
-       Tcl_DStringFree(&titleString);
-    }
-    if (ofn.lpstrInitialDir != NULL) {
-        /* XXX - huh? lpstrInitialDir is set from Tcl_DStringValue which
-           can never return NULL */
-       Tcl_DStringFree(&dirString);
-    }
-    Tcl_DStringFree(&filterString);
-    if (ofn.lpstrDefExt != NULL) {
-       Tcl_DStringFree(&extString);
-    }
-
-end:
-    Tcl_DStringFree(&utfFilterString);
-    if (ofnData.dynFileBuffer != NULL) {
-       ckfree(ofnData.dynFileBuffer);
-       ofnData.dynFileBuffer = NULL;
-    }
-
-    return result;
-}
-
-\f
-/*
- *----------------------------------------------------------------------
- *
- * GetFileName --
- *
- *     Calls GetOpenFileName() or GetSaveFileName().
- *
- * Results:
- *     See user documentation.
- *
- * Side effects:
- *     See user documentation.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-GetFileName(
-    ClientData clientData,     /* Main window associated with interpreter. */
-    Tcl_Interp *interp,                /* Current interpreter. */
-    int objc,                  /* Number of arguments. */
-    Tcl_Obj *const objv[],     /* Argument objects. */
-    enum OFNOper oper)         /* 1 to call GetOpenFileName(), 0 to call
-                                * GetSaveFileName(). */
-{
-    OFNOpts ofnOpts;
-    int result;
-
-    result = ParseOFNOptions(clientData, interp, objc, objv, oper, &ofnOpts);
-    if (result != TCL_OK)
-        return result;
-
-    if (VistaFileDialogsAvailable() && ! ofnOpts.forceXPStyle)
-        result = GetFileNameVista(interp, &ofnOpts, oper);
-    else
-        result = GetFileNameXP(interp, &ofnOpts, oper);
-
-    CleanupOFNOptions(&ofnOpts);
-    return result;
-}
-
-\f
-/*
- *-------------------------------------------------------------------------
- *
- * OFNHookProc --
- *
- *     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
-OFNHookProc(
-    HWND hdlg,                 /* Handle to child dialog window. */
-    UINT uMsg,                 /* Message identifier */
-    WPARAM wParam,             /* Message parameter */
-    LPARAM lParam)             /* Message parameter */
-{
-    ThreadSpecificData *tsdPtr =
-           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
-        * 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;
-           TCHAR *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 = (int) SendMessage(hdlg, CDM_GETSPEC, 0, 0);
-           dirsize = (int) 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 * sizeof(TCHAR));
-                   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;
-                   TCHAR *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 {
-
-                       /*
-                    * Replace directory terminating NULL with a with a backslash,
-                    * but only if not an absolute path.
-                    */
-
-                   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 = (TCHAR *) ofnData->dynFileBuffer;
-                       SendMessage(hdlg, CDM_GETSPEC, selsize, (LPARAM) buffer);
-                   } else {
-                       *(buffer-1) = '\\';
-                   }
-                   buffer[selsize] = '\0'; /* Second NULL terminator. */
-                   Tcl_DStringFree(&tmpfile);
-               }
-           } 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 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) {
-               hdlg = GetParent(hdlg);
-               tsdPtr->debugInterp = ofnData->interp;
-               Tcl_DoWhenIdle(SetTkDialog, hdlg);
-           }
-           TkWinSetUserData(hdlg, NULL);
-       }
-    }
-    return 0;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * MakeFilter --
- *
- *     Allocate a buffer to store the filters in a format understood by
- *     Windows.
- *
- * Results:
- *     A standard TCL return value.
- *
- * Side effects:
- *     ofnPtr->lpstrFilter is modified.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-MakeFilter(
-    Tcl_Interp *interp,                /* Current interpreter. */
-    Tcl_Obj *valuePtr,         /* Value of the -filetypes option */
-    Tcl_DString *dsPtr,                /* Filled with windows filter string. */
-    Tcl_Obj *initialPtr,       /* Initial type name  */
-    int *indexPtr)             /* Index of initial type in filter string */
-{
-    char *filterStr;
-    char *p;
-    const char *initial = NULL;
-    int pass;
-    int ix = 0; /* index counter */
-    FileFilterList flist;
-    FileFilter *filterPtr;
-
-    if (initialPtr) {
-       initial = Tcl_GetString(initialPtr);
-    }
-    TkInitFileFilters(&flist);
-    if (TkGetFileFilters(interp, &flist, valuePtr, 1) != TCL_OK) {
-       return TCL_ERROR;
-    }
-
-    if (flist.filters == NULL) {
-       /*
-        * Use "All Files (*.*) as the default filter if none is specified
-        */
-       const char *defaultFilter = "All Files (*.*)";
-
-       p = filterStr = ckalloc(30);
-
-       strcpy(p, defaultFilter);
-       p+= strlen(defaultFilter);
-
-       *p++ = '\0';
-       *p++ = '*';
-       *p++ = '.';
-       *p++ = '*';
-       *p++ = '\0';
-       *p++ = '\0';
-       *p = '\0';
-
-    } else {
-       size_t len;
-
-       if (valuePtr == NULL) {
-           len = 0;
-       } else {
-           (void) Tcl_GetString(valuePtr);
-           len = valuePtr->length;
-       }
-
-       /*
-        * We format the filetype into a string understood by Windows: {"Text
-        * Documents" {.doc .txt} {TEXT}} becomes "Text Documents
-        * (*.doc,*.txt)\0*.doc;*.txt\0"
-        *
-        * See the Windows OPENFILENAME manual page for details on the filter
-        * string format.
-        */
-
-       /*
-        * Since we may only add asterisks (*) to the filter, we need at most
-        * twice the size of the string to format the filter
-        */
-
-       filterStr = ckalloc(len * 3);
-
-       for (filterPtr = flist.filters, p = filterStr; filterPtr;
-               filterPtr = filterPtr->next) {
-           const char *sep;
-           FileFilterClause *clausePtr;
-
-           /*
-            * Check initial index for match, set *indexPtr. Filter index is 1
-            * based so increment first
-            */
-
-           ix++;
-           if (indexPtr && initial
-                   && (strcmp(initial, filterPtr->name) == 0)) {
-               *indexPtr = ix;
-           }
-
-           /*
-            * First, put in the name of the file type.
-            */
-
-           strcpy(p, filterPtr->name);
-           p+= strlen(filterPtr->name);
-           *p++ = ' ';
-           *p++ = '(';
-
-           for (pass = 1; pass <= 2; pass++) {
-               /*
-                * In the first pass, we format the extensions in the name
-                * field. In the second pass, we format the extensions in the
-                * filter pattern field
-                */
-
-               sep = "";
-               for (clausePtr=filterPtr->clauses;clausePtr;
-                       clausePtr=clausePtr->next) {
-                   GlobPattern *globPtr;
-
-                   for (globPtr = clausePtr->patterns; globPtr;
-                           globPtr = globPtr->next) {
-                       strcpy(p, sep);
-                       p += strlen(sep);
-                       strcpy(p, globPtr->pattern);
-                       p += strlen(globPtr->pattern);
-
-                       if (pass == 1) {
-                           sep = ",";
-                       } else {
-                           sep = ";";
-                       }
-                   }
-               }
-               if (pass == 1) {
-                   *p ++ = ')';
-               }
-               *p++ = '\0';
-           }
-       }
-
-       /*
-        * Windows requires the filter string to be ended by two NULL
-        * characters.
-        */
-
-       *p++ = '\0';
-       *p = '\0';
-    }
-
-    Tcl_DStringAppend(dsPtr, filterStr, (int) (p - filterStr));
-    ckfree(filterStr);
-
-    TkFreeFileFilters(&flist);
-    return TCL_OK;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * FreeFilterVista
- *
- *      Frees storage previously allocated by MakeFilterVista.
- *      count is the number of elements in dlgFilterPtr[]
- */
-static void FreeFilterVista(DWORD count, TCLCOMDLG_FILTERSPEC *dlgFilterPtr)
-{
-    if (dlgFilterPtr != NULL) {
-        DWORD dw;
-        for (dw = 0; dw < count; ++dw) {
-            if (dlgFilterPtr[dw].pszName != NULL)
-                ckfree(dlgFilterPtr[dw].pszName);
-            if (dlgFilterPtr[dw].pszSpec != NULL)
-                ckfree(dlgFilterPtr[dw].pszSpec);
-        }
-        ckfree(dlgFilterPtr);
-    }
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * MakeFilterVista --
- *
- *     Returns file type filters in a format required
- *     by the Vista file dialogs.
- *
- * Results:
- *     A standard TCL return value.
- *
- * Side effects:
- *      Various values are returned through the parameters as
- *      described in the comments below.
- *----------------------------------------------------------------------
- */
-static int MakeFilterVista(
-    Tcl_Interp *interp,                /* Current interpreter. */
-    OFNOpts *optsPtr,           /* Caller specified options */
-    DWORD *countPtr,            /* Will hold number of filters */
-    TCLCOMDLG_FILTERSPEC **dlgFilterPtrPtr, /* Will hold pointer to filter array.
-                                         Set to NULL if no filters specified.
-                                         Must be freed by calling
-                                         FreeFilterVista */
-    DWORD *initialIndexPtr)     /* Will hold index of default type */
-{
-    TCLCOMDLG_FILTERSPEC *dlgFilterPtr;
-    const char *initial = NULL;
-    FileFilterList flist;
-    FileFilter *filterPtr;
-    DWORD initialIndex = 0;
-    Tcl_DString ds, patterns;
-    int       i;
-
-    if (optsPtr->filterObj == NULL) {
-        *dlgFilterPtrPtr = NULL;
-        *countPtr = 0;
-        return TCL_OK;
-    }
-
-    if (optsPtr->initialTypeObj)
-       initial = Tcl_GetString(optsPtr->initialTypeObj);
-
-    TkInitFileFilters(&flist);
-    if (TkGetFileFilters(interp, &flist, optsPtr->filterObj, 1) != TCL_OK)
-       return TCL_ERROR;
-
-    if (flist.filters == NULL) {
-        *dlgFilterPtrPtr = NULL;
-        *countPtr = 0;
-        return TCL_OK;
-    }
-
-    Tcl_DStringInit(&ds);
-    Tcl_DStringInit(&patterns);
-    dlgFilterPtr = ckalloc(flist.numFilters * sizeof(*dlgFilterPtr));
-
-    for (i = 0, filterPtr = flist.filters;
-         filterPtr;
-         filterPtr = filterPtr->next, ++i) {
-        const char *sep;
-        FileFilterClause *clausePtr;
-        int nbytes;
-
-        /* Check if this entry should be shown as the default */
-        if (initial && strcmp(initial, filterPtr->name) == 0)
-            initialIndex = i+1; /* Windows filter indices are 1-based */
-
-        /* First stash away the text description of the pattern */
-       Tcl_WinUtfToTChar(filterPtr->name, -1, &ds);
-        nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
-        nbytes += sizeof(WCHAR);         /* Terminating \0 */
-        dlgFilterPtr[i].pszName = ckalloc(nbytes);
-        memmove((void *) dlgFilterPtr[i].pszName, Tcl_DStringValue(&ds), nbytes);
-        Tcl_DStringFree(&ds);
-
-        /*
-         * Loop through and join patterns with a ";" Each "clause"
-         * corresponds to a single textual description (called typename)
-         * in the tk_getOpenFile docs. Each such typename may occur
-         * multiple times and all these form a single filter entry
-         * with one clause per occurence. Further each clause may specify
-         * multiple patterns. Hence the nested loop here.
-         */
-        sep = "";
-        for (clausePtr=filterPtr->clauses ; clausePtr;
-             clausePtr=clausePtr->next) {
-            GlobPattern *globPtr;
-            for (globPtr = clausePtr->patterns; globPtr;
-                 globPtr = globPtr->next) {
-                Tcl_DStringAppend(&patterns, sep, -1);
-                Tcl_DStringAppend(&patterns, globPtr->pattern, -1);
-                sep = ";";
-            }
-        }
-
-        /* Again we need a Unicode form of the string */
-       Tcl_WinUtfToTChar(Tcl_DStringValue(&patterns), -1, &ds);
-        nbytes = Tcl_DStringLength(&ds); /* # bytes, not Unicode chars */
-        nbytes += sizeof(WCHAR);         /* Terminating \0 */
-        dlgFilterPtr[i].pszSpec = ckalloc(nbytes);
-        memmove((void *)dlgFilterPtr[i].pszSpec, Tcl_DStringValue(&ds), nbytes);
-        Tcl_DStringFree(&ds);
-        Tcl_DStringFree(&patterns);
-    }
-
-    if (initialIndex == 0)
-        initialIndex = 1;       /* If no default, show first entry */
-    *initialIndexPtr = initialIndex;
-    *dlgFilterPtrPtr = dlgFilterPtr;
-    *countPtr = flist.numFilters;
-
-    TkFreeFileFilters(&flist);
-    return TCL_OK;
-}
-
-\f
-/*
- *----------------------------------------------------------------------
- *
- * Tk_ChooseDirectoryObjCmd --
- *
- *     This function implements the "tk_chooseDirectory" dialog box for the
- *     Windows platform. See the user documentation for details on what it
- *     does. Uses the newer SHBrowseForFolder explorer type interface.
- *
- * Results:
- *     See user documentation.
- *
- * Side effects:
- *     A modal dialog window is created. Tcl_SetServiceMode() is called to
- *     allow background events to be processed
- *
- *----------------------------------------------------------------------
- *
- * The function tk_chooseDirectory pops up a dialog box for the user to select
- * a directory. The following option-value pairs are possible as command line
- * arguments:
- *
- * -initialdir dirname
- *
- * Specifies that the directories in directory should be displayed when the
- * dialog pops up. If this parameter is not specified, then the directories in
- * the current working directory are displayed. If the parameter specifies a
- * relative path, the return value will convert the relative path to an
- * absolute path. This option may not always work on the Macintosh. This is
- * not a bug. Rather, the General Controls control panel on the Mac allows the
- * end user to override the application default directory.
- *
- * -parent window
- *
- * Makes window the logical parent of the dialog. The dialog is displayed on
- * top of its parent window.
- *
- * -title titleString
- *
- * Specifies a string to display as the title of the dialog box. If this
- * option is not specified, then a default title will be displayed.
- *
- * -mustexist boolean
- *
- * Specifies whether the user may specify non-existant directories. If this
- * parameter is true, then the user may only select directories that already
- * exist. The default value is false.
- *
- * New Behaviour:
- *
- * - If mustexist = 0 and a user entered folder does not exist, a prompt will
- *   pop-up asking if the user wants another chance to change it. The old
- *   dialog just returned the bogus entry. On mustexist = 1, the entries MUST
- *   exist before exiting the box with OK.
- *
- *   Bugs:
- *
- * - If valid abs directory name is entered into the entry box and Enter
- *   pressed, the box will close returning the name. This is inconsistent when
- *   entering relative names or names with forward slashes, which are
- *   invalidated then corrected in the callback. After correction, the box is
- *   held open to allow further modification by the user.
- *
- * - Not sure how to implement localization of message prompts.
- *
- * - -title is really -message.
- *
- *----------------------------------------------------------------------
- */
-
-int
-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. */
-{
-    TCHAR path[MAX_PATH];
-    int oldMode, result;
-    LPCITEMIDLIST pidl;                /* Returned by browser */
-    BROWSEINFO bInfo;          /* Used by browser */
-    ChooseDir cdCBData;            /* Structure to pass back and forth */
-    LPMALLOC pMalloc;          /* Used by shell */
-    HWND hWnd;
-    TCHAR saveDir[MAX_PATH];
-    Tcl_DString titleString;   /* Title */
-    Tcl_DString tempString;    /* temporary */
-    Tcl_Obj *objPtr;
-    OFNOpts ofnOpts;
-    const char *utfDir;
-
-    result = ParseOFNOptions(clientData, interp, objc, objv,
-                 OFN_DIR_CHOOSE, &ofnOpts);
-    if (result != TCL_OK)
-        return result;
-
-    /* Use new dialogs if available */
-    if (VistaFileDialogsAvailable() && ! ofnOpts.forceXPStyle) {
-        result = GetFileNameVista(interp, &ofnOpts, OFN_DIR_CHOOSE);
-        CleanupOFNOptions(&ofnOpts);
-        return result;
-    }
-
-    /* Older dialogs */
-
-    path[0] = '\0';
-    ZeroMemory(&cdCBData, sizeof(ChooseDir));
-    cdCBData.interp = interp;
-    cdCBData.mustExist = ofnOpts.mustExist;
-
-    utfDir = Tcl_DStringValue(&ofnOpts.utfDirString);
-    if (utfDir[0] != '\0') {
-       const TCHAR *uniStr;
-
-        Tcl_WinUtfToTChar(Tcl_DStringValue(&ofnOpts.utfDirString), -1,
-                          &tempString);
-        uniStr = (TCHAR *) Tcl_DStringValue(&tempString);
-
-        /* Convert possible relative path to full path to keep dialog happy. */
-
-        GetFullPathName(uniStr, MAX_PATH, saveDir, NULL);
-        _tcsncpy(cdCBData.initDir, saveDir, MAX_PATH);
-    }
-
-    /* XXX - rest of this (original) code has no error checks at all. */
-
-    /*
-     * Get ready to call the browser
-     */
-
-    Tk_MakeWindowExist(ofnOpts.tkwin);
-    hWnd = Tk_GetHWND(Tk_WindowId(ofnOpts.tkwin));
-
-    /*
-     * Setup the parameters used by SHBrowseForFolder
-     */
-
-    bInfo.hwndOwner = hWnd;
-    bInfo.pszDisplayName = path;
-    bInfo.pidlRoot = NULL;
-    if (_tcslen(cdCBData.initDir) == 0) {
-       GetCurrentDirectory(MAX_PATH, cdCBData.initDir);
-    }
-    bInfo.lParam = (LPARAM) &cdCBData;
-
-    if (ofnOpts.titleObj != NULL) {
-       Tcl_WinUtfToTChar(Tcl_GetString(ofnOpts.titleObj), -1, &titleString);
-       bInfo.lpszTitle = (LPTSTR) Tcl_DStringValue(&titleString);
-    } else {
-       bInfo.lpszTitle = TEXT("Please choose a directory, then select OK.");
-    }
-
-    /*
-     * Set flags to add edit box, status text line and use the new ui. Allow
-     * override with magic variable (ignore errors in retrieval). See
-     * http://msdn.microsoft.com/en-us/library/bb773205(VS.85).aspx for
-     * possible flag values.
-     */
-
-    bInfo.ulFlags = BIF_EDITBOX | BIF_STATUSTEXT | BIF_RETURNFSANCESTORS
-       | BIF_VALIDATE | BIF_NEWDIALOGSTYLE;
-    objPtr = Tcl_GetVar2Ex(interp, "::tk::winChooseDirFlags", NULL,
-           TCL_GLOBAL_ONLY);
-    if (objPtr != NULL) {
-       int flags;
-       Tcl_GetIntFromObj(NULL, objPtr, &flags);
-       bInfo.ulFlags = flags;
-    }
-
-    /*
-     * Callback to handle events
-     */
-
-    bInfo.lpfn = (BFFCALLBACK) ChooseDirectoryValidateProc;
-
-    /*
-     * Display dialog in background and process result. We look to give the
-     * user a chance to change their mind on an invalid folder if mustexist is
-     * 0.
-     */
-
-    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
-    GetCurrentDirectory(MAX_PATH, saveDir);
-    if (SHGetMalloc(&pMalloc) == NOERROR) {
-        /*
-         * XXX - MSDN says CoInitialize must have been called before
-         * SHBrowseForFolder can be used but don't see that called anywhere.
-         */
-       pidl = SHBrowseForFolder(&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]
-        */
-
-       path[0] = '\0';
-
-       /*
-        * Null for cancel button or invalid dir, otherwise valid.
-        */
-
-       if (pidl != NULL) {
-           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 (_tcslen(cdCBData.retDir) > 0) {
-           _tcscpy(path, cdCBData.retDir);
-       }
-       pMalloc->lpVtbl->Release(pMalloc);
-    }
-    SetCurrentDirectory(saveDir);
-    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);
-
-    /*
-     * Change the pathname to the Tcl "normalized" pathname, where back
-     * slashes are used instead of forward slashes
-     */
-
-    Tcl_ResetResult(interp);
-    if (*path) {
-       Tcl_DString ds;
-
-       Tcl_SetObjResult(interp, Tcl_NewStringObj(
-               ConvertExternalFilename(path, &ds), -1));
-       Tcl_DStringFree(&ds);
-    }
-
-    CleanupOFNOptions(&ofnOpts);
-    return TCL_OK;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * ChooseDirectoryValidateProc --
- *
- *     Hook function called by the explorer ChooseDirectory dialog when
- *     events occur. It is used to validate the text entry the user may have
- *     entered.
- *
- * Results:
- *     Returns 0 to allow default processing of message, or 1 to tell default
- *     dialog function not to close.
- *
- *----------------------------------------------------------------------
- */
-
-static UINT APIENTRY
-ChooseDirectoryValidateProc(
-    HWND hwnd,
-    UINT message,
-    LPARAM lParam,
-    LPARAM lpData)
-{
-    TCHAR selDir[MAX_PATH];
-    ChooseDir *chooseDirSharedData = (ChooseDir *) lpData;
-    Tcl_DString tempString;
-    Tcl_DString initDirString;
-    TCHAR string[MAX_PATH];
-    ThreadSpecificData *tsdPtr =
-           Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
-    if (tsdPtr->debugFlag) {
-       tsdPtr->debugInterp = (Tcl_Interp *) chooseDirSharedData->interp;
-       Tcl_DoWhenIdle(SetTkDialog, hwnd);
-    }
-    chooseDirSharedData->retDir[0] = '\0';
-    switch (message) {
-    case BFFM_VALIDATEFAILED:
-       /*
-        * First save and check to see if it is a valid path name, if so then
-        * make that path the one shown in the window. Otherwise, it failed
-        * the check and should be treated as such. Use
-        * Set/GetCurrentDirectory which allows relative path names and names
-        * with forward slashes. Use Tcl_TranslateFileName to make sure names
-        * like ~ are converted correctly.
-        */
-
-       Tcl_WinTCharToUtf((TCHAR *) lParam, -1, &initDirString);
-       if (Tcl_TranslateFileName(chooseDirSharedData->interp,
-               Tcl_DStringValue(&initDirString), &tempString) == NULL) {
-           /*
-            * Should we expose the error (in the interp result) to the user
-            * at this point?
-            */
-
-           chooseDirSharedData->retDir[0] = '\0';
-           return 1;
-       }
-       Tcl_DStringFree(&initDirString);
-       Tcl_WinUtfToTChar(Tcl_DStringValue(&tempString), -1, &initDirString);
-       Tcl_DStringFree(&tempString);
-       _tcsncpy(string, (TCHAR *) Tcl_DStringValue(&initDirString),
-               MAX_PATH);
-       Tcl_DStringFree(&initDirString);
-
-       if (SetCurrentDirectory(string) == 0) {
-
-           /*
-            * Get the full path name to the user entry, at this point it does
-            * not exist so see if it is supposed to. Otherwise just return
-            * it.
-            */
-
-           GetFullPathName(string, MAX_PATH,
-                   chooseDirSharedData->retDir, NULL);
-           if (chooseDirSharedData->mustExist) {
-               /*
-                * User HAS to select a valid directory.
-                */
-
-               wsprintf(selDir, TEXT("Directory '%s' does not exist,\n")
-                       TEXT("please select or enter an existing directory."),
-                       chooseDirSharedData->retDir);
-               MessageBox(NULL, selDir, NULL, MB_ICONEXCLAMATION|MB_OK);
-               chooseDirSharedData->retDir[0] = '\0';
-               return 1;
-           }
-       } else {
-           /*
-            * Changed to new folder OK, return immediatly with the current
-            * directory in utfRetDir.
-            */
-
-           GetCurrentDirectory(MAX_PATH, chooseDirSharedData->retDir);
-           return 0;
-       }
-       return 0;
-
-    case BFFM_SELCHANGED:
-       /*
-        * Set the status window to the currently selected path and enable the
-        * OK button if a file system folder, otherwise disable the OK button
-        * for things like server names. Perhaps a new switch
-        * -enablenonfolders can be used to allow non folders to be selected.
-        *
-        * Not called when user changes edit box directly.
-        */
-
-       if (SHGetPathFromIDList((LPITEMIDLIST) lParam, selDir)) {
-           SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM) selDir);
-           // enable the OK button
-           SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
-       } else {
-           // disable the OK button
-           SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 0);
-       }
-       UpdateWindow(hwnd);
-       return 1;
-
-    case BFFM_INITIALIZED: {
-       /*
-        * Directory browser intializing - tell it where to start from, user
-        * specified parameter.
-        */
-
-       TCHAR *initDir = chooseDirSharedData->initDir;
-
-       SetCurrentDirectory(initDir);
-
-       if (*initDir == '\\') {
-           /*
-            * BFFM_SETSELECTION only understands UNC paths as pidls, so
-            * convert path to pidl using IShellFolder interface.
-            */
-
-           LPMALLOC pMalloc;
-           LPSHELLFOLDER psfFolder;
-
-           if (SUCCEEDED(SHGetMalloc(&pMalloc))) {
-               if (SUCCEEDED(SHGetDesktopFolder(&psfFolder))) {
-                   LPITEMIDLIST pidlMain;
-                   ULONG ulCount, ulAttr;
-
-                   if (SUCCEEDED(psfFolder->lpVtbl->ParseDisplayName(
-                           psfFolder, hwnd, NULL, (TCHAR *)
-                           initDir, &ulCount,&pidlMain,&ulAttr))
-                           && (pidlMain != NULL)) {
-                       SendMessage(hwnd, BFFM_SETSELECTION, FALSE,
-                               (LPARAM) pidlMain);
-                       pMalloc->lpVtbl->Free(pMalloc, pidlMain);
-                   }
-                   psfFolder->lpVtbl->Release(psfFolder);
-               }
-               pMalloc->lpVtbl->Release(pMalloc);
-           }
-       } else {
-           SendMessage(hwnd, BFFM_SETSELECTION, TRUE, (LPARAM) initDir);
-       }
-       SendMessage(hwnd, BFFM_ENABLEOK, 0, (LPARAM) 1);
-       break;
-    }
-
-    }
-    return 0;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * Tk_MessageBoxObjCmd --
- *
- *     This function implements the MessageBox window for the Windows
- *     platform. See the user documentation for details on what it does.
- *
- * Results:
- *     See user documentation.
- *
- * Side effects:
- *     None. The MessageBox window will be destroy before this function
- *     returns.
- *
- *----------------------------------------------------------------------
- */
-
-int
-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. */
-{
-    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 *const optionStrings[] = {
-       "-default",     "-detail",      "-icon",        "-message",
-       "-parent",      "-title",       "-type",        NULL
-    };
-    enum options {
-       MSG_DEFAULT,    MSG_DETAIL,     MSG_ICON,       MSG_MESSAGE,
-       MSG_PARENT,     MSG_TITLE,      MSG_TYPE
-    };
-    ThreadSpecificData *tsdPtr =
-           Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
-    defaultBtn = -1;
-    detailObj = NULL;
-    icon = MB_ICONINFORMATION;
-    messageObj = NULL;
-    parent = tkwin;
-    titleObj = NULL;
-    type = MB_OK;
-
-    for (i = 1; i < objc; i += 2) {
-       int index;
-       Tcl_Obj *optionPtr, *valuePtr;
-
-       optionPtr = objv[i];
-       valuePtr = objv[i + 1];
-
-       if (Tcl_GetIndexFromObjStruct(interp, optionPtr, optionStrings,
-               sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       if (i + 1 == objc) {
-           Tcl_SetObjResult(interp, Tcl_ObjPrintf(
-                   "value for \"%s\" missing", Tcl_GetString(optionPtr)));
-           Tcl_SetErrorCode(interp, "TK", "MSGBOX", "VALUE", NULL);
-           return TCL_ERROR;
-       }
-
-       switch ((enum options) index) {
-       case MSG_DEFAULT:
-           defaultBtn = TkFindStateNumObj(interp, optionPtr, buttonMap,
-                   valuePtr);
-           if (defaultBtn < 0) {
-               return TCL_ERROR;
-           }
-           break;
-
-       case MSG_DETAIL:
-           detailObj = valuePtr;
-           break;
-
-       case MSG_ICON:
-           icon = TkFindStateNumObj(interp, optionPtr, iconMap, valuePtr);
-           if (icon < 0) {
-               return TCL_ERROR;
-           }
-           break;
-
-       case MSG_MESSAGE:
-           messageObj = valuePtr;
-           break;
-
-       case MSG_PARENT:
-           parent = Tk_NameToWindow(interp, Tcl_GetString(valuePtr), tkwin);
-           if (parent == NULL) {
-               return TCL_ERROR;
-           }
-           break;
-
-       case MSG_TITLE:
-           titleObj = valuePtr;
-           break;
-
-       case MSG_TYPE:
-           type = TkFindStateNumObj(interp, optionPtr, typeMap, valuePtr);
-           if (type < 0) {
-               return TCL_ERROR;
-           }
-           break;
-       }
-    }
-
-    while (!Tk_IsTopLevel(parent)) {
-       parent = Tk_Parent(parent);
-    }
-    Tk_MakeWindowExist(parent);
-    hWnd = Tk_GetHWND(Tk_WindowId(parent));
-
-    flags = 0;
-    if (defaultBtn >= 0) {
-       int defaultBtnIdx = -1;
-
-       for (i = 0; i < (int) NUM_TYPES; i++) {
-           if (type == allowedTypes[i].type) {
-               int j;
-
-               for (j = 0; j < 3; j++) {
-                   if (allowedTypes[i].btnIds[j] == defaultBtn) {
-                       defaultBtnIdx = j;
-                       break;
-                   }
-               }
-               if (defaultBtnIdx < 0) {
-                   Tcl_SetObjResult(interp, Tcl_ObjPrintf(
-                           "invalid default button \"%s\"",
-                           TkFindStateString(buttonMap, defaultBtn)));
-                   Tcl_SetErrorCode(interp, "TK", "MSGBOX", "DEFAULT", NULL);
-                   return TCL_ERROR;
-               }
-               break;
-           }
-       }
-       flags = buttonFlagMap[defaultBtnIdx];
-    }
-
-    flags |= icon | type | MB_TASKMODAL | MB_SETFOREGROUND;
-
-    tmpObj = messageObj ? Tcl_DuplicateObj(messageObj)
-           : Tcl_NewUnicodeObj(NULL, 0);
-    Tcl_IncrRefCount(tmpObj);
-    if (detailObj) {
-       Tcl_AppendUnicodeToObj(tmpObj, L"\n\n", 2);
-       Tcl_AppendObjToObj(tmpObj, detailObj);
-    }
-
-    oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
-
-    /*
-     * MessageBoxW exists for all platforms. Use it to allow unicode error
-     * message to be displayed correctly where possible by the OS.
-     *
-     * In order to have the parent window icon reflected in a MessageBox, we
-     * have to create a hook that will trigger when the MessageBox is being
-     * created.
-     */
-
-    tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL);
-    tsdPtr->hBigIcon   = TkWinGetIcon(parent, ICON_BIG);
-    tsdPtr->hMsgBoxHook = SetWindowsHookEx(WH_CBT, MsgBoxCBTProc, NULL,
-           GetCurrentThreadId());
-    winCode = MessageBox(hWnd, Tcl_GetUnicode(tmpObj),
-           titleObj ? Tcl_GetUnicode(titleObj) : L"", flags);
-    UnhookWindowsHookEx(tsdPtr->hMsgBoxHook);
-    (void) 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);
-
-    Tcl_DecrRefCount(tmpObj);
-    Tcl_SetObjResult(interp, Tcl_NewStringObj(
-           TkFindStateString(buttonMap, winCode), -1));
-    return TCL_OK;
-}
-\f
-static LRESULT CALLBACK
-MsgBoxCBTProc(
-    int nCode,
-    WPARAM wParam,
-    LPARAM lParam)
-{
-    ThreadSpecificData *tsdPtr =
-           Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-
-    if (nCode == HCBT_CREATEWND) {
-       /*
-        * Window owned by our task is being created. Since the hook is
-        * installed just before the MessageBox call and removed after the
-        * MessageBox call, the window being created is either the message box
-        * or one of its controls. Check that the class is WC_DIALOG to ensure
-        * that it's the one we want.
-        */
-
-       LPCBT_CREATEWND lpcbtcreate = (LPCBT_CREATEWND) lParam;
-
-       if (WC_DIALOG == lpcbtcreate->lpcs->lpszClass) {
-           HWND hwnd = (HWND) wParam;
-
-           SendMessage(hwnd, WM_SETICON, ICON_SMALL,
-                   (LPARAM) tsdPtr->hSmallIcon);
-           SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) tsdPtr->hBigIcon);
-       }
-    }
-
-    /*
-     * Call the next hook proc, if there is one
-     */
-
-    return CallNextHookEx(tsdPtr->hMsgBoxHook, nCode, wParam, lParam);
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * SetTkDialog --
- *
- *     Records the HWND for a native dialog in the 'tk_dialog' variable so
- *     that the test-suite can operate on the correct dialog window. Use of
- *     this is enabled when a test program calls TkWinDialogDebug by calling
- *     the test command 'tkwinevent debug 1'.
- *
- * ----------------------------------------------------------------------
- */
-
-static void
-SetTkDialog(
-    ClientData clientData)
-{
-    ThreadSpecificData *tsdPtr =
-           Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
-    char buf[32];
-
-    sprintf(buf, "0x%p", (HWND) clientData);
-    Tcl_SetVar2(tsdPtr->debugInterp, "tk_dialog", NULL, buf, TCL_GLOBAL_ONLY);
-}
-\f
-/*
- * Factored out a common pattern in use in this file.
- */
-
-static const char *
-ConvertExternalFilename(
-    TCHAR *filename,
-    Tcl_DString *dsPtr)
-{
-    char *p;
-
-    Tcl_WinTCharToUtf(filename, -1, dsPtr);
-    for (p = Tcl_DStringValue(dsPtr); *p != '\0'; p++) {
-       /*
-        * Change the pathname to the Tcl "normalized" pathname, where back
-        * slashes are used instead of forward slashes
-        */
-
-       if (*p == '\\') {
-           *p = '/';
-       }
-    }
-    return Tcl_DStringValue(dsPtr);
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * 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;
-}
-\f
-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);
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * 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 */
-}
-\f
-/*
- * 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;
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * 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;
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * 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;
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * 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;
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * 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);
-}
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * 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;
-}
-\f
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */