set svn:eol-style to native
[reactos.git] / reactos / lib / comdlg32 / filedlg16.c
index d2d3480..f3a9a31 100644 (file)
-/*\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;
+}