ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

filedlg31.c
Go to the documentation of this file.
00001 /*
00002  * COMMDLG - File Dialogs
00003  *
00004  * Copyright 1994 Martin Ayotte
00005  * Copyright 1996 Albrecht Kleine
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 #include <ctype.h>
00022 #include <stdlib.h>
00023 #include <stdarg.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026 #include "windef.h"
00027 #include "winbase.h"
00028 #include "winnls.h"
00029 #include "wingdi.h"
00030 #include "winuser.h"
00031 #include "wine/unicode.h"
00032 #include "wine/debug.h"
00033 #include "winreg.h"
00034 #include "winternl.h"
00035 #include "commdlg.h"
00036 #include "shlwapi.h"
00037 
00038 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
00039 
00040 #include "cdlg.h"
00041 #include "filedlg31.h"
00042 
00043 #define BUFFILE 512
00044 #define BUFFILEALLOC 512 * sizeof(WCHAR)
00045 
00046 static const WCHAR FILE_star[] = {'*','.','*', 0};
00047 static const WCHAR FILE_bslash[] = {'\\', 0};
00048 static const WCHAR FILE_specc[] = {'%','c',':', 0};
00049 static const int fldrHeight = 16;
00050 static const int fldrWidth = 20;
00051 
00052 static HICON hFolder = 0;
00053 static HICON hFolder2 = 0;
00054 static HICON hFloppy = 0;
00055 static HICON hHDisk = 0;
00056 static HICON hCDRom = 0;
00057 static HICON hNet = 0;
00058 
00059 /***********************************************************************
00060  *              FD31_Init           [internal]
00061  */
00062 BOOL FD31_Init(void)
00063 {
00064     static BOOL initialized = 0;
00065 
00066     if (!initialized) {
00067         hFolder  = LoadImageA( COMDLG32_hInstance, "FOLDER", IMAGE_ICON, 16, 16, LR_SHARED );
00068         hFolder2 = LoadImageA( COMDLG32_hInstance, "FOLDER2", IMAGE_ICON, 16, 16, LR_SHARED );
00069         hFloppy  = LoadImageA( COMDLG32_hInstance, "FLOPPY", IMAGE_ICON, 16, 16, LR_SHARED );
00070         hHDisk   = LoadImageA( COMDLG32_hInstance, "HDISK", IMAGE_ICON, 16, 16, LR_SHARED );
00071         hCDRom   = LoadImageA( COMDLG32_hInstance, "CDROM", IMAGE_ICON, 16, 16, LR_SHARED );
00072         hNet     = LoadImageA( COMDLG32_hInstance, "NETWORK", IMAGE_ICON, 16, 16, LR_SHARED );
00073     if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 ||
00074         hHDisk == 0 || hCDRom == 0 || hNet == 0)
00075     {
00076         ERR("Error loading icons !\n");
00077         return FALSE;
00078     }
00079     initialized = TRUE;
00080     }
00081     return TRUE;
00082 }
00083 
00084 /***********************************************************************
00085  *                              FD31_StripEditControl        [internal]
00086  * Strip pathnames off the contents of the edit control.
00087  */
00088 static void FD31_StripEditControl(HWND hwnd)
00089 {
00090     WCHAR temp[BUFFILE], *cp;
00091 
00092     GetDlgItemTextW( hwnd, edt1, temp, sizeof(temp)/sizeof(WCHAR));
00093     cp = strrchrW(temp, '\\');
00094     if (cp != NULL) {
00095     strcpyW(temp, cp+1);
00096     }
00097     cp = strrchrW(temp, ':');
00098     if (cp != NULL) {
00099     strcpyW(temp, cp+1);
00100     }
00101     /* FIXME: shouldn't we do something with the result here? ;-) */
00102 }
00103 
00104 /***********************************************************************
00105  *                              FD31_CallWindowProc          [internal]
00106  *
00107  *      Call the appropriate hook
00108  */
00109 BOOL FD31_CallWindowProc(const FD31_DATA *lfs, UINT wMsg, WPARAM wParam,
00110                          LPARAM lParam)
00111 {
00112     BOOL ret;
00113 
00114     if (lfs->ofnA)
00115     {
00116         TRACE("Call hookA %p (%p, %04x, %08lx, %08lx)\n",
00117                lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
00118         ret = lfs->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
00119         TRACE("ret hookA %p (%p, %04x, %08lx, %08lx)\n",
00120                lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
00121         return ret;
00122     }
00123 
00124     TRACE("Call hookW %p (%p, %04x, %08lx, %08lx)\n",
00125            lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
00126     ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
00127     TRACE("Ret hookW %p (%p, %04x, %08lx, %08lx)\n",
00128            lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
00129     return ret;
00130 }
00131 
00132 /***********************************************************************
00133  *              FD31_GetFileType        [internal]
00134  */
00135 static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index)
00136 {
00137   int n, i;
00138   i = 0;
00139   if (cfptr)
00140     for ( ;(n = lstrlenW(cfptr)) != 0; i++)
00141       {
00142     cfptr += n + 1;
00143     if (i == index)
00144       return cfptr;
00145     cfptr += lstrlenW(cfptr) + 1;
00146       }
00147   if (fptr)
00148     for ( ;(n = lstrlenW(fptr)) != 0; i++)
00149       {
00150     fptr += n + 1;
00151     if (i == index)
00152       return fptr;
00153     fptr += lstrlenW(fptr) + 1;
00154     }
00155   return FILE_star; /* FIXME */
00156 }
00157 
00158 /***********************************************************************
00159  *              FD31_ScanDir                 [internal]
00160  */
00161 static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
00162 {
00163     WCHAR   buffer[BUFFILE];
00164     HWND    hdlg;
00165     LRESULT lRet = TRUE;
00166     HCURSOR hCursorWait, oldCursor;
00167 
00168     TRACE("Trying to change to %s\n", debugstr_w(newPath));
00169     if  ( newPath[0] && !SetCurrentDirectoryW( newPath ))
00170         return FALSE;
00171 
00172     /* get the list of spec files */
00173     lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter,
00174               ofn->lpstrFilter, ofn->nFilterIndex - 1), BUFFILE);
00175 
00176     hCursorWait = LoadCursorA(0, (LPSTR)IDC_WAIT);
00177     oldCursor = SetCursor(hCursorWait);
00178 
00179     /* list of files */
00180     if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) {
00181         WCHAR*  scptr; /* ptr on semi-colon */
00182     WCHAR*  filter = buffer;
00183 
00184     TRACE("Using filter %s\n", debugstr_w(filter));
00185     SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
00186     while (filter) {
00187         scptr = strchrW(filter, ';');
00188         if (scptr)  *scptr = 0;
00189             while (*filter == ' ') filter++;
00190         TRACE("Using file spec %s\n", debugstr_w(filter));
00191         SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter);
00192         if (scptr) *scptr = ';';
00193             filter = (scptr) ? (scptr + 1) : 0;
00194      }
00195     }
00196 
00197     /* list of directories */
00198     strcpyW(buffer, FILE_star);
00199 
00200     if (GetDlgItem(hWnd, lst2) != 0) {
00201         lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
00202     }
00203     SetCursor(oldCursor);
00204     return lRet;
00205 }
00206 
00207 /***********************************************************************
00208  *                              FD31_WMDrawItem              [internal]
00209  */
00210 LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
00211        int savedlg, const DRAWITEMSTRUCT *lpdis)
00212 {
00213     WCHAR *str;
00214     HICON hIcon;
00215     COLORREF oldText = 0, oldBk = 0;
00216 
00217     if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
00218     {
00219         if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) return FALSE;
00220     SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
00221                       (LPARAM)str);
00222 
00223     if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
00224     {
00225         oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
00226         oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
00227     }
00228     if (savedlg)
00229         SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
00230 
00231     ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1,
00232                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
00233                   &(lpdis->rcItem), str, lstrlenW(str), NULL);
00234 
00235     if (lpdis->itemState & ODS_SELECTED)
00236         DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
00237 
00238     if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
00239     {
00240         SetBkColor( lpdis->hDC, oldBk );
00241         SetTextColor( lpdis->hDC, oldText );
00242     }
00243         HeapFree(GetProcessHeap(), 0, str);
00244     return TRUE;
00245     }
00246 
00247     if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
00248     {
00249         if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
00250             return FALSE;
00251     SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
00252                       (LPARAM)str);
00253 
00254     if (lpdis->itemState & ODS_SELECTED)
00255     {
00256         oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
00257         oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
00258     }
00259     ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
00260                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
00261                   &(lpdis->rcItem), str, lstrlenW(str), NULL);
00262 
00263     if (lpdis->itemState & ODS_SELECTED)
00264         DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
00265 
00266     if (lpdis->itemState & ODS_SELECTED)
00267     {
00268         SetBkColor( lpdis->hDC, oldBk );
00269         SetTextColor( lpdis->hDC, oldText );
00270     }
00271     DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL );
00272         HeapFree(GetProcessHeap(), 0, str);
00273     return TRUE;
00274     }
00275     if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
00276     {
00277         char root[] = "a:";
00278         if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
00279             return FALSE;
00280     SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID,
00281                       (LPARAM)str);
00282         root[0] += str[2] - 'a';
00283         switch(GetDriveTypeA(root))
00284         {
00285         case DRIVE_REMOVABLE: hIcon = hFloppy; break;
00286         case DRIVE_CDROM:     hIcon = hCDRom; break;
00287         case DRIVE_REMOTE:    hIcon = hNet; break;
00288         case DRIVE_FIXED:
00289         default:           hIcon = hHDisk; break;
00290         }
00291     if (lpdis->itemState & ODS_SELECTED)
00292     {
00293         oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
00294         oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
00295     }
00296     ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
00297                   lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
00298                   &(lpdis->rcItem), str, lstrlenW(str), NULL);
00299 
00300     if (lpdis->itemState & ODS_SELECTED)
00301     {
00302         SetBkColor( lpdis->hDC, oldBk );
00303         SetTextColor( lpdis->hDC, oldText );
00304     }
00305     DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon, 16, 16, 0, 0, DI_NORMAL );
00306         HeapFree(GetProcessHeap(), 0, str);
00307     return TRUE;
00308     }
00309     return FALSE;
00310 }
00311 
00312 /***********************************************************************
00313  *                              FD31_UpdateResult            [internal]
00314  *      update the displayed file name (with path)
00315  */
00316 static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr)
00317 {
00318     int lenstr2;
00319     LPOPENFILENAMEW ofnW = lfs->ofnW;
00320     LPOPENFILENAMEA ofnA = lfs->ofnA;
00321     WCHAR tmpstr2[BUFFILE];
00322     WCHAR *p;
00323 
00324     TRACE("%s\n", debugstr_w(tmpstr));
00325     if(ofnW->Flags & OFN_NOVALIDATE)
00326         tmpstr2[0] = '\0';
00327     else
00328         GetCurrentDirectoryW(BUFFILE, tmpstr2);
00329     lenstr2 = strlenW(tmpstr2);
00330     if (lenstr2 > 3)
00331         tmpstr2[lenstr2++]='\\';
00332     lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
00333     if (!ofnW->lpstrFile)
00334         return;
00335 
00336     lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
00337 
00338     /* set filename offset */
00339     p = PathFindFileNameW(ofnW->lpstrFile);
00340     ofnW->nFileOffset = (p - ofnW->lpstrFile);
00341 
00342     /* set extension offset */
00343     p = PathFindExtensionW(ofnW->lpstrFile);
00344     ofnW->nFileExtension = (*p) ? (p - ofnW->lpstrFile) + 1 : 0;
00345 
00346     TRACE("file %s, file offset %d, ext offset %d\n",
00347           debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension);
00348 
00349     /* update the real client structures if any */
00350     if (ofnA)
00351     {
00352         LPSTR lpszTemp;
00353         if (ofnW->nMaxFile &&
00354             !WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
00355                                   ofnA->lpstrFile, ofnA->nMaxFile, NULL, NULL ))
00356             ofnA->lpstrFile[ofnA->nMaxFile-1] = 0;
00357 
00358         /* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */
00359         /* set filename offset */
00360         lpszTemp = PathFindFileNameA(ofnA->lpstrFile);
00361         ofnA->nFileOffset = (lpszTemp - ofnA->lpstrFile);
00362 
00363         /* set extension offset */
00364         lpszTemp = PathFindExtensionA(ofnA->lpstrFile);
00365         ofnA->nFileExtension = (*lpszTemp) ? (lpszTemp - ofnA->lpstrFile) + 1 : 0;
00366     }
00367 }
00368 
00369 /***********************************************************************
00370  *                              FD31_UpdateFileTitle         [internal]
00371  *      update the displayed file name (without path)
00372  */
00373 static void FD31_UpdateFileTitle(const FD31_DATA *lfs)
00374 {
00375   LONG lRet;
00376   LPOPENFILENAMEW ofnW = lfs->ofnW;
00377   LPOPENFILENAMEA ofnA = lfs->ofnA;
00378 
00379   if (ofnW->lpstrFileTitle != NULL)
00380   {
00381     lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
00382     SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
00383                              (LPARAM)ofnW->lpstrFileTitle );
00384     if (ofnA)
00385     {
00386         if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
00387                                   ofnA->lpstrFileTitle, ofnA->nMaxFileTitle, NULL, NULL ))
00388             ofnA->lpstrFileTitle[ofnA->nMaxFileTitle-1] = 0;
00389     }
00390   }
00391 }
00392 
00393 /***********************************************************************
00394  *                              FD31_DirListDblClick         [internal]
00395  */
00396 static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs )
00397 {
00398   LONG lRet;
00399   HWND hWnd = lfs->hwnd;
00400   LPWSTR pstr;
00401   WCHAR tmpstr[BUFFILE];
00402 
00403   /* get the raw string (with brackets) */
00404   lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
00405   if (lRet == LB_ERR) return TRUE;
00406   pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
00407   SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
00408              (LPARAM)pstr);
00409   strcpyW( tmpstr, pstr );
00410   HeapFree(GetProcessHeap(), 0, pstr);
00411   /* get the selected directory in tmpstr */
00412   if (tmpstr[0] == '[')
00413     {
00414       tmpstr[lstrlenW(tmpstr) - 1] = 0;
00415       strcpyW(tmpstr,tmpstr+1);
00416     }
00417   strcatW(tmpstr, FILE_bslash);
00418 
00419   FD31_ScanDir(lfs->ofnW, hWnd, tmpstr);
00420   /* notify the app */
00421   if (lfs->hook)
00422     {
00423       if (FD31_CallWindowProc(lfs, lfs->lbselchstring, lst2,
00424               MAKELONG(lRet,CD_LBSELCHANGE)))
00425         return TRUE;
00426     }
00427   return TRUE;
00428 }
00429 
00430 /***********************************************************************
00431  *                              FD31_FileListSelect         [internal]
00432  *    called when a new item is picked in the file list
00433  */
00434 static LRESULT FD31_FileListSelect( const FD31_DATA *lfs )
00435 {
00436     LONG lRet;
00437     HWND hWnd = lfs->hwnd;
00438     LPWSTR pstr;
00439 
00440     lRet =  SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
00441     if (lRet == LB_ERR)
00442         return TRUE;
00443 
00444     /* set the edit control to the chosen file */
00445     if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
00446     {
00447         SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
00448                        (LPARAM)pstr);
00449         SetDlgItemTextW( hWnd, edt1, pstr );
00450         HeapFree(GetProcessHeap(), 0, pstr);
00451     }
00452     if (lfs->hook)
00453     {
00454         FD31_CallWindowProc(lfs, lfs->lbselchstring, lst1,
00455                            MAKELONG(lRet,CD_LBSELCHANGE));
00456     }
00457     /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
00458            CD_LBSELNOITEMS */
00459     return TRUE;
00460 }
00461 
00462 /***********************************************************************
00463  *                              FD31_TestPath      [internal]
00464  *      before accepting the file name, test if it includes wild cards
00465  *      tries to scan the directory and returns TRUE if no error.
00466  */
00467 static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
00468 {
00469     HWND hWnd = lfs->hwnd;
00470     LPWSTR pBeginFileName, pstr2;
00471     WCHAR tmpstr2[BUFFILE];
00472 
00473     pBeginFileName = strrchrW(path, '\\');
00474     if (pBeginFileName == NULL)
00475     pBeginFileName = strrchrW(path, ':');
00476 
00477     if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL)
00478     {
00479         /* edit control contains wildcards */
00480         if (pBeginFileName != NULL)
00481         {
00482         lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
00483         *(pBeginFileName + 1) = 0;
00484     }
00485     else
00486     {
00487         strcpyW(tmpstr2, path);
00488             if(!(lfs->ofnW->Flags & OFN_NOVALIDATE))
00489                 *path = 0;
00490         }
00491 
00492         TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
00493         SetDlgItemTextW( hWnd, edt1, tmpstr2 );
00494         FD31_ScanDir(lfs->ofnW, hWnd, path);
00495         return (lfs->ofnW->Flags & OFN_NOVALIDATE) ? TRUE : FALSE;
00496     }
00497 
00498     /* no wildcards, we might have a directory or a filename */
00499     /* try appending a wildcard and reading the directory */
00500 
00501     pstr2 = path + lstrlenW(path);
00502     if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
00503         strcatW(path, FILE_bslash);
00504 
00505     /* if ScanDir succeeds, we have changed the directory */
00506     if (FD31_ScanDir(lfs->ofnW, hWnd, path))
00507         return FALSE; /* and path is not a valid file name */
00508 
00509     /* if not, this must be a filename */
00510 
00511     *pstr2 = 0; /* remove the wildcard added before */
00512 
00513     if (pBeginFileName != NULL)
00514     {
00515         /* strip off the pathname */
00516         *pBeginFileName = 0;
00517         SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
00518 
00519         lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
00520         /* Should we MessageBox() if this fails? */
00521         if (!FD31_ScanDir(lfs->ofnW, hWnd, path))
00522         {
00523             return FALSE;
00524         }
00525         strcpyW(path, tmpstr2);
00526     }
00527     else
00528         SetDlgItemTextW( hWnd, edt1, path );
00529     return TRUE;
00530 }
00531 
00532 /***********************************************************************
00533  *                              FD31_Validate               [internal]
00534  *   called on: click Ok button, Enter in edit, DoubleClick in file list
00535  */
00536 static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control, INT itemIndex,
00537                                  BOOL internalUse )
00538 {
00539     LONG lRet;
00540     HWND hWnd = lfs->hwnd;
00541     OPENFILENAMEW ofnsav;
00542     LPOPENFILENAMEW ofnW = lfs->ofnW;
00543     WCHAR filename[BUFFILE];
00544 
00545     ofnsav = *ofnW; /* for later restoring */
00546 
00547     /* get current file name */
00548     if (path)
00549         lstrcpynW(filename, path, sizeof(filename)/sizeof(WCHAR));
00550     else
00551         GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename)/sizeof(WCHAR));
00552 
00553     TRACE("got filename = %s\n", debugstr_w(filename));
00554     /* if we did not click in file list to get there */
00555     if (control != lst1)
00556     {
00557         if (!FD31_TestPath( lfs, filename) )
00558            return FALSE;
00559     }
00560     FD31_UpdateResult(lfs, filename);
00561 
00562     if (internalUse)
00563     { /* called internally after a change in a combo */
00564         if (lfs->hook)
00565         {
00566              FD31_CallWindowProc(lfs, lfs->lbselchstring, control,
00567                              MAKELONG(itemIndex,CD_LBSELCHANGE));
00568         }
00569         return TRUE;
00570     }
00571 
00572     FD31_UpdateFileTitle(lfs);
00573     if (lfs->hook)
00574     {
00575         lRet = FD31_CallWindowProc(lfs, lfs->fileokstring,
00576                   0, lfs->lParam );
00577         if (lRet)
00578         {
00579             *ofnW = ofnsav; /* restore old state */
00580             return FALSE;
00581         }
00582     }
00583     if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
00584     {
00585         if (ofnW->lpstrFile)
00586         {
00587             LPWSTR str = ofnW->lpstrFile;
00588             LPWSTR ptr = strrchrW(str, '\\');
00589         str[lstrlenW(str) + 1] = '\0';
00590         *ptr = 0;
00591         }
00592     }
00593     return TRUE;
00594 }
00595 
00596 /***********************************************************************
00597  *                              FD31_DiskChange             [internal]
00598  *    called when a new item is picked in the disk selection combo
00599  */
00600 static LRESULT FD31_DiskChange( const FD31_DATA *lfs )
00601 {
00602     LONG lRet;
00603     HWND hWnd = lfs->hwnd;
00604     LPWSTR pstr;
00605     WCHAR diskname[BUFFILE];
00606 
00607     FD31_StripEditControl(hWnd);
00608     lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
00609     if (lRet == LB_ERR)
00610         return 0;
00611     pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
00612     SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
00613                          (LPARAM)pstr);
00614     wsprintfW(diskname, FILE_specc, pstr[2]);
00615     HeapFree(GetProcessHeap(), 0, pstr);
00616 
00617     return FD31_Validate( lfs, diskname, cmb2, lRet, TRUE );
00618 }
00619 
00620 /***********************************************************************
00621  *                              FD31_FileTypeChange         [internal]
00622  *    called when a new item is picked in the file type combo
00623  */
00624 static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs )
00625 {
00626     LONG lRet;
00627     LPWSTR pstr;
00628 
00629     lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
00630     if (lRet == LB_ERR)
00631         return TRUE;
00632     lfs->ofnW->nFilterIndex = lRet + 1;
00633     if (lfs->ofnA)
00634         lfs->ofnA->nFilterIndex = lRet + 1;
00635     pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
00636     TRACE("Selected filter : %s\n", debugstr_w(pstr));
00637 
00638     return FD31_Validate( lfs, pstr, cmb1, lRet, TRUE );
00639 }
00640 
00641 /***********************************************************************
00642  *                              FD31_WMCommand               [internal]
00643  */
00644 LRESULT FD31_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
00645        UINT control, const FD31_DATA *lfs )
00646 {
00647     switch (control)
00648     {
00649         case lst1: /* file list */
00650         FD31_StripEditControl(hWnd);
00651         if (notification == LBN_DBLCLK)
00652         {
00653             return SendMessageW(hWnd, WM_COMMAND, IDOK, 0);
00654         }
00655         else if (notification == LBN_SELCHANGE)
00656             return FD31_FileListSelect( lfs );
00657         break;
00658 
00659         case lst2: /* directory list */
00660         FD31_StripEditControl(hWnd);
00661         if (notification == LBN_DBLCLK)
00662             return FD31_DirListDblClick( lfs );
00663         break;
00664 
00665         case cmb1: /* file type drop list */
00666         if (notification == CBN_SELCHANGE)
00667             return FD31_FileTypeChange( lfs );
00668         break;
00669 
00670         case chx1:
00671         break;
00672 
00673         case pshHelp:
00674         break;
00675 
00676         case cmb2: /* disk dropdown combo */
00677         if (notification == CBN_SELCHANGE)
00678             return FD31_DiskChange( lfs );
00679         break;
00680 
00681         case IDOK:
00682         TRACE("OK pressed\n");
00683         if (FD31_Validate( lfs, NULL, control, 0, FALSE ))
00684             EndDialog(hWnd, TRUE);
00685         return TRUE;
00686 
00687         case IDCANCEL:
00688         EndDialog(hWnd, FALSE);
00689         return TRUE;
00690 
00691         case IDABORT: /* can be sent by the hook procedure */
00692         EndDialog(hWnd, TRUE);
00693         return TRUE;
00694     }
00695     return FALSE;
00696 }
00697 
00698 /************************************************************************
00699  *                              FD31_MapStringPairsToW       [internal]
00700  *      map string pairs to Unicode
00701  */
00702 static LPWSTR FD31_MapStringPairsToW(LPCSTR strA, UINT size)
00703 {
00704     LPCSTR s;
00705     LPWSTR x;
00706     unsigned int n, len;
00707 
00708     s = strA;
00709     while (*s)
00710         s = s+strlen(s)+1;
00711     s++;
00712     n = s + 1 - strA; /* Don't forget the other \0 */
00713     if (n < size) n = size;
00714 
00715     len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
00716     x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR));
00717     MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
00718     return x;
00719 }
00720 
00721 
00722 /************************************************************************
00723  *                              FD31_DupToW                  [internal]
00724  *      duplicates an Ansi string to unicode, with a buffer size
00725  */
00726 static LPWSTR FD31_DupToW(LPCSTR str, DWORD size)
00727 {
00728     LPWSTR strW = NULL;
00729     if (str && (size > 0))
00730     {
00731         strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
00732         if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
00733     }
00734     return strW;
00735 }
00736 
00737 /************************************************************************
00738  *                              FD31_MapOfnStructA          [internal]
00739  *      map a 32 bits Ansi structure to a Unicode one
00740  */
00741 static void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL open)
00742 {
00743     UNICODE_STRING usBuffer;
00744 
00745     ofnW->lStructSize = sizeof(OPENFILENAMEW);
00746     ofnW->hwndOwner = ofnA->hwndOwner;
00747     ofnW->hInstance = ofnA->hInstance;
00748     if (ofnA->lpstrFilter)
00749         ofnW->lpstrFilter = FD31_MapStringPairsToW(ofnA->lpstrFilter, 0);
00750 
00751     if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
00752         ofnW->lpstrCustomFilter = FD31_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
00753     ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
00754     ofnW->nFilterIndex = ofnA->nFilterIndex;
00755     ofnW->nMaxFile = ofnA->nMaxFile;
00756     ofnW->lpstrFile = FD31_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
00757     ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
00758     ofnW->lpstrFileTitle = FD31_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
00759     if (ofnA->lpstrInitialDir)
00760     {
00761         RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpstrInitialDir);
00762         ofnW->lpstrInitialDir = usBuffer.Buffer;
00763     }
00764     if (ofnA->lpstrTitle) {
00765         RtlCreateUnicodeStringFromAsciiz (&usBuffer, ofnA->lpstrTitle);
00766         ofnW->lpstrTitle = usBuffer.Buffer;
00767     } else {
00768         WCHAR buf[16];
00769         LPWSTR title_tmp;
00770         int len;
00771         LoadStringW(COMDLG32_hInstance, open ? IDS_OPEN_FILE : IDS_SAVE_AS,
00772                     buf, sizeof(buf)/sizeof(WCHAR));
00773         len = lstrlenW(buf)+1;
00774         title_tmp = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
00775         memcpy(title_tmp, buf, len * sizeof(WCHAR));
00776         ofnW->lpstrTitle = title_tmp;
00777     }
00778     ofnW->Flags = ofnA->Flags;
00779     ofnW->nFileOffset = ofnA->nFileOffset;
00780     ofnW->nFileExtension = ofnA->nFileExtension;
00781     ofnW->lpstrDefExt = FD31_DupToW(ofnA->lpstrDefExt, 3);
00782     if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
00783     {
00784         if (!IS_INTRESOURCE(ofnA->lpTemplateName))
00785         {
00786             RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpTemplateName);
00787             ofnW->lpTemplateName = usBuffer.Buffer;
00788         }
00789         else /* numbered resource */
00790             ofnW->lpTemplateName = (LPCWSTR) ofnA->lpTemplateName;
00791     }
00792 }
00793 
00794 
00795 /************************************************************************
00796  *                              FD31_FreeOfnW          [internal]
00797  *      Undo all allocations done by FD31_MapOfnStructA
00798  */
00799 static void FD31_FreeOfnW(OPENFILENAMEW *ofnW)
00800 {
00801    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
00802    HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
00803    HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile);
00804    HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
00805    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
00806    HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
00807    if (!IS_INTRESOURCE(ofnW->lpTemplateName))
00808        HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
00809 }
00810 
00811 /************************************************************************
00812  *                              FD31_DestroyPrivate            [internal]
00813  *      destroys the private object
00814  */
00815 void FD31_DestroyPrivate(PFD31_DATA lfs)
00816 {
00817     HWND hwnd;
00818     if (!lfs) return;
00819     hwnd = lfs->hwnd;
00820     TRACE("destroying private allocation %p\n", lfs);
00821 
00822     /* if ofnW has been allocated, have to free everything in it */
00823     if (lfs->ofnA)
00824     {
00825         FD31_FreeOfnW(lfs->ofnW);
00826         HeapFree(GetProcessHeap(), 0, lfs->ofnW);
00827     }
00828     HeapFree(GetProcessHeap(), 0, lfs);
00829     RemovePropA(hwnd, FD31_OFN_PROP);
00830 }
00831 
00832 /************************************************************************
00833  *                              FD31_AllocPrivate            [internal]
00834  *      allocate a private object to hold 32 bits Unicode
00835  *      structure that will be used throughout the calls, while
00836  *      keeping available the original structures and a few variables
00837  *      On entry : type = dialog procedure type (16,32A,32W)
00838  *                 dlgType = dialog type (open or save)
00839  */
00840 PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode)
00841 {
00842     PFD31_DATA lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FD31_DATA));
00843 
00844     TRACE("alloc private buf %p\n", lfs);
00845     if (!lfs) return NULL;
00846     lfs->hook = FALSE;
00847     lfs->lParam = lParam;
00848     lfs->open = (dlgType == OPEN_DIALOG);
00849 
00850     if (IsUnicode)
00851     {
00852         lfs->ofnA = NULL;
00853         lfs->ofnW = (LPOPENFILENAMEW) lParam;
00854         if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
00855             if (lfs->ofnW->lpfnHook)
00856                 lfs->hook = TRUE;
00857     }
00858     else
00859     {
00860         lfs->ofnA = (LPOPENFILENAMEA) lParam;
00861         if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
00862             if (lfs->ofnA->lpfnHook)
00863                 lfs->hook = TRUE;
00864         lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*lfs->ofnW));
00865         FD31_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
00866     }
00867 
00868     if (! FD32_GetTemplate(lfs))
00869     {
00870         FD31_DestroyPrivate(lfs);
00871         return NULL;
00872     }
00873     lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
00874     lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
00875 
00876     return lfs;
00877 }
00878 
00879 /***********************************************************************
00880  *                              FD31_WMInitDialog            [internal]
00881  */
00882 
00883 LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
00884 {
00885   int i, n;
00886   WCHAR tmpstr[BUFFILE];
00887   LPWSTR pstr, old_pstr;
00888   LPOPENFILENAMEW ofn;
00889   PFD31_DATA lfs = (PFD31_DATA) lParam;
00890 
00891   if (!lfs) return FALSE;
00892   SetPropA(hWnd, FD31_OFN_PROP, lfs);
00893   lfs->hwnd = hWnd;
00894   ofn = lfs->ofnW;
00895 
00896   TRACE("flags=%x initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
00897 
00898   SetWindowTextW( hWnd, ofn->lpstrTitle );
00899   /* read custom filter information */
00900   if (ofn->lpstrCustomFilter)
00901     {
00902       pstr = ofn->lpstrCustomFilter;
00903       n = 0;
00904       TRACE("lpstrCustomFilter = %p\n", pstr);
00905       while(*pstr)
00906     {
00907       old_pstr = pstr;
00908           i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
00909                                    (LPARAM)(ofn->lpstrCustomFilter) + n );
00910           n += lstrlenW(pstr) + 1;
00911       pstr += lstrlenW(pstr) + 1;
00912       TRACE("add str=%s associated to %s\n",
00913                 debugstr_w(old_pstr), debugstr_w(pstr));
00914           SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
00915           n += lstrlenW(pstr) + 1;
00916       pstr += lstrlenW(pstr) + 1;
00917     }
00918     }
00919   /* read filter information */
00920   if (ofn->lpstrFilter) {
00921     pstr = (LPWSTR) ofn->lpstrFilter;
00922     n = 0;
00923     while(*pstr) {
00924       old_pstr = pstr;
00925       i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
00926                        (LPARAM)(ofn->lpstrFilter + n) );
00927       n += lstrlenW(pstr) + 1;
00928       pstr += lstrlenW(pstr) + 1;
00929       TRACE("add str=%s associated to %s\n",
00930                 debugstr_w(old_pstr), debugstr_w(pstr));
00931       SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
00932       n += lstrlenW(pstr) + 1;
00933       pstr += lstrlenW(pstr) + 1;
00934     }
00935   }
00936   /* set default filter */
00937   if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
00938     ofn->nFilterIndex = 1;
00939   SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
00940   if (ofn->lpstrFile && ofn->lpstrFile[0])
00941   {
00942     TRACE( "SetText of edt1 to %s\n", debugstr_w(ofn->lpstrFile) );
00943     SetDlgItemTextW( hWnd, edt1, ofn->lpstrFile );
00944   }
00945   else
00946   {
00947     lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
00948          ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
00949     TRACE("nFilterIndex = %d, SetText of edt1 to %s\n",
00950             ofn->nFilterIndex, debugstr_w(tmpstr));
00951     SetDlgItemTextW( hWnd, edt1, tmpstr );
00952   }
00953   /* get drive list */
00954   *tmpstr = 0;
00955   DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
00956   /* read initial directory */
00957   /* FIXME: Note that this is now very version-specific (See MSDN description of
00958    * the OPENFILENAME structure).  For example under 2000/XP any path in the
00959    * lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME
00960    */
00961   if (ofn->lpstrInitialDir != NULL)
00962     {
00963       int len;
00964       lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
00965       len = lstrlenW(tmpstr);
00966       if (len > 0 && tmpstr[len-1] != '\\'  && tmpstr[len-1] != ':') {
00967         tmpstr[len]='\\';
00968         tmpstr[len+1]='\0';
00969       }
00970     }
00971   else
00972     *tmpstr = 0;
00973   if (!FD31_ScanDir(ofn, hWnd, tmpstr)) {
00974     *tmpstr = 0;
00975     if (!FD31_ScanDir(ofn, hWnd, tmpstr))
00976       WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
00977   }
00978   /* select current drive in combo 2, omit missing drives */
00979   {
00980       char dir[MAX_PATH];
00981       char str[4] = "a:\\";
00982       GetCurrentDirectoryA( sizeof(dir), dir );
00983       for(i = 0, n = -1; i < 26; i++)
00984       {
00985           str[0] = 'a' + i;
00986           if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++;
00987           if (toupper(str[0]) == toupper(dir[0])) break;
00988       }
00989   }
00990   SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
00991   if (!(ofn->Flags & OFN_SHOWHELP))
00992     ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
00993   if (ofn->Flags & OFN_HIDEREADONLY)
00994     ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
00995   if (lfs->hook)
00996       return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
00997   return TRUE;
00998 }
00999 
01000 int FD31_GetFldrHeight(void)
01001 {
01002   return fldrHeight;
01003 }

Generated on Thu May 24 2012 04:23:29 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.