chore: initial commit (extracted from Launchers monorepo)
Plugin: ns7zip v2.0.0 Architectures: x86-ansi, x86-unicode, amd64-unicode License: LGPL-2.1-or-later
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
// Windows/CommonDialog.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../Common/MyBuffer.h"
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#include <commdlg.h>
|
||||
#endif
|
||||
|
||||
#ifndef _UNICODE
|
||||
#include "../Common/StringConvert.h"
|
||||
#endif
|
||||
|
||||
#include "CommonDialog.h"
|
||||
#include "Defs.h"
|
||||
// #include "FileDir.h"
|
||||
|
||||
#ifndef _UNICODE
|
||||
extern bool g_IsNT;
|
||||
#endif
|
||||
|
||||
namespace NWindows {
|
||||
|
||||
/*
|
||||
GetSaveFileName()
|
||||
GetOpenFileName()
|
||||
OPENFILENAME
|
||||
|
||||
(lpstrInitialDir) : the initial directory.
|
||||
DOCs: the algorithm for selecting the initial directory varies on different platforms:
|
||||
{
|
||||
Win2000/XP/Vista:
|
||||
1. If lpstrFile contains a path, that path is the initial directory.
|
||||
2. Otherwise, lpstrInitialDir specifies the initial directory.
|
||||
|
||||
Win7:
|
||||
If lpstrInitialDir has the same value as was passed the first time
|
||||
the application used an Open or Save As dialog box, the path
|
||||
most recently selected by the user is used as the initial directory.
|
||||
}
|
||||
|
||||
Win10:
|
||||
in:
|
||||
function supports (lpstrInitialDir) path with super prefix "\\\\?\\"
|
||||
function supports (lpstrInitialDir) path with long path
|
||||
function doesn't support absolute (lpstrFile) path with super prefix "\\\\?\\"
|
||||
function doesn't support absolute (lpstrFile) path with long path
|
||||
out: the path with super prefix "\\\\?\\" will be returned, if selected path is long
|
||||
|
||||
WinXP-64 and Win10: if no filters, the system shows all files.
|
||||
but DOCs say: If all three members are zero or NULL,
|
||||
the system does not use any filters and does not
|
||||
show any files in the file list control of the dialog box.
|
||||
|
||||
in Win7+: GetOpenFileName() and GetSaveFileName()
|
||||
do not support pstrCustomFilter feature anymore
|
||||
*/
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define MY_OFN_PROJECT 0x00400000
|
||||
#define MY_OFN_SHOW_ALL 0x01000000
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
structures
|
||||
OPENFILENAMEW
|
||||
OPENFILENAMEA
|
||||
contain additional members:
|
||||
#if (_WIN32_WINNT >= 0x0500)
|
||||
void *pvReserved;
|
||||
DWORD dwReserved;
|
||||
DWORD FlagsEx;
|
||||
#endif
|
||||
|
||||
If we compile the source code with (_WIN32_WINNT >= 0x0500), some functions
|
||||
will not work at NT 4.0, if we use sizeof(OPENFILENAME).
|
||||
We try to use reduced structure OPENFILENAME_NT4.
|
||||
*/
|
||||
|
||||
// #if defined(_WIN64) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0500)
|
||||
#if defined(__GNUC__) && (__GNUC__ <= 9) || defined(Z7_OLD_WIN_SDK)
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_OPENFILENAMEA OPENFILENAMEA
|
||||
#endif
|
||||
#define my_compatib_OPENFILENAMEW OPENFILENAMEW
|
||||
|
||||
// MinGW doesn't support some required macros. So we define them here:
|
||||
#ifndef CDSIZEOF_STRUCT
|
||||
#define CDSIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
|
||||
#endif
|
||||
#ifndef _UNICODE
|
||||
#ifndef OPENFILENAME_SIZE_VERSION_400A
|
||||
#define OPENFILENAME_SIZE_VERSION_400A CDSIZEOF_STRUCT(OPENFILENAMEA,lpTemplateName)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef OPENFILENAME_SIZE_VERSION_400W
|
||||
#define OPENFILENAME_SIZE_VERSION_400W CDSIZEOF_STRUCT(OPENFILENAMEW,lpTemplateName)
|
||||
#endif
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_OPENFILENAMEA_size OPENFILENAME_SIZE_VERSION_400A
|
||||
#endif
|
||||
#define my_compatib_OPENFILENAMEW_size OPENFILENAME_SIZE_VERSION_400W
|
||||
#else
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_OPENFILENAMEA OPENFILENAME_NT4A
|
||||
#define my_compatib_OPENFILENAMEA_size sizeof(my_compatib_OPENFILENAMEA)
|
||||
#endif
|
||||
#define my_compatib_OPENFILENAMEW OPENFILENAME_NT4W
|
||||
#define my_compatib_OPENFILENAMEW_size sizeof(my_compatib_OPENFILENAMEW)
|
||||
#endif
|
||||
/*
|
||||
#elif defined(UNDER_CE) || defined(_WIN64) || (_WIN32_WINNT < 0x0500)
|
||||
// || !defined(WINVER)
|
||||
#ifndef _UNICODE
|
||||
#define my_compatib_OPENFILENAMEA OPENFILENAMEA
|
||||
#define my_compatib_OPENFILENAMEA_size sizeof(OPENFILENAMEA)
|
||||
#endif
|
||||
#define my_compatib_OPENFILENAMEW OPENFILENAMEW
|
||||
#define my_compatib_OPENFILENAMEW_size sizeof(OPENFILENAMEW)
|
||||
#else
|
||||
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define CONV_U_To_A(dest, src, temp) AString temp; if (src) { temp = GetSystemString(src); dest = temp; }
|
||||
#endif
|
||||
|
||||
bool CCommonDialogInfo::CommonDlg_BrowseForFile(LPCWSTR lpstrInitialDir, const UStringVector &filters)
|
||||
{
|
||||
/* GetSaveFileName() and GetOpenFileName() could change current dir,
|
||||
if OFN_NOCHANGEDIR is not used.
|
||||
We can restore current dir manually, if it's required.
|
||||
22.02: we use OFN_NOCHANGEDIR. So we don't need to restore current dir manually. */
|
||||
// NFile::NDir::CCurrentDirRestorer curDirRestorer;
|
||||
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
AString tempPath;
|
||||
AStringVector f;
|
||||
unsigned i;
|
||||
for (i = 0; i < filters.Size(); i++)
|
||||
f.Add(GetSystemString(filters[i]));
|
||||
unsigned size = f.Size() + 1;
|
||||
for (i = 0; i < f.Size(); i++)
|
||||
size += f[i].Len();
|
||||
CObjArray<char> filterBuf(size);
|
||||
// memset(filterBuf, 0, size * sizeof(char));
|
||||
{
|
||||
char *dest = filterBuf;
|
||||
for (i = 0; i < f.Size(); i++)
|
||||
{
|
||||
const AString &s = f[i];
|
||||
MyStringCopy(dest, s);
|
||||
dest += s.Len() + 1;
|
||||
}
|
||||
*dest = 0;
|
||||
}
|
||||
my_compatib_OPENFILENAMEA p;
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.lStructSize = my_compatib_OPENFILENAMEA_size;
|
||||
p.hwndOwner = hwndOwner;
|
||||
if (size > 1)
|
||||
{
|
||||
p.lpstrFilter = filterBuf;
|
||||
p.nFilterIndex = (DWORD)(FilterIndex + 1);
|
||||
}
|
||||
|
||||
CONV_U_To_A(p.lpstrInitialDir, lpstrInitialDir, initialDir_a)
|
||||
CONV_U_To_A(p.lpstrTitle, lpstrTitle, title_a)
|
||||
|
||||
const AString filePath_a = GetSystemString(FilePath);
|
||||
const unsigned bufSize = MAX_PATH * 8
|
||||
+ filePath_a.Len()
|
||||
+ initialDir_a.Len();
|
||||
p.nMaxFile = bufSize;
|
||||
p.lpstrFile = tempPath.GetBuf(bufSize);
|
||||
MyStringCopy(p.lpstrFile, filePath_a);
|
||||
p.Flags =
|
||||
OFN_EXPLORER
|
||||
| OFN_HIDEREADONLY
|
||||
| OFN_NOCHANGEDIR;
|
||||
const BOOL b = SaveMode ?
|
||||
::GetSaveFileNameA((LPOPENFILENAMEA)(void *)&p) :
|
||||
::GetOpenFileNameA((LPOPENFILENAMEA)(void *)&p);
|
||||
if (!b)
|
||||
return false;
|
||||
{
|
||||
tempPath.ReleaseBuf_CalcLen(bufSize);
|
||||
FilePath = GetUnicodeString(tempPath);
|
||||
FilterIndex = (int)p.nFilterIndex - 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
UString tempPath;
|
||||
unsigned size = filters.Size() + 1;
|
||||
unsigned i;
|
||||
for (i = 0; i < filters.Size(); i++)
|
||||
size += filters[i].Len();
|
||||
CObjArray<wchar_t> filterBuf(size);
|
||||
// memset(filterBuf, 0, size * sizeof(wchar_t));
|
||||
{
|
||||
wchar_t *dest = filterBuf;
|
||||
for (i = 0; i < filters.Size(); i++)
|
||||
{
|
||||
const UString &s = filters[i];
|
||||
MyStringCopy(dest, s);
|
||||
dest += s.Len() + 1;
|
||||
}
|
||||
*dest = 0;
|
||||
// if ((unsigned)(dest + 1 - filterBuf) != size) return false;
|
||||
}
|
||||
my_compatib_OPENFILENAMEW p;
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.lStructSize = my_compatib_OPENFILENAMEW_size;
|
||||
p.hwndOwner = hwndOwner;
|
||||
if (size > 1)
|
||||
{
|
||||
p.lpstrFilter = filterBuf;
|
||||
p.nFilterIndex = (DWORD)(FilterIndex + 1);
|
||||
}
|
||||
unsigned bufSize = MAX_PATH * 8 + FilePath.Len();
|
||||
if (lpstrInitialDir)
|
||||
{
|
||||
p.lpstrInitialDir = lpstrInitialDir;
|
||||
bufSize += MyStringLen(lpstrInitialDir);
|
||||
}
|
||||
p.nMaxFile = bufSize;
|
||||
p.lpstrFile = tempPath.GetBuf(bufSize);
|
||||
MyStringCopy(p.lpstrFile, FilePath);
|
||||
p.lpstrTitle = lpstrTitle;
|
||||
p.Flags =
|
||||
OFN_EXPLORER
|
||||
| OFN_HIDEREADONLY
|
||||
| OFN_NOCHANGEDIR
|
||||
// | OFN_FORCESHOWHIDDEN // Win10 shows hidden items even without this flag
|
||||
// | OFN_PATHMUSTEXIST
|
||||
#ifdef UNDER_CE
|
||||
| (OpenFolderMode ? (MY_OFN_PROJECT | MY_OFN_SHOW_ALL) : 0)
|
||||
#endif
|
||||
;
|
||||
const BOOL b = SaveMode ?
|
||||
::GetSaveFileNameW((LPOPENFILENAMEW)(void *)&p) :
|
||||
::GetOpenFileNameW((LPOPENFILENAMEW)(void *)&p);
|
||||
/* DOCs: lpstrFile :
|
||||
if the buffer is too small, then:
|
||||
- the function returns FALSE
|
||||
- the CommDlgExtendedError() returns FNERR_BUFFERTOOSMALL
|
||||
- the first two bytes of the lpstrFile buffer contain the
|
||||
required size, in bytes or characters. */
|
||||
if (!b)
|
||||
return false;
|
||||
{
|
||||
tempPath.ReleaseBuf_CalcLen(bufSize);
|
||||
FilePath = tempPath;
|
||||
FilterIndex = (int)p.nFilterIndex - 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user