1*f6dc9357SAndroid Build Coastguard Worker // Windows/CommonDialog.cpp
2*f6dc9357SAndroid Build Coastguard Worker
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker
5*f6dc9357SAndroid Build Coastguard Worker #include "../Common/MyBuffer.h"
6*f6dc9357SAndroid Build Coastguard Worker
7*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
8*f6dc9357SAndroid Build Coastguard Worker #include <commdlg.h>
9*f6dc9357SAndroid Build Coastguard Worker #endif
10*f6dc9357SAndroid Build Coastguard Worker
11*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
12*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StringConvert.h"
13*f6dc9357SAndroid Build Coastguard Worker #endif
14*f6dc9357SAndroid Build Coastguard Worker
15*f6dc9357SAndroid Build Coastguard Worker #include "CommonDialog.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "Defs.h"
17*f6dc9357SAndroid Build Coastguard Worker // #include "FileDir.h"
18*f6dc9357SAndroid Build Coastguard Worker
19*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
20*f6dc9357SAndroid Build Coastguard Worker extern bool g_IsNT;
21*f6dc9357SAndroid Build Coastguard Worker #endif
22*f6dc9357SAndroid Build Coastguard Worker
23*f6dc9357SAndroid Build Coastguard Worker namespace NWindows {
24*f6dc9357SAndroid Build Coastguard Worker
25*f6dc9357SAndroid Build Coastguard Worker /*
26*f6dc9357SAndroid Build Coastguard Worker GetSaveFileName()
27*f6dc9357SAndroid Build Coastguard Worker GetOpenFileName()
28*f6dc9357SAndroid Build Coastguard Worker OPENFILENAME
29*f6dc9357SAndroid Build Coastguard Worker
30*f6dc9357SAndroid Build Coastguard Worker (lpstrInitialDir) : the initial directory.
31*f6dc9357SAndroid Build Coastguard Worker DOCs: the algorithm for selecting the initial directory varies on different platforms:
32*f6dc9357SAndroid Build Coastguard Worker {
33*f6dc9357SAndroid Build Coastguard Worker Win2000/XP/Vista:
34*f6dc9357SAndroid Build Coastguard Worker 1. If lpstrFile contains a path, that path is the initial directory.
35*f6dc9357SAndroid Build Coastguard Worker 2. Otherwise, lpstrInitialDir specifies the initial directory.
36*f6dc9357SAndroid Build Coastguard Worker
37*f6dc9357SAndroid Build Coastguard Worker Win7:
38*f6dc9357SAndroid Build Coastguard Worker If lpstrInitialDir has the same value as was passed the first time
39*f6dc9357SAndroid Build Coastguard Worker the application used an Open or Save As dialog box, the path
40*f6dc9357SAndroid Build Coastguard Worker most recently selected by the user is used as the initial directory.
41*f6dc9357SAndroid Build Coastguard Worker }
42*f6dc9357SAndroid Build Coastguard Worker
43*f6dc9357SAndroid Build Coastguard Worker Win10:
44*f6dc9357SAndroid Build Coastguard Worker in:
45*f6dc9357SAndroid Build Coastguard Worker function supports (lpstrInitialDir) path with super prefix "\\\\?\\"
46*f6dc9357SAndroid Build Coastguard Worker function supports (lpstrInitialDir) path with long path
47*f6dc9357SAndroid Build Coastguard Worker function doesn't support absolute (lpstrFile) path with super prefix "\\\\?\\"
48*f6dc9357SAndroid Build Coastguard Worker function doesn't support absolute (lpstrFile) path with long path
49*f6dc9357SAndroid Build Coastguard Worker out: the path with super prefix "\\\\?\\" will be returned, if selected path is long
50*f6dc9357SAndroid Build Coastguard Worker
51*f6dc9357SAndroid Build Coastguard Worker WinXP-64 and Win10: if no filters, the system shows all files.
52*f6dc9357SAndroid Build Coastguard Worker but DOCs say: If all three members are zero or NULL,
53*f6dc9357SAndroid Build Coastguard Worker the system does not use any filters and does not
54*f6dc9357SAndroid Build Coastguard Worker show any files in the file list control of the dialog box.
55*f6dc9357SAndroid Build Coastguard Worker
56*f6dc9357SAndroid Build Coastguard Worker in Win7+: GetOpenFileName() and GetSaveFileName()
57*f6dc9357SAndroid Build Coastguard Worker do not support pstrCustomFilter feature anymore
58*f6dc9357SAndroid Build Coastguard Worker */
59*f6dc9357SAndroid Build Coastguard Worker
60*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
61*f6dc9357SAndroid Build Coastguard Worker #define MY_OFN_PROJECT 0x00400000
62*f6dc9357SAndroid Build Coastguard Worker #define MY_OFN_SHOW_ALL 0x01000000
63*f6dc9357SAndroid Build Coastguard Worker #endif
64*f6dc9357SAndroid Build Coastguard Worker
65*f6dc9357SAndroid Build Coastguard Worker
66*f6dc9357SAndroid Build Coastguard Worker /*
67*f6dc9357SAndroid Build Coastguard Worker structures
68*f6dc9357SAndroid Build Coastguard Worker OPENFILENAMEW
69*f6dc9357SAndroid Build Coastguard Worker OPENFILENAMEA
70*f6dc9357SAndroid Build Coastguard Worker contain additional members:
71*f6dc9357SAndroid Build Coastguard Worker #if (_WIN32_WINNT >= 0x0500)
72*f6dc9357SAndroid Build Coastguard Worker void *pvReserved;
73*f6dc9357SAndroid Build Coastguard Worker DWORD dwReserved;
74*f6dc9357SAndroid Build Coastguard Worker DWORD FlagsEx;
75*f6dc9357SAndroid Build Coastguard Worker #endif
76*f6dc9357SAndroid Build Coastguard Worker
77*f6dc9357SAndroid Build Coastguard Worker If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions
78*f6dc9357SAndroid Build Coastguard Worker will not work at NT 4.0, if we use sizeof(OPENFILENAME).
79*f6dc9357SAndroid Build Coastguard Worker We try to use reduced structure OPENFILENAME_NT4.
80*f6dc9357SAndroid Build Coastguard Worker */
81*f6dc9357SAndroid Build Coastguard Worker
82*f6dc9357SAndroid Build Coastguard Worker // #if defined(_WIN64) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500)
83*f6dc9357SAndroid Build Coastguard Worker #if defined(__GNUC__) && (__GNUC__ <= 9) || defined(Z7_OLD_WIN_SDK)
84*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
85*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEA OPENFILENAMEA
86*f6dc9357SAndroid Build Coastguard Worker #endif
87*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEW OPENFILENAMEW
88*f6dc9357SAndroid Build Coastguard Worker
89*f6dc9357SAndroid Build Coastguard Worker // MinGW doesn't support some required macros. So we define them here:
90*f6dc9357SAndroid Build Coastguard Worker #ifndef CDSIZEOF_STRUCT
91*f6dc9357SAndroid Build Coastguard Worker #define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
92*f6dc9357SAndroid Build Coastguard Worker #endif
93*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
94*f6dc9357SAndroid Build Coastguard Worker #ifndef OPENFILENAME_SIZE_VERSION_400A
95*f6dc9357SAndroid Build Coastguard Worker #define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
96*f6dc9357SAndroid Build Coastguard Worker #endif
97*f6dc9357SAndroid Build Coastguard Worker #endif
98*f6dc9357SAndroid Build Coastguard Worker #ifndef OPENFILENAME_SIZE_VERSION_400W
99*f6dc9357SAndroid Build Coastguard Worker #define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
100*f6dc9357SAndroid Build Coastguard Worker #endif
101*f6dc9357SAndroid Build Coastguard Worker
102*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
103*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A
104*f6dc9357SAndroid Build Coastguard Worker #endif
105*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W
106*f6dc9357SAndroid Build Coastguard Worker #else
107*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
108*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEA OPENFILENAME_NT4A
109*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEA_size sizeof(my_compatib_OPENFILENAMEA)
110*f6dc9357SAndroid Build Coastguard Worker #endif
111*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEW OPENFILENAME_NT4W
112*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEW_size sizeof(my_compatib_OPENFILENAMEW)
113*f6dc9357SAndroid Build Coastguard Worker #endif
114*f6dc9357SAndroid Build Coastguard Worker /*
115*f6dc9357SAndroid Build Coastguard Worker #elif defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500)
116*f6dc9357SAndroid Build Coastguard Worker // || !defined(WINVER)
117*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
118*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEA OPENFILENAMEA
119*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA)
120*f6dc9357SAndroid Build Coastguard Worker #endif
121*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEW OPENFILENAMEW
122*f6dc9357SAndroid Build Coastguard Worker #define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW)
123*f6dc9357SAndroid Build Coastguard Worker #else
124*f6dc9357SAndroid Build Coastguard Worker
125*f6dc9357SAndroid Build Coastguard Worker #endif
126*f6dc9357SAndroid Build Coastguard Worker */
127*f6dc9357SAndroid Build Coastguard Worker
128*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
129*f6dc9357SAndroid Build Coastguard Worker #define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; }
130*f6dc9357SAndroid Build Coastguard Worker #endif
131*f6dc9357SAndroid Build Coastguard Worker
CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir,const UStringVector & filters)132*f6dc9357SAndroid Build Coastguard Worker bool CCommonDialogInfo::CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir, const UStringVector &filters)
133*f6dc9357SAndroid Build Coastguard Worker {
134*f6dc9357SAndroid Build Coastguard Worker /* GetSaveFileName() and GetOpenFileName() could change current dir,
135*f6dc9357SAndroid Build Coastguard Worker if OFN_NOCHANGEDIR is not used.
136*f6dc9357SAndroid Build Coastguard Worker We can restore current dir manually, if it's required.
137*f6dc9357SAndroid Build Coastguard Worker 22.02: we use OFN_NOCHANGEDIR. So we don't need to restore current dir manually. */
138*f6dc9357SAndroid Build Coastguard Worker // NFile::NDir::CCurrentDirRestorer curDirRestorer;
139*f6dc9357SAndroid Build Coastguard Worker
140*f6dc9357SAndroid Build Coastguard Worker #ifndef _UNICODE
141*f6dc9357SAndroid Build Coastguard Worker if (!g_IsNT)
142*f6dc9357SAndroid Build Coastguard Worker {
143*f6dc9357SAndroid Build Coastguard Worker AString tempPath;
144*f6dc9357SAndroid Build Coastguard Worker AStringVector f;
145*f6dc9357SAndroid Build Coastguard Worker unsigned i;
146*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < filters.Size(); i++)
147*f6dc9357SAndroid Build Coastguard Worker f.Add(GetSystemString(filters[i]));
148*f6dc9357SAndroid Build Coastguard Worker unsigned size = f.Size() + 1;
149*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < f.Size(); i++)
150*f6dc9357SAndroid Build Coastguard Worker size += f[i].Len();
151*f6dc9357SAndroid Build Coastguard Worker CObjArray<char> filterBuf(size);
152*f6dc9357SAndroid Build Coastguard Worker // memset(filterBuf, 0, size * sizeof(char));
153*f6dc9357SAndroid Build Coastguard Worker {
154*f6dc9357SAndroid Build Coastguard Worker char *dest = filterBuf;
155*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < f.Size(); i++)
156*f6dc9357SAndroid Build Coastguard Worker {
157*f6dc9357SAndroid Build Coastguard Worker const AString &s = f[i];
158*f6dc9357SAndroid Build Coastguard Worker MyStringCopy(dest, s);
159*f6dc9357SAndroid Build Coastguard Worker dest += s.Len() + 1;
160*f6dc9357SAndroid Build Coastguard Worker }
161*f6dc9357SAndroid Build Coastguard Worker *dest = 0;
162*f6dc9357SAndroid Build Coastguard Worker }
163*f6dc9357SAndroid Build Coastguard Worker my_compatib_OPENFILENAMEA p;
164*f6dc9357SAndroid Build Coastguard Worker memset(&p, 0, sizeof(p));
165*f6dc9357SAndroid Build Coastguard Worker p.lStructSize = my_compatib_OPENFILENAMEA_size;
166*f6dc9357SAndroid Build Coastguard Worker p.hwndOwner = hwndOwner;
167*f6dc9357SAndroid Build Coastguard Worker if (size > 1)
168*f6dc9357SAndroid Build Coastguard Worker {
169*f6dc9357SAndroid Build Coastguard Worker p.lpstrFilter = filterBuf;
170*f6dc9357SAndroid Build Coastguard Worker p.nFilterIndex = (DWORD)(FilterIndex + 1);
171*f6dc9357SAndroid Build Coastguard Worker }
172*f6dc9357SAndroid Build Coastguard Worker
173*f6dc9357SAndroid Build Coastguard Worker CONV_U_To_A(p.lpstrInitialDir, lpstrInitialDir, initialDir_a)
174*f6dc9357SAndroid Build Coastguard Worker CONV_U_To_A(p.lpstrTitle, lpstrTitle, title_a)
175*f6dc9357SAndroid Build Coastguard Worker
176*f6dc9357SAndroid Build Coastguard Worker const AString filePath_a = GetSystemString(FilePath);
177*f6dc9357SAndroid Build Coastguard Worker const unsigned bufSize = MAX_PATH * 8
178*f6dc9357SAndroid Build Coastguard Worker + filePath_a.Len()
179*f6dc9357SAndroid Build Coastguard Worker + initialDir_a.Len();
180*f6dc9357SAndroid Build Coastguard Worker p.nMaxFile = bufSize;
181*f6dc9357SAndroid Build Coastguard Worker p.lpstrFile = tempPath.GetBuf(bufSize);
182*f6dc9357SAndroid Build Coastguard Worker MyStringCopy(p.lpstrFile, filePath_a);
183*f6dc9357SAndroid Build Coastguard Worker p.Flags =
184*f6dc9357SAndroid Build Coastguard Worker OFN_EXPLORER
185*f6dc9357SAndroid Build Coastguard Worker | OFN_HIDEREADONLY
186*f6dc9357SAndroid Build Coastguard Worker | OFN_NOCHANGEDIR;
187*f6dc9357SAndroid Build Coastguard Worker const BOOL b = SaveMode ?
188*f6dc9357SAndroid Build Coastguard Worker ::GetSaveFileNameA((LPOPENFILENAMEA)(void *)&p) :
189*f6dc9357SAndroid Build Coastguard Worker ::GetOpenFileNameA((LPOPENFILENAMEA)(void *)&p);
190*f6dc9357SAndroid Build Coastguard Worker if (!b)
191*f6dc9357SAndroid Build Coastguard Worker return false;
192*f6dc9357SAndroid Build Coastguard Worker {
193*f6dc9357SAndroid Build Coastguard Worker tempPath.ReleaseBuf_CalcLen(bufSize);
194*f6dc9357SAndroid Build Coastguard Worker FilePath = GetUnicodeString(tempPath);
195*f6dc9357SAndroid Build Coastguard Worker FilterIndex = (int)p.nFilterIndex - 1;
196*f6dc9357SAndroid Build Coastguard Worker return true;
197*f6dc9357SAndroid Build Coastguard Worker }
198*f6dc9357SAndroid Build Coastguard Worker }
199*f6dc9357SAndroid Build Coastguard Worker else
200*f6dc9357SAndroid Build Coastguard Worker #endif
201*f6dc9357SAndroid Build Coastguard Worker {
202*f6dc9357SAndroid Build Coastguard Worker UString tempPath;
203*f6dc9357SAndroid Build Coastguard Worker unsigned size = filters.Size() + 1;
204*f6dc9357SAndroid Build Coastguard Worker unsigned i;
205*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < filters.Size(); i++)
206*f6dc9357SAndroid Build Coastguard Worker size += filters[i].Len();
207*f6dc9357SAndroid Build Coastguard Worker CObjArray<wchar_t> filterBuf(size);
208*f6dc9357SAndroid Build Coastguard Worker // memset(filterBuf, 0, size * sizeof(wchar_t));
209*f6dc9357SAndroid Build Coastguard Worker {
210*f6dc9357SAndroid Build Coastguard Worker wchar_t *dest = filterBuf;
211*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < filters.Size(); i++)
212*f6dc9357SAndroid Build Coastguard Worker {
213*f6dc9357SAndroid Build Coastguard Worker const UString &s = filters[i];
214*f6dc9357SAndroid Build Coastguard Worker MyStringCopy(dest, s);
215*f6dc9357SAndroid Build Coastguard Worker dest += s.Len() + 1;
216*f6dc9357SAndroid Build Coastguard Worker }
217*f6dc9357SAndroid Build Coastguard Worker *dest = 0;
218*f6dc9357SAndroid Build Coastguard Worker // if ((unsigned)(dest + 1 - filterBuf) != size) return false;
219*f6dc9357SAndroid Build Coastguard Worker }
220*f6dc9357SAndroid Build Coastguard Worker my_compatib_OPENFILENAMEW p;
221*f6dc9357SAndroid Build Coastguard Worker memset(&p, 0, sizeof(p));
222*f6dc9357SAndroid Build Coastguard Worker p.lStructSize = my_compatib_OPENFILENAMEW_size;
223*f6dc9357SAndroid Build Coastguard Worker p.hwndOwner = hwndOwner;
224*f6dc9357SAndroid Build Coastguard Worker if (size > 1)
225*f6dc9357SAndroid Build Coastguard Worker {
226*f6dc9357SAndroid Build Coastguard Worker p.lpstrFilter = filterBuf;
227*f6dc9357SAndroid Build Coastguard Worker p.nFilterIndex = (DWORD)(FilterIndex + 1);
228*f6dc9357SAndroid Build Coastguard Worker }
229*f6dc9357SAndroid Build Coastguard Worker unsigned bufSize = MAX_PATH * 8 + FilePath.Len();
230*f6dc9357SAndroid Build Coastguard Worker if (lpstrInitialDir)
231*f6dc9357SAndroid Build Coastguard Worker {
232*f6dc9357SAndroid Build Coastguard Worker p.lpstrInitialDir = lpstrInitialDir;
233*f6dc9357SAndroid Build Coastguard Worker bufSize += MyStringLen(lpstrInitialDir);
234*f6dc9357SAndroid Build Coastguard Worker }
235*f6dc9357SAndroid Build Coastguard Worker p.nMaxFile = bufSize;
236*f6dc9357SAndroid Build Coastguard Worker p.lpstrFile = tempPath.GetBuf(bufSize);
237*f6dc9357SAndroid Build Coastguard Worker MyStringCopy(p.lpstrFile, FilePath);
238*f6dc9357SAndroid Build Coastguard Worker p.lpstrTitle = lpstrTitle;
239*f6dc9357SAndroid Build Coastguard Worker p.Flags =
240*f6dc9357SAndroid Build Coastguard Worker OFN_EXPLORER
241*f6dc9357SAndroid Build Coastguard Worker | OFN_HIDEREADONLY
242*f6dc9357SAndroid Build Coastguard Worker | OFN_NOCHANGEDIR
243*f6dc9357SAndroid Build Coastguard Worker // | OFN_FORCESHOWHIDDEN // Win10 shows hidden items even without this flag
244*f6dc9357SAndroid Build Coastguard Worker // | OFN_PATHMUSTEXIST
245*f6dc9357SAndroid Build Coastguard Worker #ifdef UNDER_CE
246*f6dc9357SAndroid Build Coastguard Worker | (OpenFolderMode ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0)
247*f6dc9357SAndroid Build Coastguard Worker #endif
248*f6dc9357SAndroid Build Coastguard Worker ;
249*f6dc9357SAndroid Build Coastguard Worker const BOOL b = SaveMode ?
250*f6dc9357SAndroid Build Coastguard Worker ::GetSaveFileNameW((LPOPENFILENAMEW)(void *)&p) :
251*f6dc9357SAndroid Build Coastguard Worker ::GetOpenFileNameW((LPOPENFILENAMEW)(void *)&p);
252*f6dc9357SAndroid Build Coastguard Worker /* DOCs: lpstrFile :
253*f6dc9357SAndroid Build Coastguard Worker if the buffer is too small, then:
254*f6dc9357SAndroid Build Coastguard Worker - the function returns FALSE
255*f6dc9357SAndroid Build Coastguard Worker - the CommDlgExtendedError() returns FNERR_BUFFERTOOSMALL
256*f6dc9357SAndroid Build Coastguard Worker - the first two bytes of the lpstrFile buffer contain the
257*f6dc9357SAndroid Build Coastguard Worker required size, in bytes or characters. */
258*f6dc9357SAndroid Build Coastguard Worker if (!b)
259*f6dc9357SAndroid Build Coastguard Worker return false;
260*f6dc9357SAndroid Build Coastguard Worker {
261*f6dc9357SAndroid Build Coastguard Worker tempPath.ReleaseBuf_CalcLen(bufSize);
262*f6dc9357SAndroid Build Coastguard Worker FilePath = tempPath;
263*f6dc9357SAndroid Build Coastguard Worker FilterIndex = (int)p.nFilterIndex - 1;
264*f6dc9357SAndroid Build Coastguard Worker return true;
265*f6dc9357SAndroid Build Coastguard Worker }
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker }
268*f6dc9357SAndroid Build Coastguard Worker
269*f6dc9357SAndroid Build Coastguard Worker }
270