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 const char defaultfilter[]=" \0\0";
84 static char defaultopen[]="Open File";
85 static char defaultsave[]="Save as";
87 /***********************************************************************
89 * Windows 3.1 style OpenFileName/SaveFileName dialog
93 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
95 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
98 static LRESULT WINAPI FileOpenDlgProc(HWND hDlg, UINT msg,
99 WPARAM wParam, LPARAM lParam);
101 /***********************************************************************
102 * FileDlg_Init [internal]
104 static BOOL FileDlg_Init(void)
106 static BOOL initialized = 0;
109 HINSTANCE inst = GetModuleHandleA( "comdlg32.dll" );
112 ERR( "cannot get comdlg32.dll instance\n" );
115 hFolder = LoadImageA( inst, "FOLDER", IMAGE_ICON, 16, 16, LR_SHARED );
116 hFolder2 = LoadImageA( inst, "FOLDER2", IMAGE_ICON, 16, 16, LR_SHARED );
117 hFloppy = LoadImageA( inst, "FLOPPY", IMAGE_ICON, 16, 16, LR_SHARED );
118 hHDisk = LoadImageA( inst, "HDISK", IMAGE_ICON, 16, 16, LR_SHARED );
119 hCDRom = LoadImageA( inst, "CDROM", IMAGE_ICON, 16, 16, LR_SHARED );
120 hNet = LoadImageA( inst, "NETWORK", IMAGE_ICON, 16, 16, LR_SHARED );
121 if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 ||
122 hHDisk == 0 || hCDRom == 0 || hNet == 0)
124 ERR("Error loading icons !\n");
133 /***********************************************************************
134 * Get32BitsTemplate [internal]
136 * Get a template (or FALSE if failure) when 16 bits dialogs are used
137 * by a 32 bits application
140 BOOL Get32BitsTemplate(LFSPRIVATE lfs)
142 LPOPENFILENAMEW ofnW = lfs->ofnW;
145 if (ofnW->Flags & OFN_ENABLETEMPLATEHANDLE)
147 if (!(lfs->template = LockResource( ofnW->hInstance )))
149 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
153 else if (ofnW->Flags & OFN_ENABLETEMPLATE)
157 hResInfo = FindResourceA(lfs->ofnA->hInstance,
158 lfs->ofnA->lpTemplateName,
161 hResInfo = FindResourceW(ofnW->hInstance,
162 ofnW->lpTemplateName,
166 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
169 if (!(hDlgTmpl = LoadResource(ofnW->hInstance,
171 !(lfs->template = LockResource(hDlgTmpl)))
173 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
176 } else { /* get it from internal Wine resource */
178 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
179 lfs->open? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
181 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
184 if (!(hDlgTmpl = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
185 !(lfs->template = LockResource( hDlgTmpl )))
187 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
195 /***********************************************************************
196 * Get16BitsTemplate [internal]
198 * Get a template (FALSE if failure) when 16 bits dialogs are used
199 * by a 16 bits application
202 BOOL Get16BitsTemplate(LFSPRIVATE lfs)
204 LPOPENFILENAME16 ofn16 = lfs->ofn16;
206 HGLOBAL16 hGlobal16 = 0;
208 if (ofn16->Flags & OFN_ENABLETEMPLATEHANDLE)
209 lfs->hDlgTmpl16 = ofn16->hInstance;
210 else if (ofn16->Flags & OFN_ENABLETEMPLATE)
213 if (!(hResInfo = FindResource16(ofn16->hInstance,
214 MapSL(ofn16->lpTemplateName),
217 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
220 if (!(lfs->hDlgTmpl16 = LoadResource16( ofn16->hInstance, hResInfo )))
222 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
225 lfs->hResource16 = lfs->hDlgTmpl16;
228 { /* get resource from (32 bits) own Wine resource; convert it to 16 */
229 HANDLE hResInfo, hDlgTmpl32;
233 if (!(hResInfo = FindResourceA(COMMDLG_hInstance32,
234 lfs->open ? "OPEN_FILE":"SAVE_FILE", RT_DIALOGA)))
236 COMDLG32_SetCommDlgExtendedError(CDERR_FINDRESFAILURE);
239 if (!(hDlgTmpl32 = LoadResource(COMMDLG_hInstance32, hResInfo )) ||
240 !(template32 = LockResource( hDlgTmpl32 )))
242 COMDLG32_SetCommDlgExtendedError(CDERR_LOADRESFAILURE);
245 size = SizeofResource(GetModuleHandleA("COMDLG32"), hResInfo);
246 hGlobal16 = GlobalAlloc16(0, size);
249 COMDLG32_SetCommDlgExtendedError(CDERR_MEMALLOCFAILURE);
250 ERR("alloc failure for %ld bytes\n", size);
253 template = GlobalLock16(hGlobal16);
256 COMDLG32_SetCommDlgExtendedError(CDERR_MEMLOCKFAILURE);
257 ERR("global lock failure for %x handle\n", hGlobal16);
258 GlobalFree16(hGlobal16);
261 ConvertDialog32To16((LPVOID)template32, size, (LPVOID)template);
262 lfs->hDlgTmpl16 = hGlobal16;
263 lfs->hGlobal16 = hGlobal16;
268 /***********************************************************************
269 * FILEDLG_StripEditControl [internal]
270 * Strip pathnames off the contents of the edit control.
272 static void FILEDLG_StripEditControl(HWND hwnd)
274 WCHAR temp[BUFFILE], *cp;
276 GetDlgItemTextW( hwnd, edt1, temp, sizeof(temp)/sizeof(WCHAR));
277 cp = strrchrW(temp, '\\');
281 cp = strrchrW(temp, ':');
285 /* FIXME: shouldn't we do something with the result here? ;-) */
290 /***********************************************************************
291 * FILEDLG_CallWindowProc [internal]
293 * Call the appropriate hook
295 static BOOL FILEDLG_CallWindowProc(LFSPRIVATE lfs, UINT wMsg, WPARAM wParam,
300 return (BOOL16) CallWindowProc16(
301 (WNDPROC16)lfs->ofn16->lpfnHook, lfs->hwnd,
302 (UINT16)wMsg, (WPARAM16)wParam, lParam);
306 return (BOOL) CallWindowProcA(
307 (WNDPROC)lfs->ofnA->lpfnHook, lfs->hwnd,
308 wMsg, wParam, lParam);
313 return (BOOL) CallWindowProcW(
314 (WNDPROC)lfs->ofnW->lpfnHook, lfs->hwnd,
315 wMsg, wParam, lParam);
321 /***********************************************************************
322 * FILEDLG_ScanDir [internal]
324 static BOOL FILEDLG_ScanDir(HWND hWnd, LPWSTR newPath)
326 WCHAR buffer[BUFFILE];
329 HCURSOR hCursorWait, oldCursor;
331 if ( !SetCurrentDirectoryW( newPath ))
333 lstrcpynW(buffer, newPath, sizeof(buffer)/sizeof(WCHAR));
335 /* get the list of spec files */
336 GetDlgItemTextW(hWnd, edt1, buffer, sizeof(buffer)/sizeof(WCHAR));
338 hCursorWait = LoadCursorA(0, IDC_WAITA);
339 oldCursor = SetCursor(hCursorWait);
342 if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) {
343 WCHAR* scptr; /* ptr on semi-colon */
344 WCHAR* filter = buffer;
346 TRACE("Using filter %s\n", debugstr_w(filter));
347 SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
349 scptr = strchrW(filter, ';');
350 if (scptr) *scptr = 0;
351 while (*filter == ' ') filter++;
352 TRACE("Using file spec %s\n", debugstr_w(filter));
353 if (SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter) == LB_ERR)
355 if (scptr) *scptr = ';';
356 filter = (scptr) ? (scptr + 1) : 0;
360 /* list of directories */
361 strcpyW(buffer, FILE_star);
363 if ((hdlgDir = GetDlgItem(hWnd, lst2)) != 0) {
364 lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
366 SetCursor(oldCursor);
371 /***********************************************************************
372 * FILEDLG_GetFileType [internal]
375 static LPWSTR FILEDLG_GetFileType(LPWSTR cfptr, LPWSTR fptr, WORD index)
380 for ( ;(n = lstrlenW(cfptr)) != 0; i++)
385 cfptr += lstrlenW(cfptr) + 1;
388 for ( ;(n = lstrlenW(fptr)) != 0; i++)
393 fptr += lstrlenW(fptr) + 1;
395 return (LPWSTR) FILE_star; /* FIXME */
398 /***********************************************************************
399 * FILEDLG_WMDrawItem [internal]
401 static LONG FILEDLG_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
402 int savedlg, LPDRAWITEMSTRUCT lpdis)
406 COLORREF oldText = 0, oldBk = 0;
408 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
410 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC))) return FALSE;
411 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
414 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
416 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
417 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
420 SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
422 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1,
423 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
424 &(lpdis->rcItem), str, lstrlenW(str), NULL);
426 if (lpdis->itemState & ODS_SELECTED)
427 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
429 if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
431 SetBkColor( lpdis->hDC, oldBk );
432 SetTextColor( lpdis->hDC, oldText );
434 HeapFree(GetProcessHeap(), 0, str);
438 if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
440 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
442 SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
445 if (lpdis->itemState & ODS_SELECTED)
447 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
448 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
450 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
451 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
452 &(lpdis->rcItem), str, lstrlenW(str), NULL);
454 if (lpdis->itemState & ODS_SELECTED)
455 DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
457 if (lpdis->itemState & ODS_SELECTED)
459 SetBkColor( lpdis->hDC, oldBk );
460 SetTextColor( lpdis->hDC, oldText );
462 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder);
463 HeapFree(GetProcessHeap(), 0, str);
466 if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
469 if (!(str = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
471 SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID,
473 root[0] += str[2] - 'a';
474 switch(GetDriveTypeA(root))
476 case DRIVE_REMOVABLE: hIcon = hFloppy; break;
477 case DRIVE_CDROM: hIcon = hCDRom; break;
478 case DRIVE_REMOTE: hIcon = hNet; break;
480 default: hIcon = hHDisk; break;
482 if (lpdis->itemState & ODS_SELECTED)
484 oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
485 oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
487 ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
488 lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
489 &(lpdis->rcItem), str, lstrlenW(str), NULL);
491 if (lpdis->itemState & ODS_SELECTED)
493 SetBkColor( lpdis->hDC, oldBk );
494 SetTextColor( lpdis->hDC, oldText );
496 DrawIcon(lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon);
497 HeapFree(GetProcessHeap(), 0, str);
503 /***********************************************************************
504 * FILEDLG_WMMeasureItem [internal]
506 static LONG FILEDLG_WMMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam)
508 LPMEASUREITEMSTRUCT lpmeasure;
510 lpmeasure = (LPMEASUREITEMSTRUCT)lParam;
511 lpmeasure->itemHeight = fldrHeight;
515 /***********************************************************************
516 * FILEDLG_WMMeasureItem16 [internal]
518 static LONG FILEDLG_WMMeasureItem16(HWND16 hWnd, WPARAM16 wParam, LPARAM lParam)
520 LPMEASUREITEMSTRUCT16 lpmeasure;
522 lpmeasure = MapSL(lParam);
523 lpmeasure->itemHeight = fldrHeight;
527 /***********************************************************************
528 * FILEDLG_WMInitDialog [internal]
531 static LONG FILEDLG_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
534 WCHAR tmpstr[BUFFILE];
535 LPWSTR pstr, old_pstr;
537 LFSPRIVATE lfs = (LFSPRIVATE) lParam;
539 if (!lfs) return FALSE;
540 SetPropA(hWnd, OFN_PROP, (HANDLE)lfs);
544 TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
546 SetWindowTextW( hWnd, ofn->lpstrTitle );
547 /* read custom filter information */
548 if (ofn->lpstrCustomFilter)
550 pstr = ofn->lpstrCustomFilter;
552 TRACE("lpstrCustomFilter = %p\n", pstr);
556 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
557 (LPARAM)(ofn->lpstrCustomFilter) + n );
558 n += lstrlenW(pstr) + 1;
559 pstr += lstrlenW(pstr) + 1;
560 TRACE("add str=%s associated to %s\n",
561 debugstr_w(old_pstr), debugstr_w(pstr));
562 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
563 n += lstrlenW(pstr) + 1;
564 pstr += lstrlenW(pstr) + 1;
567 /* read filter information */
568 if (ofn->lpstrFilter) {
569 pstr = (LPWSTR) ofn->lpstrFilter;
573 i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
574 (LPARAM)(ofn->lpstrFilter + n) );
575 n += lstrlenW(pstr) + 1;
576 pstr += lstrlenW(pstr) + 1;
577 TRACE("add str=%s associated to %s\n",
578 debugstr_w(old_pstr), debugstr_w(pstr));
579 SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
580 n += lstrlenW(pstr) + 1;
581 pstr += lstrlenW(pstr) + 1;
584 /* set default filter */
585 if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
586 ofn->nFilterIndex = 1;
587 SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
588 lstrcpynW(tmpstr, FILEDLG_GetFileType(ofn->lpstrCustomFilter,
589 (LPWSTR)ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
590 TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
591 ofn->nFilterIndex, debugstr_w(tmpstr));
592 SetDlgItemTextW( hWnd, edt1, tmpstr );
595 DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
596 /* read initial directory */
597 if (ofn->lpstrInitialDir != NULL)
600 lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
601 len = lstrlenW(tmpstr);
602 if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') {
609 if (!FILEDLG_ScanDir(hWnd, tmpstr)) {
611 if (!FILEDLG_ScanDir(hWnd, tmpstr))
612 WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
614 /* select current drive in combo 2, omit missing drives */
617 char str[4] = "a:\\";
618 GetCurrentDirectoryA( sizeof(dir), dir );
619 for(i = 0, n = -1; i < 26; i++)
622 if (GetDriveTypeA(str) <= DRIVE_NO_ROOT_DIR) n++;
623 if (toupper(str[0]) == toupper(dir[0])) break;
626 SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
627 if (!(ofn->Flags & OFN_SHOWHELP))
628 ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
629 if (ofn->Flags & OFN_HIDEREADONLY)
630 ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
632 return (BOOL) FILEDLG_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
636 /***********************************************************************
637 * FILEDLG_UpdateResult [internal]
638 * update the displayed file name (with path)
640 void FILEDLG_UpdateResult(LFSPRIVATE lfs, WCHAR *tmpstr)
643 LPOPENFILENAMEW ofnW = lfs->ofnW;
644 WCHAR tmpstr2[BUFFILE];
646 GetCurrentDirectoryW(BUFFILE, tmpstr2);
647 lenstr2 = strlenW(tmpstr2);
649 tmpstr2[lenstr2++]='\\';
650 lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
652 lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
653 ofnW->nFileOffset = strrchrW(tmpstr2,'\\') - tmpstr2 +1;
654 ofnW->nFileExtension = 0;
655 while(tmpstr2[ofnW->nFileExtension] != '.' && tmpstr2[ofnW->nFileExtension] != '\0')
656 ofnW->nFileExtension++;
657 if (tmpstr2[ofnW->nFileExtension] == '\0')
658 ofnW->nFileExtension = 0;
660 ofnW->nFileExtension++;
661 /* update the real client structures if any */
663 { /* we have to convert to short (8.3) path */
664 char tmp[1024]; /* MAX_PATHNAME_LEN */
665 LPOPENFILENAME16 ofn16 = lfs->ofn16;
666 char *dest = MapSL(ofn16->lpstrFile);
667 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
668 tmp, ofnW->nMaxFile, NULL, NULL ))
669 tmp[ofnW->nMaxFile-1] = 0;
670 GetShortPathNameA(tmp, dest, ofn16->nMaxFile);
672 /* the same procedure as every year... */
673 ofn16->nFileOffset = strrchr(dest,'\\') - dest +1;
674 ofn16->nFileExtension = 0;
675 while(dest[ofn16->nFileExtension] != '.' && dest[ofn16->nFileExtension] != '\0')
676 ofn16->nFileExtension++;
677 if (dest[ofn16->nFileExtension] == '\0')
678 ofn16->nFileExtension = 0;
680 ofn16->nFileExtension++;
684 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
685 lfs->ofnA->lpstrFile, ofnW->nMaxFile, NULL, NULL ))
686 lfs->ofnA->lpstrFile[ofnW->nMaxFile-1] = 0;
687 lfs->ofnA->nFileOffset = ofnW->nFileOffset;
688 lfs->ofnA->nFileExtension = ofnW->nFileExtension;
693 /***********************************************************************
694 * FILEDLG_UpdateFileTitle [internal]
695 * update the displayed file name (without path)
697 void FILEDLG_UpdateFileTitle(LFSPRIVATE lfs)
700 LPOPENFILENAMEW ofnW = lfs->ofnW;
701 if (ofnW->lpstrFileTitle != NULL)
703 lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
704 SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
705 (LPARAM)ofnW->lpstrFileTitle );
708 char *dest = MapSL(lfs->ofn16->lpstrFileTitle);
709 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
710 dest, ofnW->nMaxFileTitle, NULL, NULL ))
711 dest[ofnW->nMaxFileTitle-1] = 0;
715 if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
716 lfs->ofnA->lpstrFileTitle, ofnW->nMaxFileTitle, NULL, NULL ))
717 lfs->ofnA->lpstrFileTitle[ofnW->nMaxFileTitle-1] = 0;
724 /***********************************************************************
725 * FILEDLG_DirListDblClick [internal]
727 static LRESULT FILEDLG_DirListDblClick( LFSPRIVATE lfs )
730 HWND hWnd = lfs->hwnd;
732 WCHAR tmpstr[BUFFILE];
734 /* get the raw string (with brackets) */
735 lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
736 if (lRet == LB_ERR) return TRUE;
737 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
738 SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
740 strcpyW( tmpstr, pstr );
741 HeapFree(GetProcessHeap(), 0, pstr);
742 /* get the selected directory in tmpstr */
743 if (tmpstr[0] == '[')
745 tmpstr[lstrlenW(tmpstr) - 1] = 0;
746 strcpyW(tmpstr,tmpstr+1);
748 strcatW(tmpstr, FILE_bslash);
750 FILEDLG_ScanDir(hWnd, tmpstr);
754 if (FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst2,
755 MAKELONG(lRet,CD_LBSELCHANGE)))
762 /***********************************************************************
763 * FILEDLG_FileListSelect [internal]
764 * called when a new item is picked in the file list
766 static LRESULT FILEDLG_FileListSelect( LFSPRIVATE lfs )
769 HWND hWnd = lfs->hwnd;
772 lRet = SendDlgItemMessageW(hWnd, lst1, LB_GETCURSEL16, 0, 0);
776 /* set the edit control to the choosen file */
777 if ((pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC)))
779 SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
781 SetDlgItemTextW( hWnd, edt1, pstr );
782 HeapFree(GetProcessHeap(), 0, pstr);
786 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, lst1,
787 MAKELONG(lRet,CD_LBSELCHANGE));
789 /* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
794 /***********************************************************************
795 * FILEDLG_TestPath [internal]
796 * before accepting the file name, test if it includes wild cards
797 * tries to scan the directory and returns TRUE if no error.
799 static LRESULT FILEDLG_TestPath( LFSPRIVATE lfs, LPWSTR path )
801 HWND hWnd = lfs->hwnd;
802 LPWSTR pBeginFileName, pstr2;
803 WCHAR tmpstr2[BUFFILE];
805 pBeginFileName = strrchrW(path, '\\');
806 if (pBeginFileName == NULL)
807 pBeginFileName = strrchrW(path, ':');
809 if (strchrW(path,'*') != NULL || strchrW(path,'?') != NULL)
811 /* edit control contains wildcards */
812 if (pBeginFileName != NULL)
814 lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
815 *(pBeginFileName + 1) = 0;
819 strcpyW(tmpstr2, path);
823 TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
824 SetDlgItemTextW( hWnd, edt1, tmpstr2 );
825 FILEDLG_ScanDir(hWnd, path);
829 /* no wildcards, we might have a directory or a filename */
830 /* try appending a wildcard and reading the directory */
832 pstr2 = path + lstrlenW(path);
833 if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
834 strcatW(path, FILE_bslash);
836 /* if ScanDir succeeds, we have changed the directory */
837 if (FILEDLG_ScanDir(hWnd, path))
840 /* if not, this must be a filename */
842 *pstr2 = 0; /* remove the wildcard added before */
844 if (pBeginFileName != NULL)
846 /* strip off the pathname */
848 SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
850 lstrcpynW(tmpstr2, pBeginFileName + 1, sizeof(tmpstr2)/sizeof(WCHAR) );
851 /* Should we MessageBox() if this fails? */
852 if (!FILEDLG_ScanDir(hWnd, path))
856 strcpyW(path, tmpstr2);
859 SetDlgItemTextW( hWnd, edt1, path );
863 /***********************************************************************
864 * FILEDLG_Validate [internal]
865 * called on: click Ok button, Enter in edit, DoubleClick in file list
867 static LRESULT FILEDLG_Validate( LFSPRIVATE lfs, LPWSTR path, UINT control, INT itemIndex,
871 HWND hWnd = lfs->hwnd;
872 OPENFILENAMEW ofnsav;
873 LPOPENFILENAMEW ofnW = lfs->ofnW;
874 WCHAR filename[BUFFILE];
876 ofnsav = *ofnW; /* for later restoring */
878 /* get current file name */
880 lstrcpynW(filename, path, sizeof(filename)/sizeof(WCHAR));
882 GetDlgItemTextW( hWnd, edt1, filename, sizeof(filename)/sizeof(WCHAR));
884 /* if we did not click in file list to get there */
887 if (!FILEDLG_TestPath( lfs, filename) )
890 FILEDLG_UpdateResult(lfs, filename);
893 { /* called internally after a change in a combo */
896 FILEDLG_CallWindowProc(lfs, lfs->lbselchstring, control,
897 MAKELONG(itemIndex,CD_LBSELCHANGE));
902 FILEDLG_UpdateFileTitle(lfs);
905 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, lfs->fileokstring,
909 *ofnW = ofnsav; /* restore old state */
913 if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
917 LPWSTR str = (LPWSTR)ofnW->lpstrFile;
918 LPWSTR ptr = strrchrW(str, '\\');
919 str[lstrlenW(str) + 1] = '\0';
926 /***********************************************************************
927 * FILEDLG_DiskChange [internal]
928 * called when a new item is picked in the disk selection combo
930 static LRESULT FILEDLG_DiskChange( LFSPRIVATE lfs )
933 HWND hWnd = lfs->hwnd;
935 WCHAR diskname[BUFFILE];
937 FILEDLG_StripEditControl(hWnd);
938 lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
941 pstr = HeapAlloc(GetProcessHeap(), 0, BUFFILEALLOC);
942 SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
944 wsprintfW(diskname, FILE_specc, pstr[2]);
945 HeapFree(GetProcessHeap(), 0, pstr);
947 return FILEDLG_Validate( lfs, diskname, cmb2, lRet, TRUE );
951 /***********************************************************************
952 * FILEDLG_FileTypeChange [internal]
953 * called when a new item is picked in the file type combo
955 static LRESULT FILEDLG_FileTypeChange( LFSPRIVATE lfs )
958 WCHAR diskname[BUFFILE];
963 lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
966 pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
967 TRACE("Selected filter : %s\n", debugstr_w(pstr));
968 SetDlgItemTextW( lfs->hwnd, edt1, pstr );
970 return FILEDLG_Validate( lfs, NULL, cmb1, lRet, TRUE );
973 /***********************************************************************
974 * FILEDLG_WMCommand [internal]
976 static LRESULT FILEDLG_WMCommand(HWND hWnd, LPARAM lParam, UINT notification,
977 UINT control, LFSPRIVATE lfs )
981 case lst1: /* file list */
982 FILEDLG_StripEditControl(hWnd);
983 if (notification == LBN_DBLCLK)
985 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
986 EndDialog(hWnd, TRUE);
989 else if (notification == LBN_SELCHANGE)
990 return FILEDLG_FileListSelect( lfs );
993 case lst2: /* directory list */
994 FILEDLG_StripEditControl(hWnd);
995 if (notification == LBN_DBLCLK)
996 return FILEDLG_DirListDblClick( lfs );
999 case cmb1: /* file type drop list */
1000 if (notification == CBN_SELCHANGE)
1001 return FILEDLG_FileTypeChange( lfs );
1010 case cmb2: /* disk dropdown combo */
1011 if (notification == CBN_SELCHANGE)
1012 return FILEDLG_DiskChange( lfs );
1016 if (FILEDLG_Validate( lfs, NULL, control, 0, FALSE ))
1017 EndDialog(hWnd, TRUE);
1021 EndDialog(hWnd, FALSE);
1024 case IDABORT: /* can be sent by the hook procedure */
1025 EndDialog(hWnd, TRUE);
1031 /***********************************************************************
1032 * FILEDLG_MapDrawItemStruct [internal]
1033 * map a 16 bits drawitem struct to 32
1035 void FILEDLG_MapDrawItemStruct(LPDRAWITEMSTRUCT16 lpdis16, LPDRAWITEMSTRUCT lpdis)
1037 lpdis->CtlType = lpdis16->CtlType;
1038 lpdis->CtlID = lpdis16->CtlID;
1039 lpdis->itemID = lpdis16->itemID;
1040 lpdis->itemAction = lpdis16->itemAction;
1041 lpdis->itemState = lpdis16->itemState;
1042 lpdis->hwndItem = lpdis16->hwndItem;
1043 lpdis->hDC = lpdis16->hDC;
1044 lpdis->rcItem.right = lpdis16->rcItem.right;
1045 lpdis->rcItem.left = lpdis16->rcItem.left;
1046 lpdis->rcItem.top = lpdis16->rcItem.top;
1047 lpdis->rcItem.bottom = lpdis16->rcItem.bottom;
1048 lpdis->itemData = lpdis16->itemData;
1051 /************************************************************************
1052 * FILEDLG_MapStringPairsToW [internal]
1053 * map string pairs to Unicode
1055 LPWSTR FILEDLG_MapStringPairsToW(LPCSTR strA, UINT size)
1066 if (n < size) n = size;
1068 len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
1069 x = HeapAlloc(GetProcessHeap(),0, len * sizeof(WCHAR));
1070 MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
1075 /************************************************************************
1076 * FILEDLG_DupToW [internal]
1077 * duplicates an Ansi string to unicode, with a buffer size
1079 LPWSTR FILEDLG_DupToW(LPCSTR str, DWORD size)
1082 if (str && (size > 0))
1084 strW = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1085 if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
1091 /************************************************************************
1092 * FILEDLG_MapOfnStructA [internal]
1093 * map a 32 bits Ansi structure to an Unicode one
1095 void FILEDLG_MapOfnStructA(LPOPENFILENAMEA ofnA, LPOPENFILENAMEW ofnW, BOOL open)
1099 ofnW->lStructSize = sizeof(OPENFILENAMEW);
1100 ofnW->hwndOwner = ofnA->hwndOwner;
1101 ofnW->hInstance = ofnA->hInstance;
1102 if (ofnA->lpstrFilter)
1103 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrFilter, 0);
1105 ofnW->lpstrFilter = FILEDLG_MapStringPairsToW(defaultfilter, 0);
1107 if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
1108 ofnW->lpstrCustomFilter = FILEDLG_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
1109 ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
1110 ofnW->nFilterIndex = ofnA->nFilterIndex;
1111 ofnW->nMaxFile = ofnA->nMaxFile;
1112 ofnW->lpstrFile = FILEDLG_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
1113 ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
1114 ofnW->lpstrFileTitle = FILEDLG_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
1115 if (ofnA->lpstrInitialDir)
1116 ofnW->lpstrInitialDir = HEAP_strdupAtoW(GetProcessHeap(),0,ofnA->lpstrInitialDir);
1117 if (ofnA->lpstrTitle)
1118 str = ofnA->lpstrTitle;
1120 /* Allocates default title (FIXME : get it from resource) */
1121 str = open ? defaultopen:defaultsave;
1122 ofnW->lpstrTitle = HEAP_strdupAtoW(GetProcessHeap(),0, str);
1123 ofnW->Flags = ofnA->Flags;
1124 ofnW->nFileOffset = ofnA->nFileOffset;
1125 ofnW->nFileExtension = ofnA->nFileExtension;
1126 ofnW->lpstrDefExt = FILEDLG_DupToW(ofnA->lpstrDefExt, 3);
1127 if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
1129 if (HIWORD(ofnA->lpTemplateName))
1130 ofnW->lpTemplateName = HEAP_strdupAtoW(GetProcessHeap(), 0, ofnA->lpTemplateName);
1131 else /* numbered resource */
1132 ofnW->lpTemplateName = (LPWSTR) ofnA->lpTemplateName;
1137 /************************************************************************
1138 * FILEDLG_MapOfnStruct16 [internal]
1139 * map a 16 bits structure to an Unicode one
1141 void FILEDLG_MapOfnStruct16(LPOPENFILENAME16 ofn16, LPOPENFILENAMEW ofnW, BOOL open)
1144 /* first convert to linear pointers */
1145 memset(&ofnA, 0, sizeof(OPENFILENAMEA));
1146 ofnA.lStructSize = sizeof(OPENFILENAMEA);
1147 ofnA.hwndOwner = ofn16->hwndOwner;
1148 ofnA.hInstance = ofn16->hInstance;
1149 if (ofn16->lpstrFilter)
1150 ofnA.lpstrFilter = MapSL(ofn16->lpstrFilter);
1151 if (ofn16->lpstrCustomFilter)
1152 ofnA.lpstrCustomFilter = MapSL(ofn16->lpstrCustomFilter);
1153 ofnA.nMaxCustFilter = ofn16->nMaxCustFilter;
1154 ofnA.nFilterIndex = ofn16->nFilterIndex;
1155 ofnA.lpstrFile = MapSL(ofn16->lpstrFile);
1156 ofnA.nMaxFile = ofn16->nMaxFile;
1157 ofnA.lpstrFileTitle = MapSL(ofn16->lpstrFileTitle);
1158 ofnA.nMaxFileTitle = ofn16->nMaxFileTitle;
1159 ofnA.lpstrInitialDir = MapSL(ofn16->lpstrInitialDir);
1160 ofnA.lpstrTitle = MapSL(ofn16->lpstrTitle);
1161 ofnA.Flags = ofn16->Flags;
1162 ofnA.nFileOffset = ofn16->nFileOffset;
1163 ofnA.nFileExtension = ofn16->nFileExtension;
1164 ofnA.lpstrDefExt = MapSL(ofn16->lpstrDefExt);
1165 if (HIWORD(ofn16->lpTemplateName))
1166 ofnA.lpTemplateName = MapSL(ofn16->lpTemplateName);
1168 ofnA.lpTemplateName = (LPSTR) ofn16->lpTemplateName; /* ressource number */
1169 /* now calls the 32 bits Ansi to Unicode version to complete the job */
1170 FILEDLG_MapOfnStructA(&ofnA, ofnW, open);
1174 /************************************************************************
1175 * FILEDLG_DestroyPrivate [internal]
1176 * destroys the private object
1178 void FILEDLG_DestroyPrivate(LFSPRIVATE lfs)
1183 /* free resources for a 16 bits dialog */
1184 if (lfs->hResource16) FreeResource16(lfs->hResource16);
1187 GlobalUnlock16(lfs->hGlobal16);
1188 GlobalFree16(lfs->hGlobal16);
1190 /* if ofnW has been allocated, have to free everything in it */
1191 if (lfs->ofn16 || lfs->ofnA)
1193 LPOPENFILENAMEW ofnW = lfs->ofnW;
1194 if (ofnW->lpstrFilter) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrFilter);
1195 if (ofnW->lpstrCustomFilter) HeapFree(GetProcessHeap(), 0, ofnW->lpstrCustomFilter);
1196 if (ofnW->lpstrFile) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFile);
1197 if (ofnW->lpstrFileTitle) HeapFree(GetProcessHeap(), 0, ofnW->lpstrFileTitle);
1198 if (ofnW->lpstrInitialDir) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrInitialDir);
1199 if (ofnW->lpstrTitle) HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpstrTitle);
1200 if ((ofnW->lpTemplateName) && (HIWORD(ofnW->lpTemplateName)))
1201 HeapFree(GetProcessHeap(), 0, (LPWSTR) ofnW->lpTemplateName);
1202 HeapFree(GetProcessHeap(), 0, ofnW);
1204 TRACE("destroying private allocation %p\n", lfs);
1205 HeapFree(GetProcessHeap(), 0, lfs);
1206 RemovePropA(hwnd, OFN_PROP);
1209 /************************************************************************
1210 * FILEDLG_AllocPrivate [internal]
1211 * allocate a private object to hold 32 bits Unicode
1212 * structure that will be used throughtout the calls, while
1213 * keeping available the original structures and a few variables
1214 * On entry : type = dialog procedure type (16,32A,32W)
1215 * dlgType = dialog type (open or save)
1217 LFSPRIVATE FILEDLG_AllocPrivate(LPARAM lParam, int type, UINT dlgType)
1219 LFSPRIVATE lfs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct FSPRIVATE));
1221 TRACE("alloc private buf %p\n", lfs);
1222 if (!lfs) return NULL;
1224 lfs->lParam = lParam;
1225 if (dlgType == OPEN_DIALOG)
1229 lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
1230 lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
1234 lfs->ofn16 = MapSL(lParam);
1235 if (lfs->ofn16->Flags & OFN_ENABLEHOOK)
1236 if (lfs->ofn16->lpfnHook)
1242 lfs->ofnA = (LPOPENFILENAMEA) lParam;
1243 if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
1244 if (lfs->ofnA->lpfnHook)
1249 lfs->ofnW = (LPOPENFILENAMEW) lParam;
1250 if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
1251 if (lfs->ofnW->lpfnHook)
1257 { /* this structure is needed internally, so create it */
1258 lfs->ofnW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(OPENFILENAMEW));
1262 FILEDLG_MapOfnStruct16(lfs->ofn16, lfs->ofnW, lfs->open);
1264 FILEDLG_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
1271 if (!Get16BitsTemplate(lfs)) ret = NULL;
1274 if (!Get32BitsTemplate(lfs)) ret = NULL;
1275 if (!ret) FILEDLG_DestroyPrivate(lfs);
1280 /***********************************************************************
1281 * GetFileName31A [internal]
1283 * Creates a win31 style dialog box for the user to select a file to open/save.
1285 BOOL WINAPI GetFileName31A(
1286 LPOPENFILENAMEA lpofn, /* addess of structure with data*/
1287 UINT dlgType /* type dialogue : open/save */
1294 if (!lpofn || !FileDlg_Init()) return FALSE;
1296 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32A, dlgType);
1299 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1300 bRet = DialogBoxIndirectParamA( hInst, lfs->template, lpofn->hwndOwner,
1301 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1302 FILEDLG_DestroyPrivate(lfs);
1305 TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile);
1310 /***********************************************************************
1311 * GetFileName31W [internal]
1313 * Creates a win31 style dialog box for the user to select a file to open/save
1315 BOOL WINAPI GetFileName31W(
1316 LPOPENFILENAMEW lpofn, /* addess of structure with data*/
1317 UINT dlgType /* type dialogue : open/save */
1324 if (!lpofn || !FileDlg_Init()) return FALSE;
1326 lfs = FILEDLG_AllocPrivate((LPARAM) lpofn, LFS32W, dlgType);
1329 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1330 bRet = DialogBoxIndirectParamW( hInst, lfs->template, lpofn->hwndOwner,
1331 (DLGPROC) FileOpenDlgProc, (DWORD) lfs);
1332 FILEDLG_DestroyPrivate(lfs);
1335 TRACE("return lpstrFile=%s !\n", debugstr_w(lpofn->lpstrFile));
1340 /* ------------------ Dialog procedures ---------------------- */
1342 /***********************************************************************
1343 * FileOpenDlgProc (COMMDLG.6)
1345 LRESULT WINAPI FileOpenDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1348 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1351 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1352 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1354 LRESULT lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1356 return lRet; /* else continue message processing */
1361 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1363 case WM_MEASUREITEM:
1364 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1367 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1368 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, FALSE, &dis);
1371 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam),wParam, lfs);
1374 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1375 switch (HIWORD(lParam))
1378 SetTextColor((HDC16)wParam, 0x00000000);
1380 case CTLCOLOR_STATIC:
1381 SetTextColor((HDC16)wParam, 0x00000000);
1390 /***********************************************************************
1391 * FileSaveDlgProc (COMMDLG.7)
1393 LRESULT WINAPI FileSaveDlgProc16(HWND16 hWnd, UINT16 wMsg, WPARAM16 wParam,
1396 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1399 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1400 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1403 lRet = (BOOL16)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1405 return lRet; /* else continue message processing */
1409 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1411 case WM_MEASUREITEM:
1412 return FILEDLG_WMMeasureItem16(hWnd, wParam, lParam);
1415 FILEDLG_MapDrawItemStruct(MapSL(lParam), &dis);
1416 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, TRUE, &dis);
1419 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(lParam), wParam, lfs);
1424 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1425 switch (HIWORD(lParam))
1428 SetTextColor((HDC16)wParam, 0x00000000);
1430 case CTLCOLOR_STATIC:
1431 SetTextColor((HDC16)wParam, 0x00000000);
1440 /***********************************************************************
1441 * FileOpenDlgProc [internal]
1442 * Used for open and save, in fact.
1444 static LRESULT WINAPI FileOpenDlgProc(HWND hWnd, UINT wMsg,
1445 WPARAM wParam, LPARAM lParam)
1447 LFSPRIVATE lfs = (LFSPRIVATE)GetPropA(hWnd,OFN_PROP);
1449 TRACE("msg=%x wparam=%x lParam=%lx\n", wMsg, wParam, lParam);
1450 if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1453 lRet = (BOOL)FILEDLG_CallWindowProc(lfs, wMsg, wParam, lParam);
1455 return lRet; /* else continue message processing */
1460 return FILEDLG_WMInitDialog(hWnd, wParam, lParam);
1462 case WM_MEASUREITEM:
1463 return FILEDLG_WMMeasureItem(hWnd, wParam, lParam);
1466 return FILEDLG_WMDrawItem(hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam);
1469 return FILEDLG_WMCommand(hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs);
1472 SetBkColor((HDC16)wParam, 0x00C0C0C0);
1473 switch (HIWORD(lParam))
1476 SetTextColor((HDC16)wParam, 0x00000000);
1478 case CTLCOLOR_STATIC:
1479 SetTextColor((HDC16)wParam, 0x00000000);
1488 /* ------------------ APIs ---------------------- */
1490 /***********************************************************************
1491 * GetOpenFileName (COMMDLG.1)
1493 * Creates a dialog box for the user to select a file to open.
1496 * TRUE on success: user selected a valid file
1497 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1500 * unknown, there are some FIXME's left.
1502 BOOL16 WINAPI GetOpenFileName16(
1503 SEGPTR ofn /* [in/out] address of structure with data*/
1508 LPOPENFILENAME16 lpofn = MapSL(ofn);
1512 if (!lpofn || !FileDlg_Init()) return FALSE;
1514 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, OPEN_DIALOG);
1517 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1518 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 6);
1519 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1520 (DLGPROC16) ptr, (DWORD) lfs);
1521 FILEDLG_DestroyPrivate(lfs);
1524 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1528 /***********************************************************************
1529 * GetSaveFileName (COMMDLG.2)
1531 * Creates a dialog box for the user to select a file to save.
1534 * TRUE on success: user enters a valid file
1535 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1538 * unknown. There are some FIXME's left.
1540 BOOL16 WINAPI GetSaveFileName16(
1541 SEGPTR ofn /* [in/out] addess of structure with data*/
1546 LPOPENFILENAME16 lpofn = MapSL(ofn);
1550 if (!lpofn || !FileDlg_Init()) return FALSE;
1552 lfs = FILEDLG_AllocPrivate((LPARAM) ofn, LFS16, SAVE_DIALOG);
1555 hInst = GetWindowLongA( lpofn->hwndOwner, GWL_HINSTANCE );
1556 ptr = GetProcAddress16(GetModuleHandle16("COMMDLG"), (LPCSTR) 7);
1557 bRet = DialogBoxIndirectParam16( hInst, lfs->hDlgTmpl16, lpofn->hwndOwner,
1558 (DLGPROC16) ptr, (DWORD) lfs);
1559 FILEDLG_DestroyPrivate(lfs);
1562 TRACE("return lpstrFile='%s' !\n", (char *)MapSL(lpofn->lpstrFile));
1566 /***********************************************************************
1567 * GetOpenFileNameA (COMDLG32.@)
1569 * Creates a dialog box for the user to select a file to open.
1572 * TRUE on success: user enters a valid file
1573 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1576 BOOL WINAPI GetOpenFileNameA(
1577 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1579 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1580 COMDLG32_SetCommDlgExtendedError(0);
1581 /* some flags don't allow to match the TWEAK_WineLook */
1582 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1584 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1589 return GetFileDialog95A(ofn, OPEN_DIALOG);
1593 return GetFileName31A(ofn, OPEN_DIALOG);
1597 /***********************************************************************
1598 * GetOpenFileNameW (COMDLG32.@)
1600 * Creates a dialog box for the user to select a file to open.
1603 * TRUE on success: user enters a valid file
1604 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1607 BOOL WINAPI GetOpenFileNameW(
1608 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1610 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1611 COMDLG32_SetCommDlgExtendedError(0);
1612 /* some flags don't allow to match the TWEAK_WineLook */
1613 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1615 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1620 return GetFileDialog95W(ofn, OPEN_DIALOG);
1624 return GetFileName31W(ofn, OPEN_DIALOG);
1628 /***********************************************************************
1629 * GetSaveFileNameA (COMDLG32.@)
1631 * Creates a dialog box for the user to select a file to save.
1634 * TRUE on success: user enters a valid file
1635 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1638 BOOL WINAPI GetSaveFileNameA(
1639 LPOPENFILENAMEA ofn) /* [in/out] address of init structure */
1641 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1642 COMDLG32_SetCommDlgExtendedError(0);
1643 /* some flags don't allow to match the TWEAK_WineLook */
1644 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1646 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1651 return GetFileDialog95A(ofn, SAVE_DIALOG);
1655 return GetFileName31A(ofn, SAVE_DIALOG);
1659 /***********************************************************************
1660 * GetSaveFileNameW (COMDLG32.@)
1662 * Creates a dialog box for the user to select a file to save.
1665 * TRUE on success: user enters a valid file
1666 * FALSE on cancel, error, close or filename-does-not-fit-in-buffer.
1669 BOOL WINAPI GetSaveFileNameW(
1670 LPOPENFILENAMEW ofn) /* [in/out] address of init structure */
1672 BOOL newlook = TRUE; /* FIXME: TWEAK_WineLook */
1673 COMDLG32_SetCommDlgExtendedError(0);
1674 /* some flags don't allow to match the TWEAK_WineLook */
1675 if (ofn->Flags & (OFN_ALLOWMULTISELECT|OFN_ENABLEHOOK|OFN_ENABLETEMPLATE))
1677 newlook = (ofn->Flags & OFN_EXPLORER) ? TRUE : FALSE;
1682 return GetFileDialog95W(ofn, SAVE_DIALOG);
1686 return GetFileName31W(ofn, SAVE_DIALOG);