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, sizeof(tmp), NULL, NULL ))
673 tmp[sizeof(tmp)-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 (ofnW->nMaxFile &&
689 !WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
690 lfs->ofnA->lpstrFile, ofnW->nMaxFile, NULL, NULL ))
691 lfs->ofnA->lpstrFile[ofnW->nMaxFile-1] = 0;
692 lfs->ofnA->nFileOffset = ofnW->nFileOffset;
693 lfs->ofnA->nFileExtension = ofnW->nFileExtension;
698 /***********************************************************************
699 * FILEDLG_UpdateFileTitle [internal]
700 * update the displayed file name (without path)
702 void FILEDLG_UpdateFileTitle(LFSPRIVATE lfs)
705 LPOPENFILENAMEW ofnW = lfs->ofnW;
706 if (ofnW->lpstrFileTitle != NULL)
708 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
709 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
710 (LPARAM)ofnW->lpstrFileTitle );
713 char *dest = MapSL(lfs->ofn16->lpstrFileTitle);
714 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
715 dest, ofnW->nMaxFileTitle, NULL, NULL ))
716 dest[ofnW->nMaxFileTitle-1] = 0;
720 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
721 lfs->ofnA->lpstrFileTitle, ofnW->nMaxFileTitle, NULL, NULL ))
722 lfs->ofnA->lpstrFileTitle[ofnW->nMaxFileTitle-1] = 0;
729 /***********************************************************************
730 * FILEDLG_DirListDblClick [internal]
732 static LRESULT FILEDLG_DirListDblClick( LFSPRIVATE lfs )
735 HWND hWnd = lfs->hwnd;
737 WCHAR tmpstr[BUFFILE];
739 /* get the raw string (with brackets) */
740 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
741 if (lRet == LB_ERR) return TRUE;
742 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
743 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
745 strcpyW( tmpstr, pstr );
746 HeapFree(GetProcessHeap(), 0, pstr);
747 /* get the selected directory in tmpstr */
748 if (tmpstr[0] == '[')
750 tmpstr[lstrlenW(tmpstr) - 1] = 0;
751 strcpyW(tmpstr,tmpstr+1);
753 strcatW(tmpstr, FILE_bslash);
755 FILEDLG_ScanDir(hWnd, tmpstr);
759 if (FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst2,
760 MAKELONG(lRet,CD_LBSELCHANGE)))
767 /***********************************************************************
768 * FILEDLG_FileListSelect [internal]
769 * called when a new item is picked in the file list
771 static LRESULT FILEDLG_FileListSelect( LFSPRIVATE lfs )
774 HWND hWnd = lfs->hwnd;
777 lRet = SendDlgItemMessageW(hWnd, lst1, LB_GETCURSEL16, 0, 0);
781 /* set the edit control to the choosen file */
782 if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
784 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
786 SetDlgItemTextW( hWnd, edt1, pstr );
787 HeapFree(GetProcessHeap(), 0, pstr);
791 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst1,
792 MAKELONG(lRet,CD_LBSELCHANGE));
794 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
799 /***********************************************************************
800 * FILEDLG_TestPath [internal]
801 * before accepting the file name, test if it includes wild cards
802 * tries to scan the directory and returns TRUE if no error.
804 static LRESULT FILEDLG_TestPath( LFSPRIVATE lfs, LPWSTR path )
806 HWND hWnd = lfs->hwnd;
807 LPWSTR pBeginFileName, pstr2;
808 WCHAR tmpstr2[BUFFILE];
810 pBeginFileName = strrchrW(path, '\\');
811 if (pBeginFileName == NULL)
812 pBeginFileName = strrchrW(path, ':');
814 if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL)
816 /* edit control contains wildcards */
817 if (pBeginFileName != NULL)
819 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
820 *(pBeginFileName + 1) = 0;
824 strcpyW(tmpstr2, path);
828 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
829 SetDlgItemTextW( hWnd, edt1, tmpstr2 );
830 FILEDLG_ScanDir(hWnd, path);
834 /* no wildcards, we might have a directory or a filename */
835 /* try appending a wildcard and reading the directory */
837 pstr2 = path + lstrlenW(path);
838 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
839 strcatW(path, FILE_bslash);
841 /* if ScanDir succeeds, we have changed the directory */
842 if (FILEDLG_ScanDir(hWnd, path))
845 /* if not, this must be a filename */
847 *pstr2 = 0; /* remove the wildcard added before */
849 if (pBeginFileName != NULL)
851 /* strip off the pathname */
853 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
855 lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
856 /* Should we MessageBox() if this fails? */
857 if (!FILEDLG_ScanDir(hWnd, path))
861 strcpyW(path, tmpstr2);
864 SetDlgItemTextW( hWnd, edt1, path );
868 /***********************************************************************
869 * FILEDLG_Validate [internal]
870 * called on: click Ok button, Enter in edit, DoubleClick in file list
872 static LRESULT FILEDLG_Validate( LFSPRIVATE lfs, LPWSTR path, UINT control, INT itemIndex,
876 HWND hWnd = lfs->hwnd;
877 OPENFILENAMEW ofnsav;
878 LPOPENFILENAMEW ofnW = lfs->ofnW;
879 WCHAR filename[BUFFILE];
881 ofnsav = *ofnW; /* for later restoring */
883 /* get current file name */
885 lstrcpynW(filename, path, sizeof(filename)/sizeof(WCHAR));
887 GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename)/sizeof(WCHAR));
889 /* if we did not click in file list to get there */
892 if (!FILEDLG_TestPath( lfs, filename) )
895 FILEDLG_UpdateResult(lfs, filename);
898 { /* called internally after a change in a combo */
901 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, control,
902 MAKELONG(itemIndex,CD_LBSELCHANGE));
907 FILEDLG_UpdateFileTitle(lfs);
910 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, lfs->fileokstring,
914 *ofnW = ofnsav; /* restore old state */
918 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
922 LPWSTR str = (LPWSTR)ofnW->lpstrFile;
923 LPWSTR ptr = strrchrW(str, '\\');
924 str[lstrlenW(str) + 1] = '\0';
931 /***********************************************************************
932 * FILEDLG_DiskChange [internal]
933 * called when a new item is picked in the disk selection combo
935 static LRESULT FILEDLG_DiskChange( LFSPRIVATE lfs )
938 HWND hWnd = lfs->hwnd;
940 WCHAR diskname[BUFFILE];
942 FILEDLG_StripEditControl(hWnd);
943 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
946 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
947 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
949 wsprintfW(diskname, FILE_specc, pstr[2]);
950 HeapFree(GetProcessHeap(), 0, pstr);
952 return FILEDLG_Validate( lfs, diskname, cmb2, lRet, TRUE );
956 /***********************************************************************
957 * FILEDLG_FileTypeChange [internal]
958 * called when a new item is picked in the file type combo
960 static LRESULT FILEDLG_FileTypeChange( LFSPRIVATE lfs )
963 WCHAR diskname[BUFFILE];
968 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
971 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
972 TRACE("Selected filter : %s\n", debugstr_w(pstr));
973 SetDlgItemTextW( lfs->hwnd, edt1, pstr );
975 return FILEDLG_Validate( lfs, NULL, cmb1, lRet, TRUE );
978 /***********************************************************************
979 * FILEDLG_WMCommand [internal]
981 static LRESULT FILEDLG_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
982 UINT control, LFSPRIVATE lfs )
986 case lst1: /* file list */
987 FILEDLG_StripEditControl(hWnd);
988 if (notification == LBN_DBLCLK)
990 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
991 EndDialog(hWnd, TRUE);
994 else if (notification == LBN_SELCHANGE)
995 return FILEDLG_FileListSelect( lfs );
998 case lst2: /* directory list */
999 FILEDLG_StripEditControl(hWnd);
1000 if (notification == LBN_DBLCLK)
1001 return FILEDLG_DirListDblClick( lfs );
1004 case cmb1: /* file type drop list */
1005 if (notification == CBN_SELCHANGE)
1006 return FILEDLG_FileTypeChange( lfs );
1015 case cmb2: /* disk dropdown combo */
1016 if (notification == CBN_SELCHANGE)
1017 return FILEDLG_DiskChange( lfs );
1021 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
1022 EndDialog(hWnd, TRUE);
1026 EndDialog(hWnd, FALSE);
1029 case IDABORT: /* can be sent by the hook procedure */
1030 EndDialog(hWnd, TRUE);
1036 /***********************************************************************
1037 * FILEDLG_MapDrawItemStruct [internal]
1038 * map a 16 bits drawitem struct to 32
1040 void FILEDLG_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)
1042 lpdis->CtlType = lpdis16->CtlType;
1043 lpdis->CtlID = lpdis16->CtlID;
1044 lpdis->itemID = lpdis16->itemID;
1045 lpdis->itemAction = lpdis16->itemAction;
1046 lpdis->itemState = lpdis16->itemState;
1047 lpdis->hwndItem = HWND_32(lpdis16->hwndItem);
1048 lpdis->hDC = lpdis16->hDC;
1049 lpdis->rcItem.right = lpdis16->rcItem.right;
1050 lpdis->rcItem.left = lpdis16->rcItem.left;
1051 lpdis->rcItem.top = lpdis16->rcItem.top;
1052 lpdis->rcItem.bottom = lpdis16->rcItem.bottom;
1053 lpdis->itemData = lpdis16->itemData;
1056 /************************************************************************
1057 * FILEDLG_MapStringPairsToW [internal]
1058 * map string pairs to Unicode
1060 static LPWSTR FILEDLG_MapStringPairsToW(LPCSTR strA, UINT size)
1070 n = s + 1 - strA; /* Don't forget the other \0 */
1071 if (n < size) n = size;
1073 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
1074 x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR));
1075 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
1080 /************************************************************************
1081 * FILEDLG_DupToW [internal]
1082 * duplicates an Ansi string to unicode, with a buffer size
1084 LPWSTR FILEDLG_DupToW(LPCSTR str, DWORD size)
1087 if (str && (size > 0))
1089 strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1090 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
1096 /************************************************************************
1097 * FILEDLG_MapOfnStructA [internal]
1098 * map a 32 bits Ansi structure to an Unicode one
1100 void FILEDLG_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
1104 ofnW->lStructSize = sizeof(OPENFILENAMEW);
1105 ofnW->hwndOwner = ofnA->hwndOwner;
1106 ofnW->hInstance = ofnA->hInstance;
1107 if (ofnA->lpstrFilter)
1108 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrFilter, 0);
1110 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
1111 ofnW->lpstrCustomFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
1112 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
1113 ofnW->nFilterIndex = ofnA->nFilterIndex;
1114 ofnW->nMaxFile = ofnA->nMaxFile;
1115 ofnW->lpstrFile = FILEDLG_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
1116 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
1117 ofnW->lpstrFileTitle = FILEDLG_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
1118 if (ofnA->lpstrInitialDir)
1119 ofnW->lpstrInitialDir = HEAP_strdupAtoW(GetProcessHeap(),0,ofnA->lpstrInitialDir);
1120 if (ofnA->lpstrTitle)
1121 str = ofnA->lpstrTitle;
1123 /* Allocates default title (FIXME : get it from resource) */
1124 str = open ? defaultopen:defaultsave;
1125 ofnW->lpstrTitle = HEAP_strdupAtoW(GetProcessHeap(),0, str);
1126 ofnW->Flags = ofnA->Flags;
1127 ofnW->nFileOffset = ofnA->nFileOffset;
1128 ofnW->nFileExtension = ofnA->nFileExtension;
1129 ofnW->lpstrDefExt = FILEDLG_DupToW(ofnA->lpstrDefExt, 3);
1130 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
1132 if (HIWORD(ofnA->lpTemplateName))
1133 ofnW->lpTemplateName = HEAP_strdupAtoW(GetProcessHeap(), 0, ofnA->lpTemplateName);
1134 else /* numbered resource */
1135 ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
1140 /************************************************************************
1141 * FILEDLG_MapOfnStruct16 [internal]
1142 * map a 16 bits structure to an Unicode one
1144 void FILEDLG_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)
1147 /* first convert to linear pointers */
1148 memset(&ofnA, 0, sizeof(OPENFILENAMEA));
1149 ofnA.lStructSize = sizeof(OPENFILENAMEA);
1150 ofnA.hwndOwner = HWND_32(ofn16->hwndOwner);
1151 ofnA.hInstance = ofn16->hInstance;
1152 if (ofn16->lpstrFilter)
1153 ofnA.lpstrFilter = MapSL(ofn16->lpstrFilter);
1154 if (ofn16->lpstrCustomFilter)
1155 ofnA.lpstrCustomFilter = MapSL(ofn16->lpstrCustomFilter);
1156 ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;
1157 ofnA.nFilterIndex = ofn16->nFilterIndex;
1158 ofnA.lpstrFile = MapSL(ofn16->lpstrFile);
1159 ofnA.nMaxFile = ofn16->nMaxFile;
1160 ofnA.lpstrFileTitle = MapSL(ofn16->lpstrFileTitle);
1161 ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;
1162 ofnA.lpstrInitialDir = MapSL(ofn16->lpstrInitialDir);
1163 ofnA.lpstrTitle = MapSL(ofn16->lpstrTitle);
1164 ofnA.Flags = ofn16->Flags;
1165 ofnA.nFileOffset = ofn16->nFileOffset;
1166 ofnA.nFileExtension = ofn16->nFileExtension;
1167 ofnA.lpstrDefExt = MapSL(ofn16->lpstrDefExt);
1168 if (HIWORD(ofn16->lpTemplateName))
1169 ofnA.lpTemplateName = MapSL(ofn16->lpTemplateName);
1171 ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */
1172 /* now calls the 32 bits Ansi to Unicode version to complete the job */
1173 FILEDLG_MapOfnStructA(&ofnA, ofnW, open);
1177 /************************************************************************
1178 * FILEDLG_DestroyPrivate [internal]
1179 * destroys the private object
1181 void FILEDLG_DestroyPrivate(LFSPRIVATE lfs)
1186 /* free resources for a 16 bits dialog */
1187 if (lfs->hResource16) FreeResource16(lfs->hResource16);
1190 GlobalUnlock16(lfs->hGlobal16);
1191 GlobalFree16(lfs->hGlobal16);
1193 /* if ofnW has been allocated, have to free everything in it */
1194 if (lfs->ofn16 || lfs->ofnA)
1196 LPOPENFILENAMEW ofnW = lfs->ofnW;
1197 if (ofnW->lpstrFilter) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
1198 if (ofnW->lpstrCustomFilter) HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
1199 if (ofnW->lpstrFile) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile);
1200 if (ofnW->lpstrFileTitle) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
1201 if (ofnW->lpstrInitialDir) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
1202 if (ofnW->lpstrTitle) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
1203 if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
1204 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
1205 HeapFree(GetProcessHeap(), 0, ofnW);
1207 TRACE("destroying private allocation %p\n", lfs);
1208 HeapFree(GetProcessHeap(), 0, lfs);
1209 RemovePropA(hwnd, OFN_PROP);
1212 /************************************************************************
1213 * FILEDLG_AllocPrivate [internal]
1214 * allocate a private object to hold 32 bits Unicode
1215 * structure that will be used throughtout the calls, while
1216 * keeping available the original structures and a few variables
1217 * On entry : type = dialog procedure type (16,32A,32W)
1218 * dlgType = dialog type (open or save)
1220 LFSPRIVATE FILEDLG_AllocPrivate(LPARAM lParam, int type, UINT dlgType)
1222 LFSPRIVATE lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FSPRIVATE));
1224 TRACE("alloc private buf %p\n", lfs);
1225 if (!lfs) return NULL;
1227 lfs->lParam = lParam;
1228 if (dlgType == OPEN_DIALOG)
1232 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
1233 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
1237 lfs->ofn16 = MapSL(lParam);
1238 if (lfs->ofn16->Flags & OFN_ENABLEHOOK)
1239 if (lfs->ofn16->lpfnHook)
1245 lfs->ofnA = (LPOPENFILENAMEA) lParam;
1246 if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
1247 if (lfs->ofnA->lpfnHook)
1252 lfs->ofnW = (LPOPENFILENAMEW) lParam;
1253 if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
1254 if (lfs->ofnW->lpfnHook)
1260 { /* this structure is needed internally, so create it */
1261 lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPENFILENAMEW));
1265 FILEDLG_MapOfnStruct16(lfs->ofn16, lfs->ofnW, lfs->open);
1267 FILEDLG_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
1274 if (!Get16BitsTemplate(lfs)) ret = NULL;
1277 if (!Get32BitsTemplate(lfs)) ret = NULL;
1278 if (!ret) FILEDLG_DestroyPrivate(lfs);
1283 /***********************************************************************
1284 * GetFileName31A [internal]
1286 * Creates a win31 style dialog box for the user to select a file to open/save.
1288 BOOL WINAPI GetFileName31A(
1289 LPOPENFILENAMEA lpofn, /* addess of structure with data*/
1290 UINT dlgType /* type dialogue : open/save */
1297 if (!lpofn || !FileDlg_Init()) return FALSE;
1299 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32A, dlgType);
1302 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1303 bRet = DialogBoxIndirectParamA( hInst, lfs->template, lpofn->hwndOwner,
1304 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1305 FILEDLG_DestroyPrivate(lfs);
1308 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile);
1313 /***********************************************************************
1314 * GetFileName31W [internal]
1316 * Creates a win31 style dialog box for the user to select a file to open/save
1318 BOOL WINAPI GetFileName31W(
1319 LPOPENFILENAMEW lpofn, /* addess of structure with data*/
1320 UINT dlgType /* type dialogue : open/save */
1327 if (!lpofn || !FileDlg_Init()) return FALSE;
1329 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32W, dlgType);
1332 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1333 bRet = DialogBoxIndirectParamW( hInst, lfs->template, lpofn->hwndOwner,
1334 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1335 FILEDLG_DestroyPrivate(lfs);
1338 TRACE("return lpstrFile=%s !\n", debugstr_w(lpofn->lpstrFile));
1343 /* ------------------ Dialog procedures ---------------------- */
1345 /***********************************************************************
1346 * FileOpenDlgProc (COMMDLG.6)
1348 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
1351 HWND hWnd = HWND_32(hWnd16);
1352 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1355 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1356 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1358 LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1360 return lRet; /* else continue message processing */
1365 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1367 case WM_MEASUREITEM:
1368 return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
1371 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1372 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
1375 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
1378 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1379 switch (HIWORD(lParam))
1382 SetTextColor((HDC16)wParam, 0x00000000);
1384 case CTLCOLOR_STATIC:
1385 SetTextColor((HDC16)wParam, 0x00000000);
1394 /***********************************************************************
1395 * FileSaveDlgProc (COMMDLG.7)
1397 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd16, UINT16 wMsg, WPARAM16 wParam,
1400 HWND hWnd = HWND_32(hWnd16);
1401 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1404 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1405 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1408 lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1410 return lRet; /* else continue message processing */
1414 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1416 case WM_MEASUREITEM:
1417 return FILEDLG_WMMeasureItem16(hWnd16, wParam, lParam);
1420 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1421 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
1424 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
1429 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1430 switch (HIWORD(lParam))
1433 SetTextColor((HDC16)wParam, 0x00000000);
1435 case CTLCOLOR_STATIC:
1436 SetTextColor((HDC16)wParam, 0x00000000);
1445 /***********************************************************************
1446 * FileOpenDlgProc [internal]
1447 * Used for open and save, in fact.
1449 static LRESULT WINAPI FileOpenDlgProc(HWND hWnd, UINT wMsg,
1450 WPARAM wParam, LPARAM lParam)
1452 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1454 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1455 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1458 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1460 return lRet; /* else continue message processing */
1465 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1467 case WM_MEASUREITEM:
1468 return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1471 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam);
1474 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs);
1477 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1478 switch (HIWORD(lParam))
1481 SetTextColor((HDC16)wParam, 0x00000000);
1483 case CTLCOLOR_STATIC:
1484 SetTextColor((HDC16)wParam, 0x00000000);
1493 /* ------------------ APIs ---------------------- */
1495 /***********************************************************************
1496 * GetOpenFileName (COMMDLG.1)
1498 * Creates a dialog box for the user to select a file to open.
1501 * TRUE on success: user selected a valid file
1502 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1505 * unknown, there are some FIXME's left.
1507 BOOL16 WINAPI GetOpenFileName16(
1508 SEGPTR ofn /* [in/out] address of structure with data*/
1513 LPOPENFILENAME16 lpofn = MapSL(ofn);
1517 if (!lpofn || !FileDlg_Init()) return FALSE;
1519 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
1522 hInst = GetWindowLongA( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
1523 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
1524 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1525 (DLGPROC16) ptr, (DWORD) lfs);
1526 FILEDLG_DestroyPrivate(lfs);
1529 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1533 /***********************************************************************
1534 * GetSaveFileName (COMMDLG.2)
1536 * Creates a dialog box for the user to select a file to save.
1539 * TRUE on success: user enters a valid file
1540 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1543 * unknown. There are some FIXME's left.
1545 BOOL16 WINAPI GetSaveFileName16(
1546 SEGPTR ofn /* [in/out] addess of structure with data*/
1551 LPOPENFILENAME16 lpofn = MapSL(ofn);
1555 if (!lpofn || !FileDlg_Init()) return FALSE;
1557 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
1560 hInst = GetWindowLongA( HWND_32(lpofn->hwndOwner), GWL_HINSTANCE );
1561 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
1562 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1563 (DLGPROC16) ptr, (DWORD) lfs);
1564 FILEDLG_DestroyPrivate(lfs);
1567 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1571 /***********************************************************************
1572 * GetOpenFileNameA (COMDLG32.@)
1574 * Creates a dialog box for the user to select a file to open.
1577 * TRUE on success: user enters a valid file
1578 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1581 BOOL WINAPI GetOpenFileNameA(
1582 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1584 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1585 COMDLG32_SetCommDlgExtendedError(0);
1586 /* some flags don't allow to match the TWEAK_WineLook */
1587 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1589 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1594 return GetFileDialog95A(ofn, OPEN_DIALOG);
1598 return GetFileName31A(ofn, OPEN_DIALOG);
1602 /***********************************************************************
1603 * GetOpenFileNameW (COMDLG32.@)
1605 * Creates a dialog box for the user to select a file to open.
1608 * TRUE on success: user enters a valid file
1609 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1612 BOOL WINAPI GetOpenFileNameW(
1613 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1615 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1616 COMDLG32_SetCommDlgExtendedError(0);
1617 /* some flags don't allow to match the TWEAK_WineLook */
1618 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1620 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1625 return GetFileDialog95W(ofn, OPEN_DIALOG);
1629 return GetFileName31W(ofn, OPEN_DIALOG);
1633 /***********************************************************************
1634 * GetSaveFileNameA (COMDLG32.@)
1636 * Creates a dialog box for the user to select a file to save.
1639 * TRUE on success: user enters a valid file
1640 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1643 BOOL WINAPI GetSaveFileNameA(
1644 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1646 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1647 COMDLG32_SetCommDlgExtendedError(0);
1648 /* some flags don't allow to match the TWEAK_WineLook */
1649 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1651 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1656 return GetFileDialog95A(ofn, SAVE_DIALOG);
1660 return GetFileName31A(ofn, SAVE_DIALOG);
1664 /***********************************************************************
1665 * GetSaveFileNameW (COMDLG32.@)
1667 * Creates a dialog box for the user to select a file to save.
1670 * TRUE on success: user enters a valid file
1671 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1674 BOOL WINAPI GetSaveFileNameW(
1675 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1677 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1678 COMDLG32_SetCommDlgExtendedError(0);
1679 /* some flags don't allow to match the TWEAK_WineLook */
1680 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1682 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1687 return GetFileDialog95W(ofn, SAVE_DIALOG);
1691 return GetFileName31W(ofn, SAVE_DIALOG);