[COMDLG32]
[reactos.git] / reactos / dll / win32 / comdlg32 / filedlg31.c
index 89bedb0..29c6310 100644 (file)
@@ -109,26 +109,69 @@ static void FD31_StripEditControl(HWND hwnd)
 BOOL FD31_CallWindowProc(const FD31_DATA *lfs, UINT wMsg, WPARAM wParam,
                          LPARAM lParam)
 {
-    return lfs->callbacks->CWP(lfs, wMsg, wParam, lParam);
+    BOOL ret;
+
+    if (lfs->ofnA)
+    {
+        TRACE("Call hookA %p (%p, %04x, %08lx, %08lx)\n",
+               lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+        ret = lfs->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
+        TRACE("ret hookA %p (%p, %04x, %08lx, %08lx)\n",
+               lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+        return ret;
+    }
+
+    TRACE("Call hookW %p (%p, %04x, %08lx, %08lx)\n",
+           lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+    ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
+    TRACE("Ret hookW %p (%p, %04x, %08lx, %08lx)\n",
+           lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
+    return ret;
+}
+
+/***********************************************************************
+ *                             FD31_GetFileType                [internal]
+ */
+static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index)
+{
+  int n, i;
+  i = 0;
+  if (cfptr)
+    for ( ;(n = lstrlenW(cfptr)) != 0; i++)
+      {
+       cfptr += n + 1;
+       if (i == index)
+         return cfptr;
+       cfptr += lstrlenW(cfptr) + 1;
+      }
+  if (fptr)
+    for ( ;(n = lstrlenW(fptr)) != 0; i++)
+      {
+       fptr += n + 1;
+       if (i == index)
+         return fptr;
+       fptr += lstrlenW(fptr) + 1;
+    }
+  return FILE_star; /* FIXME */
 }
 
 /***********************************************************************
  *                             FD31_ScanDir                 [internal]
  */
-static BOOL FD31_ScanDir(HWND hWnd, LPCWSTR newPath)
+static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
 {
-    WCHAR              buffer[BUFFILE];
-    HWND               hdlg, hdlgDir;
-    LRESULT             lRet = TRUE;
-    HCURSOR             hCursorWait, oldCursor;
+    WCHAR   buffer[BUFFILE];
+    HWND    hdlg;
+    LRESULT lRet = TRUE;
+    HCURSOR hCursorWait, oldCursor;
 
     TRACE("Trying to change to %s\n", debugstr_w(newPath));
     if  ( newPath[0] && !SetCurrentDirectoryW( newPath ))
         return FALSE;
-    lstrcpynW(buffer, newPath, sizeof(buffer)/sizeof(WCHAR));
 
     /* get the list of spec files */
-    GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer)/sizeof(WCHAR));
+    lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter,
+              ofn->lpstrFilter, ofn->nFilterIndex - 1), BUFFILE);
 
     hCursorWait = LoadCursorA(0, (LPSTR)IDC_WAIT);
     oldCursor = SetCursor(hCursorWait);
@@ -145,8 +188,7 @@ static BOOL FD31_ScanDir(HWND hWnd, LPCWSTR newPath)
            if (scptr)  *scptr = 0;
             while (*filter == ' ') filter++;
            TRACE("Using file spec %s\n", debugstr_w(filter));
-           if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
-               return FALSE;
+           SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter);
            if (scptr) *scptr = ';';
                filter = (scptr) ? (scptr + 1) : 0;
         }
@@ -155,40 +197,13 @@ static BOOL FD31_ScanDir(HWND hWnd, LPCWSTR newPath)
     /* list of directories */
     strcpyW(buffer, FILE_star);
 
-    if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
+    if (GetDlgItem(hWnd, lst2) != 0) {
         lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
     }
     SetCursor(oldCursor);
     return lRet;
 }
 
