2 * COMMDLG - File Dialogs
4 * Copyright 1994 Martin Ayotte
5 * Copyright 1996 Albrecht Kleine
15 #include "wine/winbase16.h"
16 #include "wine/winuser16.h"
17 #include "wine/unicode.h"
21 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(commdlg);
29 #define BUFFILEALLOC 512 * sizeof(WCHAR)
33 HWND hwnd; /* file dialog window handle */
34 BOOL hook; /* TRUE if the dialog is hooked */
35 UINT lbselchstring; /* registered message id */
36 UINT fileokstring; /* registered message id */
37 LPARAM lParam; /* save original lparam */
38 HANDLE16 hDlgTmpl16; /* handle for resource 16 */
39 HANDLE16 hResource16; /* handle for allocated resource 16 */
40 HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
41 LPCVOID template; /* template for 32 bits resource */
42 BOOL open; /* TRUE if open dialog, FALSE if save dialog */
43 OPENFILENAMEW *ofnW; /* original structure or work struct */
44 OPENFILENAMEA *ofnA; /* original structure if 32bits ansi dialog */
45 OPENFILENAME16 *ofn16; /* original structure if 16 bits dialog */
49 #define LFSPRIVATE struct FSPRIVATE *
55 static const WCHAR FILE_star[] = {'*','.','*', 0};
56 static const WCHAR FILE_bslash[] = {'\\', 0};
57 static const WCHAR FILE_specc[] = {'%','c',':', 0};
59 static HICON16 hFolder = 0;
60 static HICON16 hFolder2 = 0;
61 static HICON16 hFloppy = 0;
62 static HICON16 hHDisk = 0;
63 static HICON16 hCDRom = 0;
64 static HICON16 hNet = 0;
65 static int fldrHeight = 0;
66 static int fldrWidth = 0;
68 #define OFN_PROP "FILEDLG_OFN"
70 static const char defaultfilter[]=" \0\0";
71 static char defaultopen[]="Open File";
72 static char defaultsave[]="Save as";
74 /***********************************************************************
76 * Windows 3.1 style OpenFileName/SaveFileName dialog
80 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
82 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
85 static LRESULT WINAPI FileOpenDlgProc(HWND hDlg, UINT msg,
86 WPARAM wParam, LPARAM lParam);
88 /***********************************************************************
89 * FileDlg_Init [internal]
91 static BOOL FileDlg_Init(void)
93 static BOOL initialized = 0;
94 CURSORICONINFO *fldrInfo;
97 if (!hFolder) hFolder = LoadIconA(0, MAKEINTRESOURCEA(OIC_FOLDER));
98 if (!hFolder2) hFolder2 = LoadIconA(0, MAKEINTRESOURCEA(OIC_FOLDER2));
99 if (!hFloppy) hFloppy = LoadIconA(0, MAKEINTRESOURCEA(OIC_FLOPPY));
100 if (!hHDisk) hHDisk = LoadIconA(0, MAKEINTRESOURCEA(OIC_HDISK));
101 if (!hCDRom) hCDRom = LoadIconA(0, MAKEINTRESOURCEA(OIC_CDROM));
102 if (!hNet) hNet = LoadIconA(0, MAKEINTRESOURCEA(OIC_NETWORK));
103 if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 ||
104 hHDisk == 0 || hCDRom == 0 || hNet == 0)
106 ERR("Error loading icons !\n");
109 fldrInfo = (CURSORICONINFO *) GlobalLock16( hFolder2 );
112 ERR("Error measuring icons !\n");
115 fldrHeight = fldrInfo -> nHeight;
116 fldrWidth = fldrInfo -> nWidth;
117 GlobalUnlock16( hFolder2 );
124 /***********************************************************************
125 * Get32BitsTemplate [internal]
127 * Get a template (or FALSE if failure) when 16 bits dialogs are used
128 * by a 32 bits application
131 BOOL Get32BitsTemplate(LFSPRIVATE lfs)
133 LPOPENFILENAMEW ofnW = lfs->ofnW;
136 if (ofnW->Flags & OFN_ENABLETEMPLATEHANDLE)
138 if (!(lfs->template = LockResource( ofnW->hInstance )))
140 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
144 else if (ofnW->Flags & OFN_ENABLETEMPLATE)
148 hResInfo = FindResourceA(lfs->ofnA->hInstance,
149 lfs->ofnA->lpTemplateName,
152 hResInfo = FindResourceW(ofnW->hInstance,
153 ofnW->lpTemplateName,
157 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
160 if (!(hDlgTmpl = LoadResource(ofnW->hInstance,
162 !(lfs->template = LockResource(hDlgTmpl)))
164 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
167 } else { /* get it from internal Wine resource */
169 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
170 lfs->open? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
172 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
175 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
176 !(lfs->template = LockResource( hDlgTmpl )))
178 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
186 /***********************************************************************
187 * Get16BitsTemplate [internal]
189 * Get a template (FALSE if failure) when 16 bits dialogs are used
190 * by a 16 bits application
193 BOOL Get16BitsTemplate(LFSPRIVATE lfs)
195 LPOPENFILENAME16 ofn16 = lfs->ofn16;
197 HGLOBAL16 hGlobal16 = 0;
199 if (ofn16->Flags & OFN_ENABLETEMPLATEHANDLE)
200 lfs->hDlgTmpl16 = ofn16->hInstance;
201 else if (ofn16->Flags & OFN_ENABLETEMPLATE)
204 if (!(hResInfo = FindResource16(ofn16->hInstance,
205 PTR_SEG_TO_LIN(ofn16->lpTemplateName),
208 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
211 if (!(lfs->hDlgTmpl16 = LoadResource16( ofn16->hInstance, hResInfo )))
213 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
216 lfs->hResource16 = lfs->hDlgTmpl16;
219 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
220 HANDLE hResInfo, hDlgTmpl32;
224 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
225 lfs->open ? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
227 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
230 if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
231 !(template32 = LockResource( hDlgTmpl32 )))
233 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
236 size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
237 hGlobal16 = GlobalAlloc16(0, size);
240 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
241 ERR("alloc failure for %ld bytes\n", size);
244 template = GlobalLock16(hGlobal16);
247 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
248 ERR("global lock failure for %x handle\n", hGlobal16);
249 GlobalFree16(hGlobal16);
252 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
253 lfs->hDlgTmpl16 = hGlobal16;
254 lfs->hGlobal16 = hGlobal16;
259 /***********************************************************************
260 * FILEDLG_StripEditControl [internal]
261 * Strip pathnames off the contents of the edit control.
263 static void FILEDLG_StripEditControl(HWND hwnd)
265 WCHAR temp[BUFFILE], *cp;
267 GetDlgItemTextW( hwnd, edt1, temp, sizeof(temp) );
268 cp = strrchrW(temp, '\\');
272 cp = strrchrW(temp, ':');
276 /* FIXME: shouldn't we do something with the result here? ;-) */
281 /***********************************************************************
282 * FILEDLG_CallWindowProc [internal]
284 * Call the appropriate hook
286 static BOOL FILEDLG_CallWindowProc(LFSPRIVATE lfs, UINT wMsg, WPARAM wParam,
291 return (BOOL16) CallWindowProc16(
292 (WNDPROC16)lfs->ofn16->lpfnHook, lfs->hwnd,
293 (UINT16)wMsg, (WPARAM16)wParam, lParam);
297 return (BOOL) CallWindowProcA(
298 (WNDPROC)lfs->ofnA->lpfnHook, lfs->hwnd,
299 wMsg, wParam, lParam);
304 return (BOOL) CallWindowProcW(
305 (WNDPROC)lfs->ofnW->lpfnHook, lfs->hwnd,
306 wMsg, wParam, lParam);
312 /***********************************************************************
313 * FILEDLG_ScanDir [internal]
315 static BOOL FILEDLG_ScanDir(HWND hWnd, LPWSTR newPath)
317 WCHAR buffer[BUFFILE];
320 HCURSOR hCursorWait, oldCursor;
322 if ( !SetCurrentDirectoryW( newPath ))
324 lstrcpynW(buffer, newPath, sizeof(buffer));
326 /* get the list of spec files */
327 GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer));
329 hCursorWait = LoadCursorA(0, IDC_WAITA);
330 oldCursor = SetCursor(hCursorWait);
333 if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) {
334 WCHAR* scptr; /* ptr on semi-colon */
335 WCHAR* filter = buffer;
337 TRACE("Using filter %s\n", debugstr_w(filter));
338 SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
340 scptr = strchrW(filter, ';');
341 if (scptr) *scptr = 0;
342 while (*filter == ' ') filter++;
343 TRACE("Using file spec %s\n", debugstr_w(filter));
344 if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
346 if (scptr) *scptr = ';';
347 filter = (scptr) ? (scptr + 1) : 0;
351 /* list of directories */
352 strcpyW(buffer, FILE_star);
354 if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
355 lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
357 SetCursor(oldCursor);
362 /***********************************************************************
363 * FILEDLG_GetFileType [internal]
366 static LPWSTR FILEDLG_GetFileType(LPWSTR cfptr, LPWSTR fptr, WORD index)
371 for ( ;(n = lstrlenW(cfptr)) != 0; i++)
376 cfptr += lstrlenW(cfptr) + 1;
379 for ( ;(n = lstrlenW(fptr)) != 0; i++)
384 fptr += lstrlenW(fptr) + 1;
386 return (LPWSTR) FILE_star; /* FIXME */
389 /***********************************************************************
390 * FILEDLG_WMDrawItem [internal]
392 static LONG FILEDLG_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
393 int savedlg, LPDRAWITEMSTRUCT lpdis)
397 COLORREF oldText = 0, oldBk = 0;
399 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
401 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) return FALSE;
402 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
405 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
407 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
408 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
411 SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
413 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1,
414 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
415 &(lpdis->rcItem), str, lstrlenW(str), NULL);
417 if (lpdis->itemState & ODS_SELECTED)
418 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
420 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
422 SetBkColor( lpdis->hDC, oldBk );
423 SetTextColor( lpdis->hDC, oldText );
425 HeapFree(GetProcessHeap(), 0, str);
429 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
431 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
433 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
436 if (lpdis->itemState & ODS_SELECTED)
438 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
439 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
441 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
442 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
443 &(lpdis->rcItem), str, lstrlenW(str), NULL);
445 if (lpdis->itemState & ODS_SELECTED)
446 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
448 if (lpdis->itemState & ODS_SELECTED)
450 SetBkColor( lpdis->hDC, oldBk );
451 SetTextColor( lpdis->hDC, oldText );
453 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
454 HeapFree(GetProcessHeap(), 0, str);
457 if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
460 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
462 SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID,
464 root[0] += str[2] - 'a';
465 switch(GetDriveTypeA(root))
467 case DRIVE_REMOVABLE: hIcon = hFloppy; break;
468 case DRIVE_CDROM: hIcon = hCDRom; break;
469 case DRIVE_REMOTE: hIcon = hNet; break;
471 default: hIcon = hHDisk; break;
473 if (lpdis->itemState & ODS_SELECTED)
475 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
476 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
478 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
479 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
480 &(lpdis->rcItem), str, lstrlenW(str), NULL);
482 if (lpdis->itemState & ODS_SELECTED)
484 SetBkColor( lpdis->hDC, oldBk );
485 SetTextColor( lpdis->hDC, oldText );
487 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
488 HeapFree(GetProcessHeap(), 0, str);
494 /***********************************************************************
495 * FILEDLG_WMMeasureItem [internal]
497 static LONG FILEDLG_WMMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
499 LPMEASUREITEMSTRUCT lpmeasure;
501 lpmeasure = (LPMEASUREITEMSTRUCT)lParam;
502 lpmeasure->itemHeight = fldrHeight;
506 /***********************************************************************
507 * FILEDLG_WMMeasureItem16 [internal]
509 static LONG FILEDLG_WMMeasureItem16(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
511 LPMEASUREITEMSTRUCT16 lpmeasure;
513 lpmeasure = (LPMEASUREITEMSTRUCT16)PTR_SEG_TO_LIN(lParam);
514 lpmeasure->itemHeight = fldrHeight;
518 /***********************************************************************
519 * FILEDLG_WMInitDialog [internal]
522 static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
525 WCHAR tmpstr[BUFFILE];
526 LPWSTR pstr, old_pstr;
528 LFSPRIVATE lfs = (LFSPRIVATE) lParam;
530 if (!lfs) return FALSE;
531 SetPropA(hWnd, OFN_PROP, (HANDLE)lfs);
535 TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
537 SetWindowTextW( hWnd, ofn->lpstrTitle );
538 /* read custom filter information */
539 if (ofn->lpstrCustomFilter)
541 pstr = ofn->lpstrCustomFilter;
543 TRACE("lpstrCustomFilter = %p\n", pstr);
547 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
548 (LPARAM)(ofn->lpstrCustomFilter) + n );
549 n += lstrlenW(pstr) + 1;
550 pstr += lstrlenW(pstr) + 1;
551 TRACE("add str='%s' "
552 "associated to '%s'\n", debugstr_w(old_pstr), debugstr_w(pstr));
553 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
554 n += lstrlenW(pstr) + 1;
555 pstr += lstrlenW(pstr) + 1;
558 /* read filter information */
559 if (ofn->lpstrFilter) {
560 pstr = (LPWSTR) ofn->lpstrFilter;
564 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
565 (LPARAM)(ofn->lpstrFilter + n) );
566 n += lstrlenW(pstr) + 1;
567 pstr += lstrlenW(pstr) + 1;
568 TRACE("add str='%s' "
569 "associated to '%s'\n", debugstr_w(old_pstr), debugstr_w(pstr));
570 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
571 n += lstrlenW(pstr) + 1;
572 pstr += lstrlenW(pstr) + 1;
575 /* set default filter */
576 if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
577 ofn->nFilterIndex = 1;
578 SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
579 lstrcpynW(tmpstr, FILEDLG_GetFileType(ofn->lpstrCustomFilter,
580 (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
581 TRACE("nFilterIndex = %ld, SetText of edt1 to '%s'\n",
582 ofn->nFilterIndex, debugstr_w(tmpstr));
583 SetDlgItemTextW( hWnd, edt1, tmpstr );
586 DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
587 /* read initial directory */
588 if (ofn->lpstrInitialDir != NULL)
591 lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
592 len = lstrlenW(tmpstr);
593 if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') {
600 if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
602 if (!FILEDLG_ScanDir(hWnd, tmpstr))
603 WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
605 /* select current drive in combo 2, omit missing drives */
608 char str[4] = "a:\\";
609 GetCurrentDirectoryA( sizeof(dir), dir );
610 for(i = 0, n = -1; i < 26; i++)
613 if (GetDriveTypeA(str) <= DRIVE_NO_ROOT_DIR) n++;
614 if (toupper(str[0]) == toupper(dir[0])) break;
617 SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
618 if (!(ofn->Flags & OFN_SHOWHELP))
619 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
620 if (ofn->Flags & OFN_HIDEREADONLY)
621 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
623 return (BOOL) FILEDLG_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
627 /***********************************************************************
628 * FILEDLG_UpdateResult [internal]
629 * update the displayed file name (with path)
631 void FILEDLG_UpdateResult(LFSPRIVATE lfs, WCHAR *tmpstr)
634 LPOPENFILENAMEW ofnW = lfs->ofnW;
635 WCHAR tmpstr2[BUFFILE];
637 GetCurrentDirectoryW(BUFFILE, tmpstr2);
638 lenstr2 = strlenW(tmpstr2);
640 tmpstr2[lenstr2++]='\\';
641 lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
643 lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
644 ofnW->nFileOffset = strrchrW(tmpstr2,'\\') - tmpstr2 +1;
645 ofnW->nFileExtension = 0;
646 while(tmpstr2[ofnW->nFileExtension] != '.' && tmpstr2[ofnW->nFileExtension] != '\0')
647 ofnW->nFileExtension++;
648 if (tmpstr2[ofnW->nFileExtension] == '\0')
649 ofnW->nFileExtension = 0;
651 ofnW->nFileExtension++;
652 /* update the real client structures if any */
655 char *dest = PTR_SEG_TO_LIN(lfs->ofn16->lpstrFile);
656 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
657 dest, ofnW->nMaxFile, NULL, NULL ))
658 dest[ofnW->nMaxFile-1] = 0;
659 lfs->ofn16->nFileOffset = ofnW->nFileOffset;
660 lfs->ofn16->nFileExtension = ofnW->nFileExtension;
664 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
665 lfs->ofnA->lpstrFile, ofnW->nMaxFile, NULL, NULL ))
666 lfs->ofnA->lpstrFile[ofnW->nMaxFile-1] = 0;
667 lfs->ofnA->nFileOffset = ofnW->nFileOffset;
668 lfs->ofnA->nFileExtension = ofnW->nFileExtension;
673 /***********************************************************************
674 * FILEDLG_UpdateFileTitle [internal]
675 * update the displayed file name (without path)
677 void FILEDLG_UpdateFileTitle(LFSPRIVATE lfs)
680 LPOPENFILENAMEW ofnW = lfs->ofnW;
681 if (ofnW->lpstrFileTitle != NULL)
683 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
684 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
685 (LPARAM)ofnW->lpstrFileTitle );
688 char *dest = PTR_SEG_TO_LIN(lfs->ofn16->lpstrFileTitle);
689 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
690 dest, ofnW->nMaxFileTitle, NULL, NULL ))
691 dest[ofnW->nMaxFileTitle-1] = 0;
695 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
696 lfs->ofnA->lpstrFileTitle, ofnW->nMaxFileTitle, NULL, NULL ))
697 lfs->ofnA->lpstrFileTitle[ofnW->nMaxFileTitle-1] = 0;
704 /***********************************************************************
705 * FILEDLG_DirListDblClick [internal]
707 static LRESULT FILEDLG_DirListDblClick( LFSPRIVATE lfs )
710 HWND hWnd = lfs->hwnd;
712 WCHAR tmpstr[BUFFILE];
714 /* get the raw string (with brackets) */
715 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
716 if (lRet == LB_ERR) return TRUE;
717 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
718 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
720 strcpyW( tmpstr, pstr );
721 HeapFree(GetProcessHeap(), 0, pstr);
722 /* get the selected directory in tmpstr */
723 if (tmpstr[0] == '[')
725 tmpstr[lstrlenW(tmpstr) - 1] = 0;
726 strcpyW(tmpstr,tmpstr+1);
728 strcatW(tmpstr, FILE_bslash);
730 FILEDLG_ScanDir(hWnd, tmpstr);
734 if (FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst2,
735 MAKELONG(lRet,CD_LBSELCHANGE)))
742 /***********************************************************************
743 * FILEDLG_FileListSelect [internal]
744 * called when a new item is picked in the file list
746 static LRESULT FILEDLG_FileListSelect( LFSPRIVATE lfs )
749 HWND hWnd = lfs->hwnd;
752 lRet = SendDlgItemMessageW(hWnd, lst1, LB_GETCURSEL16, 0, 0);
756 /* set the edit control to the choosen file */
757 if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
759 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
761 SetDlgItemTextW( hWnd, edt1, pstr );
762 HeapFree(GetProcessHeap(), 0, pstr);
766 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst1,
767 MAKELONG(lRet,CD_LBSELCHANGE));
769 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
774 /***********************************************************************
775 * FILEDLG_TestPath [internal]
776 * before accepting the file name, test if it includes wild cards
777 * tries to scan the directory and returns TRUE if no error.
779 static LRESULT FILEDLG_TestPath( LFSPRIVATE lfs, LPWSTR path )
781 HWND hWnd = lfs->hwnd;
782 LPWSTR pBeginFileName, pstr2;
783 WCHAR tmpstr2[BUFFILE];
785 pBeginFileName = strrchrW(path, '\\');
786 if (pBeginFileName == NULL)
787 pBeginFileName = strrchrW(path, ':');
789 if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL)
791 /* edit control contains wildcards */
792 if (pBeginFileName != NULL)
794 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
795 *(pBeginFileName + 1) = 0;
799 strcpyW(tmpstr2, path);
803 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
804 SetDlgItemTextW( hWnd, edt1, tmpstr2 );
805 FILEDLG_ScanDir(hWnd, path);
809 /* no wildcards, we might have a directory or a filename */
810 /* try appending a wildcard and reading the directory */
812 pstr2 = path + lstrlenW(path);
813 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
814 strcatW(path, FILE_bslash);
816 /* if ScanDir succeeds, we have changed the directory */
817 if (FILEDLG_ScanDir(hWnd, path))
820 /* if not, this must be a filename */
822 *pstr2 = 0; /* remove the wildcard added before */
824 if (pBeginFileName != NULL)
826 /* strip off the pathname */
828 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
830 lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2) );
831 /* Should we MessageBox() if this fails? */
832 if (!FILEDLG_ScanDir(hWnd, path))
836 strcpyW(path, tmpstr2);
839 SetDlgItemTextW( hWnd, edt1, path );
843 /***********************************************************************
844 * FILEDLG_Validate [internal]
845 * called on: click Ok button, Enter in edit, DoubleClick in file list
847 static LRESULT FILEDLG_Validate( LFSPRIVATE lfs, LPWSTR path, UINT control, INT itemIndex,
851 HWND hWnd = lfs->hwnd;
852 OPENFILENAMEW ofnsav;
853 LPOPENFILENAMEW ofnW = lfs->ofnW;
854 WCHAR filename[BUFFILE];
856 ofnsav = *ofnW; /* for later restoring */
858 /* get current file name */
860 lstrcpynW(filename, path, sizeof(filename));
862 GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename) );
864 /* if we did not click in file list to get there */
867 if (!FILEDLG_TestPath( lfs, filename) )
870 FILEDLG_UpdateResult(lfs, filename);
873 { /* called internally after a change in a combo */
876 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, control,
877 MAKELONG(itemIndex,CD_LBSELCHANGE));
882 FILEDLG_UpdateFileTitle(lfs);
885 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, lfs->fileokstring,
889 *ofnW = ofnsav; /* restore old state */
893 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
897 LPWSTR str = (LPWSTR)ofnW->lpstrFile;
898 LPWSTR ptr = strrchrW(str, '\\');
899 str[lstrlenW(str) + 1] = '\0';
906 /***********************************************************************
907 * FILEDLG_DiskChange [internal]
908 * called when a new item is picked in the disk selection combo
910 static LRESULT FILEDLG_DiskChange( LFSPRIVATE lfs )
913 HWND hWnd = lfs->hwnd;
915 WCHAR diskname[BUFFILE];
917 FILEDLG_StripEditControl(hWnd);
918 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
921 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
922 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
924 wsprintfW(diskname, FILE_specc, pstr[2]);
925 HeapFree(GetProcessHeap(), 0, pstr);
927 return FILEDLG_Validate( lfs, diskname, cmb2, lRet, TRUE );
931 /***********************************************************************
932 * FILEDLG_FileTypeChange [internal]
933 * called when a new item is picked in the file type combo
935 static LRESULT FILEDLG_FileTypeChange( LFSPRIVATE lfs )
938 WCHAR diskname[BUFFILE];
943 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
946 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
947 TRACE("Selected filter : %s\n", debugstr_w(pstr));
948 SetDlgItemTextW( lfs->hwnd, edt1, pstr );
950 return FILEDLG_Validate( lfs, NULL, cmb1, lRet, TRUE );
953 /***********************************************************************
954 * FILEDLG_WMCommand [internal]
956 static LRESULT FILEDLG_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
957 UINT control, LFSPRIVATE lfs )
961 case lst1: /* file list */
962 FILEDLG_StripEditControl(hWnd);
963 if (notification == LBN_DBLCLK)
965 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
966 EndDialog(hWnd, TRUE);
969 else if (notification == LBN_SELCHANGE)
970 return FILEDLG_FileListSelect( lfs );
973 case lst2: /* directory list */
974 FILEDLG_StripEditControl(hWnd);
975 if (notification == LBN_DBLCLK)
976 return FILEDLG_DirListDblClick( lfs );
979 case cmb1: /* file type drop list */
980 if (notification == CBN_SELCHANGE)
981 return FILEDLG_FileTypeChange( lfs );
990 case cmb2: /* disk dropdown combo */
991 if (notification == CBN_SELCHANGE)
992 return FILEDLG_DiskChange( lfs );
996 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
997 EndDialog(hWnd, TRUE);
1001 EndDialog(hWnd, FALSE);
1004 case IDABORT: /* can be sent by the hook procedure */
1005 EndDialog(hWnd, TRUE);
1011 /***********************************************************************
1012 * FILEDLG_MapDrawItemStruct [internal]
1013 * map a 16 bits drawitem struct to 32
1015 void FILEDLG_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)
1017 lpdis->CtlType = lpdis16->CtlType;
1018 lpdis->CtlID = lpdis16->CtlID;
1019 lpdis->itemID = lpdis16->itemID;
1020 lpdis->itemAction = lpdis16->itemAction;
1021 lpdis->itemState = lpdis16->itemState;
1022 lpdis->hwndItem = lpdis16->hwndItem;
1023 lpdis->hDC = lpdis16->hDC;
1024 lpdis->rcItem.right = lpdis16->rcItem.right;
1025 lpdis->rcItem.left = lpdis16->rcItem.left;
1026 lpdis->rcItem.top = lpdis16->rcItem.top;
1027 lpdis->rcItem.bottom = lpdis16->rcItem.bottom;
1028 lpdis->itemData = lpdis16->itemData;
1031 /************************************************************************
1032 * FILEDLG_MapStringPairsToW [internal]
1033 * map string pairs to Unicode
1035 LPWSTR FILEDLG_MapStringPairsToW(LPCSTR strA, UINT size)
1046 if (n < size) n = size;
1048 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
1049 x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR));
1050 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
1055 /************************************************************************
1056 * FILEDLG_DupToW [internal]
1057 * duplicates an Ansi string to unicode, with a buffer size
1059 LPWSTR FILEDLG_DupToW(LPCSTR str, DWORD size)
1062 if (str && (size > 0))
1064 strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1065 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
1071 /************************************************************************
1072 * FILEDLG_MapOfnStructA [internal]
1073 * map a 32 bits Ansi structure to an Unicode one
1075 void FILEDLG_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
1079 ofnW->lStructSize = sizeof(OPENFILENAMEW);
1080 ofnW->hwndOwner = ofnA->hwndOwner;
1081 ofnW->hInstance = ofnA->hInstance;
1082 if (ofnA->lpstrFilter)
1083 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrFilter, 0);
1085 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(defaultfilter, 0);
1087 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
1088 ofnW->lpstrCustomFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
1089 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
1090 ofnW->nFilterIndex = ofnA->nFilterIndex;
1091 ofnW->nMaxFile = ofnA->nMaxFile;
1092 ofnW->lpstrFile = FILEDLG_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
1093 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
1094 ofnW->lpstrFileTitle = FILEDLG_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
1095 if (ofnA->lpstrInitialDir)
1096 ofnW->lpstrInitialDir = HEAP_strdupAtoW(GetProcessHeap(),0,ofnA->lpstrInitialDir);
1097 if (ofnA->lpstrTitle)
1098 str = ofnA->lpstrTitle;
1100 /* Allocates default title (FIXME : get it from resource) */
1101 str = open ? defaultopen:defaultsave;
1102 ofnW->lpstrTitle = HEAP_strdupAtoW(GetProcessHeap(),0, str);
1103 ofnW->Flags = ofnA->Flags;
1104 ofnW->nFileOffset = ofnA->nFileOffset;
1105 ofnW->nFileExtension = ofnA->nFileExtension;
1106 ofnW->lpstrDefExt = FILEDLG_DupToW(ofnA->lpstrDefExt, 3);
1107 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
1109 if (HIWORD(ofnA->lpTemplateName))
1110 ofnW->lpTemplateName = HEAP_strdupAtoW(GetProcessHeap(), 0, ofnA->lpTemplateName);
1111 else /* numbered resource */
1112 ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
1117 /************************************************************************
1118 * FILEDLG_MapOfnStruct16 [internal]
1119 * map a 16 bits structure to an Unicode one
1121 void FILEDLG_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)
1124 /* first convert to linear pointers */
1125 memset(&ofnA, 0, sizeof(OPENFILENAMEA));
1126 ofnA.lStructSize = sizeof(OPENFILENAMEA);
1127 ofnA.hwndOwner = ofn16->hwndOwner;
1128 ofnA.hInstance = ofn16->hInstance;
1129 if (ofn16->lpstrFilter)
1130 ofnA.lpstrFilter = PTR_SEG_TO_LIN(ofn16->lpstrFilter);
1131 if (ofn16->lpstrCustomFilter)
1132 ofnA.lpstrCustomFilter = PTR_SEG_TO_LIN(ofn16->lpstrCustomFilter);
1133 ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;
1134 ofnA.nFilterIndex = ofn16->nFilterIndex;
1135 ofnA.lpstrFile = PTR_SEG_TO_LIN(ofn16->lpstrFile);
1136 ofnA.nMaxFile = ofn16->nMaxFile;
1137 ofnA.lpstrFileTitle = PTR_SEG_TO_LIN(ofn16->lpstrFileTitle);
1138 ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;
1139 ofnA.lpstrInitialDir = PTR_SEG_TO_LIN(ofn16->lpstrInitialDir);
1140 ofnA.lpstrTitle = PTR_SEG_TO_LIN(ofn16->lpstrTitle);
1141 ofnA.Flags = ofn16->Flags;
1142 ofnA.nFileOffset = ofn16->nFileOffset;
1143 ofnA.nFileExtension = ofn16->nFileExtension;
1144 ofnA.lpstrDefExt = PTR_SEG_TO_LIN(ofn16->lpstrDefExt);
1145 if (HIWORD(ofn16->lpTemplateName))
1146 ofnA.lpTemplateName = PTR_SEG_TO_LIN(ofn16->lpTemplateName);
1148 ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */
1149 /* now calls the 32 bits Ansi to Unicode version to complete the job */
1150 FILEDLG_MapOfnStructA(&ofnA, ofnW, open);
1154 /************************************************************************
1155 * FILEDLG_DestroyPrivate [internal]
1156 * destroys the private object
1158 void FILEDLG_DestroyPrivate(LFSPRIVATE lfs)
1163 /* free resources for a 16 bits dialog */
1164 if (lfs->hResource16) FreeResource16(lfs->hResource16);
1167 GlobalUnlock16(lfs->hGlobal16);
1168 GlobalFree16(lfs->hGlobal16);
1170 /* if ofnW has been allocated, have to free everything in it */
1171 if (lfs->ofn16 || lfs->ofnA)
1173 LPOPENFILENAMEW ofnW = lfs->ofnW;
1174 if (ofnW->lpstrFilter) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
1175 if (ofnW->lpstrCustomFilter) HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
1176 if (ofnW->lpstrFile) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile);
1177 if (ofnW->lpstrFileTitle) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
1178 if (ofnW->lpstrInitialDir) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
1179 if (ofnW->lpstrTitle) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
1180 if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
1181 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
1182 HeapFree(GetProcessHeap(), 0, ofnW);
1184 TRACE("destroying private allocation %p\n", lfs);
1185 HeapFree(GetProcessHeap(), 0, lfs);
1186 RemovePropA(hwnd, OFN_PROP);
1189 /************************************************************************
1190 * FILEDLG_AllocPrivate [internal]
1191 * allocate a private object to hold 32 bits Unicode
1192 * structure that will be used throughtout the calls, while
1193 * keeping available the original structures and a few variables
1194 * On entry : type = dialog procedure type (16,32A,32W)
1195 * dlgType = dialog type (open or save)
1197 LFSPRIVATE FILEDLG_AllocPrivate(LPARAM lParam, int type, UINT dlgType)
1199 LFSPRIVATE lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FSPRIVATE));
1201 TRACE("alloc private buf %p\n", lfs);
1202 if (!lfs) return NULL;
1204 lfs->lParam = lParam;
1205 if (dlgType == OPEN_DIALOG)
1209 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRING);
1210 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRING);
1214 lfs->ofn16 = (LPOPENFILENAME16) PTR_SEG_TO_LIN(lParam);
1215 if (lfs->ofn16->Flags & OFN_ENABLEHOOK)
1216 if (lfs->ofn16->lpfnHook)
1222 lfs->ofnA = (LPOPENFILENAMEA) lParam;
1223 if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
1224 if (lfs->ofnA->lpfnHook)
1229 lfs->ofnW = (LPOPENFILENAMEW) lParam;
1230 if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
1231 if (lfs->ofnW->lpfnHook)
1237 { /* this structure is needed internally, so create it */
1238 lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPENFILENAMEW));
1242 FILEDLG_MapOfnStruct16(lfs->ofn16, lfs->ofnW, lfs->open);
1244 FILEDLG_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
1251 if (!Get16BitsTemplate(lfs)) ret = NULL;
1254 if (!Get32BitsTemplate(lfs)) ret = NULL;
1255 if (!ret) FILEDLG_DestroyPrivate(lfs);
1260 /***********************************************************************
1261 * GetFileName31A [internal]
1263 * Creates a win31 style dialog box for the user to select a file to open/save.
1265 BOOL WINAPI GetFileName31A(
1266 LPOPENFILENAMEA lpofn, /* addess of structure with data*/
1267 UINT dlgType /* type dialogue : open/save */
1274 if (!lpofn || !FileDlg_Init()) return FALSE;
1276 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32A, dlgType);
1279 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1280 bRet = DialogBoxIndirectParamA( hInst, lfs->template, lpofn->hwndOwner,
1281 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1282 FILEDLG_DestroyPrivate(lfs);
1285 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile);
1290 /***********************************************************************
1291 * GetFileName31W [internal]
1293 * Creates a win31 style dialog box for the user to select a file to open/save
1295 BOOL WINAPI GetFileName31W(
1296 LPOPENFILENAMEW lpofn, /* addess of structure with data*/
1297 UINT dlgType /* type dialogue : open/save */
1304 if (!lpofn || !FileDlg_Init()) return FALSE;
1306 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32W, dlgType);
1309 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1310 bRet = DialogBoxIndirectParamW( hInst, lfs->template, lpofn->hwndOwner,
1311 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1312 FILEDLG_DestroyPrivate(lfs);
1315 TRACE("return lpstrFile='%s' !\n", debugstr_w(lpofn->lpstrFile));
1320 /* ------------------ Dialog procedures ---------------------- */
1322 /***********************************************************************
1323 * FileOpenDlgProc16 (COMMDLG.6)
1325 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1328 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1331 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1332 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1334 LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1336 return lRet; /* else continue message processing */
1341 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1343 case WM_MEASUREITEM:
1344 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1347 FILEDLG_MapDrawItemStruct((LPDRAWITEMSTRUCT16)PTR_SEG_TO_LIN(lParam), &dis);
1348 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
1351 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
1354 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1355 switch (HIWORD(lParam))
1358 SetTextColor((HDC16)wParam, 0x00000000);
1360 case CTLCOLOR_STATIC:
1361 SetTextColor((HDC16)wParam, 0x00000000);
1370 /***********************************************************************
1371 * FileSaveDlgProc16 (COMMDLG.7)
1373 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1376 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1379 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1380 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1383 lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1385 return lRet; /* else continue message processing */
1389 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1391 case WM_MEASUREITEM:
1392 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1395 FILEDLG_MapDrawItemStruct((LPDRAWITEMSTRUCT16)PTR_SEG_TO_LIN(lParam), &dis);
1396 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
1399 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
1404 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1405 switch (HIWORD(lParam))
1408 SetTextColor((HDC16)wParam, 0x00000000);
1410 case CTLCOLOR_STATIC:
1411 SetTextColor((HDC16)wParam, 0x00000000);
1420 /***********************************************************************
1421 * FileOpenDlgProc [internal]
1422 * Used for open and save, in fact.
1424 static LRESULT WINAPI FileOpenDlgProc(HWND hWnd, UINT wMsg,
1425 WPARAM wParam, LPARAM lParam)
1427 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1429 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1430 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1433 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1435 return lRet; /* else continue message processing */
1440 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1442 case WM_MEASUREITEM:
1443 return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1446 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam);
1449 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs);
1452 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1453 switch (HIWORD(lParam))
1456 SetTextColor((HDC16)wParam, 0x00000000);
1458 case CTLCOLOR_STATIC:
1459 SetTextColor((HDC16)wParam, 0x00000000);
1468 /* ------------------ APIs ---------------------- */
1470 /***********************************************************************
1471 * GetOpenFileName16 (COMMDLG.1)
1473 * Creates a dialog box for the user to select a file to open.
1476 * TRUE on success: user selected a valid file
1477 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1480 * unknown, there are some FIXME's left.
1482 BOOL16 WINAPI GetOpenFileName16(
1483 SEGPTR ofn /* [in/out] address of structure with data*/
1488 LPOPENFILENAME16 lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(ofn);
1492 if (!lpofn || !FileDlg_Init()) return FALSE;
1494 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
1497 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1498 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
1499 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1500 (DLGPROC16) ptr, (DWORD) lfs);
1501 FILEDLG_DestroyPrivate(lfs);
1504 TRACE("return lpstrFile='%s' !\n",
1505 (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
1509 /***********************************************************************
1510 * GetSaveFileName16 (COMMDLG.2)
1512 * Creates a dialog box for the user to select a file to save.
1515 * TRUE on success: user enters a valid file
1516 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1519 * unknown. There are some FIXME's left.
1521 BOOL16 WINAPI GetSaveFileName16(
1522 SEGPTR ofn /* [in/out] addess of structure with data*/
1527 LPOPENFILENAME16 lpofn = (LPOPENFILENAME16)PTR_SEG_TO_LIN(ofn);
1531 if (!lpofn || !FileDlg_Init()) return FALSE;
1533 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
1536 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1537 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
1538 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1539 (DLGPROC16) ptr, (DWORD) lfs);
1540 FILEDLG_DestroyPrivate(lfs);
1543 TRACE("return lpstrFile='%s' !\n",
1544 (LPSTR)PTR_SEG_TO_LIN(lpofn->lpstrFile));
1548 /***********************************************************************
1549 * GetOpenFileNameA (COMDLG32.10)
1551 * Creates a dialog box for the user to select a file to open.
1554 * TRUE on success: user enters a valid file
1555 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1558 BOOL WINAPI GetOpenFileNameA(
1559 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1561 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1563 /* some flags don't allow to match the TWEAK_WineLook */
1564 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1566 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1571 return GetFileDialog95A(ofn, OPEN_DIALOG);
1575 return GetFileName31A(ofn, OPEN_DIALOG);
1579 /***********************************************************************
1580 * GetOpenFileNameW (COMDLG32.11)
1582 * Creates a dialog box for the user to select a file to open.
1585 * TRUE on success: user enters a valid file
1586 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1589 BOOL WINAPI GetOpenFileNameW(
1590 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1592 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1594 /* some flags don't allow to match the TWEAK_WineLook */
1595 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1597 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1602 return GetFileDialog95W(ofn, OPEN_DIALOG);
1606 return GetFileName31W(ofn, OPEN_DIALOG);
1610 /***********************************************************************
1611 * GetSaveFileNameA (COMDLG32.12)
1613 * Creates a dialog box for the user to select a file to save.
1616 * TRUE on success: user enters a valid file
1617 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1620 BOOL WINAPI GetSaveFileNameA(
1621 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1623 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1625 /* some flags don't allow to match the TWEAK_WineLook */
1626 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1628 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1633 return GetFileDialog95A(ofn, SAVE_DIALOG);
1637 return GetFileName31A(ofn, SAVE_DIALOG);
1641 /***********************************************************************
1642 * GetSaveFileNameW (COMDLG32.13)
1644 * Creates a dialog box for the user to select a file to save.
1647 * TRUE on success: user enters a valid file
1648 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1651 BOOL WINAPI GetSaveFileNameW(
1652 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1654 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1656 /* some flags don't allow to match the TWEAK_WineLook */
1657 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1659 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1664 return GetFileDialog95W(ofn, SAVE_DIALOG);
1668 return GetFileName31W(ofn, SAVE_DIALOG);