Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfiledlg31.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
1.7.6.1
|