Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/comdlg32/filedlg31.c
4389 views
1
/*
2
* Win 3.1 Style File Dialogs
3
*
4
* Copyright 1994 Martin Ayotte
5
* Copyright 1996 Albrecht Kleine
6
*
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.
11
*
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.
16
*
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20
*/
21
#include <ctype.h>
22
#include <stdlib.h>
23
#include <stdarg.h>
24
#include <stdio.h>
25
#include <string.h>
26
#include "windef.h"
27
#include "winbase.h"
28
#include "winnls.h"
29
#include "wingdi.h"
30
#include "winuser.h"
31
#include "wine/debug.h"
32
#include "wine/heap.h"
33
#include "winreg.h"
34
#include "winternl.h"
35
#include "commdlg.h"
36
#include "shlwapi.h"
37
#include "cderr.h"
38
39
WINE_DEFAULT_DEBUG_CHANNEL(commdlg);
40
41
#include "cdlg.h"
42
43
#define BUFFILE 512
44
#define BUFFILEALLOC 512 * sizeof(WCHAR)
45
46
static const int fldrHeight = 16;
47
static const int fldrWidth = 20;
48
49
static HICON hFolder = 0;
50
static HICON hFolder2 = 0;
51
static HICON hFloppy = 0;
52
static HICON hHDisk = 0;
53
static HICON hCDRom = 0;
54
static HICON hNet = 0;
55
56
#define FD31_OFN_PROP "FILEDLG_OFN"
57
58
typedef struct tagFD31_DATA
59
{
60
HWND hwnd; /* file dialog window handle */
61
BOOL hook; /* TRUE if the dialog is hooked */
62
UINT lbselchstring; /* registered message id */
63
UINT fileokstring; /* registered message id */
64
LPARAM lParam; /* save original lparam */
65
LPCVOID template; /* template for 32 bits resource */
66
BOOL open; /* TRUE if open dialog, FALSE if save dialog */
67
LPOPENFILENAMEW ofnW; /* pointer either to the original structure or
68
a W copy for A/16 API */
69
LPOPENFILENAMEA ofnA; /* original structure if 32bits ansi dialog */
70
} FD31_DATA, *PFD31_DATA;
71
72
/***********************************************************************
73
* FD31_Init [internal]
74
*/
75
static BOOL FD31_Init(void)
76
{
77
static BOOL initialized = FALSE;
78
79
if (!initialized) {
80
hFolder = LoadImageA( COMDLG32_hInstance, "FOLDER", IMAGE_ICON, 16, 16, LR_SHARED );
81
hFolder2 = LoadImageA( COMDLG32_hInstance, "FOLDER2", IMAGE_ICON, 16, 16, LR_SHARED );
82
hFloppy = LoadImageA( COMDLG32_hInstance, "FLOPPY", IMAGE_ICON, 16, 16, LR_SHARED );
83
hHDisk = LoadImageA( COMDLG32_hInstance, "HDISK", IMAGE_ICON, 16, 16, LR_SHARED );
84
hCDRom = LoadImageA( COMDLG32_hInstance, "CDROM", IMAGE_ICON, 16, 16, LR_SHARED );
85
hNet = LoadImageA( COMDLG32_hInstance, "NETWORK", IMAGE_ICON, 16, 16, LR_SHARED );
86
if (hFolder == 0 || hFolder2 == 0 || hFloppy == 0 ||
87
hHDisk == 0 || hCDRom == 0 || hNet == 0)
88
{
89
ERR("Error loading icons!\n");
90
return FALSE;
91
}
92
initialized = TRUE;
93
}
94
return TRUE;
95
}
96
97
/***********************************************************************
98
* FD31_StripEditControl [internal]
99
* Strip pathnames off the contents of the edit control.
100
*/
101
static void FD31_StripEditControl(HWND hwnd)
102
{
103
WCHAR temp[BUFFILE], *cp;
104
105
GetDlgItemTextW( hwnd, edt1, temp, ARRAY_SIZE(temp));
106
cp = wcsrchr(temp, '\\');
107
if (cp != NULL) {
108
lstrcpyW(temp, cp+1);
109
}
110
cp = wcsrchr(temp, ':');
111
if (cp != NULL) {
112
lstrcpyW(temp, cp+1);
113
}
114
/* FIXME: shouldn't we do something with the result here? ;-) */
115
}
116
117
/***********************************************************************
118
* FD31_CallWindowProc [internal]
119
*
120
* Call the appropriate hook
121
*/
122
static BOOL FD31_CallWindowProc(const FD31_DATA *lfs, UINT wMsg, WPARAM wParam, LPARAM lParam)
123
{
124
BOOL ret;
125
126
if (lfs->ofnA)
127
{
128
TRACE("Call hookA %p (%p, %04x, %08Ix, %08Ix)\n",
129
lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
130
ret = lfs->ofnA->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
131
TRACE("ret hookA %p (%p, %04x, %08Ix, %08Ix)\n",
132
lfs->ofnA->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
133
return ret;
134
}
135
136
TRACE("Call hookW %p (%p, %04x, %08Ix, %08Ix)\n",
137
lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
138
ret = lfs->ofnW->lpfnHook(lfs->hwnd, wMsg, wParam, lParam);
139
TRACE("Ret hookW %p (%p, %04x, %08Ix, %08Ix)\n",
140
lfs->ofnW->lpfnHook, lfs->hwnd, wMsg, wParam, lParam);
141
return ret;
142
}
143
144
/***********************************************************************
145
* FD31_GetFileType [internal]
146
*/
147
static LPCWSTR FD31_GetFileType(LPCWSTR cfptr, LPCWSTR fptr, const WORD index)
148
{
149
int n, i;
150
i = 0;
151
if (cfptr)
152
for ( ;(n = lstrlenW(cfptr)) != 0; i++)
153
{
154
cfptr += n + 1;
155
if (i == index)
156
return cfptr;
157
cfptr += lstrlenW(cfptr) + 1;
158
}
159
if (fptr)
160
for ( ;(n = lstrlenW(fptr)) != 0; i++)
161
{
162
fptr += n + 1;
163
if (i == index)
164
return fptr;
165
fptr += lstrlenW(fptr) + 1;
166
}
167
return L"*.*"; /* FIXME */
168
}
169
170
/***********************************************************************
171
* FD31_ScanDir [internal]
172
*/
173
static BOOL FD31_ScanDir(const OPENFILENAMEW *ofn, HWND hWnd, LPCWSTR newPath)
174
{
175
WCHAR buffer[BUFFILE];
176
HWND hdlg;
177
LRESULT lRet = TRUE;
178
HCURSOR hCursorWait, oldCursor;
179
180
TRACE("Trying to change to %s\n", debugstr_w(newPath));
181
if ( newPath[0] && !SetCurrentDirectoryW( newPath ))
182
return FALSE;
183
184
/* get the list of spec files */
185
lstrcpynW(buffer, FD31_GetFileType(ofn->lpstrCustomFilter,
186
ofn->lpstrFilter, ofn->nFilterIndex - 1), BUFFILE);
187
188
hCursorWait = LoadCursorA(0, (LPSTR)IDC_WAIT);
189
oldCursor = SetCursor(hCursorWait);
190
191
/* list of files */
192
if ((hdlg = GetDlgItem(hWnd, lst1)) != 0) {
193
WCHAR* scptr; /* ptr on semi-colon */
194
WCHAR* filter = buffer;
195
196
TRACE("Using filter %s\n", debugstr_w(filter));
197
SendMessageW(hdlg, LB_RESETCONTENT, 0, 0);
198
while (filter) {
199
scptr = wcschr(filter, ';');
200
if (scptr) *scptr = 0;
201
while (*filter == ' ') filter++;
202
TRACE("Using file spec %s\n", debugstr_w(filter));
203
SendMessageW(hdlg, LB_DIR, 0, (LPARAM)filter);
204
if (scptr) *scptr = ';';
205
filter = (scptr) ? (scptr + 1) : 0;
206
}
207
}
208
209
/* list of directories */
210
lstrcpyW(buffer, L"*.*");
211
212
if (GetDlgItem(hWnd, lst2) != 0) {
213
lRet = DlgDirListW(hWnd, buffer, lst2, stc1, DDL_EXCLUSIVE | DDL_DIRECTORY);
214
}
215
SetCursor(oldCursor);
216
return lRet;
217
}
218
219
/***********************************************************************
220
* FD31_WMDrawItem [internal]
221
*/
222
static LONG FD31_WMDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam,
223
int savedlg, const DRAWITEMSTRUCT *lpdis)
224
{
225
WCHAR *str;
226
HICON hIcon;
227
COLORREF oldText = 0, oldBk = 0;
228
229
if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst1)
230
{
231
if (!(str = heap_alloc(BUFFILEALLOC))) return FALSE;
232
SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
233
(LPARAM)str);
234
235
if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
236
{
237
oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
238
oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
239
}
240
if (savedlg)
241
SetTextColor(lpdis->hDC,GetSysColor(COLOR_GRAYTEXT) );
242
243
ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + 1,
244
lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
245
&(lpdis->rcItem), str, lstrlenW(str), NULL);
246
247
if (lpdis->itemState & ODS_SELECTED)
248
DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
249
250
if ((lpdis->itemState & ODS_SELECTED) && !savedlg)
251
{
252
SetBkColor( lpdis->hDC, oldBk );
253
SetTextColor( lpdis->hDC, oldText );
254
}
255
heap_free(str);
256
return TRUE;
257
}
258
259
if (lpdis->CtlType == ODT_LISTBOX && lpdis->CtlID == lst2)
260
{
261
if (!(str = heap_alloc(BUFFILEALLOC)))
262
return FALSE;
263
SendMessageW(lpdis->hwndItem, LB_GETTEXT, lpdis->itemID,
264
(LPARAM)str);
265
266
if (lpdis->itemState & ODS_SELECTED)
267
{
268
oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
269
oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
270
}
271
ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
272
lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
273
&(lpdis->rcItem), str, lstrlenW(str), NULL);
274
275
if (lpdis->itemState & ODS_SELECTED)
276
DrawFocusRect( lpdis->hDC, &(lpdis->rcItem) );
277
278
if (lpdis->itemState & ODS_SELECTED)
279
{
280
SetBkColor( lpdis->hDC, oldBk );
281
SetTextColor( lpdis->hDC, oldText );
282
}
283
DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hFolder, 16, 16, 0, 0, DI_NORMAL );
284
heap_free(str);
285
return TRUE;
286
}
287
if (lpdis->CtlType == ODT_COMBOBOX && lpdis->CtlID == cmb2)
288
{
289
char root[] = "a:";
290
if (!(str = heap_alloc(BUFFILEALLOC)))
291
return FALSE;
292
SendMessageW(lpdis->hwndItem, CB_GETLBTEXT, lpdis->itemID,
293
(LPARAM)str);
294
root[0] += str[2] - 'a';
295
switch(GetDriveTypeA(root))
296
{
297
case DRIVE_REMOVABLE: hIcon = hFloppy; break;
298
case DRIVE_CDROM: hIcon = hCDRom; break;
299
case DRIVE_REMOTE: hIcon = hNet; break;
300
case DRIVE_FIXED:
301
default: hIcon = hHDisk; break;
302
}
303
if (lpdis->itemState & ODS_SELECTED)
304
{
305
oldBk = SetBkColor( lpdis->hDC, GetSysColor( COLOR_HIGHLIGHT ) );
306
oldText = SetTextColor( lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
307
}
308
ExtTextOutW(lpdis->hDC, lpdis->rcItem.left + fldrWidth,
309
lpdis->rcItem.top + 1, ETO_OPAQUE | ETO_CLIPPED,
310
&(lpdis->rcItem), str, lstrlenW(str), NULL);
311
312
if (lpdis->itemState & ODS_SELECTED)
313
{
314
SetBkColor( lpdis->hDC, oldBk );
315
SetTextColor( lpdis->hDC, oldText );
316
}
317
DrawIconEx( lpdis->hDC, lpdis->rcItem.left, lpdis->rcItem.top, hIcon, 16, 16, 0, 0, DI_NORMAL );
318
heap_free(str);
319
return TRUE;
320
}
321
return FALSE;
322
}
323
324
/***********************************************************************
325
* FD31_UpdateResult [internal]
326
* update the displayed file name (with path)
327
*/
328
static void FD31_UpdateResult(const FD31_DATA *lfs, const WCHAR *tmpstr)
329
{
330
int lenstr2;
331
LPOPENFILENAMEW ofnW = lfs->ofnW;
332
LPOPENFILENAMEA ofnA = lfs->ofnA;
333
WCHAR tmpstr2[BUFFILE];
334
WCHAR *p;
335
336
TRACE("%s\n", debugstr_w(tmpstr));
337
if(ofnW->Flags & OFN_NOVALIDATE)
338
tmpstr2[0] = '\0';
339
else
340
GetCurrentDirectoryW(BUFFILE, tmpstr2);
341
lenstr2 = lstrlenW(tmpstr2);
342
if (lenstr2 > 3)
343
tmpstr2[lenstr2++]='\\';
344
lstrcpynW(tmpstr2+lenstr2, tmpstr, BUFFILE-lenstr2);
345
if (!ofnW->lpstrFile)
346
return;
347
348
lstrcpynW(ofnW->lpstrFile, tmpstr2, ofnW->nMaxFile);
349
350
/* set filename offset */
351
p = PathFindFileNameW(ofnW->lpstrFile);
352
ofnW->nFileOffset = (p - ofnW->lpstrFile);
353
354
/* set extension offset */
355
p = PathFindExtensionW(ofnW->lpstrFile);
356
ofnW->nFileExtension = (*p) ? (p - ofnW->lpstrFile) + 1 : 0;
357
358
TRACE("file %s, file offset %d, ext offset %d\n",
359
debugstr_w(ofnW->lpstrFile), ofnW->nFileOffset, ofnW->nFileExtension);
360
361
/* update the real client structures if any */
362
if (ofnA)
363
{
364
LPSTR lpszTemp;
365
if (ofnW->nMaxFile &&
366
!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFile, -1,
367
ofnA->lpstrFile, ofnA->nMaxFile, NULL, NULL ))
368
ofnA->lpstrFile[ofnA->nMaxFile-1] = 0;
369
370
/* offsets are not guaranteed to be the same in WCHAR to MULTIBYTE conversion */
371
/* set filename offset */
372
lpszTemp = PathFindFileNameA(ofnA->lpstrFile);
373
ofnA->nFileOffset = (lpszTemp - ofnA->lpstrFile);
374
375
/* set extension offset */
376
lpszTemp = PathFindExtensionA(ofnA->lpstrFile);
377
ofnA->nFileExtension = (*lpszTemp) ? (lpszTemp - ofnA->lpstrFile) + 1 : 0;
378
}
379
}
380
381
/***********************************************************************
382
* FD31_UpdateFileTitle [internal]
383
* update the displayed file name (without path)
384
*/
385
static void FD31_UpdateFileTitle(const FD31_DATA *lfs)
386
{
387
LONG lRet;
388
LPOPENFILENAMEW ofnW = lfs->ofnW;
389
LPOPENFILENAMEA ofnA = lfs->ofnA;
390
391
if (ofnW->lpstrFileTitle != NULL)
392
{
393
lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
394
SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETTEXT, lRet,
395
(LPARAM)ofnW->lpstrFileTitle );
396
if (ofnA)
397
{
398
if (!WideCharToMultiByte( CP_ACP, 0, ofnW->lpstrFileTitle, -1,
399
ofnA->lpstrFileTitle, ofnA->nMaxFileTitle, NULL, NULL ))
400
ofnA->lpstrFileTitle[ofnA->nMaxFileTitle-1] = 0;
401
}
402
}
403
}
404
405
/***********************************************************************
406
* FD31_DirListDblClick [internal]
407
*/
408
static LRESULT FD31_DirListDblClick( const FD31_DATA *lfs )
409
{
410
LONG lRet;
411
HWND hWnd = lfs->hwnd;
412
LPWSTR pstr;
413
WCHAR tmpstr[BUFFILE];
414
415
/* get the raw string (with brackets) */
416
lRet = SendDlgItemMessageW(hWnd, lst2, LB_GETCURSEL, 0, 0);
417
if (lRet == LB_ERR) return TRUE;
418
pstr = heap_alloc(BUFFILEALLOC);
419
SendDlgItemMessageW(hWnd, lst2, LB_GETTEXT, lRet,
420
(LPARAM)pstr);
421
lstrcpyW( tmpstr, pstr );
422
heap_free(pstr);
423
/* get the selected directory in tmpstr */
424
if (tmpstr[0] == '[')
425
{
426
tmpstr[lstrlenW(tmpstr) - 1] = 0;
427
lstrcpyW(tmpstr,tmpstr+1);
428
}
429
lstrcatW(tmpstr, L"\\");
430
431
FD31_ScanDir(lfs->ofnW, hWnd, tmpstr);
432
/* notify the app */
433
if (lfs->hook)
434
{
435
if (FD31_CallWindowProc(lfs, lfs->lbselchstring, lst2,
436
MAKELONG(lRet,CD_LBSELCHANGE)))
437
return TRUE;
438
}
439
return TRUE;
440
}
441
442
/***********************************************************************
443
* FD31_FileListSelect [internal]
444
* called when a new item is picked in the file list
445
*/
446
static LRESULT FD31_FileListSelect( const FD31_DATA *lfs )
447
{
448
LONG lRet;
449
HWND hWnd = lfs->hwnd;
450
LPWSTR pstr;
451
452
lRet = SendDlgItemMessageW(lfs->hwnd, lst1, LB_GETCURSEL, 0, 0);
453
if (lRet == LB_ERR)
454
return TRUE;
455
456
/* set the edit control to the chosen file */
457
if ((pstr = heap_alloc(BUFFILEALLOC)))
458
{
459
SendDlgItemMessageW(hWnd, lst1, LB_GETTEXT, lRet,
460
(LPARAM)pstr);
461
SetDlgItemTextW( hWnd, edt1, pstr );
462
heap_free(pstr);
463
}
464
if (lfs->hook)
465
{
466
FD31_CallWindowProc(lfs, lfs->lbselchstring, lst1,
467
MAKELONG(lRet,CD_LBSELCHANGE));
468
}
469
/* FIXME: for OFN_ALLOWMULTISELECT we need CD_LBSELSUB, CD_SELADD,
470
CD_LBSELNOITEMS */
471
return TRUE;
472
}
473
474
/***********************************************************************
475
* FD31_TestPath [internal]
476
* before accepting the file name, test if it includes wild cards
477
* tries to scan the directory and returns TRUE if no error.
478
*/
479
static LRESULT FD31_TestPath( const FD31_DATA *lfs, LPWSTR path )
480
{
481
HWND hWnd = lfs->hwnd;
482
LPWSTR pBeginFileName, pstr2;
483
WCHAR tmpstr2[BUFFILE];
484
485
pBeginFileName = wcsrchr(path, '\\');
486
if (pBeginFileName == NULL)
487
pBeginFileName = wcsrchr(path, ':');
488
489
if (wcschr(path,'*') != NULL || wcschr(path,'?') != NULL)
490
{
491
/* edit control contains wildcards */
492
if (pBeginFileName != NULL)
493
{
494
lstrcpynW(tmpstr2, pBeginFileName + 1, BUFFILE);
495
*(pBeginFileName + 1) = 0;
496
}
497
else
498
{
499
lstrcpyW(tmpstr2, path);
500
if(!(lfs->ofnW->Flags & OFN_NOVALIDATE))
501
*path = 0;
502
}
503
504
TRACE("path=%s, tmpstr2=%s\n", debugstr_w(path), debugstr_w(tmpstr2));
505
SetDlgItemTextW( hWnd, edt1, tmpstr2 );
506
FD31_ScanDir(lfs->ofnW, hWnd, path);
507
return (lfs->ofnW->Flags & OFN_NOVALIDATE) != 0;
508
}
509
510
/* no wildcards, we might have a directory or a filename */
511
/* try appending a wildcard and reading the directory */
512
513
pstr2 = path + lstrlenW(path);
514
if (pBeginFileName == NULL || *(pBeginFileName + 1) != 0)
515
lstrcatW(path, L"\\");
516
517
/* if ScanDir succeeds, we have changed the directory */
518
if (FD31_ScanDir(lfs->ofnW, hWnd, path))
519
return FALSE; /* and path is not a valid file name */
520
521
/* if not, this must be a filename */
522
523
*pstr2 = 0; /* remove the wildcard added before */
524
525
if (pBeginFileName != NULL)
526
{
527
/* strip off the pathname */
528
*pBeginFileName = 0;
529
SetDlgItemTextW( hWnd, edt1, pBeginFileName + 1 );
530
531
lstrcpynW(tmpstr2, pBeginFileName + 1, ARRAY_SIZE(tmpstr2));
532
/* Should we MessageBox() if this fails? */
533
if (!FD31_ScanDir(lfs->ofnW, hWnd, path))
534
{
535
return FALSE;
536
}
537
lstrcpyW(path, tmpstr2);
538
}
539
else
540
SetDlgItemTextW( hWnd, edt1, path );
541
return TRUE;
542
}
543
544
/***********************************************************************
545
* FD31_Validate [internal]
546
* called on: click Ok button, Enter in edit, DoubleClick in file list
547
*/
548
static LRESULT FD31_Validate( const FD31_DATA *lfs, LPCWSTR path, UINT control, INT itemIndex,
549
BOOL internalUse )
550
{
551
LONG lRet;
552
HWND hWnd = lfs->hwnd;
553
OPENFILENAMEW ofnsav;
554
LPOPENFILENAMEW ofnW = lfs->ofnW;
555
WCHAR filename[BUFFILE];
556
int copied_size = min( ofnW->lStructSize, sizeof(ofnsav) );
557
558
memcpy( &ofnsav, ofnW, copied_size ); /* for later restoring */
559
560
/* get current file name */
561
if (path)
562
lstrcpynW(filename, path, ARRAY_SIZE(filename));
563
else
564
GetDlgItemTextW( hWnd, edt1, filename, ARRAY_SIZE(filename));
565
566
TRACE("got filename = %s\n", debugstr_w(filename));
567
/* if we did not click in file list to get there */
568
if (control != lst1)
569
{
570
if (!FD31_TestPath( lfs, filename) )
571
return FALSE;
572
}
573
FD31_UpdateResult(lfs, filename);
574
575
if (internalUse)
576
{ /* called internally after a change in a combo */
577
if (lfs->hook)
578
{
579
FD31_CallWindowProc(lfs, lfs->lbselchstring, control,
580
MAKELONG(itemIndex,CD_LBSELCHANGE));
581
}
582
return TRUE;
583
}
584
585
FD31_UpdateFileTitle(lfs);
586
if (lfs->hook)
587
{
588
lRet = FD31_CallWindowProc(lfs, lfs->fileokstring,
589
0, lfs->lParam );
590
if (lRet)
591
{
592
memcpy( ofnW, &ofnsav, copied_size ); /* restore old state */
593
return FALSE;
594
}
595
}
596
if ((ofnW->Flags & OFN_ALLOWMULTISELECT) && (ofnW->Flags & OFN_EXPLORER))
597
{
598
if (ofnW->lpstrFile)
599
{
600
LPWSTR str = ofnW->lpstrFile;
601
LPWSTR ptr = wcsrchr(str, '\\');
602
str[lstrlenW(str) + 1] = '\0';
603
*ptr = 0;
604
}
605
}
606
return TRUE;
607
}
608
609
/***********************************************************************
610
* FD31_DiskChange [internal]
611
* called when a new item is picked in the disk selection combo
612
*/
613
static LRESULT FD31_DiskChange( const FD31_DATA *lfs )
614
{
615
LONG lRet;
616
HWND hWnd = lfs->hwnd;
617
LPWSTR pstr;
618
WCHAR diskname[BUFFILE];
619
620
FD31_StripEditControl(hWnd);
621
lRet = SendDlgItemMessageW(hWnd, cmb2, CB_GETCURSEL, 0, 0L);
622
if (lRet == LB_ERR)
623
return 0;
624
pstr = heap_alloc(BUFFILEALLOC);
625
SendDlgItemMessageW(hWnd, cmb2, CB_GETLBTEXT, lRet,
626
(LPARAM)pstr);
627
wsprintfW(diskname, L"%c:", pstr[2]);
628
heap_free(pstr);
629
630
return FD31_Validate( lfs, diskname, cmb2, lRet, TRUE );
631
}
632
633
/***********************************************************************
634
* FD31_FileTypeChange [internal]
635
* called when a new item is picked in the file type combo
636
*/
637
static LRESULT FD31_FileTypeChange( const FD31_DATA *lfs )
638
{
639
LONG lRet;
640
LPWSTR pstr;
641
642
lRet = SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETCURSEL, 0, 0);
643
if (lRet == LB_ERR)
644
return TRUE;
645
lfs->ofnW->nFilterIndex = lRet + 1;
646
if (lfs->ofnA)
647
lfs->ofnA->nFilterIndex = lRet + 1;
648
pstr = (LPWSTR)SendDlgItemMessageW(lfs->hwnd, cmb1, CB_GETITEMDATA, lRet, 0);
649
TRACE("Selected filter : %s\n", debugstr_w(pstr));
650
651
return FD31_Validate( lfs, pstr, cmb1, lRet, TRUE );
652
}
653
654
/***********************************************************************
655
* FD31_WMCommand [internal]
656
*/
657
static LRESULT FD31_WMCommand( HWND hWnd, LPARAM lParam, UINT notification,
658
UINT control, const FD31_DATA *lfs )
659
{
660
switch (control)
661
{
662
case lst1: /* file list */
663
FD31_StripEditControl(hWnd);
664
if (notification == LBN_DBLCLK)
665
{
666
return SendMessageW(hWnd, WM_COMMAND, IDOK, 0);
667
}
668
else if (notification == LBN_SELCHANGE)
669
return FD31_FileListSelect( lfs );
670
break;
671
672
case lst2: /* directory list */
673
FD31_StripEditControl(hWnd);
674
if (notification == LBN_DBLCLK)
675
return FD31_DirListDblClick( lfs );
676
break;
677
678
case cmb1: /* file type drop list */
679
if (notification == CBN_SELCHANGE)
680
return FD31_FileTypeChange( lfs );
681
break;
682
683
case chx1:
684
break;
685
686
case pshHelp:
687
break;
688
689
case cmb2: /* disk dropdown combo */
690
if (notification == CBN_SELCHANGE)
691
return FD31_DiskChange( lfs );
692
break;
693
694
case IDOK:
695
TRACE("OK pressed\n");
696
if (FD31_Validate( lfs, NULL, control, 0, FALSE ))
697
EndDialog(hWnd, TRUE);
698
return TRUE;
699
700
case IDCANCEL:
701
EndDialog(hWnd, FALSE);
702
return TRUE;
703
704
case IDABORT: /* can be sent by the hook procedure */
705
EndDialog(hWnd, TRUE);
706
return TRUE;
707
}
708
return FALSE;
709
}
710
711
/************************************************************************
712
* FD31_MapStringPairsToW [internal]
713
* map string pairs to Unicode
714
*/
715
static LPWSTR FD31_MapStringPairsToW(LPCSTR strA, UINT size)
716
{
717
LPCSTR s;
718
LPWSTR x;
719
unsigned int n, len;
720
721
s = strA;
722
while (*s)
723
s = s+strlen(s)+1;
724
s++;
725
n = s + 1 - strA; /* Don't forget the other \0 */
726
if (n < size) n = size;
727
728
len = MultiByteToWideChar( CP_ACP, 0, strA, n, NULL, 0 );
729
x = heap_alloc(len * sizeof(WCHAR));
730
MultiByteToWideChar( CP_ACP, 0, strA, n, x, len );
731
return x;
732
}
733
734
735
/************************************************************************
736
* FD31_DupToW [internal]
737
* duplicates an Ansi string to unicode, with a buffer size
738
*/
739
static LPWSTR FD31_DupToW(LPCSTR str, DWORD size)
740
{
741
LPWSTR strW = NULL;
742
if (str && (size > 0))
743
{
744
strW = heap_alloc(size * sizeof(WCHAR));
745
if (strW) MultiByteToWideChar( CP_ACP, 0, str, -1, strW, size );
746
}
747
return strW;
748
}
749
750
/************************************************************************
751
* FD31_MapOfnStructA [internal]
752
* map a 32 bits Ansi structure to a Unicode one
753
*/
754
static void FD31_MapOfnStructA(const OPENFILENAMEA *ofnA, LPOPENFILENAMEW ofnW, BOOL open)
755
{
756
UNICODE_STRING usBuffer;
757
758
ofnW->hwndOwner = ofnA->hwndOwner;
759
ofnW->hInstance = ofnA->hInstance;
760
if (ofnA->lpstrFilter)
761
ofnW->lpstrFilter = FD31_MapStringPairsToW(ofnA->lpstrFilter, 0);
762
763
if ((ofnA->lpstrCustomFilter) && (*(ofnA->lpstrCustomFilter)))
764
ofnW->lpstrCustomFilter = FD31_MapStringPairsToW(ofnA->lpstrCustomFilter, ofnA->nMaxCustFilter);
765
ofnW->nMaxCustFilter = ofnA->nMaxCustFilter;
766
ofnW->nFilterIndex = ofnA->nFilterIndex;
767
ofnW->nMaxFile = ofnA->nMaxFile;
768
ofnW->lpstrFile = FD31_DupToW(ofnA->lpstrFile, ofnW->nMaxFile);
769
ofnW->nMaxFileTitle = ofnA->nMaxFileTitle;
770
ofnW->lpstrFileTitle = FD31_DupToW(ofnA->lpstrFileTitle, ofnW->nMaxFileTitle);
771
if (ofnA->lpstrInitialDir)
772
{
773
RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpstrInitialDir);
774
ofnW->lpstrInitialDir = usBuffer.Buffer;
775
}
776
if (ofnA->lpstrTitle) {
777
RtlCreateUnicodeStringFromAsciiz (&usBuffer, ofnA->lpstrTitle);
778
ofnW->lpstrTitle = usBuffer.Buffer;
779
} else {
780
WCHAR buf[16];
781
LPWSTR title_tmp;
782
int len;
783
LoadStringW(COMDLG32_hInstance, open ? IDS_OPEN_FILE : IDS_SAVE_AS, buf, ARRAY_SIZE(buf));
784
len = lstrlenW(buf)+1;
785
title_tmp = heap_alloc(len * sizeof(WCHAR));
786
memcpy(title_tmp, buf, len * sizeof(WCHAR));
787
ofnW->lpstrTitle = title_tmp;
788
}
789
ofnW->Flags = ofnA->Flags;
790
ofnW->nFileOffset = ofnA->nFileOffset;
791
ofnW->nFileExtension = ofnA->nFileExtension;
792
ofnW->lpstrDefExt = FD31_DupToW(ofnA->lpstrDefExt, 3);
793
if ((ofnA->Flags & OFN_ENABLETEMPLATE) && (ofnA->lpTemplateName))
794
{
795
if (!IS_INTRESOURCE(ofnA->lpTemplateName))
796
{
797
RtlCreateUnicodeStringFromAsciiz (&usBuffer,ofnA->lpTemplateName);
798
ofnW->lpTemplateName = usBuffer.Buffer;
799
}
800
else /* numbered resource */
801
ofnW->lpTemplateName = (LPCWSTR) ofnA->lpTemplateName;
802
}
803
if (ofnW->lStructSize > OPENFILENAME_SIZE_VERSION_400W)
804
{
805
ofnW->pvReserved = ofnA->pvReserved;
806
ofnW->dwReserved = ofnA->dwReserved;
807
ofnW->FlagsEx = ofnA->FlagsEx;
808
}
809
}
810
811
812
/************************************************************************
813
* FD31_FreeOfnW [internal]
814
* Undo all allocations done by FD31_MapOfnStructA
815
*/
816
static void FD31_FreeOfnW(OPENFILENAMEW *ofnW)
817
{
818
heap_free((void *)ofnW->lpstrFilter);
819
heap_free(ofnW->lpstrCustomFilter);
820
heap_free(ofnW->lpstrFile);
821
heap_free(ofnW->lpstrFileTitle);
822
heap_free((void *)ofnW->lpstrInitialDir);
823
heap_free((void *)ofnW->lpstrTitle);
824
if (!IS_INTRESOURCE(ofnW->lpTemplateName))
825
heap_free((void *)ofnW->lpTemplateName);
826
}
827
828
/************************************************************************
829
* FD31_DestroyPrivate [internal]
830
* destroys the private object
831
*/
832
static void FD31_DestroyPrivate(PFD31_DATA lfs)
833
{
834
HWND hwnd;
835
if (!lfs) return;
836
hwnd = lfs->hwnd;
837
TRACE("destroying private allocation %p\n", lfs);
838
839
/* if ofnW has been allocated, have to free everything in it */
840
if (lfs->ofnA)
841
{
842
FD31_FreeOfnW(lfs->ofnW);
843
heap_free(lfs->ofnW);
844
}
845
heap_free(lfs);
846
RemovePropA(hwnd, FD31_OFN_PROP);
847
}
848
849
/***********************************************************************
850
* FD31_GetTemplate [internal]
851
*
852
* Get a template (or FALSE if failure) when 16 bits dialogs are used
853
* by a 32 bits application
854
*
855
*/
856
static BOOL FD31_GetTemplate(PFD31_DATA lfs)
857
{
858
LPOPENFILENAMEW ofnW = lfs->ofnW;
859
LPOPENFILENAMEA ofnA = lfs->ofnA;
860
HANDLE hDlgTmpl;
861
862
if (ofnW->Flags & OFN_ENABLETEMPLATEHANDLE)
863
{
864
if (!(lfs->template = LockResource( ofnW->hInstance )))
865
{
866
COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE );
867
return FALSE;
868
}
869
}
870
else if (ofnW->Flags & OFN_ENABLETEMPLATE)
871
{
872
HRSRC hResInfo;
873
if (ofnA)
874
hResInfo = FindResourceA( ofnA->hInstance, ofnA->lpTemplateName, (LPSTR)RT_DIALOG );
875
else
876
hResInfo = FindResourceW( ofnW->hInstance, ofnW->lpTemplateName, (LPWSTR)RT_DIALOG );
877
if (!hResInfo)
878
{
879
COMDLG32_SetCommDlgExtendedError( CDERR_FINDRESFAILURE );
880
return FALSE;
881
}
882
if (!(hDlgTmpl = LoadResource( ofnW->hInstance, hResInfo )) ||
883
!(lfs->template = LockResource( hDlgTmpl )))
884
{
885
COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE );
886
return FALSE;
887
}
888
}
889
else /* get it from internal Wine resource */
890
{
891
HRSRC hResInfo;
892
if (!(hResInfo = FindResourceA( COMDLG32_hInstance, lfs->open ? "OPEN_FILE" : "SAVE_FILE", (LPSTR)RT_DIALOG )))
893
{
894
COMDLG32_SetCommDlgExtendedError( CDERR_FINDRESFAILURE );
895
return FALSE;
896
}
897
if (!(hDlgTmpl = LoadResource( COMDLG32_hInstance, hResInfo )) ||
898
!(lfs->template = LockResource( hDlgTmpl )))
899
{
900
COMDLG32_SetCommDlgExtendedError( CDERR_LOADRESFAILURE );
901
return FALSE;
902
}
903
}
904
return TRUE;
905
}
906
907
/************************************************************************
908
* FD31_AllocPrivate [internal]
909
* allocate a private object to hold 32 bits Unicode
910
* structure that will be used throughout the calls, while
911
* keeping available the original structures and a few variables
912
* On entry : type = dialog procedure type (16,32A,32W)
913
* dlgType = dialog type (open or save)
914
*/
915
static PFD31_DATA FD31_AllocPrivate(LPARAM lParam, UINT dlgType, BOOL IsUnicode)
916
{
917
FD31_DATA *lfs = heap_alloc_zero(sizeof(*lfs));
918
919
TRACE("alloc private buf %p\n", lfs);
920
if (!lfs) return NULL;
921
lfs->hook = FALSE;
922
lfs->lParam = lParam;
923
lfs->open = (dlgType == OPEN_DIALOG);
924
925
if (IsUnicode)
926
{
927
lfs->ofnA = NULL;
928
lfs->ofnW = (LPOPENFILENAMEW) lParam;
929
if (lfs->ofnW->Flags & OFN_ENABLEHOOK)
930
if (lfs->ofnW->lpfnHook)
931
lfs->hook = TRUE;
932
}
933
else
934
{
935
lfs->ofnA = (LPOPENFILENAMEA) lParam;
936
if (lfs->ofnA->Flags & OFN_ENABLEHOOK)
937
if (lfs->ofnA->lpfnHook)
938
lfs->hook = TRUE;
939
lfs->ofnW = heap_alloc_zero(lfs->ofnA->lStructSize);
940
lfs->ofnW->lStructSize = lfs->ofnA->lStructSize;
941
FD31_MapOfnStructA(lfs->ofnA, lfs->ofnW, lfs->open);
942
}
943
944
if (! FD31_GetTemplate(lfs))
945
{
946
FD31_DestroyPrivate(lfs);
947
return NULL;
948
}
949
lfs->lbselchstring = RegisterWindowMessageA(LBSELCHSTRINGA);
950
lfs->fileokstring = RegisterWindowMessageA(FILEOKSTRINGA);
951
952
return lfs;
953
}
954
955
/***********************************************************************
956
* FD31_WMInitDialog [internal]
957
*/
958
static LONG FD31_WMInitDialog(HWND hWnd, WPARAM wParam, LPARAM lParam)
959
{
960
int i, n;
961
WCHAR tmpstr[BUFFILE];
962
LPWSTR pstr, old_pstr;
963
LPOPENFILENAMEW ofn;
964
PFD31_DATA lfs = (PFD31_DATA) lParam;
965
966
if (!lfs) return FALSE;
967
SetPropA(hWnd, FD31_OFN_PROP, lfs);
968
lfs->hwnd = hWnd;
969
ofn = lfs->ofnW;
970
971
TRACE("flags=%lx initialdir=%s\n", ofn->Flags, debugstr_w(ofn->lpstrInitialDir));
972
973
SetWindowTextW( hWnd, ofn->lpstrTitle );
974
/* read custom filter information */
975
if (ofn->lpstrCustomFilter)
976
{
977
pstr = ofn->lpstrCustomFilter;
978
n = 0;
979
TRACE("lpstrCustomFilter = %p\n", pstr);
980
while(*pstr)
981
{
982
old_pstr = pstr;
983
i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
984
(LPARAM)(ofn->lpstrCustomFilter) + n );
985
n += lstrlenW(pstr) + 1;
986
pstr += lstrlenW(pstr) + 1;
987
TRACE("add str=%s associated to %s\n",
988
debugstr_w(old_pstr), debugstr_w(pstr));
989
SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
990
n += lstrlenW(pstr) + 1;
991
pstr += lstrlenW(pstr) + 1;
992
}
993
}
994
/* read filter information */
995
if (ofn->lpstrFilter) {
996
pstr = (LPWSTR) ofn->lpstrFilter;
997
n = 0;
998
while(*pstr) {
999
old_pstr = pstr;
1000
i = SendDlgItemMessageW(hWnd, cmb1, CB_ADDSTRING, 0,
1001
(LPARAM)(ofn->lpstrFilter + n) );
1002
n += lstrlenW(pstr) + 1;
1003
pstr += lstrlenW(pstr) + 1;
1004
TRACE("add str=%s associated to %s\n",
1005
debugstr_w(old_pstr), debugstr_w(pstr));
1006
SendDlgItemMessageW(hWnd, cmb1, CB_SETITEMDATA, i, (LPARAM)pstr);
1007
n += lstrlenW(pstr) + 1;
1008
pstr += lstrlenW(pstr) + 1;
1009
}
1010
}
1011
/* set default filter */
1012
if (ofn->nFilterIndex == 0 && ofn->lpstrCustomFilter == NULL)
1013
ofn->nFilterIndex = 1;
1014
SendDlgItemMessageW(hWnd, cmb1, CB_SETCURSEL, ofn->nFilterIndex - 1, 0);
1015
if (ofn->lpstrFile && ofn->lpstrFile[0])
1016
{
1017
TRACE( "SetText of edt1 to %s\n", debugstr_w(ofn->lpstrFile) );
1018
SetDlgItemTextW( hWnd, edt1, ofn->lpstrFile );
1019
}
1020
else
1021
{
1022
lstrcpynW(tmpstr, FD31_GetFileType(ofn->lpstrCustomFilter,
1023
ofn->lpstrFilter, ofn->nFilterIndex - 1),BUFFILE);
1024
TRACE("nFilterIndex = %ld, SetText of edt1 to %s\n",
1025
ofn->nFilterIndex, debugstr_w(tmpstr));
1026
SetDlgItemTextW( hWnd, edt1, tmpstr );
1027
}
1028
/* get drive list */
1029
*tmpstr = 0;
1030
DlgDirListComboBoxW(hWnd, tmpstr, cmb2, 0, DDL_DRIVES | DDL_EXCLUSIVE);
1031
/* read initial directory */
1032
/* FIXME: Note that this is now very version-specific (See MSDN description of
1033
* the OPENFILENAME structure). For example under 2000/XP any path in the
1034
* lpstrFile overrides the lpstrInitialDir, but not under 95/98/ME
1035
*/
1036
if (ofn->lpstrInitialDir != NULL)
1037
{
1038
int len;
1039
lstrcpynW(tmpstr, ofn->lpstrInitialDir, 511);
1040
len = lstrlenW(tmpstr);
1041
if (len > 0 && tmpstr[len-1] != '\\' && tmpstr[len-1] != ':') {
1042
tmpstr[len]='\\';
1043
tmpstr[len+1]='\0';
1044
}
1045
}
1046
else
1047
*tmpstr = 0;
1048
if (!FD31_ScanDir(ofn, hWnd, tmpstr)) {
1049
*tmpstr = 0;
1050
if (!FD31_ScanDir(ofn, hWnd, tmpstr))
1051
WARN("Couldn't read initial directory %s!\n", debugstr_w(tmpstr));
1052
}
1053
/* select current drive in combo 2, omit missing drives */
1054
{
1055
char dir[MAX_PATH];
1056
char str[4] = "a:\\";
1057
GetCurrentDirectoryA( sizeof(dir), dir );
1058
for(i = 0, n = -1; i < 26; i++)
1059
{
1060
str[0] = 'a' + i;
1061
if (GetDriveTypeA(str) > DRIVE_NO_ROOT_DIR) n++;
1062
if (toupper(str[0]) == toupper(dir[0])) break;
1063
}
1064
}
1065
SendDlgItemMessageW(hWnd, cmb2, CB_SETCURSEL, n, 0);
1066
if (!(ofn->Flags & OFN_SHOWHELP))
1067
ShowWindow(GetDlgItem(hWnd, pshHelp), SW_HIDE);
1068
if (ofn->Flags & OFN_HIDEREADONLY)
1069
ShowWindow(GetDlgItem(hWnd, chx1), SW_HIDE);
1070
if (lfs->hook)
1071
return FD31_CallWindowProc(lfs, WM_INITDIALOG, wParam, lfs->lParam);
1072
return TRUE;
1073
}
1074
1075
static int FD31_GetFldrHeight(void)
1076
{
1077
return fldrHeight;
1078
}
1079
1080
/***********************************************************************
1081
* FD31_WMMeasureItem [internal]
1082
*/
1083
static LONG FD31_WMMeasureItem(LPARAM lParam)
1084
{
1085
LPMEASUREITEMSTRUCT lpmeasure;
1086
1087
lpmeasure = (LPMEASUREITEMSTRUCT)lParam;
1088
lpmeasure->itemHeight = FD31_GetFldrHeight();
1089
return TRUE;
1090
}
1091
1092
1093
/***********************************************************************
1094
* FileOpenDlgProc [internal]
1095
* Used for open and save, in fact.
1096
*/
1097
static INT_PTR CALLBACK FD31_FileOpenDlgProc(HWND hWnd, UINT wMsg,
1098
WPARAM wParam, LPARAM lParam)
1099
{
1100
PFD31_DATA lfs = (PFD31_DATA)GetPropA( hWnd, FD31_OFN_PROP );
1101
1102
TRACE("msg=%x wparam=%Ix lParam=%Ix\n", wMsg, wParam, lParam);
1103
if ((wMsg != WM_INITDIALOG) && lfs && lfs->hook)
1104
{
1105
INT_PTR lRet;
1106
lRet = (INT_PTR)FD31_CallWindowProc( lfs, wMsg, wParam, lParam );
1107
if (lRet) return lRet; /* else continue message processing */
1108
}
1109
switch (wMsg)
1110
{
1111
case WM_INITDIALOG:
1112
return FD31_WMInitDialog( hWnd, wParam, lParam );
1113
1114
case WM_MEASUREITEM:
1115
return FD31_WMMeasureItem( lParam );
1116
1117
case WM_DRAWITEM:
1118
return FD31_WMDrawItem( hWnd, wParam, lParam, !lfs->open, (DRAWITEMSTRUCT *)lParam );
1119
1120
case WM_COMMAND:
1121
return FD31_WMCommand( hWnd, lParam, HIWORD(wParam), LOWORD(wParam), lfs );
1122
#if 0
1123
case WM_CTLCOLOR:
1124
SetBkColor( (HDC16)wParam, 0x00C0C0C0 );
1125
switch (HIWORD(lParam))
1126
{
1127
case CTLCOLOR_BTN:
1128
SetTextColor( (HDC16)wParam, 0x00000000 );
1129
return hGRAYBrush;
1130
case CTLCOLOR_STATIC:
1131
SetTextColor( (HDC16)wParam, 0x00000000 );
1132
return hGRAYBrush;
1133
}
1134
break;
1135
#endif
1136
}
1137
return FALSE;
1138
}
1139
1140
/***********************************************************************
1141
* GetFileName31A [internal]
1142
*
1143
* Creates a win31 style dialog box for the user to select a file to open/save.
1144
*/
1145
BOOL GetFileName31A( OPENFILENAMEA *lpofn, UINT dlgType )
1146
{
1147
BOOL bRet = FALSE;
1148
PFD31_DATA lfs;
1149
1150
if (!lpofn || !FD31_Init()) return FALSE;
1151
1152
TRACE("ofn flags %08lx\n", lpofn->Flags);
1153
lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, FALSE);
1154
if (lfs)
1155
{
1156
bRet = DialogBoxIndirectParamA( COMDLG32_hInstance, lfs->template, lpofn->hwndOwner,
1157
FD31_FileOpenDlgProc, (LPARAM)lfs);
1158
FD31_DestroyPrivate(lfs);
1159
}
1160
1161
TRACE("return lpstrFile='%s' !\n", lpofn->lpstrFile);
1162
return bRet;
1163
}
1164
1165
/***********************************************************************
1166
* GetFileName31W [internal]
1167
*
1168
* Creates a win31 style dialog box for the user to select a file to open/save
1169
*/
1170
BOOL GetFileName31W( OPENFILENAMEW *lpofn, UINT dlgType )
1171
{
1172
BOOL bRet = FALSE;
1173
PFD31_DATA lfs;
1174
1175
if (!lpofn || !FD31_Init()) return FALSE;
1176
1177
lfs = FD31_AllocPrivate((LPARAM) lpofn, dlgType, TRUE);
1178
if (lfs)
1179
{
1180
bRet = DialogBoxIndirectParamW( COMDLG32_hInstance, lfs->template, lpofn->hwndOwner,
1181
FD31_FileOpenDlgProc, (LPARAM)lfs);
1182
FD31_DestroyPrivate(lfs);
1183
}
1184
1185
TRACE("file %s, file offset %d, ext offset %d\n",
1186
debugstr_w(lpofn->lpstrFile), lpofn->nFileOffset, lpofn->nFileExtension);
1187
return bRet;
1188
}
1189
1190