-/***********************************************************************
- *                             FD31_GetFileType                [internal]
- */
-
-static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index)
-{
-  int n, i;
-  i = 0;
-  if (cfptr)
-    for ( ;(n = lstrlenW(cfptr)) != 0; i++)
-      {
-       cfptr += n + 1;
-       if (i == index)
-         return cfptr;
-       cfptr += lstrlenW(cfptr) + 1;
-      }
-  if (fptr)
-    for ( ;(n = lstrlenW(fptr)) != 0; i++)
-      {
-       fptr += n + 1;
-       if (i == index)
-         return fptr;
-       fptr += lstrlenW(fptr) + 1;
-    }
-  return FILE_star; /* FIXME */
-}
-
 /***********************************************************************
  *                              FD31_WMDrawItem              [internal]
  */
@@ -253,7 +268,7 @@ LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
            SetBkColor( lpdis->hDC, oldBk );
            SetTextColor( lpdis->hDC, oldText );
        }
-       DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
+       DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL );
         HeapFree(GetProcessHeap(), 0, str);
        return TRUE;
     }
@@ -287,7 +302,7 @@ LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
            SetBkColor( lpdis->hDC, oldBk );
            SetTextColor( lpdis->hDC, oldText );
        }
-       DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
+       DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon, 16, 16, 0, 0, DI_NORMAL );
         HeapFree(GetProcessHeap(), 0, str);
        return TRUE;
     }
@@ -302,6 +317,7 @@ static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr)
 {
     int lenstr2;
     LPOPENFILENAMEW ofnW = lfs->ofnW;
+    LPOPENFILENAMEA ofnA = lfs->ofnA;
     WCHAR tmpstr2[BUFFILE];
     WCHAR *p;
 
@@ -314,8 +330,10 @@ static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr)
     if (lenstr2 > 3)
         tmpstr2[lenstr2++]='\\';
     lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
-    if (ofnW->lpstrFile)
-        lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
+    if (!ofnW->lpstrFile)
+        return;
+
+    lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
 
     /* set filename offset */
     p = PathFindFileNameW(ofnW->lpstrFile);
@@ -329,7 +347,23 @@ static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr)
           debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension);
 
     /* update the real client structures if any */
-    lfs->callbacks->UpdateResult(lfs);
+    if (ofnA)
+    {
+        LPSTR lpszTemp;
+        if (ofnW->nMaxFile &&
+            !WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
+                                  ofnA->lpstrFile, ofnA->nMaxFile, NULL, NULL ))
+            ofnA->lpstrFile[ofnA->nMaxFile-1] = 0;
+
+        /* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */
+        /* set filename offset */
+        lpszTemp = PathFindFileNameA(ofnA->lpstrFile);
+        ofnA->nFileOffset = (lpszTemp - ofnA->lpstrFile);
+
+        /* set extension offset */
+        lpszTemp = PathFindExtensionA(ofnA->lpstrFile);
+        ofnA->nFileExtension = (*lpszTemp) ? (lpszTemp - ofnA->lpstrFile) + 1 : 0;
+    }
 }
 
 /***********************************************************************
@@ -340,12 +374,19 @@ static void FD31_UpdateFileTitle(const FD31_DATA *lfs)
 {
   LONG lRet;
   LPOPENFILENAMEW ofnW = lfs->ofnW;
+  LPOPENFILENAMEA ofnA = lfs->ofnA;
+
   if (ofnW->lpstrFileTitle != NULL)
   {
     lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
     SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
                              (LPARAM)ofnW->lpstrFileTitle );
-    lfs->callbacks->UpdateFileTitle(lfs);
+    if (ofnA)
+    {
+        if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
+                                  ofnA->lpstrFileTitle, ofnA->nMaxFileTitle, NULL, NULL ))
+            ofnA->lpstrFileTitle[ofnA->nMaxFileTitle-1] = 0;
+    }
   }
 }
 
@@ -375,7 +416,7 @@ static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs )
     }
   strcatW(tmpstr, FILE_bslash);
 
-  FD31_ScanDir(hWnd, tmpstr);
+  FD31_ScanDir(lfs->ofnW, hWnd, tmpstr);
   /* notify the app */
   if (lfs->hook)
     {
@@ -396,7 +437,7 @@ static LRESULT FD31_FileListSelect( const FD31_DATA *lfs )
     HWND hWnd = lfs->hwnd;
     LPWSTR pstr;
 
-    lRet = lfs->callbacks->SendLbGetCurSel(lfs);
+    lRet =  SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
     if (lRet == LB_ERR)
         return TRUE;
 
@@ -450,7 +491,7 @@ static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
 
         TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
         SetDlgItemTextW( hWnd, edt1, tmpstr2 );
-        FD31_ScanDir(hWnd, path);
+        FD31_ScanDir(lfs->ofnW, hWnd, path);
         return (lfs->ofnW->Flags & OFN_NOVALIDATE) ? TRUE : FALSE;
     }
 
