2 * COMMDLG - File Dialogs
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "wine/winbase16.h"
30 #include "wine/winuser16.h"
31 #include "wine/unicode.h"
34 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
42 #define BUFFILEALLOC 512 * sizeof(WCHAR)
46 HWND hwnd; /* file dialog window handle */
47 BOOL hook; /* TRUE if the dialog is hooked */
48 UINT lbselchstring; /* registered message id */
49 UINT fileokstring; /* registered message id */
50 LPARAM lParam; /* save original lparam */
51 HANDLE16 hDlgTmpl16; /* handle for resource 16 */
52 HANDLE16 hResource16; /* handle for allocated resource 16 */
53 HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
54 LPCVOID template; /* template for 32 bits resource */
55 BOOL open; /* TRUE if open dialog, FALSE if save dialog */
56 OPENFILENAMEW *ofnW; /* original structure or work struct */
57 OPENFILENAMEA *ofnA; /* original structure if 32bits ansi dialog */
58 OPENFILENAME16 *ofn16; /* original structure if 16 bits dialog */
62 #define LFSPRIVATE struct FSPRIVATE *
68 static const WCHAR FILE_star[] = {'*','.','*', 0};
69 static const WCHAR FILE_bslash[] = {'\\', 0};
70 static const WCHAR FILE_specc[] = {'%','c',':', 0};
72 static HICON hFolder = 0;
73 static HICON hFolder2 = 0;
74 static HICON hFloppy = 0;
75 static HICON hHDisk = 0;
76 static HICON hCDRom = 0;
77 static HICON hNet = 0;
78 static const int fldrHeight = 16;
79 static const int fldrWidth = 20;
81 #define OFN_PROP "FILEDLG_OFN"
83 static char defaultopen[]="Open File";
84 static char defaultsave[]="Save as";
86 /***********************************************************************
88 * Windows 3.1 style OpenFileName/SaveFileName dialog
92 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
94 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
97 static LRESULT WINAPI FileOpenDlgProc(HWND hDlg, UINT msg,
98 WPARAM wParam, LPARAM lParam);
100 /***********************************************************************
101 * FileDlg_Init [internal]
103 static BOOL FileDlg_Init(void)
105 static BOOL initialized = 0;
108 HINSTANCE inst = GetModuleHandleA( "comdlg32.dll" );
111 ERR( "cannot get comdlg32.dll instance\n" );
114 hFolder = LoadImageA( inst, "FOLDER", IMAGE_ICON, 16, 16, LR_SHARED );
115 hFolder2 = LoadImageA( inst, "FOLDER2", IMAGE_ICON, 16, 16, LR_SHARED );
116 hFloppy = LoadImageA( inst, "FLOPPY", IMAGE_ICON, 16, 16, LR_SHARED );
117 hHDisk = LoadImageA( inst, "HDISK", IMAGE_ICON, 16, 16, LR_SHARED );
118 hCDRom = LoadImageA( inst, "CDROM", IMAGE_ICON, 16, 16, LR_SHARED );
119 hNet = LoadImageA( inst, "NETWORK", IMAGE_ICON, 16, 16, LR_SHARED );
120 if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 ||
121 hHDisk == 0 || hCDRom == 0 || hNet == 0)
123 ERR("Error loading icons !\n");
132 /***********************************************************************
133 * Get32BitsTemplate [internal]
135 * Get a template (or FALSE if failure) when 16 bits dialogs are used
136 * by a 32 bits application
139 BOOL Get32BitsTemplate(LFSPRIVATE lfs)
141 LPOPENFILENAMEW ofnW = lfs->ofnW;
144 if (ofnW->Flags & OFN_ENABLETEMPLATEHANDLE)
146 if (!(lfs->template = LockResource( ofnW->hInstance )))
148 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
152 else if (ofnW->Flags & OFN_ENABLETEMPLATE)
156 hResInfo = FindResourceA(lfs->ofnA->hInstance,
157 lfs->ofnA->lpTemplateName,
160 hResInfo = FindResourceW(ofnW->hInstance,
161 ofnW->lpTemplateName,
165 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
168 if (!(hDlgTmpl = LoadResource(ofnW->hInstance,
170 !(lfs->template = LockResource(hDlgTmpl)))
172 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
175 } else { /* get it from internal Wine resource */
177 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
178 lfs->open? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
180 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
183 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
184 !(lfs->template = LockResource( hDlgTmpl )))
186 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
194 /***********************************************************************
195 * Get16BitsTemplate [internal]
197 * Get a template (FALSE if failure) when 16 bits dialogs are used
198 * by a 16 bits application
201 BOOL Get16BitsTemplate(LFSPRIVATE lfs)
203 LPOPENFILENAME16 ofn16 = lfs->ofn16;
205 HGLOBAL16 hGlobal16 = 0;
207 if (ofn16->Flags & OFN_ENABLETEMPLATEHANDLE)
208 lfs->hDlgTmpl16 = ofn16->hInstance;
209 else if (ofn16->Flags & OFN_ENABLETEMPLATE)
212 if (!(hResInfo = FindResource16(ofn16->hInstance,
213 MapSL(ofn16->lpTemplateName),
216 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
219 if (!(lfs->hDlgTmpl16 = LoadResource16( ofn16->hInstance, hResInfo )))
221 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
224 lfs->hResource16 = lfs->hDlgTmpl16;
227 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
233 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
234 lfs->open ? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
236 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
239 if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
240 !(template32 = LockResource( hDlgTmpl32 )))
242 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
245 size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
246 hGlobal16 = GlobalAlloc16(0, size);
249 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
250 ERR("alloc failure for %ld bytes\n", size);
253 template = GlobalLock16(hGlobal16);
256 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
257 ERR("global lock failure for %x handle\n", hGlobal16);
258 GlobalFree16(hGlobal16);
261 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
262 lfs->hDlgTmpl16 = hGlobal16;
263 lfs->hGlobal16 = hGlobal16;
268 /***********************************************************************
269 * FILEDLG_StripEditControl [internal]
270 * Strip pathnames off the contents of the edit control.
272 static void FILEDLG_StripEditControl(HWND hwnd)
274 WCHAR temp[BUFFILE], *cp;
276 GetDlgItemTextW( hwnd, edt1, temp, sizeof(temp)/sizeof(WCHAR));
277 cp = strrchrW(temp, '\\');
281 cp = strrchrW(temp, ':');
285 /* FIXME: shouldn't we do something with the result here? ;-) */
290 /***********************************************************************
291 * FILEDLG_CallWindowProc [internal]
293 * Call the appropriate hook
295 static BOOL FILEDLG_CallWindowProc(LFSPRIVATE lfs, UINT wMsg, WPARAM wParam,
300 return (BOOL16) CallWindowProc16(
301 (WNDPROC16)lfs->ofn16->lpfnHook, HWND_16(lfs->hwnd),
302 (UINT16)wMsg, (WPARAM16)wParam, lParam);
306 return (BOOL) CallWindowProcA(
307 (WNDPROC)lfs->ofnA->lpfnHook, lfs->hwnd,
308 wMsg, wParam, lParam);
313 return (BOOL) CallWindowProcW(
314 (WNDPROC)lfs->ofnW->lpfnHook, lfs->hwnd,
315 wMsg, wParam, lParam);
321 /***********************************************************************
322 * FILEDLG_ScanDir [internal]
324 static BOOL FILEDLG_ScanDir(HWND hWnd, LPWSTR newPath)
326 WCHAR buffer[BUFFILE];
329 HCURSOR hCursorWait, oldCursor;
331 if ( !SetCurrentDirectoryW( newPath ))
333 lstrcpynW(buffer, newPath, sizeof(buffer)/sizeof(WCHAR));
335 /* get the list of spec files */
336 GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer)/sizeof(WCHAR));
338 hCursorWait = LoadCursorA(0, IDC_WAITA);
339 oldCursor = SetCursor(hCursorWait);
342 if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) {
343 WCHAR* scptr; /* ptr on semi-colon */
344 WCHAR* filter = buffer;
346 TRACE("Using filter %s\n", debugstr_w(filter));
347 SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
349 scptr = strchrW(filter, ';');
350 if (scptr) *scptr = 0;
351 while (*filter == ' ') filter++;
352 TRACE("Using file spec %s\n", debugstr_w(filter));
353 if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
355 if (scptr) *scptr = ';';
356 filter = (scptr) ? (scptr + 1) : 0;
360 /* list of directories */
361 strcpyW(buffer, FILE_star);
363 if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
364 lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
366 SetCursor(oldCursor);
371 /***********************************************************************
372 * FILEDLG_GetFileType [internal]
375 static LPWSTR FILEDLG_GetFileType(LPWSTR cfptr, LPWSTR fptr, WORD index)
380 for ( ;(n = lstrlenW(cfptr)) != 0; i++)
385 cfptr += lstrlenW(cfptr) + 1;
388 for ( ;(n = lstrlenW(fptr)) != 0; i++)
393 fptr += lstrlenW(fptr) + 1;
395 return (LPWSTR) FILE_star; /* FIXME */
398 /***********************************************************************
399 * FILEDLG_WMDrawItem [internal]
401 static LONG FILEDLG_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
402 int savedlg, LPDRAWITEMSTRUCT lpdis)
406 COLORREF oldText = 0, oldBk = 0;
408 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
410 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) return FALSE;
411 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
414 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
416 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
417 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
420 SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
422 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1,
423 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
424 &(lpdis->rcItem), str, lstrlenW(str), NULL);
426 if (lpdis->itemState & ODS_SELECTED)
427 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
429 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
431 SetBkColor( lpdis->hDC, oldBk );
432 SetTextColor( lpdis->hDC, oldText );
434 HeapFree(GetProcessHeap(), 0, str);
438 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
440 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
442 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
445 if (lpdis->itemState & ODS_SELECTED)
447 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
448 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
450 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
451 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
452 &(lpdis->rcItem), str, lstrlenW(str), NULL);
454 if (lpdis->itemState & ODS_SELECTED)
455 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
457 if (lpdis->itemState & ODS_SELECTED)
459 SetBkColor( lpdis->hDC, oldBk );
460 SetTextColor( lpdis->hDC, oldText );
462 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
463 HeapFree(GetProcessHeap(), 0, str);
466 if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
469 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
471 SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID,
473 root[0] += str[2] - 'a';
474 switch(GetDriveTypeA(root))
476 case DRIVE_REMOVABLE: hIcon = hFloppy; break;
477 case DRIVE_CDROM: hIcon = hCDRom; break;
478 case DRIVE_REMOTE: hIcon = hNet; break;
480 default: hIcon = hHDisk; break;
482 if (lpdis->itemState & ODS_SELECTED)
484 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
485 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
487 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
488 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
489 &(lpdis->rcItem), str, lstrlenW(str), NULL);
491 if (lpdis->itemState & ODS_SELECTED)
493 SetBkColor( lpdis->hDC, oldBk );
494 SetTextColor( lpdis->hDC, oldText );
496 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
497 HeapFree(GetProcessHeap(), 0, str);
503 /***********************************************************************
504 * FILEDLG_WMMeasureItem [internal]
506 static LONG FILEDLG_WMMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
508 LPMEASUREITEMSTRUCT lpmeasure;
510 lpmeasure = (LPMEASUREITEMSTRUCT)lParam;
511 lpmeasure->itemHeight = fldrHeight;
515 /***********************************************************************
516 * FILEDLG_WMMeasureItem16 [internal]
518 static LONG FILEDLG_WMMeasureItem16(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
520 LPMEASUREITEMSTRUCT16 lpmeasure;
522 lpmeasure = MapSL(lParam);
523 lpmeasure->itemHeight = fldrHeight;
527 /***********************************************************************
528 * FILEDLG_WMInitDialog [internal]
531 static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
534 WCHAR tmpstr[BUFFILE];
535 LPWSTR pstr, old_pstr;
537 LFSPRIVATE lfs = (LFSPRIVATE) lParam;
539 if (!lfs) return FALSE;
540 SetPropA(hWnd, OFN_PROP, (HANDLE)lfs);
544 TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
546 SetWindowTextW( hWnd, ofn->lpstrTitle );
547 /* read custom filter information */
548 if (ofn->lpstrCustomFilter)
550 pstr = ofn->lpstrCustomFilter;
552 TRACE("lpstrCustomFilter = %p\n", pstr);
556 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
557 (LPARAM)(ofn->lpstrCustomFilter) + n );
558 n += lstrlenW(pstr) + 1;
559 pstr += lstrlenW(pstr) + 1;
560 TRACE("add str=%s associated to %s\n",
561 debugstr_w(old_pstr), debugstr_w(pstr));
562 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
563 n += lstrlenW(pstr) + 1;
564 pstr += lstrlenW(pstr) + 1;
567 /* read filter information */
568 if (ofn->lpstrFilter) {
569 pstr = (LPWSTR) ofn->lpstrFilter;
573 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
574 (LPARAM)(ofn->lpstrFilter + n) );
575 n += lstrlenW(pstr) + 1;
576 pstr += lstrlenW(pstr) + 1;
577 TRACE("add str=%s associated to %s\n",
578 debugstr_w(old_pstr), debugstr_w(pstr));
579 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
580 n += lstrlenW(pstr) + 1;
581 pstr += lstrlenW(pstr) + 1;
584 /* set default filter */
585 if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
586 ofn->nFilterIndex = 1;
587 SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
588 lstrcpynW(tmpstr, FILEDLG_GetFileType(ofn->lpstrCustomFilter,
589 (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
590 TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
591 ofn->nFilterIndex, debugstr_w(tmpstr));
592 SetDlgItemTextW( hWnd, edt1, tmpstr );
595 DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
596 /* read initial directory */
597 /* FIXME: Note that this is now very version-specific (See MSDN description of
598 * the OPENFILENAME structure). For example under 2000/XP any path in the
599 * lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME
601 if (ofn->lpstrInitialDir != NULL)
604 lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
605 len = lstrlenW(tmpstr);
606 if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') {
613 if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
615 if (!FILEDLG_ScanDir(hWnd, tmpstr))
616 WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
618 /* select current drive in combo 2, omit missing drives */
621 char str[4] = "a:\\";
622 GetCurrentDirectoryA( sizeof(dir), dir );
623 for(i = 0, n = -1; i < 26; i++)
626 if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++;
627 if (toupper(str[0]) == toupper(dir[0])) break;
630 SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
631 if (!(ofn->Flags & OFN_SHOWHELP))
632 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
633 if (ofn->Flags & OFN_HIDEREADONLY)
634 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
636 return (BOOL) FILEDLG_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
640 /***********************************************************************
641 * FILEDLG_UpdateResult [internal]
642 * update the displayed file name (with path)
644 void FILEDLG_UpdateResult(LFSPRIVATE lfs, WCHAR *tmpstr)
647 LPOPENFILENAMEW ofnW = lfs->ofnW;
648 WCHAR tmpstr2[BUFFILE];
650 GetCurrentDirectoryW(BUFFILE, tmpstr2);
651 lenstr2 = strlenW(tmpstr2);
653 tmpstr2[lenstr2++]='\\';
654 lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
656 lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
657 ofnW->nFileOffset = strrchrW(tmpstr2,'\\') - tmpstr2 +1;
658 ofnW->nFileExtension = 0;
659 while(tmpstr2[ofnW->nFileExtension] != '.' && tmpstr2[ofnW->nFileExtension] != '\0')
660 ofnW->nFileExtension++;
661 if (tmpstr2[ofnW->nFileExtension] == '\0')
662 ofnW->nFileExtension = 0;
664 ofnW->nFileExtension++;
665 /* update the real client structures if any */
667 { /* we have to convert to short (8.3) path */
668 char tmp[1024]; /* MAX_PATHNAME_LEN */
669 LPOPENFILENAME16 ofn16 = lfs->ofn16;
670 char *dest = MapSL(ofn16->lpstrFile);
671 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
672 tmp, ofnW->nMaxFile, NULL, NULL ))
673 tmp[ofnW->nMaxFile-1] = 0;
674 GetShortPathNameA(tmp, dest, ofn16->nMaxFile);
676 /* the same procedure as every year... */
677 ofn16->nFileOffset = strrchr(dest,'\\') - dest +1;
678 ofn16->nFileExtension = 0;
679 while(dest[ofn16->nFileExtension] != '.' && dest[ofn16->nFileExtension] != '\0')
680 ofn16->nFileExtension++;
681 if (dest[ofn16->nFileExtension] == '\0')
682 ofn16->nFileExtension = 0;
684 ofn16->nFileExtension++;
688 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
689 lfs->ofnA->lpstrFile, ofnW->nMaxFile, NULL, NULL ))
690 lfs->ofnA->lpstrFile[ofnW->nMaxFile-1] = 0;
691 lfs->ofnA->nFileOffset = ofnW->nFileOffset;
692 lfs->ofnA->nFileExtension = ofnW->nFileExtension;
697 /***********************************************************************
698 * FILEDLG_UpdateFileTitle [internal]
699 * update the displayed file name (without path)
701 void FILEDLG_UpdateFileTitle(LFSPRIVATE lfs)
704 LPOPENFILENAMEW ofnW = lfs->ofnW;
705 if (ofnW->lpstrFileTitle != NULL)
707 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
708 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
709 (LPARAM)ofnW->lpstrFileTitle );
712 char *dest = MapSL(lfs->ofn16->lpstrFileTitle);
713 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
714 dest, ofnW->nMaxFileTitle, NULL, NULL ))
715 dest[ofnW->nMaxFileTitle-1] = 0;
719 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
720 lfs->ofnA->lpstrFileTitle, ofnW->nMaxFileTitle, NULL, NULL ))
721 lfs->ofnA->lpstrFileTitle[ofnW->nMaxFileTitle-1] = 0;
728 /***********************************************************************
729 * FILEDLG_DirListDblClick [internal]
731 static LRESULT FILEDLG_DirListDblClick( LFSPRIVATE lfs )
734 HWND hWnd = lfs->hwnd;
736 WCHAR tmpstr[BUFFILE];
738 /* get the raw string (with brackets) */
739 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
740 if (lRet == LB_ERR) return TRUE;
741 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
742 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
744 strcpyW( tmpstr, pstr );
745 HeapFree(GetProcessHeap(), 0, pstr);
746 /* get the selected directory in tmpstr */
747 if (tmpstr[0] == '[')
749 tmpstr[lstrlenW(tmpstr) - 1] = 0;
750 strcpyW(tmpstr,tmpstr+1);
752 strcatW(tmpstr, FILE_bslash);
754 FILEDLG_ScanDir(hWnd, tmpstr);
758 if (FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst2,
759 MAKELONG(lRet,CD_LBSELCHANGE)))
766 /***********************************************************************
767 * FILEDLG_FileListSelect [internal]
768 * called when a new item is picked in the file list
770 static LRESULT FILEDLG_FileListSelect( LFSPRIVATE lfs )
773 HWND hWnd = lfs->hwnd;
776 lRet = SendDlgItemMessageW(hWnd, lst1, LB_GETCURSEL16, 0, 0);
780 /* set the edit control to the choosen file */
781 if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
783 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
785 SetDlgItemTextW( hWnd, edt1, pstr );
786 HeapFree(GetProcessHeap(), 0, pstr);
790 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst1,
791 MAKELONG(lRet,CD_LBSELCHANGE));
793 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
798 /***********************************************************************
799 * FILEDLG_TestPath [internal]
800 * before accepting the file name, test if it includes wild cards
801 * tries to scan the directory and returns TRUE if no error.
803 static LRESULT FILEDLG_TestPath( LFSPRIVATE lfs, LPWSTR path )
805 HWND hWnd = lfs->hwnd;
806 LPWSTR pBeginFileName, pstr2;
807 WCHAR tmpstr2[BUFFILE];
809 pBeginFileName = strrchrW(path, '\\');
810 if (pBeginFileName == NULL)
811 pBeginFileName = strrchrW(path, ':');
813 if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL)
815 /* edit control contains wildcards */
816 if (pBeginFileName != NULL)
818 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
819 *(pBeginFileName + 1) = 0;
823 strcpyW(tmpstr2, path);
827 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
828 SetDlgItemTextW( hWnd, edt1, tmpstr2 );
829 FILEDLG_ScanDir(hWnd, path);
833 /* no wildcards, we might have a directory or a filename */
834 /* try appending a wildcard and reading the directory */
836 pstr2 = path + lstrlenW(path);
837 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
838 strcatW(path, FILE_bslash);
840 /* if ScanDir succeeds, we have changed the directory */
841 if (FILEDLG_ScanDir(hWnd, path))
844 /* if not, this must be a filename */
846 *pstr2 = 0; /* remove the wildcard added before */
848 if (pBeginFileName != NULL)
850 /* strip off the pathname */
852 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
854 lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
855 /* Should we MessageBox() if this fails? */
856 if (!FILEDLG_ScanDir(hWnd, path))
860 strcpyW(path, tmpstr2);
863 SetDlgItemTextW( hWnd, edt1, path );
867 /***********************************************************************
868 * FILEDLG_Validate [internal]
869 * called on: click Ok button, Enter in edit, DoubleClick in file list
871 static LRESULT FILEDLG_Validate( LFSPRIVATE lfs, LPWSTR path, UINT control, INT itemIndex,
875 HWND hWnd = lfs->hwnd;
876 OPENFILENAMEW ofnsav;
877 LPOPENFILENAMEW ofnW = lfs->ofnW;
878 WCHAR filename[BUFFILE];
880 ofnsav = *ofnW; /* for later restoring */
882 /* get current file name */
884 lstrcpynW(filename, path, sizeof(filename)/sizeof(WCHAR));
886 GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename)/sizeof(WCHAR));
888 /* if we did not click in file list to get there */
891 if (!FILEDLG_TestPath( lfs, filename) )
894 FILEDLG_UpdateResult(lfs, filename);
897 { /* called internally after a change in a combo */
900 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, control,
901 MAKELONG(itemIndex,CD_LBSELCHANGE));
906 FILEDLG_UpdateFileTitle(lfs);
909 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, lfs->fileokstring,
913 *ofnW = ofnsav; /* restore old state */
917 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
921 LPWSTR str = (LPWSTR)ofnW->lpstrFile;
922 LPWSTR ptr = strrchrW(str, '\\');
923 str[lstrlenW(str) + 1] = '\0';
930 /***********************************************************************
931 * FILEDLG_DiskChange [internal]
932 * called when a new item is picked in the disk selection combo
934 static LRESULT FILEDLG_DiskChange( LFSPRIVATE lfs )
937 HWND hWnd = lfs->hwnd;
939 WCHAR diskname[BUFFILE];
941 FILEDLG_StripEditControl(hWnd);
942 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
945 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
946 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
948 wsprintfW(diskname, FILE_specc, pstr[2]);
949 HeapFree(GetProcessHeap(), 0, pstr);
951 return FILEDLG_Validate( lfs, diskname, cmb2, lRet, TRUE );
955 /***********************************************************************
956 * FILEDLG_FileTypeChange [internal]
957 * called when a new item is picked in the file type combo
959 static LRESULT FILEDLG_FileTypeChange( LFSPRIVATE lfs )
962 WCHAR diskname[BUFFILE];
967 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
970 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
971 TRACE("Selected filter : %s\n", debugstr_w(pstr));
972 SetDlgItemTextW( lfs->hwnd, edt1, pstr );
974 return FILEDLG_Validate( lfs, NULL, cmb1, lRet, TRUE );
977 /***********************************************************************
978 * FILEDLG_WMCommand [internal]
980 static LRESULT FILEDLG_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
981 UINT control, LFSPRIVATE lfs )
985 case lst1: /* file list */
986 FILEDLG_StripEditControl(hWnd);
987 if (notification == LBN_DBLCLK)
989 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
990 EndDialog(hWnd, TRUE);
993 else if (notification == LBN_SELCHANGE)
994 return FILEDLG_FileListSelect( lfs );
997 case lst2: /* directory list */
998 FILEDLG_StripEditControl(hWnd);
999 if (notification == LBN_DBLCLK)
1000 return FILEDLG_DirListDblClick( lfs );
1003 case cmb1: /* file type drop list */
1004 if (notification == CBN_SELCHANGE)
1005 return FILEDLG_FileTypeChange( lfs );
1014 case cmb2: /* disk dropdown combo */
1015 if (notification == CBN_SELCHANGE)
1016 return FILEDLG_DiskChange( lfs );
1020 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
1021 EndDialog(hWnd, TRUE);
1025 EndDialog(hWnd, FALSE);
1028 case IDABORT: /* can be sent by the hook procedure */
1029 EndDialog(hWnd, TRUE);
1035 /***********************************************************************
1036 * FILEDLG_MapDrawItemStruct [internal]
1037 * map a 16 bits drawitem struct to 32
1039 void FILEDLG_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)
1041 lpdis->CtlType = lpdis16->CtlType;
1042 lpdis->CtlID = lpdis16->CtlID;
1043 lpdis->itemID = lpdis16->itemID;
1044 lpdis->itemAction = lpdis16->itemAction;
1045 lpdis->itemState = lpdis16->itemState;
1046 lpdis->hwndItem = HWND_32(lpdis16->hwndItem);
1047 lpdis->hDC = lpdis16->hDC;
1048 lpdis->rcItem.right = lpdis16->rcItem.right;
1049 lpdis->rcItem.left = lpdis16->rcItem.left;
1050 lpdis->rcItem.top = lpdis16->rcItem.top;
1051 lpdis->rcItem.bottom = lpdis16->rcItem.bottom;
1052 lpdis->itemData = lpdis16->itemData;
1055 /************************************************************************
1056 * FILEDLG_MapStringPairsToW [internal]
1057 * map string pairs to Unicode
1059 static LPWSTR FILEDLG_MapStringPairsToW(LPCSTR strA, UINT size)
1069 n = s + 1 - strA; /* Don't forget the other \0 */
1070 if (n < size) n = size;
1072 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
1073 x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR));
1074 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
1079 /************************************************************************
1080 * FILEDLG_DupToW [internal]
1081 * duplicates an Ansi string to unicode, with a buffer size
1083 LPWSTR FILEDLG_DupToW(LPCSTR str, DWORD size)
1086 if (str && (size > 0))
1088 strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1089 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
1095 /************************************************************************
1096 * FILEDLG_MapOfnStructA [internal]
1097 * map a 32 bits Ansi structure to an Unicode one
1099 void FILEDLG_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
1103 ofnW->lStructSize = sizeof(OPENFILENAMEW);
1104 ofnW->hwndOwner = ofnA->hwndOwner;
1105 ofnW->hInstance = ofnA->hInstance;
1106 if (ofnA->lpstrFilter)
1107 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrFilter, 0);
1109 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
1110 ofnW->lpstrCustomFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
1111 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
1112 ofnW->nFilterIndex = ofnA->nFilterIndex;
1113 ofnW->nMaxFile = ofnA->nMaxFile;
1114 ofnW->lpstrFile = FILEDLG_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
1115 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
1116 ofnW->lpstrFileTitle = FILEDLG_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
1117 if (ofnA->lpstrInitialDir)
1118 ofnW->lpstrInitialDir = HEAP_strdupAtoW(GetProcessHeap(),0,ofnA->lpstrInitialDir);
1119 if (ofnA->lpstrTitle)
1120 str = ofnA->lpstrTitle;
1122 /* Allocates default title (FIXME : get it from resource) */
1123 str = open ? defaultopen:defaultsave;
1124 ofnW->lpstrTitle = HEAP_strdupAtoW(GetProcessHeap(),0, str);
1125 ofnW->Flags = ofnA->Flags;
1126 ofnW->nFileOffset = ofnA->nFileOffset;
1127 ofnW->nFileExtension = ofnA->nFileExtension;
1128 ofnW->lpstrDefExt = FILEDLG_DupToW(ofnA->lpstrDefExt, 3);
1129 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
1131 if (HIWORD(ofnA->lpTemplateName))
1132 ofnW->lpTemplateName = HEAP_strdupAtoW(GetProcessHeap(), 0, ofnA->lpTemplateName);
1133 else /* numbered resource */
1134 ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
1139 /************************************************************************
1140 * FILEDLG_MapOfnStruct16 [internal]
1141 * map a 16 bits structure to an Unicode one
1143 void FILEDLG_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)
1146 /* first convert to linear pointers */
1147 memset(&ofnA, 0, sizeof(OPENFILENAMEA));
1148 ofnA.lStructSize = sizeof(OPENFILENAMEA);
1149 ofnA.hwndOwner = HWND_32(ofn16->hwndOwner);
1150 ofnA.hInstance = ofn16->hInstance;
1151 if (ofn16->lpstrFilter)
1152 ofnA.lpstrFilter = MapSL(ofn16->lpstrFilter);
1153 if (ofn16->lpstrCustomFilter)
1154 ofnA.lpstrCustomFilter = MapSL(ofn16->lpstrCustomFilter);
1155 ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;
1156 ofnA.nFilterIndex = ofn16->nFilterIndex;
1157 ofnA.lpstrFile = MapSL(ofn16->lpstrFile);
1158 ofnA.nMaxFile = ofn16->nMaxFile;
1159 ofnA.lpstrFileTitle = MapSL(ofn16->lpstrFileTitle);
1160 ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;
1161 ofnA.lpstrInitialDir = MapSL(ofn16->lpstrInitialDir);
1162 ofnA.lpstrTitle = MapSL(ofn16->lpstrTitle);
1163 ofnA.Flags = ofn16->Flags;
1164 ofnA.nFileOffset = ofn16->nFileOffset;
1165 ofnA.nFileExtension = ofn16->nFileExtension;
1166 ofnA.lpstrDefExt = MapSL(ofn16->lpstrDefExt);
1167 if (HIWORD(ofn16->lpTemplateName))
1168 ofnA.lpTemplateName = MapSL(ofn16->lpTemplateName);
1170 ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */
1171 /* now calls the 32 bits Ansi to Unicode version to complete the job */
1172 FILEDLG_MapOfnStructA(&ofnA, ofnW, open);
1176 /************************************************************************
1177 * FILEDLG_DestroyPrivate [internal]
1178 * destroys the private object
1180 void FILEDLG_DestroyPrivate(LFSPRIVATE lfs)
1185 /* free resources for a 16 bits dialog */
1186 if (lfs->hResource16) FreeResource16(lfs->hResource16);
1189 GlobalUnlock16(lfs->hGlobal16);
1190 GlobalFree16(lfs->hGlobal16);
1192 /* if ofnW has been allocated, have to free everything in it */
1193 if (lfs->ofn16 || lfs->ofnA)
1195 LPOPENFILENAMEW ofnW = lfs->ofnW;
1196 if (ofnW->lpstrFilter) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
1197 if (ofnW->lpstrCustomFilter) HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
1198 if (ofnW->lpstrFile) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile);
1199 if (ofnW->lpstrFileTitle) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
1200 if (ofnW->lpstrInitialDir) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
1201 if (ofnW->lpstrTitle) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
1202 if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
1203 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
1204 HeapFree(GetProcessHeap(), 0, ofnW);
1206 TRACE("destroying private allocation %p\n", lfs);
1207 HeapFree(GetProcessHeap(), 0, lfs);
1208 RemovePropA(hwnd, OFN_PROP);
1211 /************************************************************************
1212 * FILEDLG_AllocPrivate [internal]
1213 * allocate a private object to hold 32 bits Unicode
1214 * structure that will be used throughtout the calls, while
1215 * keeping available the original structures and a few variables
1216 * On entry : type = dialog procedure type (16,32A,32W)
1217 * dlgType = dialog type (open or save)
1219 LFSPRIVATE FILEDLG_AllocPrivate(LPARAM lParam, int type, UINT dlgType)
1221 LFSPRIVATE lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FSPRIVATE));
1223 TRACE("alloc private buf %p\n", lfs);
1224 if (!lfs) return NULL;
1226 lfs->lParam = lParam;
1227 if (dlgType == OPEN_DIALOG)
1231 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
1232 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
1236 lfs->ofn16 = MapSL(lParam);
1237 if (lfs->ofn16->Flags & OFN_ENABLEHOOK)
1238 if (lfs->ofn16->lpfnHook)
1244 lfs->ofnA = (LPOPENFILENAMEA) lParam;
1245 if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
1246 if (lfs->ofnA->lpfnHook)
1251 lfs->ofnW = (LPOPENFILENAMEW) lParam;
1252 if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
1253 if (lfs->ofnW->lpfnHook)
1259 { /* this structure is needed internally, so create it */
1260 lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPENFILENAMEW));
1264 FILEDLG_MapOfnStruct16(lfs->ofn16, lfs->ofnW, lfs->open);
1266 FILEDLG_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
1273 if (!Get16BitsTemplate(lfs)) ret = NULL;
1276 if (!Get32BitsTemplate(lfs)) ret = NULL;
1277 if (!ret) FILEDLG_DestroyPrivate(lfs);
1282 /***********************************************************************
1283 * GetFileName31A [internal]
1285 * Creates a win31 style dialog box for the user to select a file to open/save.
1287 BOOL WINAPI GetFileName31A(
1288 LPOPENFILENAMEA lpofn, /* addess of structure with data*/
1289 UINT dlgType /* type dialogue : open/save */
1296 if (!lpofn || !FileDlg_Init()) return FALSE;
1298 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32A, dlgType);
1301 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1302 bRet = DialogBoxIndirectParamA( hInst, lfs->template, lpofn->hwndOwner,
1303 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1304 FILEDLG_DestroyPrivate(lfs);
1307 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile);
1312 /***********************************************************************
1313 * GetFileName31W [internal]
1315 * Creates a win31 style dialog box for the user to select a file to open/save
1317 BOOL WINAPI GetFileName31W(
1318 LPOPENFILENAMEW lpofn, /* addess of structure with data*/
1319 UINT dlgType /* type dialogue : open/save */
1326 if (!lpofn || !FileDlg_Init()) return FALSE;
1328 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32W, dlgType);
1331 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1332 bRet = DialogBoxIndirectParamW( hInst, lfs->template, lpofn->hwndOwner,
1333 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1334 FILEDLG_DestroyPrivate(lfs);
1337 TRACE("return lpstrFile=%s !\n", debugstr_w(lpofn->lpstrFile));
1342 /* ------------------ Dialog procedures ---------------------- */
1344 /***********************************************************************
1345 * FileOpenDlgProc (COMMDLG.6)
1347 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
1350 HWND hWnd = HWND_32(hWnd16);
1351 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1354 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1355 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1357 LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1359 return lRet; /* else continue message processing */
1364 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1366 case WM_MEASUREITEM:
1367 return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
1370 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1371 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
1374 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
1377 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1378 switch (HIWORD(lParam))
1381 SetTextColor((HDC16)wParam, 0x00000000);
1383 case CTLCOLOR_STATIC:
1384 SetTextColor((HDC16)wParam, 0x00000000);
1393 /***********************************************************************
1394 * FileSaveDlgProc (COMMDLG.7)
1396 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
1399 HWND hWnd = HWND_32(hWnd16);
1400 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1403 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1404 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1407 lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1409 return lRet; /* else continue message processing */
1413 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1415 case WM_MEASUREITEM:
1416 return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
1419 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1420 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
1423 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
1428 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1429 switch (HIWORD(lParam))
1432 SetTextColor((HDC16)wParam, 0x00000000);
1434 case CTLCOLOR_STATIC:
1435 SetTextColor((HDC16)wParam, 0x00000000);
1444 /***********************************************************************
1445 * FileOpenDlgProc [internal]
1446 * Used for open and save, in fact.
1448 static LRESULT WINAPI FileOpenDlgProc(HWND hWnd, UINT wMsg,
1449 WPARAM wParam, LPARAM lParam)
1451 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1453 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1454 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1457 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1459 return lRet; /* else continue message processing */
1464 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1466 case WM_MEASUREITEM:
1467 return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1470 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam);
1473 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs);
1476 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1477 switch (HIWORD(lParam))
1480 SetTextColor((HDC16)wParam, 0x00000000);
1482 case CTLCOLOR_STATIC:
1483 SetTextColor((HDC16)wParam, 0x00000000);
1492 /* ------------------ APIs ---------------------- */
1494 /***********************************************************************
1495 * GetOpenFileName (COMMDLG.1)
1497 * Creates a dialog box for the user to select a file to open.
1500 * TRUE on success: user selected a valid file
1501 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1504 * unknown, there are some FIXME's left.
1506 BOOL16 WINAPI GetOpenFileName16(
1507 SEGPTR ofn /* [in/out] address of structure with data*/
1512 LPOPENFILENAME16 lpofn = MapSL(ofn);
1516 if (!lpofn || !FileDlg_Init()) return FALSE;
1518 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
1521 hInst = GetWindowLongA( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
1522 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
1523 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1524 (DLGPROC16) ptr, (DWORD) lfs);
1525 FILEDLG_DestroyPrivate(lfs);
1528 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1532 /***********************************************************************
1533 * GetSaveFileName (COMMDLG.2)
1535 * Creates a dialog box for the user to select a file to save.
1538 * TRUE on success: user enters a valid file
1539 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1542 * unknown. There are some FIXME's left.
1544 BOOL16 WINAPI GetSaveFileName16(
1545 SEGPTR ofn /* [in/out] addess of structure with data*/
1550 LPOPENFILENAME16 lpofn = MapSL(ofn);
1554 if (!lpofn || !FileDlg_Init()) return FALSE;
1556 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
1559 hInst = GetWindowLongA( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
1560 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
1561 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1562 (DLGPROC16) ptr, (DWORD) lfs);
1563 FILEDLG_DestroyPrivate(lfs);
1566 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1570 /***********************************************************************
1571 * GetOpenFileNameA (COMDLG32.@)
1573 * Creates a dialog box for the user to select a file to open.
1576 * TRUE on success: user enters a valid file
1577 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1580 BOOL WINAPI GetOpenFileNameA(
1581 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1583 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1584 COMDLG32_SetCommDlgExtendedError(0);
1585 /* some flags don't allow to match the TWEAK_WineLook */
1586 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1588 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1593 return GetFileDialog95A(ofn, OPEN_DIALOG);
1597 return GetFileName31A(ofn, OPEN_DIALOG);
1601 /***********************************************************************
1602 * GetOpenFileNameW (COMDLG32.@)
1604 * Creates a dialog box for the user to select a file to open.
1607 * TRUE on success: user enters a valid file
1608 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1611 BOOL WINAPI GetOpenFileNameW(
1612 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1614 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1615 COMDLG32_SetCommDlgExtendedError(0);
1616 /* some flags don't allow to match the TWEAK_WineLook */
1617 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1619 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1624 return GetFileDialog95W(ofn, OPEN_DIALOG);
1628 return GetFileName31W(ofn, OPEN_DIALOG);
1632 /***********************************************************************
1633 * GetSaveFileNameA (COMDLG32.@)
1635 * Creates a dialog box for the user to select a file to save.
1638 * TRUE on success: user enters a valid file
1639 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1642 BOOL WINAPI GetSaveFileNameA(
1643 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1645 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1646 COMDLG32_SetCommDlgExtendedError(0);
1647 /* some flags don't allow to match the TWEAK_WineLook */
1648 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1650 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1655 return GetFileDialog95A(ofn, SAVE_DIALOG);
1659 return GetFileName31A(ofn, SAVE_DIALOG);
1663 /***********************************************************************
1664 * GetSaveFileNameW (COMDLG32.@)
1666 * Creates a dialog box for the user to select a file to save.
1669 * TRUE on success: user enters a valid file
1670 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1673 BOOL WINAPI GetSaveFileNameW(
1674 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1676 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1677 COMDLG32_SetCommDlgExtendedError(0);
1678 /* some flags don't allow to match the TWEAK_WineLook */
1679 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1681 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1686 return GetFileDialog95W(ofn, SAVE_DIALOG);
1690 return GetFileName31W(ofn, SAVE_DIALOG);