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 HICON16 hFolder = 0;
73 static HICON16 hFolder2 = 0;
74 static HICON16 hFloppy = 0;
75 static HICON16 hHDisk = 0;
76 static HICON16 hCDRom = 0;
77 static HICON16 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 */
228 HANDLE hResInfo, hDlgTmpl32;
232 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
233 lfs->open ? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
235 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
238 if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
239 !(template32 = LockResource( hDlgTmpl32 )))
241 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
244 size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
245 hGlobal16 = GlobalAlloc16(0, size);
248 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
249 ERR("alloc failure for %ld bytes\n", size);
252 template = GlobalLock16(hGlobal16);
255 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
256 ERR("global lock failure for %x handle\n", hGlobal16);
257 GlobalFree16(hGlobal16);
260 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
261 lfs->hDlgTmpl16 = hGlobal16;
262 lfs->hGlobal16 = hGlobal16;
267 /***********************************************************************
268 * FILEDLG_StripEditControl [internal]
269 * Strip pathnames off the contents of the edit control.
271 static void FILEDLG_StripEditControl(HWND hwnd)
273 WCHAR temp[BUFFILE], *cp;
275 GetDlgItemTextW( hwnd, edt1, temp, sizeof(temp)/sizeof(WCHAR));
276 cp = strrchrW(temp, '\\');
280 cp = strrchrW(temp, ':');
284 /* FIXME: shouldn't we do something with the result here? ;-) */
289 /***********************************************************************
290 * FILEDLG_CallWindowProc [internal]
292 * Call the appropriate hook
294 static BOOL FILEDLG_CallWindowProc(LFSPRIVATE lfs, UINT wMsg, WPARAM wParam,
299 return (BOOL16) CallWindowProc16(
300 (WNDPROC16)lfs->ofn16->lpfnHook, lfs->hwnd,
301 (UINT16)wMsg, (WPARAM16)wParam, lParam);
305 return (BOOL) CallWindowProcA(
306 (WNDPROC)lfs->ofnA->lpfnHook, lfs->hwnd,
307 wMsg, wParam, lParam);
312 return (BOOL) CallWindowProcW(
313 (WNDPROC)lfs->ofnW->lpfnHook, lfs->hwnd,
314 wMsg, wParam, lParam);
320 /***********************************************************************
321 * FILEDLG_ScanDir [internal]
323 static BOOL FILEDLG_ScanDir(HWND hWnd, LPWSTR newPath)
325 WCHAR buffer[BUFFILE];
328 HCURSOR hCursorWait, oldCursor;
330 if ( !SetCurrentDirectoryW( newPath ))
332 lstrcpynW(buffer, newPath, sizeof(buffer)/sizeof(WCHAR));
334 /* get the list of spec files */
335 GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer)/sizeof(WCHAR));
337 hCursorWait = LoadCursorA(0, IDC_WAITA);
338 oldCursor = SetCursor(hCursorWait);
341 if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) {
342 WCHAR* scptr; /* ptr on semi-colon */
343 WCHAR* filter = buffer;
345 TRACE("Using filter %s\n", debugstr_w(filter));
346 SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
348 scptr = strchrW(filter, ';');
349 if (scptr) *scptr = 0;
350 while (*filter == ' ') filter++;
351 TRACE("Using file spec %s\n", debugstr_w(filter));
352 if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
354 if (scptr) *scptr = ';';
355 filter = (scptr) ? (scptr + 1) : 0;
359 /* list of directories */
360 strcpyW(buffer, FILE_star);
362 if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
363 lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
365 SetCursor(oldCursor);
370 /***********************************************************************
371 * FILEDLG_GetFileType [internal]
374 static LPWSTR FILEDLG_GetFileType(LPWSTR cfptr, LPWSTR fptr, WORD index)
379 for ( ;(n = lstrlenW(cfptr)) != 0; i++)
384 cfptr += lstrlenW(cfptr) + 1;
387 for ( ;(n = lstrlenW(fptr)) != 0; i++)
392 fptr += lstrlenW(fptr) + 1;
394 return (LPWSTR) FILE_star; /* FIXME */
397 /***********************************************************************
398 * FILEDLG_WMDrawItem [internal]
400 static LONG FILEDLG_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
401 int savedlg, LPDRAWITEMSTRUCT lpdis)
405 COLORREF oldText = 0, oldBk = 0;
407 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
409 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) return FALSE;
410 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
413 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
415 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
416 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
419 SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
421 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1,
422 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
423 &(lpdis->rcItem), str, lstrlenW(str), NULL);
425 if (lpdis->itemState & ODS_SELECTED)
426 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
428 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
430 SetBkColor( lpdis->hDC, oldBk );
431 SetTextColor( lpdis->hDC, oldText );
433 HeapFree(GetProcessHeap(), 0, str);
437 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
439 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
441 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
444 if (lpdis->itemState & ODS_SELECTED)
446 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
447 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
449 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
450 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
451 &(lpdis->rcItem), str, lstrlenW(str), NULL);
453 if (lpdis->itemState & ODS_SELECTED)
454 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
456 if (lpdis->itemState & ODS_SELECTED)
458 SetBkColor( lpdis->hDC, oldBk );
459 SetTextColor( lpdis->hDC, oldText );
461 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
462 HeapFree(GetProcessHeap(), 0, str);
465 if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
468 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
470 SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID,
472 root[0] += str[2] - 'a';
473 switch(GetDriveTypeA(root))
475 case DRIVE_REMOVABLE: hIcon = hFloppy; break;
476 case DRIVE_CDROM: hIcon = hCDRom; break;
477 case DRIVE_REMOTE: hIcon = hNet; break;
479 default: hIcon = hHDisk; break;
481 if (lpdis->itemState & ODS_SELECTED)
483 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
484 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
486 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
487 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
488 &(lpdis->rcItem), str, lstrlenW(str), NULL);
490 if (lpdis->itemState & ODS_SELECTED)
492 SetBkColor( lpdis->hDC, oldBk );
493 SetTextColor( lpdis->hDC, oldText );
495 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
496 HeapFree(GetProcessHeap(), 0, str);
502 /***********************************************************************
503 * FILEDLG_WMMeasureItem [internal]
505 static LONG FILEDLG_WMMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
507 LPMEASUREITEMSTRUCT lpmeasure;
509 lpmeasure = (LPMEASUREITEMSTRUCT)lParam;
510 lpmeasure->itemHeight = fldrHeight;
514 /***********************************************************************
515 * FILEDLG_WMMeasureItem16 [internal]
517 static LONG FILEDLG_WMMeasureItem16(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
519 LPMEASUREITEMSTRUCT16 lpmeasure;
521 lpmeasure = MapSL(lParam);
522 lpmeasure->itemHeight = fldrHeight;
526 /***********************************************************************
527 * FILEDLG_WMInitDialog [internal]
530 static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
533 WCHAR tmpstr[BUFFILE];
534 LPWSTR pstr, old_pstr;
536 LFSPRIVATE lfs = (LFSPRIVATE) lParam;
538 if (!lfs) return FALSE;
539 SetPropA(hWnd, OFN_PROP, (HANDLE)lfs);
543 TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
545 SetWindowTextW( hWnd, ofn->lpstrTitle );
546 /* read custom filter information */
547 if (ofn->lpstrCustomFilter)
549 pstr = ofn->lpstrCustomFilter;
551 TRACE("lpstrCustomFilter = %p\n", pstr);
555 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
556 (LPARAM)(ofn->lpstrCustomFilter) + n );
557 n += lstrlenW(pstr) + 1;
558 pstr += lstrlenW(pstr) + 1;
559 TRACE("add str=%s associated to %s\n",
560 debugstr_w(old_pstr), debugstr_w(pstr));
561 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
562 n += lstrlenW(pstr) + 1;
563 pstr += lstrlenW(pstr) + 1;
566 /* read filter information */
567 if (ofn->lpstrFilter) {
568 pstr = (LPWSTR) ofn->lpstrFilter;
572 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
573 (LPARAM)(ofn->lpstrFilter + n) );
574 n += lstrlenW(pstr) + 1;
575 pstr += lstrlenW(pstr) + 1;
576 TRACE("add str=%s associated to %s\n",
577 debugstr_w(old_pstr), debugstr_w(pstr));
578 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
579 n += lstrlenW(pstr) + 1;
580 pstr += lstrlenW(pstr) + 1;
583 /* set default filter */
584 if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
585 ofn->nFilterIndex = 1;
586 SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
587 lstrcpynW(tmpstr, FILEDLG_GetFileType(ofn->lpstrCustomFilter,
588 (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
589 TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
590 ofn->nFilterIndex, debugstr_w(tmpstr));
591 SetDlgItemTextW( hWnd, edt1, tmpstr );
594 DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
595 /* read initial directory */
596 /* FIXME: Note that this is now very version-specific (See MSDN description of
597 * the OPENFILENAME structure). For example under 2000/XP any path in the
598 * lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME
600 if (ofn->lpstrInitialDir != NULL)
603 lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
604 len = lstrlenW(tmpstr);
605 if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') {
612 if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
614 if (!FILEDLG_ScanDir(hWnd, tmpstr))
615 WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
617 /* select current drive in combo 2, omit missing drives */
620 char str[4] = "a:\\";
621 GetCurrentDirectoryA( sizeof(dir), dir );
622 for(i = 0, n = -1; i < 26; i++)
625 if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++;
626 if (toupper(str[0]) == toupper(dir[0])) break;
629 SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
630 if (!(ofn->Flags & OFN_SHOWHELP))
631 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
632 if (ofn->Flags & OFN_HIDEREADONLY)
633 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
635 return (BOOL) FILEDLG_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
639 /***********************************************************************
640 * FILEDLG_UpdateResult [internal]
641 * update the displayed file name (with path)
643 void FILEDLG_UpdateResult(LFSPRIVATE lfs, WCHAR *tmpstr)
646 LPOPENFILENAMEW ofnW = lfs->ofnW;
647 WCHAR tmpstr2[BUFFILE];
649 GetCurrentDirectoryW(BUFFILE, tmpstr2);
650 lenstr2 = strlenW(tmpstr2);
652 tmpstr2[lenstr2++]='\\';
653 lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
655 lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
656 ofnW->nFileOffset = strrchrW(tmpstr2,'\\') - tmpstr2 +1;
657 ofnW->nFileExtension = 0;
658 while(tmpstr2[ofnW->nFileExtension] != '.' && tmpstr2[ofnW->nFileExtension] != '\0')
659 ofnW->nFileExtension++;
660 if (tmpstr2[ofnW->nFileExtension] == '\0')
661 ofnW->nFileExtension = 0;
663 ofnW->nFileExtension++;
664 /* update the real client structures if any */
666 { /* we have to convert to short (8.3) path */
667 char tmp[1024]; /* MAX_PATHNAME_LEN */
668 LPOPENFILENAME16 ofn16 = lfs->ofn16;
669 char *dest = MapSL(ofn16->lpstrFile);
670 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
671 tmp, ofnW->nMaxFile, NULL, NULL ))
672 tmp[ofnW->nMaxFile-1] = 0;
673 GetShortPathNameA(tmp, dest, ofn16->nMaxFile);
675 /* the same procedure as every year... */
676 ofn16->nFileOffset = strrchr(dest,'\\') - dest +1;
677 ofn16->nFileExtension = 0;
678 while(dest[ofn16->nFileExtension] != '.' && dest[ofn16->nFileExtension] != '\0')
679 ofn16->nFileExtension++;
680 if (dest[ofn16->nFileExtension] == '\0')
681 ofn16->nFileExtension = 0;
683 ofn16->nFileExtension++;
687 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
688 lfs->ofnA->lpstrFile, ofnW->nMaxFile, NULL, NULL ))
689 lfs->ofnA->lpstrFile[ofnW->nMaxFile-1] = 0;
690 lfs->ofnA->nFileOffset = ofnW->nFileOffset;
691 lfs->ofnA->nFileExtension = ofnW->nFileExtension;
696 /***********************************************************************
697 * FILEDLG_UpdateFileTitle [internal]
698 * update the displayed file name (without path)
700 void FILEDLG_UpdateFileTitle(LFSPRIVATE lfs)
703 LPOPENFILENAMEW ofnW = lfs->ofnW;
704 if (ofnW->lpstrFileTitle != NULL)
706 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
707 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
708 (LPARAM)ofnW->lpstrFileTitle );
711 char *dest = MapSL(lfs->ofn16->lpstrFileTitle);
712 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
713 dest, ofnW->nMaxFileTitle, NULL, NULL ))
714 dest[ofnW->nMaxFileTitle-1] = 0;
718 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
719 lfs->ofnA->lpstrFileTitle, ofnW->nMaxFileTitle, NULL, NULL ))
720 lfs->ofnA->lpstrFileTitle[ofnW->nMaxFileTitle-1] = 0;
727 /***********************************************************************
728 * FILEDLG_DirListDblClick [internal]
730 static LRESULT FILEDLG_DirListDblClick( LFSPRIVATE lfs )
733 HWND hWnd = lfs->hwnd;
735 WCHAR tmpstr[BUFFILE];
737 /* get the raw string (with brackets) */
738 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
739 if (lRet == LB_ERR) return TRUE;
740 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
741 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
743 strcpyW( tmpstr, pstr );
744 HeapFree(GetProcessHeap(), 0, pstr);
745 /* get the selected directory in tmpstr */
746 if (tmpstr[0] == '[')
748 tmpstr[lstrlenW(tmpstr) - 1] = 0;
749 strcpyW(tmpstr,tmpstr+1);
751 strcatW(tmpstr, FILE_bslash);
753 FILEDLG_ScanDir(hWnd, tmpstr);
757 if (FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst2,
758 MAKELONG(lRet,CD_LBSELCHANGE)))
765 /***********************************************************************
766 * FILEDLG_FileListSelect [internal]
767 * called when a new item is picked in the file list
769 static LRESULT FILEDLG_FileListSelect( LFSPRIVATE lfs )
772 HWND hWnd = lfs->hwnd;
775 lRet = SendDlgItemMessageW(hWnd, lst1, LB_GETCURSEL16, 0, 0);
779 /* set the edit control to the choosen file */
780 if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
782 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
784 SetDlgItemTextW( hWnd, edt1, pstr );
785 HeapFree(GetProcessHeap(), 0, pstr);
789 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst1,
790 MAKELONG(lRet,CD_LBSELCHANGE));
792 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
797 /***********************************************************************
798 * FILEDLG_TestPath [internal]
799 * before accepting the file name, test if it includes wild cards
800 * tries to scan the directory and returns TRUE if no error.
802 static LRESULT FILEDLG_TestPath( LFSPRIVATE lfs, LPWSTR path )
804 HWND hWnd = lfs->hwnd;
805 LPWSTR pBeginFileName, pstr2;
806 WCHAR tmpstr2[BUFFILE];
808 pBeginFileName = strrchrW(path, '\\');
809 if (pBeginFileName == NULL)
810 pBeginFileName = strrchrW(path, ':');
812 if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL)
814 /* edit control contains wildcards */
815 if (pBeginFileName != NULL)
817 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
818 *(pBeginFileName + 1) = 0;
822 strcpyW(tmpstr2, path);
826 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
827 SetDlgItemTextW( hWnd, edt1, tmpstr2 );
828 FILEDLG_ScanDir(hWnd, path);
832 /* no wildcards, we might have a directory or a filename */
833 /* try appending a wildcard and reading the directory */
835 pstr2 = path + lstrlenW(path);
836 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
837 strcatW(path, FILE_bslash);
839 /* if ScanDir succeeds, we have changed the directory */
840 if (FILEDLG_ScanDir(hWnd, path))
843 /* if not, this must be a filename */
845 *pstr2 = 0; /* remove the wildcard added before */
847 if (pBeginFileName != NULL)
849 /* strip off the pathname */
851 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
853 lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
854 /* Should we MessageBox() if this fails? */
855 if (!FILEDLG_ScanDir(hWnd, path))
859 strcpyW(path, tmpstr2);
862 SetDlgItemTextW( hWnd, edt1, path );
866 /***********************************************************************
867 * FILEDLG_Validate [internal]
868 * called on: click Ok button, Enter in edit, DoubleClick in file list
870 static LRESULT FILEDLG_Validate( LFSPRIVATE lfs, LPWSTR path, UINT control, INT itemIndex,
874 HWND hWnd = lfs->hwnd;
875 OPENFILENAMEW ofnsav;
876 LPOPENFILENAMEW ofnW = lfs->ofnW;
877 WCHAR filename[BUFFILE];
879 ofnsav = *ofnW; /* for later restoring */
881 /* get current file name */
883 lstrcpynW(filename, path, sizeof(filename)/sizeof(WCHAR));
885 GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename)/sizeof(WCHAR));
887 /* if we did not click in file list to get there */
890 if (!FILEDLG_TestPath( lfs, filename) )
893 FILEDLG_UpdateResult(lfs, filename);
896 { /* called internally after a change in a combo */
899 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, control,
900 MAKELONG(itemIndex,CD_LBSELCHANGE));
905 FILEDLG_UpdateFileTitle(lfs);
908 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, lfs->fileokstring,
912 *ofnW = ofnsav; /* restore old state */
916 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
920 LPWSTR str = (LPWSTR)ofnW->lpstrFile;
921 LPWSTR ptr = strrchrW(str, '\\');
922 str[lstrlenW(str) + 1] = '\0';
929 /***********************************************************************
930 * FILEDLG_DiskChange [internal]
931 * called when a new item is picked in the disk selection combo
933 static LRESULT FILEDLG_DiskChange( LFSPRIVATE lfs )
936 HWND hWnd = lfs->hwnd;
938 WCHAR diskname[BUFFILE];
940 FILEDLG_StripEditControl(hWnd);
941 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
944 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
945 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
947 wsprintfW(diskname, FILE_specc, pstr[2]);
948 HeapFree(GetProcessHeap(), 0, pstr);
950 return FILEDLG_Validate( lfs, diskname, cmb2, lRet, TRUE );
954 /***********************************************************************
955 * FILEDLG_FileTypeChange [internal]
956 * called when a new item is picked in the file type combo
958 static LRESULT FILEDLG_FileTypeChange( LFSPRIVATE lfs )
961 WCHAR diskname[BUFFILE];
966 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
969 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
970 TRACE("Selected filter : %s\n", debugstr_w(pstr));
971 SetDlgItemTextW( lfs->hwnd, edt1, pstr );
973 return FILEDLG_Validate( lfs, NULL, cmb1, lRet, TRUE );
976 /***********************************************************************
977 * FILEDLG_WMCommand [internal]
979 static LRESULT FILEDLG_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
980 UINT control, LFSPRIVATE lfs )
984 case lst1: /* file list */
985 FILEDLG_StripEditControl(hWnd);
986 if (notification == LBN_DBLCLK)
988 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
989 EndDialog(hWnd, TRUE);
992 else if (notification == LBN_SELCHANGE)
993 return FILEDLG_FileListSelect( lfs );
996 case lst2: /* directory list */
997 FILEDLG_StripEditControl(hWnd);
998 if (notification == LBN_DBLCLK)
999 return FILEDLG_DirListDblClick( lfs );
1002 case cmb1: /* file type drop list */
1003 if (notification == CBN_SELCHANGE)
1004 return FILEDLG_FileTypeChange( lfs );
1013 case cmb2: /* disk dropdown combo */
1014 if (notification == CBN_SELCHANGE)
1015 return FILEDLG_DiskChange( lfs );
1019 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
1020 EndDialog(hWnd, TRUE);
1024 EndDialog(hWnd, FALSE);
1027 case IDABORT: /* can be sent by the hook procedure */
1028 EndDialog(hWnd, TRUE);
1034 /***********************************************************************
1035 * FILEDLG_MapDrawItemStruct [internal]
1036 * map a 16 bits drawitem struct to 32
1038 void FILEDLG_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)
1040 lpdis->CtlType = lpdis16->CtlType;
1041 lpdis->CtlID = lpdis16->CtlID;
1042 lpdis->itemID = lpdis16->itemID;
1043 lpdis->itemAction = lpdis16->itemAction;
1044 lpdis->itemState = lpdis16->itemState;
1045 lpdis->hwndItem = lpdis16->hwndItem;
1046 lpdis->hDC = lpdis16->hDC;
1047 lpdis->rcItem.right = lpdis16->rcItem.right;
1048 lpdis->rcItem.left = lpdis16->rcItem.left;
1049 lpdis->rcItem.top = lpdis16->rcItem.top;
1050 lpdis->rcItem.bottom = lpdis16->rcItem.bottom;
1051 lpdis->itemData = lpdis16->itemData;
1054 /************************************************************************
1055 * FILEDLG_MapStringPairsToW [internal]
1056 * map string pairs to Unicode
1058 static LPWSTR FILEDLG_MapStringPairsToW(LPCSTR strA, UINT size)
1068 n = s + 1 - strA; /* Don't forget the other \0 */
1069 if (n < size) n = size;
1071 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
1072 x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR));
1073 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
1078 /************************************************************************
1079 * FILEDLG_DupToW [internal]
1080 * duplicates an Ansi string to unicode, with a buffer size
1082 LPWSTR FILEDLG_DupToW(LPCSTR str, DWORD size)
1085 if (str && (size > 0))
1087 strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1088 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
1094 /************************************************************************
1095 * FILEDLG_MapOfnStructA [internal]
1096 * map a 32 bits Ansi structure to an Unicode one
1098 void FILEDLG_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
1102 ofnW->lStructSize = sizeof(OPENFILENAMEW);
1103 ofnW->hwndOwner = ofnA->hwndOwner;
1104 ofnW->hInstance = ofnA->hInstance;
1105 if (ofnA->lpstrFilter)
1106 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrFilter, 0);
1108 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
1109 ofnW->lpstrCustomFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
1110 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
1111 ofnW->nFilterIndex = ofnA->nFilterIndex;
1112 ofnW->nMaxFile = ofnA->nMaxFile;
1113 ofnW->lpstrFile = FILEDLG_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
1114 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
1115 ofnW->lpstrFileTitle = FILEDLG_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
1116 if (ofnA->lpstrInitialDir)
1117 ofnW->lpstrInitialDir = HEAP_strdupAtoW(GetProcessHeap(),0,ofnA->lpstrInitialDir);
1118 if (ofnA->lpstrTitle)
1119 str = ofnA->lpstrTitle;
1121 /* Allocates default title (FIXME : get it from resource) */
1122 str = open ? defaultopen:defaultsave;
1123 ofnW->lpstrTitle = HEAP_strdupAtoW(GetProcessHeap(),0, str);
1124 ofnW->Flags = ofnA->Flags;
1125 ofnW->nFileOffset = ofnA->nFileOffset;
1126 ofnW->nFileExtension = ofnA->nFileExtension;
1127 ofnW->lpstrDefExt = FILEDLG_DupToW(ofnA->lpstrDefExt, 3);
1128 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
1130 if (HIWORD(ofnA->lpTemplateName))
1131 ofnW->lpTemplateName = HEAP_strdupAtoW(GetProcessHeap(), 0, ofnA->lpTemplateName);
1132 else /* numbered resource */
1133 ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
1138 /************************************************************************
1139 * FILEDLG_MapOfnStruct16 [internal]
1140 * map a 16 bits structure to an Unicode one
1142 void FILEDLG_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)
1145 /* first convert to linear pointers */
1146 memset(&ofnA, 0, sizeof(OPENFILENAMEA));
1147 ofnA.lStructSize = sizeof(OPENFILENAMEA);
1148 ofnA.hwndOwner = ofn16->hwndOwner;
1149 ofnA.hInstance = ofn16->hInstance;
1150 if (ofn16->lpstrFilter)
1151 ofnA.lpstrFilter = MapSL(ofn16->lpstrFilter);
1152 if (ofn16->lpstrCustomFilter)
1153 ofnA.lpstrCustomFilter = MapSL(ofn16->lpstrCustomFilter);
1154 ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;
1155 ofnA.nFilterIndex = ofn16->nFilterIndex;
1156 ofnA.lpstrFile = MapSL(ofn16->lpstrFile);
1157 ofnA.nMaxFile = ofn16->nMaxFile;
1158 ofnA.lpstrFileTitle = MapSL(ofn16->lpstrFileTitle);
1159 ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;
1160 ofnA.lpstrInitialDir = MapSL(ofn16->lpstrInitialDir);
1161 ofnA.lpstrTitle = MapSL(ofn16->lpstrTitle);
1162 ofnA.Flags = ofn16->Flags;
1163 ofnA.nFileOffset = ofn16->nFileOffset;
1164 ofnA.nFileExtension = ofn16->nFileExtension;
1165 ofnA.lpstrDefExt = MapSL(ofn16->lpstrDefExt);
1166 if (HIWORD(ofn16->lpTemplateName))
1167 ofnA.lpTemplateName = MapSL(ofn16->lpTemplateName);
1169 ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */
1170 /* now calls the 32 bits Ansi to Unicode version to complete the job */
1171 FILEDLG_MapOfnStructA(&ofnA, ofnW, open);
1175 /************************************************************************
1176 * FILEDLG_DestroyPrivate [internal]
1177 * destroys the private object
1179 void FILEDLG_DestroyPrivate(LFSPRIVATE lfs)
1184 /* free resources for a 16 bits dialog */
1185 if (lfs->hResource16) FreeResource16(lfs->hResource16);
1188 GlobalUnlock16(lfs->hGlobal16);
1189 GlobalFree16(lfs->hGlobal16);
1191 /* if ofnW has been allocated, have to free everything in it */
1192 if (lfs->ofn16 || lfs->ofnA)
1194 LPOPENFILENAMEW ofnW = lfs->ofnW;
1195 if (ofnW->lpstrFilter) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
1196 if (ofnW->lpstrCustomFilter) HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
1197 if (ofnW->lpstrFile) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile);
1198 if (ofnW->lpstrFileTitle) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
1199 if (ofnW->lpstrInitialDir) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
1200 if (ofnW->lpstrTitle) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
1201 if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
1202 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
1203 HeapFree(GetProcessHeap(), 0, ofnW);
1205 TRACE("destroying private allocation %p\n", lfs);
1206 HeapFree(GetProcessHeap(), 0, lfs);
1207 RemovePropA(hwnd, OFN_PROP);
1210 /************************************************************************
1211 * FILEDLG_AllocPrivate [internal]
1212 * allocate a private object to hold 32 bits Unicode
1213 * structure that will be used throughtout the calls, while
1214 * keeping available the original structures and a few variables
1215 * On entry : type = dialog procedure type (16,32A,32W)
1216 * dlgType = dialog type (open or save)
1218 LFSPRIVATE FILEDLG_AllocPrivate(LPARAM lParam, int type, UINT dlgType)
1220 LFSPRIVATE lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FSPRIVATE));
1222 TRACE("alloc private buf %p\n", lfs);
1223 if (!lfs) return NULL;
1225 lfs->lParam = lParam;
1226 if (dlgType == OPEN_DIALOG)
1230 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
1231 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
1235 lfs->ofn16 = MapSL(lParam);
1236 if (lfs->ofn16->Flags & OFN_ENABLEHOOK)
1237 if (lfs->ofn16->lpfnHook)
1243 lfs->ofnA = (LPOPENFILENAMEA) lParam;
1244 if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
1245 if (lfs->ofnA->lpfnHook)
1250 lfs->ofnW = (LPOPENFILENAMEW) lParam;
1251 if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
1252 if (lfs->ofnW->lpfnHook)
1258 { /* this structure is needed internally, so create it */
1259 lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPENFILENAMEW));
1263 FILEDLG_MapOfnStruct16(lfs->ofn16, lfs->ofnW, lfs->open);
1265 FILEDLG_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
1272 if (!Get16BitsTemplate(lfs)) ret = NULL;
1275 if (!Get32BitsTemplate(lfs)) ret = NULL;
1276 if (!ret) FILEDLG_DestroyPrivate(lfs);
1281 /***********************************************************************
1282 * GetFileName31A [internal]
1284 * Creates a win31 style dialog box for the user to select a file to open/save.
1286 BOOL WINAPI GetFileName31A(
1287 LPOPENFILENAMEA lpofn, /* addess of structure with data*/
1288 UINT dlgType /* type dialogue : open/save */
1295 if (!lpofn || !FileDlg_Init()) return FALSE;
1297 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32A, dlgType);
1300 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1301 bRet = DialogBoxIndirectParamA( hInst, lfs->template, lpofn->hwndOwner,
1302 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1303 FILEDLG_DestroyPrivate(lfs);
1306 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile);
1311 /***********************************************************************
1312 * GetFileName31W [internal]
1314 * Creates a win31 style dialog box for the user to select a file to open/save
1316 BOOL WINAPI GetFileName31W(
1317 LPOPENFILENAMEW lpofn, /* addess of structure with data*/
1318 UINT dlgType /* type dialogue : open/save */
1325 if (!lpofn || !FileDlg_Init()) return FALSE;
1327 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32W, dlgType);
1330 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1331 bRet = DialogBoxIndirectParamW( hInst, lfs->template, lpofn->hwndOwner,
1332 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1333 FILEDLG_DestroyPrivate(lfs);
1336 TRACE("return lpstrFile=%s !\n", debugstr_w(lpofn->lpstrFile));
1341 /* ------------------ Dialog procedures ---------------------- */
1343 /***********************************************************************
1344 * FileOpenDlgProc (COMMDLG.6)
1346 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1349 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1352 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1353 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1355 LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1357 return lRet; /* else continue message processing */
1362 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1364 case WM_MEASUREITEM:
1365 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1368 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1369 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
1372 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
1375 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1376 switch (HIWORD(lParam))
1379 SetTextColor((HDC16)wParam, 0x00000000);
1381 case CTLCOLOR_STATIC:
1382 SetTextColor((HDC16)wParam, 0x00000000);
1391 /***********************************************************************
1392 * FileSaveDlgProc (COMMDLG.7)
1394 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1397 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1400 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1401 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1404 lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1406 return lRet; /* else continue message processing */
1410 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1412 case WM_MEASUREITEM:
1413 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1416 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1417 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
1420 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
1425 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1426 switch (HIWORD(lParam))
1429 SetTextColor((HDC16)wParam, 0x00000000);
1431 case CTLCOLOR_STATIC:
1432 SetTextColor((HDC16)wParam, 0x00000000);
1441 /***********************************************************************
1442 * FileOpenDlgProc [internal]
1443 * Used for open and save, in fact.
1445 static LRESULT WINAPI FileOpenDlgProc(HWND hWnd, UINT wMsg,
1446 WPARAM wParam, LPARAM lParam)
1448 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1450 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1451 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1454 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1456 return lRet; /* else continue message processing */
1461 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1463 case WM_MEASUREITEM:
1464 return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1467 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam);
1470 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs);
1473 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1474 switch (HIWORD(lParam))
1477 SetTextColor((HDC16)wParam, 0x00000000);
1479 case CTLCOLOR_STATIC:
1480 SetTextColor((HDC16)wParam, 0x00000000);
1489 /* ------------------ APIs ---------------------- */
1491 /***********************************************************************
1492 * GetOpenFileName (COMMDLG.1)
1494 * Creates a dialog box for the user to select a file to open.
1497 * TRUE on success: user selected a valid file
1498 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1501 * unknown, there are some FIXME's left.
1503 BOOL16 WINAPI GetOpenFileName16(
1504 SEGPTR ofn /* [in/out] address of structure with data*/
1509 LPOPENFILENAME16 lpofn = MapSL(ofn);
1513 if (!lpofn || !FileDlg_Init()) return FALSE;
1515 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
1518 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1519 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
1520 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1521 (DLGPROC16) ptr, (DWORD) lfs);
1522 FILEDLG_DestroyPrivate(lfs);
1525 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1529 /***********************************************************************
1530 * GetSaveFileName (COMMDLG.2)
1532 * Creates a dialog box for the user to select a file to save.
1535 * TRUE on success: user enters a valid file
1536 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1539 * unknown. There are some FIXME's left.
1541 BOOL16 WINAPI GetSaveFileName16(
1542 SEGPTR ofn /* [in/out] addess of structure with data*/
1547 LPOPENFILENAME16 lpofn = MapSL(ofn);
1551 if (!lpofn || !FileDlg_Init()) return FALSE;
1553 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
1556 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1557 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
1558 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1559 (DLGPROC16) ptr, (DWORD) lfs);
1560 FILEDLG_DestroyPrivate(lfs);
1563 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1567 /***********************************************************************
1568 * GetOpenFileNameA (COMDLG32.@)
1570 * Creates a dialog box for the user to select a file to open.
1573 * TRUE on success: user enters a valid file
1574 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1577 BOOL WINAPI GetOpenFileNameA(
1578 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1580 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1581 COMDLG32_SetCommDlgExtendedError(0);
1582 /* some flags don't allow to match the TWEAK_WineLook */
1583 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1585 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1590 return GetFileDialog95A(ofn, OPEN_DIALOG);
1594 return GetFileName31A(ofn, OPEN_DIALOG);
1598 /***********************************************************************
1599 * GetOpenFileNameW (COMDLG32.@)
1601 * Creates a dialog box for the user to select a file to open.
1604 * TRUE on success: user enters a valid file
1605 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1608 BOOL WINAPI GetOpenFileNameW(
1609 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1611 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1612 COMDLG32_SetCommDlgExtendedError(0);
1613 /* some flags don't allow to match the TWEAK_WineLook */
1614 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1616 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1621 return GetFileDialog95W(ofn, OPEN_DIALOG);
1625 return GetFileName31W(ofn, OPEN_DIALOG);
1629 /***********************************************************************
1630 * GetSaveFileNameA (COMDLG32.@)
1632 * Creates a dialog box for the user to select a file to save.
1635 * TRUE on success: user enters a valid file
1636 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1639 BOOL WINAPI GetSaveFileNameA(
1640 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1642 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1643 COMDLG32_SetCommDlgExtendedError(0);
1644 /* some flags don't allow to match the TWEAK_WineLook */
1645 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1647 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1652 return GetFileDialog95A(ofn, SAVE_DIALOG);
1656 return GetFileName31A(ofn, SAVE_DIALOG);
1660 /***********************************************************************
1661 * GetSaveFileNameW (COMDLG32.@)
1663 * Creates a dialog box for the user to select a file to save.
1666 * TRUE on success: user enters a valid file
1667 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1670 BOOL WINAPI GetSaveFileNameW(
1671 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1673 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1674 COMDLG32_SetCommDlgExtendedError(0);
1675 /* some flags don't allow to match the TWEAK_WineLook */
1676 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1678 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1683 return GetFileDialog95W(ofn, SAVE_DIALOG);
1687 return GetFileName31W(ofn, SAVE_DIALOG);