@@ -462,7 +503,7 @@ static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
         strcatW(path, FILE_bslash);
 
     /* if ScanDir succeeds, we have changed the directory */
-    if (FD31_ScanDir(hWnd, path))
+    if (FD31_ScanDir(lfs->ofnW, hWnd, path))
         return FALSE; /* and path is not a valid file name */
 
     /* if not, this must be a filename */
@@ -477,7 +518,7 @@ static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
 
         lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
         /* Should we MessageBox() if this fails? */
-        if (!FD31_ScanDir(hWnd, path))
+        if (!FD31_ScanDir(lfs->ofnW, hWnd, path))
         {
             return FALSE;
         }
@@ -531,7 +572,7 @@ static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control,
     FD31_UpdateFileTitle(lfs);
     if (lfs->hook)
     {
-        lRet = (BOOL)FD31_CallWindowProc(lfs, lfs->fileokstring,
+        lRet = FD31_CallWindowProc(lfs, lfs->fileokstring,
                   0, lfs->lParam );
         if (lRet)
         {
@@ -543,7 +584,7 @@ static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control,
     {
         if (ofnW->lpstrFile)
         {
-            LPWSTR str = (LPWSTR)ofnW->lpstrFile;
+            LPWSTR str = ofnW->lpstrFile;
             LPWSTR ptr = strrchrW(str, '\\');
            str[lstrlenW(str) + 1] = '\0';
            *ptr = 0;
@@ -590,7 +631,6 @@ static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs )
         return TRUE;
     pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
     TRACE("Selected filter : %s\n", debugstr_w(pstr));
-    SetDlgItemTextW( lfs->hwnd, edt1, pstr );
 
     return FD31_Validate( lfs, NULL, cmb1, lRet, TRUE );
 }
@@ -693,7 +733,7 @@ static LPWSTR FD31_DupToW(LPCSTR str, DWORD size)
 
 /************************************************************************
  *                              FD31_MapOfnStructA          [internal]
- *      map a 32 bits Ansi structure to an Unicode one
+ *      map a 32 bits Ansi structure to a Unicode one
  */
 void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL open)
 {
@@ -738,7 +778,7 @@ void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL op
     ofnW->lpstrDefExt = FD31_DupToW(ofnA->lpstrDefExt, 3);
     if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
     {
-        if (HIWORD(ofnA->lpTemplateName))
+        if (!IS_INTRESOURCE(ofnA->lpTemplateName))
         {
             RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpTemplateName);
             ofnW->lpTemplateName = usBuffer.Buffer;
@@ -761,7 +801,7 @@ void FD31_FreeOfnW(OPENFILENAMEW *ofnW)
    HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
-   if (HIWORD(ofnW->lpTemplateName))
+   if (!IS_INTRESOURCE(ofnW->lpTemplateName))
        HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
 }
 
@@ -775,7 +815,13 @@ void FD31_DestroyPrivate(PFD31_DATA lfs)
     if (!lfs) return;
     hwnd = lfs->hwnd;
     TRACE("destroying private allocation %p\n", lfs);
-    lfs->callbacks->Destroy(lfs);
+
+    /* if ofnW has been allocated, have to free everything in it */
+    if (lfs->ofnA)
+    {
+        FD31_FreeOfnW(lfs->ofnW);
+        HeapFree(GetProcessHeap(), 0, lfs->ofnW);
+    }
     HeapFree(GetProcessHeap(), 0, lfs);
     RemovePropA(hwnd, FD31_OFN_PROP);
 }
@@ -783,13 +829,12 @@ void FD31_DestroyPrivate(PFD31_DATA lfs)
 /************************************************************************
  *                              FD31_AllocPrivate            [internal]
  *      allocate a private object to hold 32 bits Unicode
- *      structure that will be used throughtout the calls, while
+ *      structure that will be used throughout the calls, while
  *      keeping available the original structures and a few variables
  *      On entry : type = dialog procedure type (16,32A,32W)
  *                 dlgType = dialog type (open or save)
  */
-PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType,
-                             PFD31_CALLBACKS callbacks, DWORD data)
+PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode)
 {
     PFD31_DATA lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FD31_DATA));
 
