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"
20 #include "debugtools.h"
23 DEFAULT_DEBUG_CHANNEL(commdlg);
28 #define BUFFILEALLOC 512 * sizeof(WCHAR)
32 HWND hwnd; /* file dialog window handle */
33 BOOL hook; /* TRUE if the dialog is hooked */
34 UINT lbselchstring; /* registered message id */
35 UINT fileokstring; /* registered message id */
36 LPARAM lParam; /* save original lparam */
37 HANDLE16 hDlgTmpl16; /* handle for resource 16 */
38 HANDLE16 hResource16; /* handle for allocated resource 16 */
39 HANDLE16 hGlobal16; /* 16 bits mem block (resources) */
40 LPCVOID template; /* template for 32 bits resource */
41 BOOL open; /* TRUE if open dialog, FALSE if save dialog */
42 OPENFILENAMEW *ofnW; /* original structure or work struct */
43 OPENFILENAMEA *ofnA; /* original structure if 32bits ansi dialog */
44 OPENFILENAME16 *ofn16; /* original structure if 16 bits dialog */
48 #define LFSPRIVATE struct FSPRIVATE *
54 static const WCHAR FILE_star[] = {'*','.','*', 0};
55 static const WCHAR FILE_bslash[] = {'\\', 0};
56 static const WCHAR FILE_specc[] = {'%','c',':', 0};
58 static HICON16 hFolder = 0;
59 static HICON16 hFolder2 = 0;
60 static HICON16 hFloppy = 0;
61 static HICON16 hHDisk = 0;
62 static HICON16 hCDRom = 0;
63 static HICON16 hNet = 0;
64 static const int fldrHeight = 16;
65 static const int fldrWidth = 20;
67 #define OFN_PROP "FILEDLG_OFN"
69 static const char defaultfilter[]=" \0\0";
70 static char defaultopen[]="Open File";
71 static char defaultsave[]="Save as";
73 /***********************************************************************
75 * Windows 3.1 style OpenFileName/SaveFileName dialog
79 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
81 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
84 static LRESULT WINAPI FileOpenDlgProc(HWND hDlg, UINT msg,
85 WPARAM wParam, LPARAM lParam);
87 /***********************************************************************
88 * FileDlg_Init [internal]
90 static BOOL FileDlg_Init(void)
92 static BOOL initialized = 0;
95 HINSTANCE inst = GetModuleHandleA( "comdlg32.dll" );
98 ERR( "cannot get comdlg32.dll instance\n" );
101 hFolder = LoadImageA( inst, "FOLDER", IMAGE_ICON, 16, 16, LR_SHARED );
102 hFolder2 = LoadImageA( inst, "FOLDER2", IMAGE_ICON, 16, 16, LR_SHARED );
103 hFloppy = LoadImageA( inst, "FLOPPY", IMAGE_ICON, 16, 16, LR_SHARED );
104 hHDisk = LoadImageA( inst, "HDISK", IMAGE_ICON, 16, 16, LR_SHARED );
105 hCDRom = LoadImageA( inst, "CDROM", IMAGE_ICON, 16, 16, LR_SHARED );
106 hNet = LoadImageA( inst, "NETWORK", IMAGE_ICON, 16, 16, LR_SHARED );
107 if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 ||
108 hHDisk == 0 || hCDRom == 0 || hNet == 0)
110 ERR("Error loading icons !\n");
119 /***********************************************************************
120 * Get32BitsTemplate [internal]
122 * Get a template (or FALSE if failure) when 16 bits dialogs are used
123 * by a 32 bits application
126 BOOL Get32BitsTemplate(LFSPRIVATE lfs)
128 LPOPENFILENAMEW ofnW = lfs->ofnW;
131 if (ofnW->Flags & OFN_ENABLETEMPLATEHANDLE)
133 if (!(lfs->template = LockResource( ofnW->hInstance )))
135 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
139 else if (ofnW->Flags & OFN_ENABLETEMPLATE)
143 hResInfo = FindResourceA(lfs->ofnA->hInstance,
144 lfs->ofnA->lpTemplateName,
147 hResInfo = FindResourceW(ofnW->hInstance,
148 ofnW->lpTemplateName,
152 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
155 if (!(hDlgTmpl = LoadResource(ofnW->hInstance,
157 !(lfs->template = LockResource(hDlgTmpl)))
159 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
162 } else { /* get it from internal Wine resource */
164 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
165 lfs->open? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
167 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
170 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
171 !(lfs->template = LockResource( hDlgTmpl )))
173 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
181 /***********************************************************************
182 * Get16BitsTemplate [internal]
184 * Get a template (FALSE if failure) when 16 bits dialogs are used
185 * by a 16 bits application
188 BOOL Get16BitsTemplate(LFSPRIVATE lfs)
190 LPOPENFILENAME16 ofn16 = lfs->ofn16;
192 HGLOBAL16 hGlobal16 = 0;
194 if (ofn16->Flags & OFN_ENABLETEMPLATEHANDLE)
195 lfs->hDlgTmpl16 = ofn16->hInstance;
196 else if (ofn16->Flags & OFN_ENABLETEMPLATE)
199 if (!(hResInfo = FindResource16(ofn16->hInstance,
200 MapSL(ofn16->lpTemplateName),
203 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
206 if (!(lfs->hDlgTmpl16 = LoadResource16( ofn16->hInstance, hResInfo )))
208 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
211 lfs->hResource16 = lfs->hDlgTmpl16;
214 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
215 HANDLE hResInfo, hDlgTmpl32;
219 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
220 lfs->open ? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
222 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
225 if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
226 !(template32 = LockResource( hDlgTmpl32 )))
228 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
231 size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
232 hGlobal16 = GlobalAlloc16(0, size);
235 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
236 ERR("alloc failure for %ld bytes\n", size);
239 template = GlobalLock16(hGlobal16);
242 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
243 ERR("global lock failure for %x handle\n", hGlobal16);
244 GlobalFree16(hGlobal16);
247 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
248 lfs->hDlgTmpl16 = hGlobal16;
249 lfs->hGlobal16 = hGlobal16;
254 /***********************************************************************
255 * FILEDLG_StripEditControl [internal]
256 * Strip pathnames off the contents of the edit control.
258 static void FILEDLG_StripEditControl(HWND hwnd)
260 WCHAR temp[BUFFILE], *cp;
262 GetDlgItemTextW( hwnd, edt1, temp, sizeof(temp)/sizeof(WCHAR));
263 cp = strrchrW(temp, '\\');
267 cp = strrchrW(temp, ':');
271 /* FIXME: shouldn't we do something with the result here? ;-) */
276 /***********************************************************************
277 * FILEDLG_CallWindowProc [internal]
279 * Call the appropriate hook
281 static BOOL FILEDLG_CallWindowProc(LFSPRIVATE lfs, UINT wMsg, WPARAM wParam,
286 return (BOOL16) CallWindowProc16(
287 (WNDPROC16)lfs->ofn16->lpfnHook, lfs->hwnd,
288 (UINT16)wMsg, (WPARAM16)wParam, lParam);
292 return (BOOL) CallWindowProcA(
293 (WNDPROC)lfs->ofnA->lpfnHook, lfs->hwnd,
294 wMsg, wParam, lParam);
299 return (BOOL) CallWindowProcW(
300 (WNDPROC)lfs->ofnW->lpfnHook, lfs->hwnd,
301 wMsg, wParam, lParam);
307 /***********************************************************************
308 * FILEDLG_ScanDir [internal]
310 static BOOL FILEDLG_ScanDir(HWND hWnd, LPWSTR newPath)
312 WCHAR buffer[BUFFILE];
315 HCURSOR hCursorWait, oldCursor;
317 if ( !SetCurrentDirectoryW( newPath ))
319 lstrcpynW(buffer, newPath, sizeof(buffer)/sizeof(WCHAR));
321 /* get the list of spec files */
322 GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer)/sizeof(WCHAR));
324 hCursorWait = LoadCursorA(0, IDC_WAITA);
325 oldCursor = SetCursor(hCursorWait);
328 if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) {
329 WCHAR* scptr; /* ptr on semi-colon */
330 WCHAR* filter = buffer;
332 TRACE("Using filter %s\n", debugstr_w(filter));
333 SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
335 scptr = strchrW(filter, ';');
336 if (scptr) *scptr = 0;
337 while (*filter == ' ') filter++;
338 TRACE("Using file spec %s\n", debugstr_w(filter));
339 if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
341 if (scptr) *scptr = ';';
342 filter = (scptr) ? (scptr + 1) : 0;
346 /* list of directories */
347 strcpyW(buffer, FILE_star);
349 if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
350 lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
352 SetCursor(oldCursor);
357 /***********************************************************************
358 * FILEDLG_GetFileType [internal]
361 static LPWSTR FILEDLG_GetFileType(LPWSTR cfptr, LPWSTR fptr, WORD index)
366 for ( ;(n = lstrlenW(cfptr)) != 0; i++)
371 cfptr += lstrlenW(cfptr) + 1;
374 for ( ;(n = lstrlenW(fptr)) != 0; i++)
379 fptr += lstrlenW(fptr) + 1;
381 return (LPWSTR) FILE_star; /* FIXME */
384 /***********************************************************************
385 * FILEDLG_WMDrawItem [internal]
387 static LONG FILEDLG_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
388 int savedlg, LPDRAWITEMSTRUCT lpdis)
392 COLORREF oldText = 0, oldBk = 0;
394 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
396 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) return FALSE;
397 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
400 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
402 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
403 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
406 SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
408 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1,
409 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
410 &(lpdis->rcItem), str, lstrlenW(str), NULL);
412 if (lpdis->itemState & ODS_SELECTED)
413 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
415 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
417 SetBkColor( lpdis->hDC, oldBk );
418 SetTextColor( lpdis->hDC, oldText );
420 HeapFree(GetProcessHeap(), 0, str);
424 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
426 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
428 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
431 if (lpdis->itemState & ODS_SELECTED)
433 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
434 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
436 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
437 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
438 &(lpdis->rcItem), str, lstrlenW(str), NULL);
440 if (lpdis->itemState & ODS_SELECTED)
441 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
443 if (lpdis->itemState & ODS_SELECTED)
445 SetBkColor( lpdis->hDC, oldBk );
446 SetTextColor( lpdis->hDC, oldText );
448 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
449 HeapFree(GetProcessHeap(), 0, str);
452 if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
455 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
457 SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID,
459 root[0] += str[2] - 'a';
460 switch(GetDriveTypeA(root))
462 case DRIVE_REMOVABLE: hIcon = hFloppy; break;
463 case DRIVE_CDROM: hIcon = hCDRom; break;
464 case DRIVE_REMOTE: hIcon = hNet; break;
466 default: hIcon = hHDisk; break;
468 if (lpdis->itemState & ODS_SELECTED)
470 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
471 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
473 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
474 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
475 &(lpdis->rcItem), str, lstrlenW(str), NULL);
477 if (lpdis->itemState & ODS_SELECTED)
479 SetBkColor( lpdis->hDC, oldBk );
480 SetTextColor( lpdis->hDC, oldText );
482 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
483 HeapFree(GetProcessHeap(), 0, str);
489 /***********************************************************************
490 * FILEDLG_WMMeasureItem [internal]
492 static LONG FILEDLG_WMMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
494 LPMEASUREITEMSTRUCT lpmeasure;
496 lpmeasure = (LPMEASUREITEMSTRUCT)lParam;
497 lpmeasure->itemHeight = fldrHeight;
501 /***********************************************************************
502 * FILEDLG_WMMeasureItem16 [internal]
504 static LONG FILEDLG_WMMeasureItem16(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
506 LPMEASUREITEMSTRUCT16 lpmeasure;
508 lpmeasure = MapSL(lParam);
509 lpmeasure->itemHeight = fldrHeight;
513 /***********************************************************************
514 * FILEDLG_WMInitDialog [internal]
517 static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
520 WCHAR tmpstr[BUFFILE];
521 LPWSTR pstr, old_pstr;
523 LFSPRIVATE lfs = (LFSPRIVATE) lParam;
525 if (!lfs) return FALSE;
526 SetPropA(hWnd, OFN_PROP, (HANDLE)lfs);
530 TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
532 SetWindowTextW( hWnd, ofn->lpstrTitle );
533 /* read custom filter information */
534 if (ofn->lpstrCustomFilter)
536 pstr = ofn->lpstrCustomFilter;
538 TRACE("lpstrCustomFilter = %p\n", pstr);
542 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
543 (LPARAM)(ofn->lpstrCustomFilter) + n );
544 n += lstrlenW(pstr) + 1;
545 pstr += lstrlenW(pstr) + 1;
546 TRACE("add str=%s associated to %s\n",
547 debugstr_w(old_pstr), debugstr_w(pstr));
548 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
549 n += lstrlenW(pstr) + 1;
550 pstr += lstrlenW(pstr) + 1;
553 /* read filter information */
554 if (ofn->lpstrFilter) {
555 pstr = (LPWSTR) ofn->lpstrFilter;
559 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
560 (LPARAM)(ofn->lpstrFilter + n) );
561 n += lstrlenW(pstr) + 1;
562 pstr += lstrlenW(pstr) + 1;
563 TRACE("add str=%s associated to %s\n",
564 debugstr_w(old_pstr), debugstr_w(pstr));
565 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
566 n += lstrlenW(pstr) + 1;
567 pstr += lstrlenW(pstr) + 1;
570 /* set default filter */
571 if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
572 ofn->nFilterIndex = 1;
573 SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
574 lstrcpynW(tmpstr, FILEDLG_GetFileType(ofn->lpstrCustomFilter,
575 (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
576 TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
577 ofn->nFilterIndex, debugstr_w(tmpstr));
578 SetDlgItemTextW( hWnd, edt1, tmpstr );
581 DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
582 /* read initial directory */
583 if (ofn->lpstrInitialDir != NULL)
586 lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
587 len = lstrlenW(tmpstr);
588 if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') {
595 if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
597 if (!FILEDLG_ScanDir(hWnd, tmpstr))
598 WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
600 /* select current drive in combo 2, omit missing drives */
603 char str[4] = "a:\\";
604 GetCurrentDirectoryA( sizeof(dir), dir );
605 for(i = 0, n = -1; i < 26; i++)
608 if (GetDriveTypeA(str) <= DRIVE_NO_ROOT_DIR) n++;
609 if (toupper(str[0]) == toupper(dir[0])) break;
612 SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
613 if (!(ofn->Flags & OFN_SHOWHELP))
614 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
615 if (ofn->Flags & OFN_HIDEREADONLY)
616 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
618 return (BOOL) FILEDLG_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
622 /***********************************************************************
623 * FILEDLG_UpdateResult [internal]
624 * update the displayed file name (with path)
626 void FILEDLG_UpdateResult(LFSPRIVATE lfs, WCHAR *tmpstr)
629 LPOPENFILENAMEW ofnW = lfs->ofnW;
630 WCHAR tmpstr2[BUFFILE];
632 GetCurrentDirectoryW(BUFFILE, tmpstr2);
633 lenstr2 = strlenW(tmpstr2);
635 tmpstr2[lenstr2++]='\\';
636 lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
638 lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
639 ofnW->nFileOffset = strrchrW(tmpstr2,'\\') - tmpstr2 +1;
640 ofnW->nFileExtension = 0;
641 while(tmpstr2[ofnW->nFileExtension] != '.' && tmpstr2[ofnW->nFileExtension] != '\0')
642 ofnW->nFileExtension++;
643 if (tmpstr2[ofnW->nFileExtension] == '\0')
644 ofnW->nFileExtension = 0;
646 ofnW->nFileExtension++;
647 /* update the real client structures if any */
649 { /* we have to convert to short (8.3) path */
650 char tmp[1024]; /* MAX_PATHNAME_LEN */
651 LPOPENFILENAME16 ofn16 = lfs->ofn16;
652 char *dest = MapSL(ofn16->lpstrFile);
653 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
654 tmp, ofnW->nMaxFile, NULL, NULL ))
655 tmp[ofnW->nMaxFile-1] = 0;
656 GetShortPathNameA(tmp, dest, ofn16->nMaxFile);
658 /* the same procedure as every year... */
659 ofn16->nFileOffset = strrchr(dest,'\\') - dest +1;
660 ofn16->nFileExtension = 0;
661 while(dest[ofn16->nFileExtension] != '.' && dest[ofn16->nFileExtension] != '\0')
662 ofn16->nFileExtension++;
663 if (dest[ofn16->nFileExtension] == '\0')
664 ofn16->nFileExtension = 0;
666 ofn16->nFileExtension++;
670 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
671 lfs->ofnA->lpstrFile, ofnW->nMaxFile, NULL, NULL ))
672 lfs->ofnA->lpstrFile[ofnW->nMaxFile-1] = 0;
673 lfs->ofnA->nFileOffset = ofnW->nFileOffset;
674 lfs->ofnA->nFileExtension = ofnW->nFileExtension;
679 /***********************************************************************
680 * FILEDLG_UpdateFileTitle [internal]
681 * update the displayed file name (without path)
683 void FILEDLG_UpdateFileTitle(LFSPRIVATE lfs)
686 LPOPENFILENAMEW ofnW = lfs->ofnW;
687 if (ofnW->lpstrFileTitle != NULL)
689 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
690 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
691 (LPARAM)ofnW->lpstrFileTitle );
694 char *dest = MapSL(lfs->ofn16->lpstrFileTitle);
695 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
696 dest, ofnW->nMaxFileTitle, NULL, NULL ))
697 dest[ofnW->nMaxFileTitle-1] = 0;
701 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
702 lfs->ofnA->lpstrFileTitle, ofnW->nMaxFileTitle, NULL, NULL ))
703 lfs->ofnA->lpstrFileTitle[ofnW->nMaxFileTitle-1] = 0;
710 /***********************************************************************
711 * FILEDLG_DirListDblClick [internal]
713 static LRESULT FILEDLG_DirListDblClick( LFSPRIVATE lfs )
716 HWND hWnd = lfs->hwnd;
718 WCHAR tmpstr[BUFFILE];
720 /* get the raw string (with brackets) */
721 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
722 if (lRet == LB_ERR) return TRUE;
723 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
724 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
726 strcpyW( tmpstr, pstr );
727 HeapFree(GetProcessHeap(), 0, pstr);
728 /* get the selected directory in tmpstr */
729 if (tmpstr[0] == '[')
731 tmpstr[lstrlenW(tmpstr) - 1] = 0;
732 strcpyW(tmpstr,tmpstr+1);
734 strcatW(tmpstr, FILE_bslash);
736 FILEDLG_ScanDir(hWnd, tmpstr);
740 if (FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst2,
741 MAKELONG(lRet,CD_LBSELCHANGE)))
748 /***********************************************************************
749 * FILEDLG_FileListSelect [internal]
750 * called when a new item is picked in the file list
752 static LRESULT FILEDLG_FileListSelect( LFSPRIVATE lfs )
755 HWND hWnd = lfs->hwnd;
758 lRet = SendDlgItemMessageW(hWnd, lst1, LB_GETCURSEL16, 0, 0);
762 /* set the edit control to the choosen file */
763 if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
765 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
767 SetDlgItemTextW( hWnd, edt1, pstr );
768 HeapFree(GetProcessHeap(), 0, pstr);
772 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst1,
773 MAKELONG(lRet,CD_LBSELCHANGE));
775 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
780 /***********************************************************************
781 * FILEDLG_TestPath [internal]
782 * before accepting the file name, test if it includes wild cards
783 * tries to scan the directory and returns TRUE if no error.
785 static LRESULT FILEDLG_TestPath( LFSPRIVATE lfs, LPWSTR path )
787 HWND hWnd = lfs->hwnd;
788 LPWSTR pBeginFileName, pstr2;
789 WCHAR tmpstr2[BUFFILE];
791 pBeginFileName = strrchrW(path, '\\');
792 if (pBeginFileName == NULL)
793 pBeginFileName = strrchrW(path, ':');
795 if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL)
797 /* edit control contains wildcards */
798 if (pBeginFileName != NULL)
800 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
801 *(pBeginFileName + 1) = 0;
805 strcpyW(tmpstr2, path);
809 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
810 SetDlgItemTextW( hWnd, edt1, tmpstr2 );
811 FILEDLG_ScanDir(hWnd, path);
815 /* no wildcards, we might have a directory or a filename */
816 /* try appending a wildcard and reading the directory */
818 pstr2 = path + lstrlenW(path);
819 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
820 strcatW(path, FILE_bslash);
822 /* if ScanDir succeeds, we have changed the directory */
823 if (FILEDLG_ScanDir(hWnd, path))
826 /* if not, this must be a filename */
828 *pstr2 = 0; /* remove the wildcard added before */
830 if (pBeginFileName != NULL)
832 /* strip off the pathname */
834 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
836 lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
837 /* Should we MessageBox() if this fails? */
838 if (!FILEDLG_ScanDir(hWnd, path))
842 strcpyW(path, tmpstr2);
845 SetDlgItemTextW( hWnd, edt1, path );
849 /***********************************************************************
850 * FILEDLG_Validate [internal]
851 * called on: click Ok button, Enter in edit, DoubleClick in file list
853 static LRESULT FILEDLG_Validate( LFSPRIVATE lfs, LPWSTR path, UINT control, INT itemIndex,
857 HWND hWnd = lfs->hwnd;
858 OPENFILENAMEW ofnsav;
859 LPOPENFILENAMEW ofnW = lfs->ofnW;
860 WCHAR filename[BUFFILE];
862 ofnsav = *ofnW; /* for later restoring */
864 /* get current file name */
866 lstrcpynW(filename, path, sizeof(filename)/sizeof(WCHAR));
868 GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename)/sizeof(WCHAR));
870 /* if we did not click in file list to get there */
873 if (!FILEDLG_TestPath( lfs, filename) )
876 FILEDLG_UpdateResult(lfs, filename);
879 { /* called internally after a change in a combo */
882 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, control,
883 MAKELONG(itemIndex,CD_LBSELCHANGE));
888 FILEDLG_UpdateFileTitle(lfs);
891 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, lfs->fileokstring,
895 *ofnW = ofnsav; /* restore old state */
899 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
903 LPWSTR str = (LPWSTR)ofnW->lpstrFile;
904 LPWSTR ptr = strrchrW(str, '\\');
905 str[lstrlenW(str) + 1] = '\0';
912 /***********************************************************************
913 * FILEDLG_DiskChange [internal]
914 * called when a new item is picked in the disk selection combo
916 static LRESULT FILEDLG_DiskChange( LFSPRIVATE lfs )
919 HWND hWnd = lfs->hwnd;
921 WCHAR diskname[BUFFILE];
923 FILEDLG_StripEditControl(hWnd);
924 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
927 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
928 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
930 wsprintfW(diskname, FILE_specc, pstr[2]);
931 HeapFree(GetProcessHeap(), 0, pstr);
933 return FILEDLG_Validate( lfs, diskname, cmb2, lRet, TRUE );
937 /***********************************************************************
938 * FILEDLG_FileTypeChange [internal]
939 * called when a new item is picked in the file type combo
941 static LRESULT FILEDLG_FileTypeChange( LFSPRIVATE lfs )
944 WCHAR diskname[BUFFILE];
949 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
952 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
953 TRACE("Selected filter : %s\n", debugstr_w(pstr));
954 SetDlgItemTextW( lfs->hwnd, edt1, pstr );
956 return FILEDLG_Validate( lfs, NULL, cmb1, lRet, TRUE );
959 /***********************************************************************
960 * FILEDLG_WMCommand [internal]
962 static LRESULT FILEDLG_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
963 UINT control, LFSPRIVATE lfs )
967 case lst1: /* file list */
968 FILEDLG_StripEditControl(hWnd);
969 if (notification == LBN_DBLCLK)
971 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
972 EndDialog(hWnd, TRUE);
975 else if (notification == LBN_SELCHANGE)
976 return FILEDLG_FileListSelect( lfs );
979 case lst2: /* directory list */
980 FILEDLG_StripEditControl(hWnd);
981 if (notification == LBN_DBLCLK)
982 return FILEDLG_DirListDblClick( lfs );
985 case cmb1: /* file type drop list */
986 if (notification == CBN_SELCHANGE)
987 return FILEDLG_FileTypeChange( lfs );
996 case cmb2: /* disk dropdown combo */
997 if (notification == CBN_SELCHANGE)
998 return FILEDLG_DiskChange( lfs );
1002 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
1003 EndDialog(hWnd, TRUE);
1007 EndDialog(hWnd, FALSE);
1010 case IDABORT: /* can be sent by the hook procedure */
1011 EndDialog(hWnd, TRUE);
1017 /***********************************************************************
1018 * FILEDLG_MapDrawItemStruct [internal]
1019 * map a 16 bits drawitem struct to 32
1021 void FILEDLG_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)
1023 lpdis->CtlType = lpdis16->CtlType;
1024 lpdis->CtlID = lpdis16->CtlID;
1025 lpdis->itemID = lpdis16->itemID;
1026 lpdis->itemAction = lpdis16->itemAction;
1027 lpdis->itemState = lpdis16->itemState;
1028 lpdis->hwndItem = lpdis16->hwndItem;
1029 lpdis->hDC = lpdis16->hDC;
1030 lpdis->rcItem.right = lpdis16->rcItem.right;
1031 lpdis->rcItem.left = lpdis16->rcItem.left;
1032 lpdis->rcItem.top = lpdis16->rcItem.top;
1033 lpdis->rcItem.bottom = lpdis16->rcItem.bottom;
1034 lpdis->itemData = lpdis16->itemData;
1037 /************************************************************************
1038 * FILEDLG_MapStringPairsToW [internal]
1039 * map string pairs to Unicode
1041 LPWSTR FILEDLG_MapStringPairsToW(LPCSTR strA, UINT size)
1052 if (n < size) n = size;
1054 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
1055 x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR));
1056 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
1061 /************************************************************************
1062 * FILEDLG_DupToW [internal]
1063 * duplicates an Ansi string to unicode, with a buffer size
1065 LPWSTR FILEDLG_DupToW(LPCSTR str, DWORD size)
1068 if (str && (size > 0))
1070 strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1071 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
1077 /************************************************************************
1078 * FILEDLG_MapOfnStructA [internal]
1079 * map a 32 bits Ansi structure to an Unicode one
1081 void FILEDLG_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
1085 ofnW->lStructSize = sizeof(OPENFILENAMEW);
1086 ofnW->hwndOwner = ofnA->hwndOwner;
1087 ofnW->hInstance = ofnA->hInstance;
1088 if (ofnA->lpstrFilter)
1089 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrFilter, 0);
1091 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(defaultfilter, 0);
1093 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
1094 ofnW->lpstrCustomFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
1095 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
1096 ofnW->nFilterIndex = ofnA->nFilterIndex;
1097 ofnW->nMaxFile = ofnA->nMaxFile;
1098 ofnW->lpstrFile = FILEDLG_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
1099 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
1100 ofnW->lpstrFileTitle = FILEDLG_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
1101 if (ofnA->lpstrInitialDir)
1102 ofnW->lpstrInitialDir = HEAP_strdupAtoW(GetProcessHeap(),0,ofnA->lpstrInitialDir);
1103 if (ofnA->lpstrTitle)
1104 str = ofnA->lpstrTitle;
1106 /* Allocates default title (FIXME : get it from resource) */
1107 str = open ? defaultopen:defaultsave;
1108 ofnW->lpstrTitle = HEAP_strdupAtoW(GetProcessHeap(),0, str);
1109 ofnW->Flags = ofnA->Flags;
1110 ofnW->nFileOffset = ofnA->nFileOffset;
1111 ofnW->nFileExtension = ofnA->nFileExtension;
1112 ofnW->lpstrDefExt = FILEDLG_DupToW(ofnA->lpstrDefExt, 3);
1113 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
1115 if (HIWORD(ofnA->lpTemplateName))
1116 ofnW->lpTemplateName = HEAP_strdupAtoW(GetProcessHeap(), 0, ofnA->lpTemplateName);
1117 else /* numbered resource */
1118 ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
1123 /************************************************************************
1124 * FILEDLG_MapOfnStruct16 [internal]
1125 * map a 16 bits structure to an Unicode one
1127 void FILEDLG_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)
1130 /* first convert to linear pointers */
1131 memset(&ofnA, 0, sizeof(OPENFILENAMEA));
1132 ofnA.lStructSize = sizeof(OPENFILENAMEA);
1133 ofnA.hwndOwner = ofn16->hwndOwner;
1134 ofnA.hInstance = ofn16->hInstance;
1135 if (ofn16->lpstrFilter)
1136 ofnA.lpstrFilter = MapSL(ofn16->lpstrFilter);
1137 if (ofn16->lpstrCustomFilter)
1138 ofnA.lpstrCustomFilter = MapSL(ofn16->lpstrCustomFilter);
1139 ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;
1140 ofnA.nFilterIndex = ofn16->nFilterIndex;
1141 ofnA.lpstrFile = MapSL(ofn16->lpstrFile);
1142 ofnA.nMaxFile = ofn16->nMaxFile;
1143 ofnA.lpstrFileTitle = MapSL(ofn16->lpstrFileTitle);
1144 ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;
1145 ofnA.lpstrInitialDir = MapSL(ofn16->lpstrInitialDir);
1146 ofnA.lpstrTitle = MapSL(ofn16->lpstrTitle);
1147 ofnA.Flags = ofn16->Flags;
1148 ofnA.nFileOffset = ofn16->nFileOffset;
1149 ofnA.nFileExtension = ofn16->nFileExtension;
1150 ofnA.lpstrDefExt = MapSL(ofn16->lpstrDefExt);
1151 if (HIWORD(ofn16->lpTemplateName))
1152 ofnA.lpTemplateName = MapSL(ofn16->lpTemplateName);
1154 ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */
1155 /* now calls the 32 bits Ansi to Unicode version to complete the job */
1156 FILEDLG_MapOfnStructA(&ofnA, ofnW, open);
1160 /************************************************************************
1161 * FILEDLG_DestroyPrivate [internal]
1162 * destroys the private object
1164 void FILEDLG_DestroyPrivate(LFSPRIVATE lfs)
1169 /* free resources for a 16 bits dialog */
1170 if (lfs->hResource16) FreeResource16(lfs->hResource16);
1173 GlobalUnlock16(lfs->hGlobal16);
1174 GlobalFree16(lfs->hGlobal16);
1176 /* if ofnW has been allocated, have to free everything in it */
1177 if (lfs->ofn16 || lfs->ofnA)
1179 LPOPENFILENAMEW ofnW = lfs->ofnW;
1180 if (ofnW->lpstrFilter) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
1181 if (ofnW->lpstrCustomFilter) HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
1182 if (ofnW->lpstrFile) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile);
1183 if (ofnW->lpstrFileTitle) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
1184 if (ofnW->lpstrInitialDir) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
1185 if (ofnW->lpstrTitle) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
1186 if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
1187 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
1188 HeapFree(GetProcessHeap(), 0, ofnW);
1190 TRACE("destroying private allocation %p\n", lfs);
1191 HeapFree(GetProcessHeap(), 0, lfs);
1192 RemovePropA(hwnd, OFN_PROP);
1195 /************************************************************************
1196 * FILEDLG_AllocPrivate [internal]
1197 * allocate a private object to hold 32 bits Unicode
1198 * structure that will be used throughtout the calls, while
1199 * keeping available the original structures and a few variables
1200 * On entry : type = dialog procedure type (16,32A,32W)
1201 * dlgType = dialog type (open or save)
1203 LFSPRIVATE FILEDLG_AllocPrivate(LPARAM lParam, int type, UINT dlgType)
1205 LFSPRIVATE lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FSPRIVATE));
1207 TRACE("alloc private buf %p\n", lfs);
1208 if (!lfs) return NULL;
1210 lfs->lParam = lParam;
1211 if (dlgType == OPEN_DIALOG)
1215 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
1216 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
1220 lfs->ofn16 = MapSL(lParam);
1221 if (lfs->ofn16->Flags & OFN_ENABLEHOOK)
1222 if (lfs->ofn16->lpfnHook)
1228 lfs->ofnA = (LPOPENFILENAMEA) lParam;
1229 if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
1230 if (lfs->ofnA->lpfnHook)
1235 lfs->ofnW = (LPOPENFILENAMEW) lParam;
1236 if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
1237 if (lfs->ofnW->lpfnHook)
1243 { /* this structure is needed internally, so create it */
1244 lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPENFILENAMEW));
1248 FILEDLG_MapOfnStruct16(lfs->ofn16, lfs->ofnW, lfs->open);
1250 FILEDLG_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
1257 if (!Get16BitsTemplate(lfs)) ret = NULL;
1260 if (!Get32BitsTemplate(lfs)) ret = NULL;
1261 if (!ret) FILEDLG_DestroyPrivate(lfs);
1266 /***********************************************************************
1267 * GetFileName31A [internal]
1269 * Creates a win31 style dialog box for the user to select a file to open/save.
1271 BOOL WINAPI GetFileName31A(
1272 LPOPENFILENAMEA lpofn, /* addess of structure with data*/
1273 UINT dlgType /* type dialogue : open/save */
1280 if (!lpofn || !FileDlg_Init()) return FALSE;
1282 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32A, dlgType);
1285 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1286 bRet = DialogBoxIndirectParamA( hInst, lfs->template, lpofn->hwndOwner,
1287 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1288 FILEDLG_DestroyPrivate(lfs);
1291 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile);
1296 /***********************************************************************
1297 * GetFileName31W [internal]
1299 * Creates a win31 style dialog box for the user to select a file to open/save
1301 BOOL WINAPI GetFileName31W(
1302 LPOPENFILENAMEW lpofn, /* addess of structure with data*/
1303 UINT dlgType /* type dialogue : open/save */
1310 if (!lpofn || !FileDlg_Init()) return FALSE;
1312 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32W, dlgType);
1315 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1316 bRet = DialogBoxIndirectParamW( hInst, lfs->template, lpofn->hwndOwner,
1317 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1318 FILEDLG_DestroyPrivate(lfs);
1321 TRACE("return lpstrFile=%s !\n", debugstr_w(lpofn->lpstrFile));
1326 /* ------------------ Dialog procedures ---------------------- */
1328 /***********************************************************************
1329 * FileOpenDlgProc16 (COMMDLG.6)
1331 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1334 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1337 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1338 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1340 LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1342 return lRet; /* else continue message processing */
1347 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1349 case WM_MEASUREITEM:
1350 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1353 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1354 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
1357 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
1360 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1361 switch (HIWORD(lParam))
1364 SetTextColor((HDC16)wParam, 0x00000000);
1366 case CTLCOLOR_STATIC:
1367 SetTextColor((HDC16)wParam, 0x00000000);
1376 /***********************************************************************
1377 * FileSaveDlgProc16 (COMMDLG.7)
1379 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1382 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1385 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1386 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1389 lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1391 return lRet; /* else continue message processing */
1395 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1397 case WM_MEASUREITEM:
1398 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1401 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1402 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
1405 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
1410 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1411 switch (HIWORD(lParam))
1414 SetTextColor((HDC16)wParam, 0x00000000);
1416 case CTLCOLOR_STATIC:
1417 SetTextColor((HDC16)wParam, 0x00000000);
1426 /***********************************************************************
1427 * FileOpenDlgProc [internal]
1428 * Used for open and save, in fact.
1430 static LRESULT WINAPI FileOpenDlgProc(HWND hWnd, UINT wMsg,
1431 WPARAM wParam, LPARAM lParam)
1433 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1435 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1436 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1439 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1441 return lRet; /* else continue message processing */
1446 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1448 case WM_MEASUREITEM:
1449 return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1452 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam);
1455 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs);
1458 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1459 switch (HIWORD(lParam))
1462 SetTextColor((HDC16)wParam, 0x00000000);
1464 case CTLCOLOR_STATIC:
1465 SetTextColor((HDC16)wParam, 0x00000000);
1474 /* ------------------ APIs ---------------------- */
1476 /***********************************************************************
1477 * GetOpenFileName16 (COMMDLG.1)
1479 * Creates a dialog box for the user to select a file to open.
1482 * TRUE on success: user selected a valid file
1483 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1486 * unknown, there are some FIXME's left.
1488 BOOL16 WINAPI GetOpenFileName16(
1489 SEGPTR ofn /* [in/out] address of structure with data*/
1494 LPOPENFILENAME16 lpofn = MapSL(ofn);
1498 if (!lpofn || !FileDlg_Init()) return FALSE;
1500 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
1503 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1504 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
1505 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1506 (DLGPROC16) ptr, (DWORD) lfs);
1507 FILEDLG_DestroyPrivate(lfs);
1510 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1514 /***********************************************************************
1515 * GetSaveFileName16 (COMMDLG.2)
1517 * Creates a dialog box for the user to select a file to save.
1520 * TRUE on success: user enters a valid file
1521 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1524 * unknown. There are some FIXME's left.
1526 BOOL16 WINAPI GetSaveFileName16(
1527 SEGPTR ofn /* [in/out] addess of structure with data*/
1532 LPOPENFILENAME16 lpofn = MapSL(ofn);
1536 if (!lpofn || !FileDlg_Init()) return FALSE;
1538 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
1541 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1542 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
1543 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1544 (DLGPROC16) ptr, (DWORD) lfs);
1545 FILEDLG_DestroyPrivate(lfs);
1548 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1552 /***********************************************************************
1553 * GetOpenFileNameA (COMDLG32.@)
1555 * Creates a dialog box for the user to select a file to open.
1558 * TRUE on success: user enters a valid file
1559 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1562 BOOL WINAPI GetOpenFileNameA(
1563 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1565 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1566 COMDLG32_SetCommDlgExtendedError(0);
1567 /* some flags don't allow to match the TWEAK_WineLook */
1568 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1570 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1575 return GetFileDialog95A(ofn, OPEN_DIALOG);
1579 return GetFileName31A(ofn, OPEN_DIALOG);
1583 /***********************************************************************
1584 * GetOpenFileNameW (COMDLG32.@)
1586 * Creates a dialog box for the user to select a file to open.
1589 * TRUE on success: user enters a valid file
1590 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1593 BOOL WINAPI GetOpenFileNameW(
1594 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1596 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1597 COMDLG32_SetCommDlgExtendedError(0);
1598 /* some flags don't allow to match the TWEAK_WineLook */
1599 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1601 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1606 return GetFileDialog95W(ofn, OPEN_DIALOG);
1610 return GetFileName31W(ofn, OPEN_DIALOG);
1614 /***********************************************************************
1615 * GetSaveFileNameA (COMDLG32.@)
1617 * Creates a dialog box for the user to select a file to save.
1620 * TRUE on success: user enters a valid file
1621 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1624 BOOL WINAPI GetSaveFileNameA(
1625 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1627 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1628 COMDLG32_SetCommDlgExtendedError(0);
1629 /* some flags don't allow to match the TWEAK_WineLook */
1630 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1632 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1637 return GetFileDialog95A(ofn, SAVE_DIALOG);
1641 return GetFileName31A(ofn, SAVE_DIALOG);
1645 /***********************************************************************
1646 * GetSaveFileNameW (COMDLG32.@)
1648 * Creates a dialog box for the user to select a file to save.
1651 * TRUE on success: user enters a valid file
1652 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1655 BOOL WINAPI GetSaveFileNameW(
1656 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1658 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1659 COMDLG32_SetCommDlgExtendedError(0);
1660 /* some flags don't allow to match the TWEAK_WineLook */
1661 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1663 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1668 return GetFileDialog95W(ofn, SAVE_DIALOG);
1672 return GetFileName31W(ofn, SAVE_DIALOG);