1 /* 2 * Win 3.1 Style File Dialogs 3 * 4 * Copyright 1994 Martin Ayotte 5 * Copyright 1996 Albrecht Kleine 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 #include <ctype.h> 22 #include <stdlib.h> 23 #include <stdarg.h> 24 #include <stdio.h> 25 #include <string.h> 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winnls.h" 29 #include "wingdi.h" 30 #include "winuser.h" 31 #include "wine/unicode.h" 32 #include "wine/debug.h" 33 #include "winreg.h" 34 #include "winternl.h" 35 #include "commdlg.h" 36 #include "shlwapi.h" 37 #include "cderr.h" 38 39 WINE_DEFAULT_DEBUG_CHANNEL(commdlg); 40 41 #include "cdlg.h" 42 43 #define BUFFILE 512 44 #define BUFFILEALLOC 512 * sizeof(WCHAR) 45 46 static const WCHAR FILE_star[] = {'*','.','*', 0}; 47 static const WCHAR FILE_bslash[] = {'\\', 0}; 48 static const WCHAR FILE_specc[] = {'%','c',':', 0}; 49 static const int fldrHeight = 16; 50 static const int fldrWidth = 20; 51 52 static HICON hFolder = 0; 53 static HICON hFolder2 = 0; 54 static HICON hFloppy = 0; 55 static HICON hHDisk = 0; 56 static HICON hCDRom = 0; 57 static HICON hNet = 0; 58 59 #define FD31_OFN_PROP "FILEDLG_OFN" 60 61 typedef struct tagFD31_DATA 62 { 63 HWND hwnd; /* file dialog window handle */ 64 BOOL hook; /* TRUE if the dialog is hooked */ 65 UINT lbselchstring; /* registered message id */ 66 UINT fileokstring; /* registered message id */ 67 LPARAM lParam; /* save original lparam */ 68 LPCVOID template; /* template for 32 bits resource */ 69 BOOL open; /* TRUE if open dialog, FALSE if save dialog */ 70 LPOPENFILENAMEW ofnW; /* pointer either to the original structure or 71 a W copy for A/16 API */ 72 LPOPENFILENAMEA ofnA; /* original structure if 32bits ansi dialog */ 73 } FD31_DATA, *PFD31_DATA; 74 75 /*********************************************************************** 76 * FD31_Init [internal] 77 */ 78 static BOOL FD31_Init(void) 79 { 80 static BOOL initialized = FALSE; 81 82 if (!initialized) { 83 hFolder = LoadImageA( COMDLG32_hInstance, "FOLDER", IMAGE_ICON, 16, 16, LR_SHARED ); 84 hFolder2 = LoadImageA( COMDLG32_hInstance, "FOLDER2", IMAGE_ICON, 16, 16, LR_SHARED ); 85 hFloppy = LoadImageA( COMDLG32_hInstance, "FLOPPY", IMAGE_ICON, 16, 16, LR_SHARED ); 86 hHDisk = LoadImageA( COMDLG32_hInstance, "HDISK", IMAGE_ICON, 16, 16, LR_SHARED ); 87 hCDRom = LoadImageA( COMDLG32_hInstance, "CDROM", IMAGE_ICON, 16, 16, LR_SHARED ); 88 hNet = LoadImageA( COMDLG32_hInstance, "NETWORK", IMAGE_ICON, 16, 16, LR_SHARED ); 89 if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 || 90 hHDisk == 0 || hCDRom == 0 || hNet == 0) 91 { 92 ERR("Error loading icons!\n"); 93 return FALSE; 94 } 95 initialized = TRUE; 96 } 97 return TRUE; 98 } 99 100 /*********************************************************************** 101 * FD31_StripEditControl [internal] 102 * Strip pathnames off the contents of the edit control. 103 */ 104 static void FD31_StripEditControl(HWND hwnd) 105 { 106 WCHAR temp[BUFFILE], *cp; 107 108 GetDlgItemTextW( hwnd, edt1, temp, sizeof(temp)/sizeof(WCHAR)); 109 cp = strrchrW(temp, '\\'); 110 if (cp != NULL) { 111 strcpyW(temp, cp+1); 112 } 113 cp = strrchrW(temp, ':'); 114 if (cp != NULL) { 115 strcpyW(temp, cp+1); 116 } 117 /* FIXME: shouldn't we do something with the result here? ;-) */ 118 } 119 120 /*********************************************************************** 121 * FD31_CallWindowProc [internal] 122 * 123 * Call the appropriate hook 124 */ 125 static BOOL FD31_CallWindowProc(const FD31_DATA *lfs, UINT wMsg, WPARAM wParam, LPARAM lParam) 126 { 127 BOOL ret; 128 129 if (lfs->ofnA) 130 { 131 TRACE("Call hookA %p (%p, %04x, %08lx, %08lx)\n", 132 lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 133 ret = lfs->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam); 134 TRACE("ret hookA %p (%p, %04x, %08lx, %08lx)\n", 135 lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 136 return ret; 137 } 138 139 TRACE("Call hookW %p (%p, %04x, %08lx, %08lx)\n", 140 lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 141 ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam); 142 TRACE("Ret hookW %p (%p, %04x, %08lx, %08lx)\n", 143 lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam); 144 return ret; 145 } 146 147 /*********************************************************************** 148 * FD31_GetFileType [internal] 149 */ 150 static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index) 151 { 152 int n, i; 153 i = 0; 154 if (cfptr) 155 for ( ;(n = lstrlenW(cfptr)) != 0; i++) 156 { 157 cfptr += n + 1; 158 if (i == index) 159 return cfptr; 160 cfptr += lstrlenW(cfptr) + 1; 161 } 162 if (fptr) 163 for ( ;(n = lstrlenW(fptr)) != 0; i++) 164 { 165 fptr += n + 1; 166 if (i == index) 167 return fptr; 168 fptr += lstrlenW(fptr) + 1; 169 } 170 return FILE_star; /* FIXME */ 171 } 172 173 /*********************************************************************** 174 * FD31_ScanDir [internal] 175 */ 176 static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath) 177 { 178 WCHAR buffer[BUFFILE]; 179 HWND hdlg; 180 LRESULT lRet = TRUE; 181 HCURSOR hCursorWait, oldCursor; 182 183 TRACE("Trying to change to %s\n", debugstr_w(newPath)); 184 if ( newPath[0] && !SetCurrentDirectoryW( newPath )) 185 return FALSE; 186 187 /* get the list of spec files */ 188 lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter, 189 ofn->lpstrFilter, ofn->nFilterIndex - 1), BUFFILE); 190 191 hCursorWait = LoadCursorA(0, (LPSTR)IDC_WAIT); 192 oldCursor = SetCursor(hCursorWait); 193 194 /* list of files */ 195 if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) { 196 WCHAR* scptr; /* ptr on semi-colon */ 197 WCHAR* filter = buffer; 198 199 TRACE("Using filter %s\n", debugstr_w(filter)); 200 SendMessageW(hdlg, LB_RESETCONTENT, 0, 0); 201 while (filter) { 202 scptr = strchrW(filter, ';'); 203 if (scptr) *scptr = 0; 204 while (*filter == ' ') filter++; 205 TRACE("Using file spec %s\n", debugstr_w(filter)); 206 SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter); 207 if (scptr) *scptr = ';'; 208 filter = (scptr) ? (scptr + 1) : 0; 209 } 210 } 211 212 /* list of directories */ 213 strcpyW(buffer, FILE_star); 214 215 if (GetDlgItem(hWnd, lst2) != 0) { 216 lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY); 217 } 218 SetCursor(oldCursor); 219 return lRet; 220 } 221 222 /*********************************************************************** 223 * FD31_WMDrawItem [internal] 224 */ 225 static LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam, 226 int savedlg, const DRAWITEMSTRUCT *lpdis) 227 { 228 WCHAR *str; 229 HICON hIcon; 230 COLORREF oldText = 0, oldBk = 0; 231 232 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1) 233 { 234 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) return FALSE; 235 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, 236 (LPARAM)str); 237 238 if ((lpdis->itemState & ODS_SELECTED) && !savedlg) 239 { 240 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) ); 241 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 242 } 243 if (savedlg) 244 SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) ); 245 246 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1, 247 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED, 248 &(lpdis->rcItem), str, lstrlenW(str), NULL); 249 250 if (lpdis->itemState & ODS_SELECTED) 251 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) ); 252 253 if ((lpdis->itemState & ODS_SELECTED) && !savedlg) 254 { 255 SetBkColor( lpdis->hDC, oldBk ); 256 SetTextColor( lpdis->hDC, oldText ); 257 } 258 HeapFree(GetProcessHeap(), 0, str); 259 return TRUE; 260 } 261 262 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2) 263 { 264 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) 265 return FALSE; 266 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID, 267 (LPARAM)str); 268 269 if (lpdis->itemState & ODS_SELECTED) 270 { 271 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) ); 272 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 273 } 274 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth, 275 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED, 276 &(lpdis->rcItem), str, lstrlenW(str), NULL); 277 278 if (lpdis->itemState & ODS_SELECTED) 279 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) ); 280 281 if (lpdis->itemState & ODS_SELECTED) 282 { 283 SetBkColor( lpdis->hDC, oldBk ); 284 SetTextColor( lpdis->hDC, oldText ); 285 } 286 DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL ); 287 HeapFree(GetProcessHeap(), 0, str); 288 return TRUE; 289 } 290 if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2) 291 { 292 char root[] = "a:"; 293 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) 294 return FALSE; 295 SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID, 296 (LPARAM)str); 297 root[0] += str[2] - 'a'; 298 switch(GetDriveTypeA(root)) 299 { 300 case DRIVE_REMOVABLE: hIcon = hFloppy; break; 301 case DRIVE_CDROM: hIcon = hCDRom; break; 302 case DRIVE_REMOTE: hIcon = hNet; break; 303 case DRIVE_FIXED: 304 default: hIcon = hHDisk; break; 305 } 306 if (lpdis->itemState & ODS_SELECTED) 307 { 308 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) ); 309 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); 310 } 311 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth, 312 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED, 313 &(lpdis->rcItem), str, lstrlenW(str), NULL); 314 315 if (lpdis->itemState & ODS_SELECTED) 316 { 317 SetBkColor( lpdis->hDC, oldBk ); 318 SetTextColor( lpdis->hDC, oldText ); 319 } 320 DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon, 16, 16, 0, 0, DI_NORMAL ); 321 HeapFree(GetProcessHeap(), 0, str); 322 return TRUE; 323 } 324 return FALSE; 325 } 326 327 /*********************************************************************** 328 * FD31_UpdateResult [internal] 329 * update the displayed file name (with path) 330 */ 331 static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr) 332 { 333 int lenstr2; 334 LPOPENFILENAMEW ofnW = lfs->ofnW; 335 LPOPENFILENAMEA ofnA = lfs->ofnA; 336 WCHAR tmpstr2[BUFFILE]; 337 WCHAR *p; 338 339 TRACE("%s\n", debugstr_w(tmpstr)); 340 if(ofnW->Flags & OFN_NOVALIDATE) 341 tmpstr2[0] = '\0'; 342 else 343 GetCurrentDirectoryW(BUFFILE, tmpstr2); 344 lenstr2 = strlenW(tmpstr2); 345 if (lenstr2 > 3) 346 tmpstr2[lenstr2++]='\\'; 347 lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2); 348 if (!ofnW->lpstrFile) 349 return; 350 351 lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile); 352 353 /* set filename offset */ 354 p = PathFindFileNameW(ofnW->lpstrFile); 355 ofnW->nFileOffset = (p - ofnW->lpstrFile); 356 357 /* set extension offset */ 358 p = PathFindExtensionW(ofnW->lpstrFile); 359 ofnW->nFileExtension = (*p) ? (p - ofnW->lpstrFile) + 1 : 0; 360 361 TRACE("file %s, file offset %d, ext offset %d\n", 362 debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension); 363 364 /* update the real client structures if any */ 365 if (ofnA) 366 { 367 LPSTR lpszTemp; 368 if (ofnW->nMaxFile && 369 !WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1, 370 ofnA->lpstrFile, ofnA->nMaxFile, NULL, NULL )) 371 ofnA->lpstrFile[ofnA->nMaxFile-1] = 0; 372 373 /* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */ 374 /* set filename offset */ 375 lpszTemp = PathFindFileNameA(ofnA->lpstrFile); 376 ofnA->nFileOffset = (lpszTemp - ofnA->lpstrFile); 377 378 /* set extension offset */ 379 lpszTemp = PathFindExtensionA(ofnA->lpstrFile); 380 ofnA->nFileExtension = (*lpszTemp) ? (lpszTemp - ofnA->lpstrFile) + 1 : 0; 381 } 382 } 383 384 /*********************************************************************** 385 * FD31_UpdateFileTitle [internal] 386 * update the displayed file name (without path) 387 */ 388 static void FD31_UpdateFileTitle(const FD31_DATA *lfs) 389 { 390 LONG lRet; 391 LPOPENFILENAMEW ofnW = lfs->ofnW; 392 LPOPENFILENAMEA ofnA = lfs->ofnA; 393 394 if (ofnW->lpstrFileTitle != NULL) 395 { 396 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0); 397 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet, 398 (LPARAM)ofnW->lpstrFileTitle ); 399 if (ofnA) 400 { 401 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1, 402 ofnA->lpstrFileTitle, ofnA->nMaxFileTitle, NULL, NULL )) 403 ofnA->lpstrFileTitle[ofnA->nMaxFileTitle-1] = 0; 404 } 405 } 406 } 407 408 /*********************************************************************** 409 * FD31_DirListDblClick [internal] 410 */ 411 static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs ) 412 { 413 LONG lRet; 414 HWND hWnd = lfs->hwnd; 415 LPWSTR pstr; 416 WCHAR tmpstr[BUFFILE]; 417 418 /* get the raw string (with brackets) */ 419 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0); 420 if (lRet == LB_ERR) return TRUE; 421 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC); 422 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet, 423 (LPARAM)pstr); 424 strcpyW( tmpstr, pstr ); 425 HeapFree(GetProcessHeap(), 0, pstr); 426 /* get the selected directory in tmpstr */ 427 if (tmpstr[0] == '[') 428 { 429 tmpstr[lstrlenW(tmpstr) - 1] = 0; 430 strcpyW(tmpstr,tmpstr+1); 431 } 432 strcatW(tmpstr, FILE_bslash); 433 434 FD31_ScanDir(lfs->ofnW, hWnd, tmpstr); 435 /* notify the app */ 436 if (lfs->hook) 437 { 438 if (FD31_CallWindowProc(lfs, lfs->lbselchstring, lst2, 439 MAKELONG(lRet,CD_LBSELCHANGE))) 440 return TRUE; 441 } 442 return TRUE; 443 } 444 445 /*********************************************************************** 446 * FD31_FileListSelect [internal] 447 * called when a new item is picked in the file list 448 */ 449 static LRESULT FD31_FileListSelect( const FD31_DATA *lfs ) 450 { 451 LONG lRet; 452 HWND hWnd = lfs->hwnd; 453 LPWSTR pstr; 454 455 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0); 456 if (lRet == LB_ERR) 457 return TRUE; 458 459 /* set the edit control to the chosen file */ 460 if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) 461 { 462 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet, 463 (LPARAM)pstr); 464 SetDlgItemTextW( hWnd, edt1, pstr ); 465 HeapFree(GetProcessHeap(), 0, pstr); 466 } 467 if (lfs->hook) 468 { 469 FD31_CallWindowProc(lfs, lfs->lbselchstring, lst1, 470 MAKELONG(lRet,CD_LBSELCHANGE)); 471 } 472 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD, 473 CD_LBSELNOITEMS */ 474 return TRUE; 475 } 476 477 /*********************************************************************** 478 * FD31_TestPath [internal] 479 * before accepting the file name, test if it includes wild cards 480 * tries to scan the directory and returns TRUE if no error. 481 */ 482 static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path ) 483 { 484 HWND hWnd = lfs->hwnd; 485 LPWSTR pBeginFileName, pstr2; 486 WCHAR tmpstr2[BUFFILE]; 487 488 pBeginFileName = strrchrW(path, '\\'); 489 if (pBeginFileName == NULL) 490 pBeginFileName = strrchrW(path, ':'); 491 492 if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL) 493 { 494 /* edit control contains wildcards */ 495 if (pBeginFileName != NULL) 496 { 497 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE); 498 *(pBeginFileName + 1) = 0; 499 } 500 else 501 { 502 strcpyW(tmpstr2, path); 503 if(!(lfs->ofnW->Flags & OFN_NOVALIDATE)) 504 *path = 0; 505 } 506 507 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2)); 508 SetDlgItemTextW( hWnd, edt1, tmpstr2 ); 509 FD31_ScanDir(lfs->ofnW, hWnd, path); 510 return (lfs->ofnW->Flags & OFN_NOVALIDATE) != 0; 511 } 512 513 /* no wildcards, we might have a directory or a filename */ 514 /* try appending a wildcard and reading the directory */ 515 516 pstr2 = path + lstrlenW(path); 517 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0) 518 strcatW(path, FILE_bslash); 519 520 /* if ScanDir succeeds, we have changed the directory */ 521 if (FD31_ScanDir(lfs->ofnW, hWnd, path)) 522 return FALSE; /* and path is not a valid file name */ 523 524 /* if not, this must be a filename */ 525 526 *pstr2 = 0; /* remove the wildcard added before */ 527 528 if (pBeginFileName != NULL) 529 { 530 /* strip off the pathname */ 531 *pBeginFileName = 0; 532 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 ); 533 534 lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) ); 535 /* Should we MessageBox() if this fails? */ 536 if (!FD31_ScanDir(lfs->ofnW, hWnd, path)) 537 { 538 return FALSE; 539 } 540 strcpyW(path, tmpstr2); 541 } 542 else 543 SetDlgItemTextW( hWnd, edt1, path ); 544 return TRUE; 545 } 546 547 /*********************************************************************** 548 * FD31_Validate [internal] 549 * called on: click Ok button, Enter in edit, DoubleClick in file list 550 */ 551 static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control, INT itemIndex, 552 BOOL internalUse ) 553 { 554 LONG lRet; 555 HWND hWnd = lfs->hwnd; 556 OPENFILENAMEW ofnsav; 557 LPOPENFILENAMEW ofnW = lfs->ofnW; 558 WCHAR filename[BUFFILE]; 559 int copied_size = min( ofnW->lStructSize, sizeof(ofnsav) ); 560 561 memcpy( &ofnsav, ofnW, copied_size ); /* for later restoring */ 562 563 /* get current file name */ 564 if (path) 565 lstrcpynW(filename, path, sizeof(filename)/sizeof(WCHAR)); 566 else 567 GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename)/sizeof(WCHAR)); 568 569 TRACE("got filename = %s\n", debugstr_w(filename)); 570 /* if we did not click in file list to get there */ 571 if (control != lst1) 572 { 573 if (!FD31_TestPath( lfs, filename) ) 574 return FALSE; 575 } 576 FD31_UpdateResult(lfs, filename); 577 578 if (internalUse) 579 { /* called internally after a change in a combo */ 580 if (lfs->hook) 581 { 582 FD31_CallWindowProc(lfs, lfs->lbselchstring, control, 583 MAKELONG(itemIndex,CD_LBSELCHANGE)); 584 } 585 return TRUE; 586 } 587 588 FD31_UpdateFileTitle(lfs); 589 if (lfs->hook) 590 { 591 lRet = FD31_CallWindowProc(lfs, lfs->fileokstring, 592 0, lfs->lParam ); 593 if (lRet) 594 { 595 memcpy( ofnW, &ofnsav, copied_size ); /* restore old state */ 596 return FALSE; 597 } 598 } 599 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER)) 600 { 601 if (ofnW->lpstrFile) 602 { 603 LPWSTR str = ofnW->lpstrFile; 604 LPWSTR ptr = strrchrW(str, '\\'); 605 str[lstrlenW(str) + 1] = '\0'; 606 *ptr = 0; 607 } 608 } 609 return TRUE; 610 } 611 612 /*********************************************************************** 613 * FD31_DiskChange [internal] 614 * called when a new item is picked in the disk selection combo 615 */ 616 static LRESULT FD31_DiskChange( const FD31_DATA *lfs ) 617 { 618 LONG lRet; 619 HWND hWnd = lfs->hwnd; 620 LPWSTR pstr; 621 WCHAR diskname[BUFFILE]; 622 623 FD31_StripEditControl(hWnd); 624 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L); 625 if (lRet == LB_ERR) 626 return 0; 627 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC); 628 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet, 629 (LPARAM)pstr); 630 wsprintfW(diskname, FILE_specc, pstr[2]); 631 HeapFree(GetProcessHeap(), 0, pstr); 632 633 return FD31_Validate( lfs, diskname, cmb2, lRet, TRUE ); 634 } 635 636 /*********************************************************************** 637 * FD31_FileTypeChange [internal] 638 * called when a new item is picked in the file type combo 639 */ 640 static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs ) 641 { 642 LONG lRet; 643 LPWSTR pstr; 644 645 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0); 646 if (lRet == LB_ERR) 647 return TRUE; 648 lfs->ofnW->nFilterIndex = lRet + 1; 649 if (lfs->ofnA) 650 lfs->ofnA->nFilterIndex = lRet + 1; 651 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0); 652 TRACE("Selected filter : %s\n", debugstr_w(pstr)); 653 654 return FD31_Validate( lfs, pstr, cmb1, lRet, TRUE ); 655 } 656 657 /*********************************************************************** 658 * FD31_WMCommand [internal] 659 */ 660 static LRESULT FD31_WMCommand( HWND hWnd, LPARAM lParam, UINT notification, 661 UINT control, const FD31_DATA *lfs ) 662 { 663 switch (control) 664 { 665 case lst1: /* file list */ 666 FD31_StripEditControl(hWnd); 667 if (notification == LBN_DBLCLK) 668 { 669 return SendMessageW(hWnd, WM_COMMAND, IDOK, 0); 670 } 671 else if (notification == LBN_SELCHANGE) 672 return FD31_FileListSelect( lfs ); 673 break; 674 675 case lst2: /* directory list */ 676 FD31_StripEditControl(hWnd); 677 if (notification == LBN_DBLCLK) 678 return FD31_DirListDblClick( lfs ); 679 break; 680 681 case cmb1: /* file type drop list */ 682 if (notification == CBN_SELCHANGE) 683 return FD31_FileTypeChange( lfs ); 684 break; 685 686 case chx1: 687 break; 688 689 case pshHelp: 690 break; 691 692 case cmb2: /* disk dropdown combo */ 693 if (notification == CBN_SELCHANGE) 694 return FD31_DiskChange( lfs ); 695 break; 696 697 case IDOK: 698 TRACE("OK pressed\n"); 699 if (FD31_Validate( lfs, NULL, control, 0, FALSE )) 700 EndDialog(hWnd, TRUE); 701 return TRUE; 702 703 case IDCANCEL: 704 EndDialog(hWnd, FALSE); 705 return TRUE; 706 707 case IDABORT: /* can be sent by the hook procedure */ 708 EndDialog(hWnd, TRUE); 709 return TRUE; 710 } 711 return FALSE; 712 } 713 714 /************************************************************************ 715 * FD31_MapStringPairsToW [internal] 716 * map string pairs to Unicode 717 */ 718 static LPWSTR FD31_MapStringPairsToW(LPCSTR strA, UINT size) 719 { 720 LPCSTR s; 721 LPWSTR x; 722 unsigned int n, len; 723 724 s = strA; 725 while (*s) 726 s = s+strlen(s)+1; 727 s++; 728 n = s + 1 - strA; /* Don't forget the other \0 */ 729 if (n < size) n = size; 730 731 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 ); 732 x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR)); 733 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len ); 734 return x; 735 } 736 737 738 /************************************************************************ 739 * FD31_DupToW [internal] 740 * duplicates an Ansi string to unicode, with a buffer size 741 */ 742 static LPWSTR FD31_DupToW(LPCSTR str, DWORD size) 743 { 744 LPWSTR strW = NULL; 745 if (str && (size > 0)) 746 { 747 strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); 748 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size ); 749 } 750 return strW; 751 } 752 753 /************************************************************************ 754 * FD31_MapOfnStructA [internal] 755 * map a 32 bits Ansi structure to a Unicode one 756 */ 757 static void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL open) 758 { 759 UNICODE_STRING usBuffer; 760 761 ofnW->hwndOwner = ofnA->hwndOwner; 762 ofnW->hInstance = ofnA->hInstance; 763 if (ofnA->lpstrFilter) 764 ofnW->lpstrFilter = FD31_MapStringPairsToW(ofnA->lpstrFilter, 0); 765 766 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter))) 767 ofnW->lpstrCustomFilter = FD31_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter); 768 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter; 769 ofnW->nFilterIndex = ofnA->nFilterIndex; 770 ofnW->nMaxFile = ofnA->nMaxFile; 771 ofnW->lpstrFile = FD31_DupToW(ofnA->lpstrFile, ofnW->nMaxFile); 772 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle; 773 ofnW->lpstrFileTitle = FD31_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle); 774 if (ofnA->lpstrInitialDir) 775 { 776 RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpstrInitialDir); 777 ofnW->lpstrInitialDir = usBuffer.Buffer; 778 } 779 if (ofnA->lpstrTitle) { 780 RtlCreateUnicodeStringFromAsciiz (&usBuffer, ofnA->lpstrTitle); 781 ofnW->lpstrTitle = usBuffer.Buffer; 782 } else { 783 WCHAR buf[16]; 784 LPWSTR title_tmp; 785 int len; 786 LoadStringW(COMDLG32_hInstance, open ? IDS_OPEN_FILE : IDS_SAVE_AS, 787 buf, sizeof(buf)/sizeof(WCHAR)); 788 len = lstrlenW(buf)+1; 789 title_tmp = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 790 memcpy(title_tmp, buf, len * sizeof(WCHAR)); 791 ofnW->lpstrTitle = title_tmp; 792 } 793 ofnW->Flags = ofnA->Flags; 794 ofnW->nFileOffset = ofnA->nFileOffset; 795 ofnW->nFileExtension = ofnA->nFileExtension; 796 ofnW->lpstrDefExt = FD31_DupToW(ofnA->lpstrDefExt, 3); 797 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName)) 798 { 799 if (!IS_INTRESOURCE(ofnA->lpTemplateName)) 800 { 801 RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpTemplateName); 802 ofnW->lpTemplateName = usBuffer.Buffer; 803 } 804 else /* numbered resource */ 805 ofnW->lpTemplateName = (LPCWSTR) ofnA->lpTemplateName; 806 } 807 if (ofnW->lStructSize > OPENFILENAME_SIZE_VERSION_400W) 808 { 809 ofnW->pvReserved = ofnA->pvReserved; 810 ofnW->dwReserved = ofnA->dwReserved; 811 ofnW->FlagsEx = ofnA->FlagsEx; 812 } 813 } 814 815 816 /************************************************************************ 817 * FD31_FreeOfnW [internal] 818 * Undo all allocations done by FD31_MapOfnStructA 819 */ 820 static void FD31_FreeOfnW(OPENFILENAMEW *ofnW) 821 { 822 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter); 823 HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter); 824 HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile); 825 HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle); 826 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir); 827 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle); 828 if (!IS_INTRESOURCE(ofnW->lpTemplateName)) 829 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName); 830 } 831 832 /************************************************************************ 833 * FD31_DestroyPrivate [internal] 834 * destroys the private object 835 */ 836 static void FD31_DestroyPrivate(PFD31_DATA lfs) 837 { 838 HWND hwnd; 839 if (!lfs) return; 840 hwnd = lfs->hwnd; 841 TRACE("destroying private allocation %p\n", lfs); 842 843 /* if ofnW has been allocated, have to free everything in it */ 844 if (lfs->ofnA) 845 { 846 FD31_FreeOfnW(lfs->ofnW); 847 HeapFree(GetProcessHeap(), 0, lfs->ofnW); 848 } 849 HeapFree(GetProcessHeap(), 0, lfs); 850 RemovePropA(hwnd, FD31_OFN_PROP); 851 } 852 853 /*********************************************************************** 854 * FD31_GetTemplate [internal] 855 * 856 * Get a template (or FALSE if failure) when 16 bits dialogs are used 857 * by a 32 bits application 858 * 859 */ 860 static BOOL FD31_GetTemplate(PFD31_DATA lfs) 861 { 862 LPOPENFILENAMEW ofnW = lfs->ofnW; 863 LPOPENFILENAMEA ofnA = lfs->ofnA; 864 HANDLE hDlgTmpl; 865 866 if (ofnW->Flags & OFN_ENABLETEMPLATEHANDLE) 867 { 868 if (!(lfs->template = LockResource( ofnW->hInstance ))) 869 { 870 COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE ); 871 return FALSE; 872 } 873 } 874 else if (ofnW->Flags & OFN_ENABLETEMPLATE) 875 { 876 HRSRC hResInfo; 877 if (ofnA) 878 hResInfo = FindResourceA( ofnA->hInstance, ofnA->lpTemplateName, (LPSTR)RT_DIALOG ); 879 else 880 hResInfo = FindResourceW( ofnW->hInstance, ofnW->lpTemplateName, (LPWSTR)RT_DIALOG ); 881 if (!hResInfo) 882 { 883 COMDLG32_SetCommDlgExtendedError( CDERR_FINDRESFAILURE ); 884 return FALSE; 885 } 886 if (!(hDlgTmpl = LoadResource( ofnW->hInstance, hResInfo )) || 887 !(lfs->template = LockResource( hDlgTmpl ))) 888 { 889 COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE ); 890 return FALSE; 891 } 892 } 893 else /* get it from internal Wine resource */ 894 { 895 HRSRC hResInfo; 896 if (!(hResInfo = FindResourceA( COMDLG32_hInstance, lfs->open ? "OPEN_FILE" : "SAVE_FILE", (LPSTR)RT_DIALOG ))) 897 { 898 COMDLG32_SetCommDlgExtendedError( CDERR_FINDRESFAILURE ); 899 return FALSE; 900 } 901 if (!(hDlgTmpl = LoadResource( COMDLG32_hInstance, hResInfo )) || 902 !(lfs->template = LockResource( hDlgTmpl ))) 903 { 904 COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE ); 905 return FALSE; 906 } 907 } 908 return TRUE; 909 } 910 911 /************************************************************************ 912 * FD31_AllocPrivate [internal] 913 * allocate a private object to hold 32 bits Unicode 914 * structure that will be used throughout the calls, while 915 * keeping available the original structures and a few variables 916 * On entry : type = dialog procedure type (16,32A,32W) 917 * dlgType = dialog type (open or save) 918 */ 919 static PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode) 920 { 921 PFD31_DATA lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FD31_DATA)); 922 923 TRACE("alloc private buf %p\n", lfs); 924 if (!lfs) return NULL; 925 lfs->hook = FALSE; 926 lfs->lParam = lParam; 927 lfs->open = (dlgType == OPEN_DIALOG); 928 929 if (IsUnicode) 930 { 931 lfs->ofnA = NULL; 932 lfs->ofnW = (LPOPENFILENAMEW) lParam; 933 if (lfs->ofnW->Flags & OFN_ENABLEHOOK) 934 if (lfs->ofnW->lpfnHook) 935 lfs->hook = TRUE; 936 } 937 else 938 { 939 lfs->ofnA = (LPOPENFILENAMEA) lParam; 940 if (lfs->ofnA->Flags & OFN_ENABLEHOOK) 941 if (lfs->ofnA->lpfnHook) 942 lfs->hook = TRUE; 943 lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lfs->ofnA->lStructSize); 944 lfs->ofnW->lStructSize = lfs->ofnA->lStructSize; 945 FD31_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open); 946 } 947 948 if (! FD31_GetTemplate(lfs)) 949 { 950 FD31_DestroyPrivate(lfs); 951 return NULL; 952 } 953 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA); 954 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA); 955 956 return lfs; 957 } 958 959 /*********************************************************************** 960 * FD31_WMInitDialog [internal] 961 */ 962 static LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam) 963 { 964 int i, n; 965 WCHAR tmpstr[BUFFILE]; 966 LPWSTR pstr, old_pstr; 967 LPOPENFILENAMEW ofn; 968 PFD31_DATA lfs = (PFD31_DATA) lParam; 969 970 if (!lfs) return FALSE; 971 SetPropA(hWnd, FD31_OFN_PROP, lfs); 972 lfs->hwnd = hWnd; 973 ofn = lfs->ofnW; 974 975 TRACE("flags=%x initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir)); 976 977 SetWindowTextW( hWnd, ofn->lpstrTitle ); 978 /* read custom filter information */ 979 if (ofn->lpstrCustomFilter) 980 { 981 pstr = ofn->lpstrCustomFilter; 982 n = 0; 983 TRACE("lpstrCustomFilter = %p\n", pstr); 984 while(*pstr) 985 { 986 old_pstr = pstr; 987 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0, 988 (LPARAM)(ofn->lpstrCustomFilter) + n ); 989 n += lstrlenW(pstr) + 1; 990 pstr += lstrlenW(pstr) + 1; 991 TRACE("add str=%s associated to %s\n", 992 debugstr_w(old_pstr), debugstr_w(pstr)); 993 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr); 994 n += lstrlenW(pstr) + 1; 995 pstr += lstrlenW(pstr) + 1; 996 } 997 } 998 /* read filter information */ 999 if (ofn->lpstrFilter) { 1000 pstr = (LPWSTR) ofn->lpstrFilter; 1001 n = 0; 1002 while(*pstr) { 1003 old_pstr = pstr; 1004 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0, 1005 (LPARAM)(ofn->lpstrFilter + n) ); 1006 n += lstrlenW(pstr) + 1; 1007 pstr += lstrlenW(pstr) + 1; 1008 TRACE("add str=%s associated to %s\n", 1009 debugstr_w(old_pstr), debugstr_w(pstr)); 1010 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr); 1011 n += lstrlenW(pstr) + 1; 1012 pstr += lstrlenW(pstr) + 1; 1013 } 1014 } 1015 /* set default filter */ 1016 if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL) 1017 ofn->nFilterIndex = 1; 1018 SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0); 1019 if (ofn->lpstrFile && ofn->lpstrFile[0]) 1020 { 1021 TRACE( "SetText of edt1 to %s\n", debugstr_w(ofn->lpstrFile) ); 1022 SetDlgItemTextW( hWnd, edt1, ofn->lpstrFile ); 1023 } 1024 else 1025 { 1026 lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter, 1027 ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE); 1028 TRACE("nFilterIndex = %d, SetText of edt1 to %s\n", 1029 ofn->nFilterIndex, debugstr_w(tmpstr)); 1030 SetDlgItemTextW( hWnd, edt1, tmpstr ); 1031 } 1032 /* get drive list */ 1033 *tmpstr = 0; 1034 DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE); 1035 /* read initial directory */ 1036 /* FIXME: Note that this is now very version-specific (See MSDN description of 1037 * the OPENFILENAME structure). For example under 2000/XP any path in the 1038 * lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME 1039 */ 1040 if (ofn->lpstrInitialDir != NULL) 1041 { 1042 int len; 1043 lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511); 1044 len = lstrlenW(tmpstr); 1045 if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') { 1046 tmpstr[len]='\\'; 1047 tmpstr[len+1]='\0'; 1048 } 1049 } 1050 else 1051 *tmpstr = 0; 1052 if (!FD31_ScanDir(ofn, hWnd, tmpstr)) { 1053 *tmpstr = 0; 1054 if (!FD31_ScanDir(ofn, hWnd, tmpstr)) 1055 WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr)); 1056 } 1057 /* select current drive in combo 2, omit missing drives */ 1058 { 1059 char dir[MAX_PATH]; 1060 char str[4] = "a:\\"; 1061 GetCurrentDirectoryA( sizeof(dir), dir ); 1062 for(i = 0, n = -1; i < 26; i++) 1063 { 1064 str[0] = 'a' + i; 1065 if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++; 1066 if (toupper(str[0]) == toupper(dir[0])) break; 1067 } 1068 } 1069 SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0); 1070 if (!(ofn->Flags & OFN_SHOWHELP)) 1071 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE); 1072 if (ofn->Flags & OFN_HIDEREADONLY) 1073 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE); 1074 if (lfs->hook) 1075 return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam); 1076 return TRUE; 1077 } 1078 1079 static int FD31_GetFldrHeight(void) 1080 { 1081 return fldrHeight; 1082 } 1083 1084 /*********************************************************************** 1085 * FD31_WMMeasureItem [internal] 1086 */ 1087 static LONG FD31_WMMeasureItem(LPARAM lParam) 1088 { 1089 LPMEASUREITEMSTRUCT lpmeasure; 1090 1091 lpmeasure = (LPMEASUREITEMSTRUCT)lParam; 1092 lpmeasure->itemHeight = FD31_GetFldrHeight(); 1093 return TRUE; 1094 } 1095 1096 1097 /*********************************************************************** 1098 * FileOpenDlgProc [internal] 1099 * Used for open and save, in fact. 1100 */ 1101 static INT_PTR CALLBACK FD31_FileOpenDlgProc(HWND hWnd, UINT wMsg, 1102 WPARAM wParam, LPARAM lParam) 1103 { 1104 PFD31_DATA lfs = (PFD31_DATA)GetPropA( hWnd, FD31_OFN_PROP ); 1105 1106 TRACE("msg=%x wparam=%lx lParam=%lx\n", wMsg, wParam, lParam); 1107 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook) 1108 { 1109 INT_PTR lRet; 1110 lRet = (INT_PTR)FD31_CallWindowProc( lfs, wMsg, wParam, lParam ); 1111 if (lRet) return lRet; /* else continue message processing */ 1112 } 1113 switch (wMsg) 1114 { 1115 case WM_INITDIALOG: 1116 return FD31_WMInitDialog( hWnd, wParam, lParam ); 1117 1118 case WM_MEASUREITEM: 1119 return FD31_WMMeasureItem( lParam ); 1120 1121 case WM_DRAWITEM: 1122 return FD31_WMDrawItem( hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam ); 1123 1124 case WM_COMMAND: 1125 return FD31_WMCommand( hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs ); 1126 #if 0 1127 case WM_CTLCOLOR: 1128 SetBkColor( (HDC16)wParam, 0x00C0C0C0 ); 1129 switch (HIWORD(lParam)) 1130 { 1131 case CTLCOLOR_BTN: 1132 SetTextColor( (HDC16)wParam, 0x00000000 ); 1133 return hGRAYBrush; 1134 case CTLCOLOR_STATIC: 1135 SetTextColor( (HDC16)wParam, 0x00000000 ); 1136 return hGRAYBrush; 1137 } 1138 break; 1139 #endif 1140 } 1141 return FALSE; 1142 } 1143 1144 /*********************************************************************** 1145 * GetFileName31A [internal] 1146 * 1147 * Creates a win31 style dialog box for the user to select a file to open/save. 1148 */ 1149 BOOL GetFileName31A( OPENFILENAMEA *lpofn, UINT dlgType ) 1150 { 1151 BOOL bRet = FALSE; 1152 PFD31_DATA lfs; 1153 1154 if (!lpofn || !FD31_Init()) return FALSE; 1155 1156 TRACE("ofn flags %08x\n", lpofn->Flags); 1157 lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, FALSE); 1158 if (lfs) 1159 { 1160 bRet = DialogBoxIndirectParamA( COMDLG32_hInstance, lfs->template, lpofn->hwndOwner, 1161 FD31_FileOpenDlgProc, (LPARAM)lfs); 1162 FD31_DestroyPrivate(lfs); 1163 } 1164 1165 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile); 1166 return bRet; 1167 } 1168 1169 /*********************************************************************** 1170 * GetFileName31W [internal] 1171 * 1172 * Creates a win31 style dialog box for the user to select a file to open/save 1173 */ 1174 BOOL GetFileName31W( OPENFILENAMEW *lpofn, UINT dlgType ) 1175 { 1176 BOOL bRet = FALSE; 1177 PFD31_DATA lfs; 1178 1179 if (!lpofn || !FD31_Init()) return FALSE; 1180 1181 lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, TRUE); 1182 if (lfs) 1183 { 1184 bRet = DialogBoxIndirectParamW( COMDLG32_hInstance, lfs->template, lpofn->hwndOwner, 1185 FD31_FileOpenDlgProc, (LPARAM)lfs); 1186 FD31_DestroyPrivate(lfs); 1187 } 1188 1189 TRACE("file %s, file offset %d, ext offset %d\n", 1190 debugstr_w(lpofn->lpstrFile), lpofn->nFileOffset, lpofn->nFileExtension); 1191 return bRet; 1192 } 1193