-/*\r
- * COMMDLG - File Dialogs\r
- *\r
- * Copyright 1994 Martin Ayotte\r
- * Copyright 1996 Albrecht Kleine\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- */\r
-#include <stdarg.h>\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "wine/winbase16.h"\r
-#include "winuser.h"\r
-#include "wine/winuser16.h"\r
-#include "wine/debug.h"\r
-#include "cderr.h"\r
-#include "commdlg.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(commdlg);\r
-\r
-#include "cdlg.h"\r
-#include "cdlg16.h"\r
-#include "filedlg31.h"\r
-\r
-typedef struct tagFD16_PRIVATE\r
-{\r
- HANDLE16 hDlgTmpl16; /* handle for resource 16 */\r
- HANDLE16 hResource16; /* handle for allocated resource 16 */\r
- HANDLE16 hGlobal16; /* 16 bits mem block (resources) */\r
- OPENFILENAME16 *ofn16; /* original structure if 16 bits dialog */\r
-} FD16_PRIVATE, *PFD16_PRIVATE;\r
-\r
-/************************************************************************\r
- * FD16_MapOfnStruct16 [internal]\r
- * map a 16 bits structure to an Unicode one\r
- */\r
-void FD16_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)\r
-{\r
- OPENFILENAMEA ofnA;\r
- /* first convert to linear pointers */\r
- memset(&ofnA, 0, sizeof(OPENFILENAMEA));\r
- ofnA.lStructSize = sizeof(OPENFILENAMEA);\r
- ofnA.hwndOwner = HWND_32(ofn16->hwndOwner);\r
- ofnA.hInstance = HINSTANCE_32(ofn16->hInstance);\r
- if (ofn16->lpstrFilter)\r
- ofnA.lpstrFilter = MapSL(ofn16->lpstrFilter);\r
- if (ofn16->lpstrCustomFilter)\r
- ofnA.lpstrCustomFilter = MapSL(ofn16->lpstrCustomFilter);\r
- ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;\r
- ofnA.nFilterIndex = ofn16->nFilterIndex;\r
- ofnA.lpstrFile = MapSL(ofn16->lpstrFile);\r
- ofnA.nMaxFile = ofn16->nMaxFile;\r
- ofnA.lpstrFileTitle = MapSL(ofn16->lpstrFileTitle);\r
- ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;\r
- ofnA.lpstrInitialDir = MapSL(ofn16->lpstrInitialDir);\r
- ofnA.lpstrTitle = MapSL(ofn16->lpstrTitle);\r
- ofnA.Flags = ofn16->Flags;\r
- ofnA.nFileOffset = ofn16->nFileOffset;\r
- ofnA.nFileExtension = ofn16->nFileExtension;\r
- ofnA.lpstrDefExt = MapSL(ofn16->lpstrDefExt);\r
- if (HIWORD(ofn16->lpTemplateName))\r
- ofnA.lpTemplateName = MapSL(ofn16->lpTemplateName);\r
- else\r
- ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */\r
- /* now calls the 32 bits Ansi to Unicode version to complete the job */\r
- FD31_MapOfnStructA(&ofnA, ofnW, open);\r
-}\r
-\r
-/***********************************************************************\r
- * FD16_GetTemplate [internal]\r
- *\r
- * Get a template (FALSE if failure) when 16 bits dialogs are used\r
- * by a 16 bits application\r
- *\r
- */\r
-BOOL FD16_GetTemplate(PFD31_DATA lfs)\r
-{\r
- PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;\r
- LPOPENFILENAME16 ofn16 = priv->ofn16;\r
- LPCVOID template;\r
- HGLOBAL16 hGlobal16 = 0;\r
-\r
- if (ofn16->Flags & OFN_ENABLETEMPLATEHANDLE)\r
- priv->hDlgTmpl16 = ofn16->hInstance;\r
- else if (ofn16->Flags & OFN_ENABLETEMPLATE)\r
- {\r
- HANDLE16 hResInfo;\r
- if (!(hResInfo = FindResource16(ofn16->hInstance,\r
- MapSL(ofn16->lpTemplateName),\r
- (LPSTR)RT_DIALOG)))\r
- {\r
- COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);\r
- return FALSE;\r
- }\r
- if (!(priv->hDlgTmpl16 = LoadResource16( ofn16->hInstance, hResInfo )))\r
- {\r
- COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);\r
- return FALSE;\r
- }\r
- priv->hResource16 = priv->hDlgTmpl16;\r
- }\r
- else\r
- { /* get resource from (32 bits) own Wine resource; convert it to 16 */\r
- HRSRC hResInfo;\r
- HGLOBAL hDlgTmpl32;\r
- LPCVOID template32;\r
- DWORD size;\r
-\r
- if (!(hResInfo = FindResourceA(COMDLG32_hInstance,\r
- lfs->open ? "OPEN_FILE":"SAVE_FILE", (LPSTR)RT_DIALOG)))\r
- {\r
- COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);\r
- return FALSE;\r
- }\r
- if (!(hDlgTmpl32 = LoadResource(COMDLG32_hInstance, hResInfo )) ||\r
- !(template32 = LockResource( hDlgTmpl32 )))\r
- {\r
- COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);\r
- return FALSE;\r
- }\r
- size = SizeofResource(COMDLG32_hInstance, hResInfo);\r
- hGlobal16 = GlobalAlloc16(0, size);\r
- if (!hGlobal16)\r
- {\r
- COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);\r
- ERR("alloc failure for %ld bytes\n", size);\r
- return FALSE;\r
- }\r
- template = GlobalLock16(hGlobal16);\r
- if (!template)\r
- {\r
- COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);\r
- ERR("global lock failure for %x handle\n", hGlobal16);\r
- GlobalFree16(hGlobal16);\r
- return FALSE;\r
- }\r
- ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);\r
- priv->hDlgTmpl16 = hGlobal16;\r
- priv->hGlobal16 = hGlobal16;\r
- }\r
- return TRUE;\r
-}\r
-\r
-/************************************************************************\r
- * FD16_Init [internal]\r
- * called from the common 16/32 code to initialize 16 bit data\r
- */\r
-static BOOL CALLBACK FD16_Init(LPARAM lParam, PFD31_DATA lfs, DWORD data)\r
-{\r
- PFD16_PRIVATE priv;\r
-\r
- priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FD16_PRIVATE));\r
- lfs->private1632 = priv;\r
- if (NULL == lfs->private1632) return FALSE;\r
-\r
- priv->ofn16 = MapSL(lParam);\r
- if (priv->ofn16->Flags & OFN_ENABLEHOOK)\r
- if (priv->ofn16->lpfnHook)\r
- lfs->hook = TRUE;\r
-\r
- lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW));\r
- FD16_MapOfnStruct16(priv->ofn16, lfs->ofnW, lfs->open);\r
-\r
- if (! FD16_GetTemplate(lfs)) return FALSE;\r
-\r
- return TRUE;\r
-}\r
-\r
-/***********************************************************************\r
- * FD16_CallWindowProc [internal]\r
- *\r
- * called from the common 16/32 code to call the appropriate hook\r
- */\r
-BOOL CALLBACK FD16_CallWindowProc(PFD31_DATA lfs, UINT wMsg, WPARAM wParam,\r
- LPARAM lParam)\r
-{\r
- PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;\r
-\r
- if (priv->ofn16)\r
- {\r
- return (BOOL16) CallWindowProc16(\r
- (WNDPROC16)priv->ofn16->lpfnHook, HWND_16(lfs->hwnd),\r
- (UINT16)wMsg, (WPARAM16)wParam, lParam);\r
- }\r
- return FALSE;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * FD31_UpdateResult [internal]\r
- * update the real client structures\r
- */\r
-static void CALLBACK FD16_UpdateResult(PFD31_DATA lfs)\r
-{\r
- PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;\r
- LPOPENFILENAMEW ofnW = lfs->ofnW;\r
-\r
- if (priv->ofn16)\r
- { /* we have to convert to short (8.3) path */\r
- char tmp[1024]; /* MAX_PATHNAME_LEN */\r
- LPOPENFILENAME16 ofn16 = priv->ofn16;\r
- char *dest = MapSL(ofn16->lpstrFile);\r
- char *bs16;\r
- if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,\r
- tmp, sizeof(tmp), NULL, NULL ))\r
- tmp[sizeof(tmp)-1] = 0;\r
- GetShortPathNameA(tmp, dest, ofn16->nMaxFile);\r
-\r
- /* the same procedure as every year... */\r
- if((bs16 = strrchr(dest, '\\')) != NULL)\r
- ofn16->nFileOffset = bs16 - dest +1;\r
- else\r
- ofn16->nFileOffset = 0;\r
- ofn16->nFileExtension = 0;\r
- while(dest[ofn16->nFileExtension] != '.' && dest[ofn16->nFileExtension] != '\0')\r
- ofn16->nFileExtension++;\r
- if (dest[ofn16->nFileExtension] == '\0')\r
- ofn16->nFileExtension = 0;\r
- else\r
- ofn16->nFileExtension++;\r
- }\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * FD16_UpdateFileTitle [internal]\r
- * update the real client structures\r
- */\r
-static void CALLBACK FD16_UpdateFileTitle(PFD31_DATA lfs)\r
-{\r
- PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;\r
- LPOPENFILENAMEW ofnW = lfs->ofnW;\r
-\r
- if (priv->ofn16)\r
- {\r
- char *dest = MapSL(priv->ofn16->lpstrFileTitle);\r
- if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,\r
- dest, ofnW->nMaxFileTitle, NULL, NULL ))\r
- dest[ofnW->nMaxFileTitle-1] = 0;\r
- }\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * FD16_SendLbGetCurSel [internal]\r
- * retrieve selected listbox item\r
- */\r
-static LRESULT CALLBACK FD16_SendLbGetCurSel(PFD31_DATA lfs)\r
-{\r
- return SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL16, 0, 0);\r
-}\r
-\r
-\r
-/************************************************************************\r
- * FD16_Destroy [internal]\r
- * called from the common 16/32 code to cleanup 32 bit data\r
- */\r
-static void CALLBACK FD16_Destroy(PFD31_DATA lfs)\r
-{\r
- PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;\r
-\r
- /* free resources for a 16 bits dialog */\r
- if (NULL != priv)\r
- {\r
- if (priv->hResource16) FreeResource16(priv->hResource16);\r
- if (priv->hGlobal16)\r
- {\r
- GlobalUnlock16(priv->hGlobal16);\r
- GlobalFree16(priv->hGlobal16);\r
- }\r
- FD31_FreeOfnW(lfs->ofnW);\r
- HeapFree(GetProcessHeap(), 0, lfs->ofnW);\r
- }\r
-}\r
-\r
-static void FD16_SetupCallbacks(PFD31_CALLBACKS callbacks)\r
-{\r
- callbacks->Init = FD16_Init;\r
- callbacks->CWP = FD16_CallWindowProc;\r
- callbacks->UpdateResult = FD16_UpdateResult;\r
- callbacks->UpdateFileTitle = FD16_UpdateFileTitle;\r
- callbacks->SendLbGetCurSel = FD16_SendLbGetCurSel;\r
- callbacks->Destroy = FD16_Destroy;\r
-}\r
-\r
-/***********************************************************************\r
- * FD16_MapDrawItemStruct [internal]\r
- * map a 16 bits drawitem struct to 32\r
- */\r
-static void FD16_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)\r
-{\r
- lpdis->CtlType = lpdis16->CtlType;\r
- lpdis->CtlID = lpdis16->CtlID;\r
- lpdis->itemID = lpdis16->itemID;\r
- lpdis->itemAction = lpdis16->itemAction;\r
- lpdis->itemState = lpdis16->itemState;\r
- lpdis->hwndItem = HWND_32(lpdis16->hwndItem);\r
- lpdis->hDC = HDC_32(lpdis16->hDC);\r
- lpdis->rcItem.right = lpdis16->rcItem.right;\r
- lpdis->rcItem.left = lpdis16->rcItem.left;\r
- lpdis->rcItem.top = lpdis16->rcItem.top;\r
- lpdis->rcItem.bottom = lpdis16->rcItem.bottom;\r
- lpdis->itemData = lpdis16->itemData;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * FD16_WMMeasureItem16 [internal]\r
- */\r
-static LONG FD16_WMMeasureItem(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)\r
-{\r
- LPMEASUREITEMSTRUCT16 lpmeasure;\r
-\r
- lpmeasure = MapSL(lParam);\r
- lpmeasure->itemHeight = FD31_GetFldrHeight();\r
- return TRUE;\r
-}\r
-\r
-/* ------------------ Dialog procedures ---------------------- */\r
-\r
-/***********************************************************************\r
- * FileOpenDlgProc (COMMDLG.6)\r
- */\r
-BOOL16 CALLBACK FileOpenDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam, LPARAM lParam)\r
-{\r
- HWND hWnd = HWND_32(hWnd16);\r
- PFD31_DATA lfs = (PFD31_DATA)GetPropA(hWnd,FD31_OFN_PROP);\r
- DRAWITEMSTRUCT dis;\r
-\r
- TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);\r
- if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)\r
- {\r
- LRESULT lRet = (BOOL16)FD31_CallWindowProc(lfs, wMsg, wParam, lParam);\r
- if (lRet)\r
- return lRet; /* else continue message processing */\r
- }\r
- switch (wMsg)\r
- {\r
- case WM_INITDIALOG:\r
- return FD31_WMInitDialog(hWnd, wParam, lParam);\r
-\r
- case WM_MEASUREITEM:\r
- return FD16_WMMeasureItem(hWnd16, wParam, lParam);\r
-\r
- case WM_DRAWITEM:\r
- FD16_MapDrawItemStruct(MapSL(lParam), &dis);\r
- return FD31_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);\r
-\r
- case WM_COMMAND:\r
- return FD31_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);\r
-#if 0\r
- case WM_CTLCOLOR:\r
- SetBkColor((HDC16)wParam, 0x00C0C0C0);\r
- switch (HIWORD(lParam))\r
- {\r
- case CTLCOLOR_BTN:\r
- SetTextColor((HDC16)wParam, 0x00000000);\r
- return hGRAYBrush;\r
- case CTLCOLOR_STATIC:\r
- SetTextColor((HDC16)wParam, 0x00000000);\r
- return hGRAYBrush;\r
- }\r
- break;\r
-#endif\r
- }\r
- return FALSE;\r
-}\r
-\r
-/***********************************************************************\r
- * FileSaveDlgProc (COMMDLG.7)\r
- */\r
-BOOL16 CALLBACK FileSaveDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam, LPARAM lParam)\r
-{\r
- HWND hWnd = HWND_32(hWnd16);\r
- PFD31_DATA lfs = (PFD31_DATA)GetPropA(hWnd,FD31_OFN_PROP);\r
- DRAWITEMSTRUCT dis;\r
-\r
- TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);\r
- if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)\r
- {\r
- LRESULT lRet;\r
- lRet = (BOOL16)FD31_CallWindowProc(lfs, wMsg, wParam, lParam);\r
- if (lRet)\r
- return lRet; /* else continue message processing */\r
- }\r
- switch (wMsg) {\r
- case WM_INITDIALOG:\r
- return FD31_WMInitDialog(hWnd, wParam, lParam);\r
-\r
- case WM_MEASUREITEM:\r
- return FD16_WMMeasureItem(hWnd16, wParam, lParam);\r
-\r
- case WM_DRAWITEM:\r
- FD16_MapDrawItemStruct(MapSL(lParam), &dis);\r
- return FD31_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);\r
-\r
- case WM_COMMAND:\r
- return FD31_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);\r
- }\r
-\r
- /*\r
- case WM_CTLCOLOR:\r
- SetBkColor((HDC16)wParam, 0x00C0C0C0);\r
- switch (HIWORD(lParam))\r
- {\r
- case CTLCOLOR_BTN:\r
- SetTextColor((HDC16)wParam, 0x00000000);\r
- return hGRAYBrush;\r
- case CTLCOLOR_STATIC:\r
- SetTextColor((HDC16)wParam, 0x00000000);\r
- return hGRAYBrush;\r
- }\r
- return FALSE;\r
-\r
- */\r
- return FALSE;\r
-}\r
-\r
-/* ------------------ APIs ---------------------- */\r
-\r
-/***********************************************************************\r
- * GetOpenFileName (COMMDLG.1)\r
- *\r
- * Creates a dialog box for the user to select a file to open.\r
- *\r
- * RETURNS\r
- * TRUE on success: user selected a valid file\r
- * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.\r
- *\r
- * BUGS\r
- * unknown, there are some FIXME's left.\r
- */\r
-BOOL16 WINAPI GetOpenFileName16(\r
- SEGPTR ofn /* [in/out] address of structure with data*/\r
- )\r
-{\r
- HINSTANCE16 hInst;\r
- BOOL bRet = FALSE;\r
- LPOPENFILENAME16 lpofn = MapSL(ofn);\r
- PFD31_DATA lfs;\r
- FARPROC16 ptr;\r
- FD31_CALLBACKS callbacks;\r
- PFD16_PRIVATE priv;\r
-\r
- if (!lpofn || !FD31_Init()) return FALSE;\r
-\r
- FD16_SetupCallbacks(&callbacks);\r
- lfs = FD31_AllocPrivate((LPARAM) ofn, OPEN_DIALOG, &callbacks, 0);\r
- if (lfs)\r
- {\r
- priv = (PFD16_PRIVATE) lfs->private1632;\r
- hInst = GetWindowLongPtrA( HWND_32(lpofn->hwndOwner), GWLP_HINSTANCE );\r
- ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);\r
- bRet = DialogBoxIndirectParam16( hInst, priv->hDlgTmpl16, lpofn->hwndOwner,\r
- (DLGPROC16) ptr, (LPARAM) lfs);\r
- FD31_DestroyPrivate(lfs);\r
- }\r
-\r
- TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));\r
- return bRet;\r
-}\r
-\r
-/***********************************************************************\r
- * GetSaveFileName (COMMDLG.2)\r
- *\r
- * Creates a dialog box for the user to select a file to save.\r
- *\r
- * RETURNS\r
- * TRUE on success: user enters a valid file\r
- * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.\r
- *\r
- * BUGS\r
- * unknown. There are some FIXME's left.\r
- */\r
-BOOL16 WINAPI GetSaveFileName16(\r
- SEGPTR ofn /* [in/out] addess of structure with data*/\r
- )\r
-{\r
- HINSTANCE16 hInst;\r
- BOOL bRet = FALSE;\r
- LPOPENFILENAME16 lpofn = MapSL(ofn);\r
- PFD31_DATA lfs;\r
- FARPROC16 ptr;\r
- FD31_CALLBACKS callbacks;\r
- PFD16_PRIVATE priv;\r
-\r
- if (!lpofn || !FD31_Init()) return FALSE;\r
-\r
- FD16_SetupCallbacks(&callbacks);\r
- lfs = FD31_AllocPrivate((LPARAM) ofn, SAVE_DIALOG, &callbacks, 0);\r
- if (lfs)\r
- {\r
- priv = (PFD16_PRIVATE) lfs->private1632;\r
- hInst = GetWindowLongPtrA( HWND_32(lpofn->hwndOwner), GWLP_HINSTANCE );\r
- ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);\r
- bRet = DialogBoxIndirectParam16( hInst, priv->hDlgTmpl16, lpofn->hwndOwner,\r
- (DLGPROC16) ptr, (LPARAM) lfs);\r
- FD31_DestroyPrivate(lfs);\r
- }\r
-\r
- TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));\r
- return bRet;\r
-}\r
+/*
+ * COMMDLG - File Dialogs
+ *
+ * Copyright 1994 Martin Ayotte
+ * Copyright 1996 Albrecht Kleine
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "wine/winbase16.h"
+#include "winuser.h"
+#include "wine/winuser16.h"
+#include "wine/debug.h"
+#include "cderr.h"
+#include "commdlg.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
+
+#include "cdlg.h"
+#include "cdlg16.h"
+#include "filedlg31.h"
+
+typedef struct tagFD16_PRIVATE
+{
+ HANDLE16 hDlgTmpl16; /* handle for resource 16 */
+ HANDLE16 hResource16; /* handle for allocated resource 16 */
+ HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
+ OPENFILENAME16 *ofn16; /* original structure if 16 bits dialog */
+} FD16_PRIVATE, *PFD16_PRIVATE;
+
+/************************************************************************
+ * FD16_MapOfnStruct16 [internal]
+ * map a 16 bits structure to an Unicode one
+ */
+void FD16_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)
+{
+ OPENFILENAMEA ofnA;
+ /* first convert to linear pointers */
+ memset(&ofnA, 0, sizeof(OPENFILENAMEA));
+ ofnA.lStructSize = sizeof(OPENFILENAMEA);
+ ofnA.hwndOwner = HWND_32(ofn16->hwndOwner);
+ ofnA.hInstance = HINSTANCE_32(ofn16->hInstance);
+ if (ofn16->lpstrFilter)
+ ofnA.lpstrFilter = MapSL(ofn16->lpstrFilter);
+ if (ofn16->lpstrCustomFilter)
+ ofnA.lpstrCustomFilter = MapSL(ofn16->lpstrCustomFilter);
+ ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;
+ ofnA.nFilterIndex = ofn16->nFilterIndex;
+ ofnA.lpstrFile = MapSL(ofn16->lpstrFile);
+ ofnA.nMaxFile = ofn16->nMaxFile;
+ ofnA.lpstrFileTitle = MapSL(ofn16->lpstrFileTitle);
+ ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;
+ ofnA.lpstrInitialDir = MapSL(ofn16->lpstrInitialDir);
+ ofnA.lpstrTitle = MapSL(ofn16->lpstrTitle);
+ ofnA.Flags = ofn16->Flags;
+ ofnA.nFileOffset = ofn16->nFileOffset;
+ ofnA.nFileExtension = ofn16->nFileExtension;
+ ofnA.lpstrDefExt = MapSL(ofn16->lpstrDefExt);
+ if (HIWORD(ofn16->lpTemplateName))
+ ofnA.lpTemplateName = MapSL(ofn16->lpTemplateName);
+ else
+ ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */
+ /* now calls the 32 bits Ansi to Unicode version to complete the job */
+ FD31_MapOfnStructA(&ofnA, ofnW, open);
+}
+
+/***********************************************************************
+ * FD16_GetTemplate [internal]
+ *
+ * Get a template (FALSE if failure) when 16 bits dialogs are used
+ * by a 16 bits application
+ *
+ */
+BOOL FD16_GetTemplate(PFD31_DATA lfs)
+{
+ PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;
+ LPOPENFILENAME16 ofn16 = priv->ofn16;
+ LPCVOID template;
+ HGLOBAL16 hGlobal16 = 0;
+
+ if (ofn16->Flags & OFN_ENABLETEMPLATEHANDLE)
+ priv->hDlgTmpl16 = ofn16->hInstance;
+ else if (ofn16->Flags & OFN_ENABLETEMPLATE)
+ {
+ HANDLE16 hResInfo;
+ if (!(hResInfo = FindResource16(ofn16->hInstance,
+ MapSL(ofn16->lpTemplateName),
+ (LPSTR)RT_DIALOG)))
+ {
+ COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
+ return FALSE;
+ }
+ if (!(priv->hDlgTmpl16 = LoadResource16( ofn16->hInstance, hResInfo )))
+ {
+ COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
+ return FALSE;
+ }
+ priv->hResource16 = priv->hDlgTmpl16;
+ }
+ else
+ { /* get resource from (32 bits) own Wine resource; convert it to 16 */
+ HRSRC hResInfo;
+ HGLOBAL hDlgTmpl32;
+ LPCVOID template32;
+ DWORD size;
+
+ if (!(hResInfo = FindResourceA(COMDLG32_hInstance,
+ lfs->open ? "OPEN_FILE":"SAVE_FILE", (LPSTR)RT_DIALOG)))
+ {
+ COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
+ return FALSE;
+ }
+ if (!(hDlgTmpl32 = LoadResource(COMDLG32_hInstance, hResInfo )) ||
+ !(template32 = LockResource( hDlgTmpl32 )))
+ {
+ COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
+ return FALSE;
+ }
+ size = SizeofResource(COMDLG32_hInstance, hResInfo);
+ hGlobal16 = GlobalAlloc16(0, size);
+ if (!hGlobal16)
+ {
+ COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
+ ERR("alloc failure for %ld bytes\n", size);
+ return FALSE;
+ }
+ template = GlobalLock16(hGlobal16);
+ if (!template)
+ {
+ COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
+ ERR("global lock failure for %x handle\n", hGlobal16);
+ GlobalFree16(hGlobal16);
+ return FALSE;
+ }
+ ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
+ priv->hDlgTmpl16 = hGlobal16;
+ priv->hGlobal16 = hGlobal16;
+ }
+ return TRUE;
+}
+
+/************************************************************************
+ * FD16_Init [internal]
+ * called from the common 16/32 code to initialize 16 bit data
+ */
+static BOOL CALLBACK FD16_Init(LPARAM lParam, PFD31_DATA lfs, DWORD data)
+{
+ PFD16_PRIVATE priv;
+
+ priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FD16_PRIVATE));
+ lfs->private1632 = priv;
+ if (NULL == lfs->private1632) return FALSE;
+
+ priv->ofn16 = MapSL(lParam);
+ if (priv->ofn16->Flags & OFN_ENABLEHOOK)
+ if (priv->ofn16->lpfnHook)
+ lfs->hook = TRUE;
+
+ lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW));
+ FD16_MapOfnStruct16(priv->ofn16, lfs->ofnW, lfs->open);
+
+ if (! FD16_GetTemplate(lfs)) return FALSE;
+
+ return TRUE;
+}
+
+/***********************************************************************
+ * FD16_CallWindowProc [internal]
+ *
+ * called from the common 16/32 code to call the appropriate hook
+ */
+BOOL CALLBACK FD16_CallWindowProc(PFD31_DATA lfs, UINT wMsg, WPARAM wParam,
+ LPARAM lParam)
+{
+ PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;
+
+ if (priv->ofn16)
+ {
+ return (BOOL16) CallWindowProc16(
+ (WNDPROC16)priv->ofn16->lpfnHook, HWND_16(lfs->hwnd),
+ (UINT16)wMsg, (WPARAM16)wParam, lParam);
+ }
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * FD31_UpdateResult [internal]
+ * update the real client structures
+ */
+static void CALLBACK FD16_UpdateResult(PFD31_DATA lfs)
+{
+ PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;
+ LPOPENFILENAMEW ofnW = lfs->ofnW;
+
+ if (priv->ofn16)
+ { /* we have to convert to short (8.3) path */
+ char tmp[1024]; /* MAX_PATHNAME_LEN */
+ LPOPENFILENAME16 ofn16 = priv->ofn16;
+ char *dest = MapSL(ofn16->lpstrFile);
+ char *bs16;
+ if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
+ tmp, sizeof(tmp), NULL, NULL ))
+ tmp[sizeof(tmp)-1] = 0;
+ GetShortPathNameA(tmp, dest, ofn16->nMaxFile);
+
+ /* the same procedure as every year... */
+ if((bs16 = strrchr(dest, '\\')) != NULL)
+ ofn16->nFileOffset = bs16 - dest +1;
+ else
+ ofn16->nFileOffset = 0;
+ ofn16->nFileExtension = 0;
+ while(dest[ofn16->nFileExtension] != '.' && dest[ofn16->nFileExtension] != '\0')
+ ofn16->nFileExtension++;
+ if (dest[ofn16->nFileExtension] == '\0')
+ ofn16->nFileExtension = 0;
+ else
+ ofn16->nFileExtension++;
+ }
+}
+
+
+/***********************************************************************
+ * FD16_UpdateFileTitle [internal]
+ * update the real client structures
+ */
+static void CALLBACK FD16_UpdateFileTitle(PFD31_DATA lfs)
+{
+ PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;
+ LPOPENFILENAMEW ofnW = lfs->ofnW;
+
+ if (priv->ofn16)
+ {
+ char *dest = MapSL(priv->ofn16->lpstrFileTitle);
+ if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
+ dest, ofnW->nMaxFileTitle, NULL, NULL ))
+ dest[ofnW->nMaxFileTitle-1] = 0;
+ }
+}
+
+
+/***********************************************************************
+ * FD16_SendLbGetCurSel [internal]
+ * retrieve selected listbox item
+ */
+static LRESULT CALLBACK FD16_SendLbGetCurSel(PFD31_DATA lfs)
+{
+ return SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL16, 0, 0);
+}
+
+
+/************************************************************************
+ * FD16_Destroy [internal]
+ * called from the common 16/32 code to cleanup 32 bit data
+ */
+static void CALLBACK FD16_Destroy(PFD31_DATA lfs)
+{
+ PFD16_PRIVATE priv = (PFD16_PRIVATE) lfs->private1632;
+
+ /* free resources for a 16 bits dialog */
+ if (NULL != priv)
+ {
+ if (priv->hResource16) FreeResource16(priv->hResource16);
+ if (priv->hGlobal16)
+ {
+ GlobalUnlock16(priv->hGlobal16);
+ GlobalFree16(priv->hGlobal16);
+ }
+ FD31_FreeOfnW(lfs->ofnW);
+ HeapFree(GetProcessHeap(), 0, lfs->ofnW);
+ }
+}
+
+static void FD16_SetupCallbacks(PFD31_CALLBACKS callbacks)
+{
+ callbacks->Init = FD16_Init;
+ callbacks->CWP = FD16_CallWindowProc;
+ callbacks->UpdateResult = FD16_UpdateResult;
+ callbacks->UpdateFileTitle = FD16_UpdateFileTitle;
+ callbacks->SendLbGetCurSel = FD16_SendLbGetCurSel;
+ callbacks->Destroy = FD16_Destroy;
+}
+
+/***********************************************************************
+ * FD16_MapDrawItemStruct [internal]
+ * map a 16 bits drawitem struct to 32
+ */
+static void FD16_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)
+{
+ lpdis->CtlType = lpdis16->CtlType;
+ lpdis->CtlID = lpdis16->CtlID;
+ lpdis->itemID = lpdis16->itemID;
+ lpdis->itemAction = lpdis16->itemAction;
+ lpdis->itemState = lpdis16->itemState;
+ lpdis->hwndItem = HWND_32(lpdis16->hwndItem);
+ lpdis->hDC = HDC_32(lpdis16->hDC);
+ lpdis->rcItem.right = lpdis16->rcItem.right;
+ lpdis->rcItem.left = lpdis16->rcItem.left;
+ lpdis->rcItem.top = lpdis16->rcItem.top;
+ lpdis->rcItem.bottom = lpdis16->rcItem.bottom;
+ lpdis->itemData = lpdis16->itemData;
+}
+
+
+/***********************************************************************
+ * FD16_WMMeasureItem16 [internal]
+ */
+static LONG FD16_WMMeasureItem(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
+{
+ LPMEASUREITEMSTRUCT16 lpmeasure;
+
+ lpmeasure = MapSL(lParam);
+ lpmeasure->itemHeight = FD31_GetFldrHeight();
+ return TRUE;
+}
+
+/* ------------------ Dialog procedures ---------------------- */
+
+/***********************************************************************
+ * FileOpenDlgProc (COMMDLG.6)
+ */
+BOOL16 CALLBACK FileOpenDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam, LPARAM lParam)
+{
+ HWND hWnd = HWND_32(hWnd16);
+ PFD31_DATA lfs = (PFD31_DATA)GetPropA(hWnd,FD31_OFN_PROP);
+ DRAWITEMSTRUCT dis;
+
+ TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
+ if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
+ {
+ LRESULT lRet = (BOOL16)FD31_CallWindowProc(lfs, wMsg, wParam, lParam);
+ if (lRet)
+ return lRet; /* else continue message processing */
+ }
+ switch (wMsg)
+ {
+ case WM_INITDIALOG:
+ return FD31_WMInitDialog(hWnd, wParam, lParam);
+
+ case WM_MEASUREITEM:
+ return FD16_WMMeasureItem(hWnd16, wParam, lParam);
+
+ case WM_DRAWITEM:
+ FD16_MapDrawItemStruct(MapSL(lParam), &dis);
+ return FD31_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
+
+ case WM_COMMAND:
+ return FD31_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
+#if 0
+ case WM_CTLCOLOR:
+ SetBkColor((HDC16)wParam, 0x00C0C0C0);
+ switch (HIWORD(lParam))
+ {
+ case CTLCOLOR_BTN:
+ SetTextColor((HDC16)wParam, 0x00000000);
+ return hGRAYBrush;
+ case CTLCOLOR_STATIC:
+ SetTextColor((HDC16)wParam, 0x00000000);
+ return hGRAYBrush;
+ }
+ break;
+#endif
+ }
+ return FALSE;
+}
+
+/***********************************************************************
+ * FileSaveDlgProc (COMMDLG.7)
+ */
+BOOL16 CALLBACK FileSaveDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam, LPARAM lParam)
+{
+ HWND hWnd = HWND_32(hWnd16);
+ PFD31_DATA lfs = (PFD31_DATA)GetPropA(hWnd,FD31_OFN_PROP);
+ DRAWITEMSTRUCT dis;
+
+ TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
+ if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
+ {
+ LRESULT lRet;
+ lRet = (BOOL16)FD31_CallWindowProc(lfs, wMsg, wParam, lParam);
+ if (lRet)
+ return lRet; /* else continue message processing */
+ }
+ switch (wMsg) {
+ case WM_INITDIALOG:
+ return FD31_WMInitDialog(hWnd, wParam, lParam);
+
+ case WM_MEASUREITEM:
+ return FD16_WMMeasureItem(hWnd16, wParam, lParam);
+
+ case WM_DRAWITEM:
+ FD16_MapDrawItemStruct(MapSL(lParam), &dis);
+ return FD31_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
+
+ case WM_COMMAND:
+ return FD31_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
+ }
+
+ /*
+ case WM_CTLCOLOR:
+ SetBkColor((HDC16)wParam, 0x00C0C0C0);
+ switch (HIWORD(lParam))
+ {
+ case CTLCOLOR_BTN:
+ SetTextColor((HDC16)wParam, 0x00000000);
+ return hGRAYBrush;
+ case CTLCOLOR_STATIC:
+ SetTextColor((HDC16)wParam, 0x00000000);
+ return hGRAYBrush;
+ }
+ return FALSE;
+
+ */
+ return FALSE;
+}
+
+/* ------------------ APIs ---------------------- */
+
+/***********************************************************************
+ * GetOpenFileName (COMMDLG.1)
+ *
+ * Creates a dialog box for the user to select a file to open.
+ *
+ * RETURNS
+ * TRUE on success: user selected a valid file
+ * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
+ *
+ * BUGS
+ * unknown, there are some FIXME's left.
+ */
+BOOL16 WINAPI GetOpenFileName16(
+ SEGPTR ofn /* [in/out] address of structure with data*/
+ )
+{
+ HINSTANCE16 hInst;
+ BOOL bRet = FALSE;
+ LPOPENFILENAME16 lpofn = MapSL(ofn);
+ PFD31_DATA lfs;
+ FARPROC16 ptr;
+ FD31_CALLBACKS callbacks;
+ PFD16_PRIVATE priv;
+
+ if (!lpofn || !FD31_Init()) return FALSE;
+
+ FD16_SetupCallbacks(&callbacks);
+ lfs = FD31_AllocPrivate((LPARAM) ofn, OPEN_DIALOG, &callbacks, 0);
+ if (lfs)
+ {
+ priv = (PFD16_PRIVATE) lfs->private1632;
+ hInst = GetWindowLongPtrA( HWND_32(lpofn->hwndOwner), GWLP_HINSTANCE );
+ ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
+ bRet = DialogBoxIndirectParam16( hInst, priv->hDlgTmpl16, lpofn->hwndOwner,
+ (DLGPROC16) ptr, (LPARAM) lfs);
+ FD31_DestroyPrivate(lfs);
+ }
+
+ TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
+ return bRet;
+}
+
+/***********************************************************************
+ * GetSaveFileName (COMMDLG.2)
+ *
+ * Creates a dialog box for the user to select a file to save.
+ *
+ * RETURNS
+ * TRUE on success: user enters a valid file
+ * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
+ *
+ * BUGS
+ * unknown. There are some FIXME's left.
+ */
+BOOL16 WINAPI GetSaveFileName16(
+ SEGPTR ofn /* [in/out] addess of structure with data*/
+ )
+{
+ HINSTANCE16 hInst;
+ BOOL bRet = FALSE;
+ LPOPENFILENAME16 lpofn = MapSL(ofn);
+ PFD31_DATA lfs;
+ FARPROC16 ptr;
+ FD31_CALLBACKS callbacks;
+ PFD16_PRIVATE priv;
+
+ if (!lpofn || !FD31_Init()) return FALSE;
+
+ FD16_SetupCallbacks(&callbacks);
+ lfs = FD31_AllocPrivate((LPARAM) ofn, SAVE_DIALOG, &callbacks, 0);
+ if (lfs)
+ {
+ priv = (PFD16_PRIVATE) lfs->private1632;
+ hInst = GetWindowLongPtrA( HWND_32(lpofn->hwndOwner), GWLP_HINSTANCE );
+ ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
+ bRet = DialogBoxIndirectParam16( hInst, priv->hDlgTmpl16, lpofn->hwndOwner,
+ (DLGPROC16) ptr, (LPARAM) lfs);
+ FD31_DestroyPrivate(lfs);
+ }
+
+ TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
+ return bRet;
+}