1 // todo: support win7/vista extensions rather than GetOpenFileName? -- merge win7filedialog into here.
4 #include "filebrowse.h"
6 #include "win32_utf8.h"
7 #include "wdlcstring.h"
11 #ifdef _MSC_VER // todo: win7filedialog.cpp support for mingw32
12 #define WDL_FILEBROWSE_WIN7VISTAMODE
19 #ifdef WDL_FILEBROWSE_WIN7VISTAMODE // win7/vista file dialog support
20 #include "win7filedialog.cpp"
22 // stuff since win7filedialog.h collides with shlobj.h below
23 #define tagSHCONTF tagSHCONTF___
24 #define SHCONTF SHCONTF___
25 #define SHCONTF_FOLDERS SHCONTF_FOLDERS___
26 #define SHCONTF_NONFOLDERS SHCONTF_NONFOLDERS___
27 #define SHCONTF_INCLUDEHIDDEN SHCONTF_INCLUDEHIDDEN___
28 #define SHCONTF_SHAREABLE SHCONTF_SHAREABLE__
29 #define SHCONTF_INIT_ON_FIRST_NEXT SHCONTF_INIT_ON_FIRST_NEXT__
30 #define SHCONTF_NETPRINTERSRCH SHCONTF_NETPRINTERSRCH__
31 #define SHCONTF_STORAGE SHCONTF_STORAGE__
36 // include after win7filedialog.*
42 #ifndef BIF_NEWDIALOGSTYLE
43 #define BIF_NEWDIALOGSTYLE 0x40
47 static void WDL_fixfnforopenfn(char *buf
)
52 if (WDL_IS_DIRCHAR(*p
)) *p
= WDL_DIRCHAR
;
56 if (buf
[0] && buf
[1] == ':')
62 while (p
[0]==WDL_DIRCHAR
&& p
[1] == WDL_DIRCHAR
) p
++;
72 static int CALLBACK WINAPI
WDL_BrowseCallbackProc( HWND hwnd
, UINT uMsg
, LPARAM lParam
, LPARAM lpData
)
76 case BFFM_INITIALIZED
:
78 if (lpData
&& ((char *)lpData
)[0])
80 #ifndef WDL_NO_SUPPORT_UTF8
81 WDL_UTF8_SendBFFM_SETSEL(hwnd
, (const char *)lpData
);
83 SendMessage(hwnd
, BFFM_SETSELECTION
, 1, lpData
);
94 bool WDL_ChooseDirectory(HWND parent
, const char *text
, const char *initialdir
, char *fn
, int fnsize
, bool preservecwd
)
97 GetCurrentDirectory(sizeof(olddir
),olddir
);
100 lstrcpyn_safe(name
,initialdir
?initialdir
:"",sizeof(name
));
101 BROWSEINFO bi
={parent
,NULL
, name
, text
, BIF_RETURNONLYFSDIRS
|BIF_NEWDIALOGSTYLE
, WDL_BrowseCallbackProc
, (LPARAM
)name
,};
102 LPITEMIDLIST idlist
= SHBrowseForFolderUTF8( &bi
);
103 if (idlist
&& SHGetPathFromIDListUTF8(idlist
, name
, sizeof(name
)))
108 lstrcpyn_safe(fn
,name
,fnsize
);
114 bool r
= BrowseForDirectory(text
,initialdir
,fn
,fnsize
);
115 if (preservecwd
) SetCurrentDirectory(olddir
);
120 static const char *stristr(const char* a
, const char* b
)
122 const size_t n
= strlen(a
), len
= strlen(b
);
123 for (size_t i
= 0; i
+len
<= n
; ++i
) if (!strnicmp(a
+i
, b
, len
)) return a
+i
;
127 bool WDL_ChooseFileForSave(HWND parent
,
129 const char *initialdir
,
130 const char *initialfile
,
141 struct SWELL_DialogResourceIndex
*reshead
146 GetCurrentDirectory(sizeof(cwd
),cwd
);
150 memset(temp
,0,sizeof(temp
));
151 if (initialfile
) lstrcpyn_safe(temp
,initialfile
,sizeof(temp
));
152 WDL_fixfnforopenfn(temp
);
154 #ifdef WDL_FILEBROWSE_WIN7VISTAMODE
156 Win7FileDialog
fd(text
, 1);
159 fd
.addOptions(FOS_DONTADDTORECENT
);
160 //vista+ file open dialog
162 GetCurrentDirectory(sizeof(olddir
),olddir
);
164 fd
.setFilterList(extlist
);
167 fd
.setDefaultExtension(defext
);
170 const char *p
= extlist
;
173 if(*p
) p
+=strlen(p
)+1;
175 if(stristr(p
, defext
))
177 fd
.setFileTypeIndex(i
+1);
184 fd
.setFolder(initialdir
?initialdir
:olddir
, 0);
187 //check for folder name
188 if (WDL_remove_filepart(temp
))
191 fd
.setFolder(temp
, 0);
192 fd
.setFilename(temp
+ strlen(temp
) + 1);
195 fd
.setFilename(*temp
? temp
: initialfile
);
197 fd
.setTemplate(hInstance
, dlgid
, (LPOFNHOOKPROC
)dlgProc
);
201 //ifilesavedialog saves the last folder automatically
202 fd
.getResult(fn
, fnsize
);
204 if (preservecwd
) SetCurrentDirectory(olddir
);
208 if (preservecwd
) SetCurrentDirectory(olddir
);
215 OPENFILENAME l
={sizeof(l
),parent
, hInstance
, extlist
, NULL
,0, 0, temp
, sizeof(temp
)-1, NULL
, 0, initialdir
&&initialdir
[0] ? initialdir
: cwd
, text
,
216 OFN_HIDEREADONLY
|OFN_EXPLORER
|OFN_OVERWRITEPROMPT
,0,0,defext
, 0, (LPOFNHOOKPROC
)dlgProc
, dlgid
};
218 if (hInstance
&&dlgProc
&&dlgid
) l
.Flags
|= OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
|OFN_ENABLESIZING
;
219 if (preservecwd
) l
.Flags
|= OFN_NOCHANGEDIR
;
221 if (!GetSaveFileName(&l
)||!temp
[0])
223 if (preservecwd
) SetCurrentDirectory(cwd
);
226 if (preservecwd
) SetCurrentDirectory(cwd
);
227 lstrcpyn_safe(fn
,temp
,fnsize
);
231 BrowseFile_SetTemplate(dlgid
,(DLGPROC
)dlgProc
,reshead
);
233 if (initialfile
&& *initialfile
)
235 lstrcpyn_safe(if_temp
,initialfile
,sizeof(if_temp
));
236 WDL_fixfnforopenfn(if_temp
);
237 initialfile
= if_temp
;
241 if (defext
&& *defext
== '.') initialfile
= defext
; // SWELL supports default extension in filename field
244 bool r
= BrowseForSaveFile(text
,initialdir
,initialfile
,extlist
,fn
,fnsize
);
246 if (preservecwd
) SetCurrentDirectory(cwd
);
253 char *WDL_ChooseFileForOpen2(HWND parent
,
255 const char *initialdir
,
256 const char *initialfile
,
268 struct SWELL_DialogResourceIndex
*reshead
273 GetCurrentDirectory(sizeof(olddir
),olddir
);
277 #ifdef WDL_FILEBROWSE_WIN7VISTAMODE
280 Win7FileDialog
fd(text
);
283 //vista+ file open dialog
284 fd
.addOptions(FOS_FILEMUSTEXIST
|(allowmul
?FOS_ALLOWMULTISELECT
:0));
285 fd
.setFilterList(extlist
);
288 fd
.setDefaultExtension(defext
);
291 const char *p
= extlist
;
294 if(*p
) p
+=strlen(p
)+1;
296 if(stristr(p
, defext
))
298 fd
.setFileTypeIndex(i
+1);
305 fd
.setFolder(initialdir
?initialdir
:olddir
, 0);
306 fd
.setTemplate(hInstance
, dlgid
, (LPOFNHOOKPROC
)dlgProc
);
310 lstrcpyn_safe(temp
,initialfile
,sizeof(temp
));
311 //check for folder name
312 if (WDL_remove_filepart(temp
))
315 fd
.setFolder(temp
, 0);
316 fd
.setFilename(temp
+ strlen(temp
) + 1);
319 fd
.setFilename(temp
);
328 //ifileopendialog saves the last folder automatically
331 fd
.getResult(temp
, sizeof(temp
)-1);
332 ret
= temp
[0] ? strdup(temp
) : NULL
;
337 int totallen
=0, cnt
=fd
.getResultCount();
340 // sets an empty path as 1st returned string for multipath support
341 // (when selecting files among search results for ex.)
347 for (i
=0; i
<cnt
; i
++)
349 int len
= fd
.getResult(i
, temp
, sizeof(temp
)-1);
350 p
= len
? (char*)realloc(ret
, totallen
+ len
+ ((i
==cnt
-1)?1:0)) : NULL
;
354 memcpy(ret
+totallen
, temp
, len
);
364 if (ret
) p
[totallen
]=0;
367 if (preservecwd
) SetCurrentDirectory(olddir
);
371 if (preservecwd
) SetCurrentDirectory(olddir
);
377 int temp_size
= allowmul
? 256*1024-1 : 4096-1;
378 char *temp
= (char *)calloc(temp_size
+1,1);
380 OPENFILENAME l
={sizeof(l
), parent
, hInstance
, extlist
, NULL
, 0, 0, temp
, temp_size
, NULL
, 0, initialdir
, text
,
381 OFN_HIDEREADONLY
|OFN_EXPLORER
|OFN_FILEMUSTEXIST
,0,0, (char *)(defext
? defext
: ""), 0, (LPOFNHOOKPROC
)dlgProc
, dlgid
};
383 if (hInstance
&&dlgProc
&&dlgid
) l
.Flags
|= OFN_ENABLEHOOK
|OFN_ENABLETEMPLATE
|OFN_ENABLESIZING
;
384 if (allowmul
) l
.Flags
|=OFN_ALLOWMULTISELECT
;
385 if (preservecwd
) l
.Flags
|=OFN_NOCHANGEDIR
;
387 if (initialfile
) lstrcpyn_safe(temp
,initialfile
,temp_size
);
389 WDL_fixfnforopenfn(temp
);
391 if (!l
.lpstrInitialDir
||!l
.lpstrInitialDir
[0]) l
.lpstrInitialDir
=olddir
;
393 int r
= GetOpenFileName(&l
);
394 if (preservecwd
) SetCurrentDirectory(olddir
);
403 lstrcpyn_safe(if_temp
,initialfile
,sizeof(if_temp
));
404 WDL_fixfnforopenfn(if_temp
);
405 initialfile
= if_temp
;
409 BrowseFile_SetTemplate(dlgid
,(DLGPROC
)dlgProc
,reshead
);
410 char *ret
= BrowseForFiles(text
,initialdir
,initialfile
,allowmul
,extlist
);
411 if (preservecwd
) SetCurrentDirectory(olddir
);
417 char *WDL_ChooseFileForOpen(HWND parent
,
419 const char *initialdir
,
420 const char *initialfile
,
432 struct SWELL_DialogResourceIndex
*reshead
436 return WDL_ChooseFileForOpen2(parent
,text
, initialdir
,initialfile
,extlist
,defext
,preservecwd
,allowmul
?1:0,dlgid
,dlgProc
,