@@ -798,8 +843,26 @@ PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType,
     lfs->hook = FALSE;
     lfs->lParam = lParam;
     lfs->open = (dlgType == OPEN_DIALOG);
-    lfs->callbacks = callbacks;
-    if (! lfs->callbacks->Init(lParam, lfs, data))
+
+    if (IsUnicode)
+    {
+        lfs->ofnA = NULL;
+        lfs->ofnW = (LPOPENFILENAMEW) lParam;
+        if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
+            if (lfs->ofnW->lpfnHook)
+                lfs->hook = TRUE;
+    }
+    else
+    {
+        lfs->ofnA = (LPOPENFILENAMEA) lParam;
+        if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
+            if (lfs->ofnA->lpfnHook)
+                lfs->hook = TRUE;
+        lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW));
+        FD31_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
+    }
+
+    if (! FD32_GetTemplate(lfs))
     {
         FD31_DestroyPrivate(lfs);
         return NULL;
@@ -823,7 +886,7 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
   PFD31_DATA lfs = (PFD31_DATA) lParam;
 
   if (!lfs) return FALSE;
-  SetPropA(hWnd, FD31_OFN_PROP, (HANDLE)lfs);
+  SetPropA(hWnd, FD31_OFN_PROP, lfs);
   lfs->hwnd = hWnd;
   ofn = lfs->ofnW;
 
@@ -871,11 +934,19 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
   if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
        ofn->nFilterIndex = 1;
   SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
-  lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
+  if (ofn->lpstrFile && ofn->lpstrFile[0])
+  {
+    TRACE( "SetText of edt1 to %s\n", debugstr_w(ofn->lpstrFile) );
+    SetDlgItemTextW( hWnd, edt1, ofn->lpstrFile );
+  }
+  else
+  {
+    lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
             ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
-  TRACE("nFilterIndex = %d, SetText of edt1 to %s\n",
+    TRACE("nFilterIndex = %d, SetText of edt1 to %s\n",
                        ofn->nFilterIndex, debugstr_w(tmpstr));
-  SetDlgItemTextW( hWnd, edt1, tmpstr );
+    SetDlgItemTextW( hWnd, edt1, tmpstr );
+  }
   /* get drive list */
   *tmpstr = 0;
   DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
@@ -896,9 +967,9 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
     }
   else
     *tmpstr = 0;
-  if (!FD31_ScanDir(hWnd, tmpstr)) {
+  if (!FD31_ScanDir(ofn, hWnd, tmpstr)) {
     *tmpstr = 0;
-    if (!FD31_ScanDir(hWnd, tmpstr))
+    if (!FD31_ScanDir(ofn, hWnd, tmpstr))
       WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
   }
   /* select current drive in combo 2, omit missing drives */
@@ -919,7 +990,7 @@ LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
   if (ofn->Flags & OFN_HIDEREADONLY)
     ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
   if (lfs->hook)
-      return (BOOL) FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
+      return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
   return TRUE;
 }