mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-27 08:09:31 +00:00
update NFD to 67345b80eb
This commit is contained in:
parent
a5f3e70653
commit
166128dd73
7 changed files with 170 additions and 171 deletions
|
|
@ -47,16 +47,20 @@ int main( void )
|
|||
}
|
||||
```
|
||||
|
||||
See [NFD.h](src/include/nfd.h) for more options.
|
||||
See self-documenting API [NFD.h](src/include/nfd.h) for more options.
|
||||
|
||||
# Screenshots #
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
## Changelog ##
|
||||
|
||||
- **Major** version increments denote API or ABI departure.
|
||||
- **Minor** version increments denote build or trivial departures.
|
||||
- **Micro** version increments just recompile and drop-in.
|
||||
|
||||
release | what's new | date
|
||||
--------|-----------------------------|---------
|
||||
1.0.0 | initial | oct 2014
|
||||
|
|
@ -64,11 +68,15 @@ release | what's new | date
|
|||
1.1.1 | mingw support, build fixes | aug 2016
|
||||
1.1.2 | test_pickfolder() added | aug 2016
|
||||
1.1.3 | zenity linux backend added | nov 2017
|
||||
1.1.3 | fix char type in decls | nov 2017
|
||||
<i></i> | fix char type in decls | nov 2017
|
||||
1.1.4 | fix win32 memleaks | dec 2018
|
||||
1.1.4 | improve win32 errorhandling | dec 2018
|
||||
1.1.4 | macos fix focus bug | dec 2018
|
||||
|
||||
<i></i> | improve win32 errorhandling | dec 2018
|
||||
<i></i> | macos fix focus bug | dec 2018
|
||||
1.1.5 | win32 fix com reinitialize | aug 2019
|
||||
1.1.6 | fix osx filter bug | aug 2019
|
||||
<i></i> | remove deprecated scons | aug 2019
|
||||
<i></i> | fix mingw compilation | aug 2019
|
||||
<i></i> | -Wextra warning cleanup | aug 2019
|
||||
|
||||
## Building ##
|
||||
|
||||
|
|
@ -76,13 +84,13 @@ NFD uses [Premake5](https://premake.github.io/download.html) generated Makefiles
|
|||
|
||||
If you need to run Premake5 directly, further [build documentation](docs/build.md) is available.
|
||||
|
||||
Previously, NFD used SCons to build. It still works, but is now deprecated; updates to it are discouraged. Opt to use the native build system where possible.
|
||||
Previously, NFD used SCons to build. As of 1.1.6, SCons support has been removed entirely.
|
||||
|
||||
`nfd.a` will be built for release builds, and `nfd_d.a` will be built for debug builds.
|
||||
|
||||
### Makefiles ###
|
||||
|
||||
The makefile offers five options, with `release_x64` as the default.
|
||||
The makefile offers up to four options, with `release_x64` as the default.
|
||||
|
||||
make config=release_x86
|
||||
make config=release_x64
|
||||
|
|
@ -96,6 +104,7 @@ The makefile offers five options, with `release_x64` as the default.
|
|||
3. Add `build/<debug|release>/<arch>` to the library search path.
|
||||
|
||||
#### Linux GTK ####
|
||||
|
||||
`apt-get libgtk-3-dev` installs the gtk dependency for library compilation.
|
||||
|
||||
On Linux, you have the option of compiling and linking against GTK. If you use it, the recommended way to compile is to include the arguments of `pkg-config --cflags --libs gtk+-3.0`.
|
||||
|
|
@ -105,16 +114,18 @@ On Linux, you have the option of compiling and linking against GTK. If you use
|
|||
Alternatively, you can use the Zenity backend by running the Makefile in `build/gmake_linux_zenity`. Zenity runs the dialog in its own address space, but requires the user to have Zenity correctly installed and configured on their system.
|
||||
|
||||
#### MacOS ####
|
||||
|
||||
On Mac OS, add `AppKit` to the list of frameworks.
|
||||
|
||||
#### Windows ####
|
||||
On Windows, ensure you are building against `comctl32.lib`.
|
||||
|
||||
On Windows, ensure you are linking against `comctl32.lib`.
|
||||
|
||||
## Usage ##
|
||||
|
||||
See `NFD.h` for API calls. See `tests/*.c` for example code.
|
||||
|
||||
After compiling, `build/bin` contains compiled test programs.
|
||||
After compiling, `build/bin` contains compiled test programs. The appropriate subdirectory under `build/lib` contains the built library.
|
||||
|
||||
## File Filter Syntax ##
|
||||
|
||||
|
|
@ -141,14 +152,16 @@ See [test_opendialogmultiple.c](test/test_opendialogmultiple.c).
|
|||
|
||||
# Known Limitations #
|
||||
|
||||
I accept quality code patches, or will resolve these and other matters through support. See [submitting pull requests](docs/submitting_pull_requests.md) for details.
|
||||
I accept quality code patches, or will resolve these and other matters through support. See [contributing](docs/contributing.md) for details.
|
||||
|
||||
- No support for Windows XP's legacy dialogs such as `GetOpenFileName`.
|
||||
- No support for file filter names -- ex: "Image Files" (*.png, *.jpg). Nameless filters are supported, however.
|
||||
- GTK Zenity implementation's process exec error handling does not gracefully handle numerous error cases, choosing to abort rather than cleanup and return.
|
||||
- GTK 3 spams one warning per dialog created.
|
||||
|
||||
# Copyright and Credit #
|
||||
|
||||
Copyright © 2014-2017 [Frogtoss Games](http://www.frogtoss.com), Inc.
|
||||
Copyright © 2014-2019 [Frogtoss Games](http://www.frogtoss.com), Inc.
|
||||
File [LICENSE](LICENSE) covers all files in this repo.
|
||||
|
||||
Native File Dialog by Michael Labbe
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ static NSArray *BuildAllowedFileTypes( const char *filterList )
|
|||
{
|
||||
if ( filterList[i] == ',' || filterList[i] == ';' || filterList[i] == '\0' )
|
||||
{
|
||||
++p_typebuf;
|
||||
if (filterList[i] != '\0')
|
||||
++p_typebuf;
|
||||
*p_typebuf = '\0';
|
||||
|
||||
NSString *thisType = [NSString stringWithUTF8String: typebuf];
|
||||
[buildFilterList addObject:thisType];
|
||||
p_typebuf = typebuf;
|
||||
|
|
|
|||
|
|
@ -92,13 +92,13 @@ int NFDi_SafeStrncpy( char *dst, const char *src, size_t maxCopy )
|
|||
|
||||
|
||||
/* adapted from microutf8 */
|
||||
size_t NFDi_UTF8_Strlen( const nfdchar_t *str )
|
||||
int32_t NFDi_UTF8_Strlen( const nfdchar_t *str )
|
||||
{
|
||||
/* This function doesn't properly check validity of UTF-8 character
|
||||
sequence, it is supposed to use only with valid UTF-8 strings. */
|
||||
|
||||
size_t character_count = 0;
|
||||
size_t i = 0; /* Counter used to iterate over string. */
|
||||
int32_t character_count = 0;
|
||||
int32_t i = 0; /* Counter used to iterate over string. */
|
||||
nfdchar_t maybe_bom[4];
|
||||
|
||||
/* If there is UTF-8 BOM ignore it. */
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "nfd.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
@ -26,7 +28,7 @@ void *NFDi_Malloc( size_t bytes );
|
|||
void NFDi_Free( void *ptr );
|
||||
void NFDi_SetError( const char *msg );
|
||||
int NFDi_SafeStrncpy( char *dst, const char *src, size_t maxCopy );
|
||||
size_t NFDi_UTF8_Strlen( const nfdchar_t *str );
|
||||
int32_t NFDi_UTF8_Strlen( const nfdchar_t *str );
|
||||
int NFDi_IsFilterSegmentChar( char ch );
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -4,14 +4,6 @@
|
|||
http://www.frogtoss.com/labs
|
||||
*/
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
/* only locally define UNICODE in this compilation unit */
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
// Explicitly setting NTDDI version, this is necessary for the MinGW compiler
|
||||
|
|
@ -19,6 +11,15 @@
|
|||
#define _WIN32_WINNT _WIN32_WINNT_VISTA
|
||||
#endif
|
||||
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
/* only locally define UNICODE in this compilation unit */
|
||||
#ifndef UNICODE
|
||||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
|
@ -27,6 +28,33 @@
|
|||
#include "nfd_common.h"
|
||||
|
||||
|
||||
#define COM_INITFLAGS ::COINIT_APARTMENTTHREADED | ::COINIT_DISABLE_OLE1DDE
|
||||
|
||||
static BOOL COMIsInitialized(HRESULT coResult)
|
||||
{
|
||||
if (coResult == RPC_E_CHANGED_MODE)
|
||||
{
|
||||
// If COM was previously initialized with different init flags,
|
||||
// NFD still needs to operate. Eat this warning.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return SUCCEEDED(coResult);
|
||||
}
|
||||
|
||||
static HRESULT COMInit(void)
|
||||
{
|
||||
return ::CoInitializeEx(NULL, COM_INITFLAGS);
|
||||
}
|
||||
|
||||
static void COMUninit(HRESULT coResult)
|
||||
{
|
||||
// do not uninitialize if RPC_E_CHANGED_MODE occurred -- this
|
||||
// case does not refcount COM.
|
||||
if (SUCCEEDED(coResult))
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
// allocs the space in outPath -- call free()
|
||||
static void CopyWCharToNFDChar( const wchar_t *inStr, nfdchar_t **outStr )
|
||||
{
|
||||
|
|
@ -58,11 +86,9 @@ static size_t GetUTF8ByteCountForWChar( const wchar_t *str )
|
|||
return bytesNeeded+1;
|
||||
}
|
||||
|
||||
// write to outPtr -- no free() necessary. No memory stomp tests are done -- they must be done
|
||||
// before entering this function.
|
||||
// write to outPtr -- no free() necessary.
|
||||
static int CopyWCharToExistingNFDCharBuffer( const wchar_t *inStr, nfdchar_t *outPtr )
|
||||
{
|
||||
int inStrCharacterCount = static_cast<int>(wcslen(inStr));
|
||||
int bytesNeeded = static_cast<int>(GetUTF8ByteCountForWChar( inStr ));
|
||||
|
||||
/* invocation copies null term */
|
||||
|
|
@ -120,7 +146,8 @@ static int AppendExtensionToSpecBuf( const char *ext, char *specBuf, size_t spec
|
|||
|
||||
char extWildcard[NFD_MAX_STRLEN];
|
||||
int bytesWritten = sprintf_s( extWildcard, NFD_MAX_STRLEN, "*.%s", ext );
|
||||
assert( bytesWritten == strlen(ext)+2 );
|
||||
assert( bytesWritten == (int)(strlen(ext)+2) );
|
||||
_NFD_UNUSED(bytesWritten);
|
||||
|
||||
strncat( specBuf, extWildcard, specBufLen - strlen(specBuf) - 1 );
|
||||
|
||||
|
|
@ -129,7 +156,6 @@ static int AppendExtensionToSpecBuf( const char *ext, char *specBuf, size_t spec
|
|||
|
||||
static nfdresult_t AddFiltersToDialog( ::IFileDialog *fileOpenDialog, const char *filterList )
|
||||
{
|
||||
const wchar_t EMPTY_WSTR[] = L"";
|
||||
const wchar_t WILDCARD[] = L"*.*";
|
||||
|
||||
if ( !filterList || strlen(filterList) == 0 )
|
||||
|
|
@ -167,7 +193,6 @@ static nfdresult_t AddFiltersToDialog( ::IFileDialog *fileOpenDialog, const char
|
|||
p_filterList = filterList;
|
||||
char typebuf[NFD_MAX_STRLEN] = {0}; /* one per comma or semicolon */
|
||||
char *p_typebuf = typebuf;
|
||||
char filterName[NFD_MAX_STRLEN] = {0};
|
||||
|
||||
char specbuf[NFD_MAX_STRLEN] = {0}; /* one per semicolon */
|
||||
|
||||
|
|
@ -364,22 +389,17 @@ nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList,
|
|||
nfdchar_t **outPath )
|
||||
{
|
||||
nfdresult_t nfdResult = NFD_ERROR;
|
||||
|
||||
|
||||
// Init COM library.
|
||||
HRESULT coResult = ::CoInitializeEx(NULL,
|
||||
::COINIT_APARTMENTTHREADED |
|
||||
::COINIT_DISABLE_OLE1DDE );
|
||||
|
||||
::IFileOpenDialog *fileOpenDialog(NULL);
|
||||
|
||||
if ( !SUCCEEDED(coResult))
|
||||
{
|
||||
fileOpenDialog = NULL;
|
||||
HRESULT coResult = COMInit();
|
||||
if (!COMIsInitialized(coResult))
|
||||
{
|
||||
NFDi_SetError("Could not initialize COM.");
|
||||
goto end;
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
// Create dialog
|
||||
::IFileOpenDialog *fileOpenDialog(NULL);
|
||||
HRESULT result = ::CoCreateInstance(::CLSID_FileOpenDialog, NULL,
|
||||
CLSCTX_ALL, ::IID_IFileOpenDialog,
|
||||
reinterpret_cast<void**>(&fileOpenDialog) );
|
||||
|
|
@ -449,8 +469,7 @@ end:
|
|||
if (fileOpenDialog)
|
||||
fileOpenDialog->Release();
|
||||
|
||||
if (SUCCEEDED(coResult))
|
||||
::CoUninitialize();
|
||||
COMUninit(coResult);
|
||||
|
||||
return nfdResult;
|
||||
}
|
||||
|
|
@ -460,20 +479,17 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList,
|
|||
nfdpathset_t *outPaths )
|
||||
{
|
||||
nfdresult_t nfdResult = NFD_ERROR;
|
||||
|
||||
// Init COM library.
|
||||
HRESULT coResult = ::CoInitializeEx(NULL,
|
||||
::COINIT_APARTMENTTHREADED |
|
||||
::COINIT_DISABLE_OLE1DDE );
|
||||
if ( !SUCCEEDED(coResult))
|
||||
|
||||
|
||||
HRESULT coResult = COMInit();
|
||||
if (!COMIsInitialized(coResult))
|
||||
{
|
||||
NFDi_SetError("Could not initialize COM.");
|
||||
return NFD_ERROR;
|
||||
NFDi_SetError("Could not initialize COM.");
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
::IFileOpenDialog *fileOpenDialog(NULL);
|
||||
|
||||
// Create dialog
|
||||
::IFileOpenDialog *fileOpenDialog(NULL);
|
||||
HRESULT result = ::CoCreateInstance(::CLSID_FileOpenDialog, NULL,
|
||||
CLSCTX_ALL, ::IID_IFileOpenDialog,
|
||||
reinterpret_cast<void**>(&fileOpenDialog) );
|
||||
|
|
@ -547,8 +563,7 @@ end:
|
|||
if ( fileOpenDialog )
|
||||
fileOpenDialog->Release();
|
||||
|
||||
if (SUCCEEDED(coResult))
|
||||
::CoUninitialize();
|
||||
COMUninit(coResult);
|
||||
|
||||
return nfdResult;
|
||||
}
|
||||
|
|
@ -558,20 +573,16 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
|
|||
nfdchar_t **outPath )
|
||||
{
|
||||
nfdresult_t nfdResult = NFD_ERROR;
|
||||
|
||||
// Init COM library.
|
||||
HRESULT coResult = ::CoInitializeEx(NULL,
|
||||
::COINIT_APARTMENTTHREADED |
|
||||
::COINIT_DISABLE_OLE1DDE );
|
||||
if ( !SUCCEEDED(coResult))
|
||||
|
||||
HRESULT coResult = COMInit();
|
||||
if (!COMIsInitialized(coResult))
|
||||
{
|
||||
NFDi_SetError("Could not initialize COM.");
|
||||
return NFD_ERROR;
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
::IFileSaveDialog *fileSaveDialog(NULL);
|
||||
|
||||
|
||||
// Create dialog
|
||||
::IFileSaveDialog *fileSaveDialog(NULL);
|
||||
HRESULT result = ::CoCreateInstance(::CLSID_FileSaveDialog, NULL,
|
||||
CLSCTX_ALL, ::IID_IFileSaveDialog,
|
||||
reinterpret_cast<void**>(&fileSaveDialog) );
|
||||
|
|
@ -642,139 +653,110 @@ end:
|
|||
if ( fileSaveDialog )
|
||||
fileSaveDialog->Release();
|
||||
|
||||
if (SUCCEEDED(coResult))
|
||||
::CoUninitialize();
|
||||
|
||||
COMUninit(coResult);
|
||||
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
class AutoCoInit
|
||||
{
|
||||
public:
|
||||
AutoCoInit()
|
||||
{
|
||||
mResult = ::CoInitializeEx(NULL,
|
||||
::COINIT_APARTMENTTHREADED |
|
||||
::COINIT_DISABLE_OLE1DDE);
|
||||
}
|
||||
|
||||
~AutoCoInit()
|
||||
{
|
||||
if (SUCCEEDED(mResult))
|
||||
{
|
||||
::CoUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Result() const { return mResult; }
|
||||
private:
|
||||
HRESULT mResult;
|
||||
};
|
||||
|
||||
// VS2010 hasn't got a copy of CComPtr - this was first added in the 2003 SDK, so we make our own small CComPtr instead
|
||||
template<class T>
|
||||
class ComPtr
|
||||
{
|
||||
public:
|
||||
ComPtr() : mPtr(NULL) { }
|
||||
~ComPtr()
|
||||
{
|
||||
if (mPtr)
|
||||
{
|
||||
mPtr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
T* Ptr() const { return mPtr; }
|
||||
T** operator&() { return &mPtr; }
|
||||
T* operator->() const { return mPtr; }
|
||||
private:
|
||||
// Don't allow copy or assignment
|
||||
ComPtr(const ComPtr&);
|
||||
ComPtr& operator = (const ComPtr&) const;
|
||||
T* mPtr;
|
||||
};
|
||||
|
||||
nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
|
||||
nfdchar_t **outPath)
|
||||
{
|
||||
// Init COM
|
||||
AutoCoInit autoCoInit;
|
||||
if (!SUCCEEDED(autoCoInit.Result()))
|
||||
nfdresult_t nfdResult = NFD_ERROR;
|
||||
DWORD dwOptions = 0;
|
||||
|
||||
HRESULT coResult = COMInit();
|
||||
if (!COMIsInitialized(coResult))
|
||||
{
|
||||
NFDi_SetError("CoInitializeEx failed.");
|
||||
return NFD_ERROR;
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
// Create the file dialog COM object
|
||||
ComPtr<IFileDialog> pFileDialog;
|
||||
if (!SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog,
|
||||
NULL,
|
||||
CLSCTX_ALL,
|
||||
IID_PPV_ARGS(&pFileDialog))))
|
||||
{
|
||||
// Create dialog
|
||||
::IFileOpenDialog *fileDialog(NULL);
|
||||
HRESULT result = CoCreateInstance(CLSID_FileOpenDialog,
|
||||
NULL,
|
||||
CLSCTX_ALL,
|
||||
IID_PPV_ARGS(&fileDialog));
|
||||
if ( !SUCCEEDED(result) )
|
||||
{
|
||||
NFDi_SetError("CoCreateInstance for CLSID_FileOpenDialog failed.");
|
||||
return NFD_ERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Set the default path
|
||||
if (SetDefaultPath(pFileDialog.Ptr(), defaultPath) != NFD_OKAY)
|
||||
if (SetDefaultPath(fileDialog, defaultPath) != NFD_OKAY)
|
||||
{
|
||||
NFDi_SetError("SetDefaultPath failed.");
|
||||
return NFD_ERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Get the dialogs options
|
||||
DWORD dwOptions = 0;
|
||||
if (!SUCCEEDED(pFileDialog->GetOptions(&dwOptions)))
|
||||
if (!SUCCEEDED(fileDialog->GetOptions(&dwOptions)))
|
||||
{
|
||||
NFDi_SetError("GetOptions for IFileDialog failed.");
|
||||
return NFD_ERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Add in FOS_PICKFOLDERS which hides files and only allows selection of folders
|
||||
if (!SUCCEEDED(pFileDialog->SetOptions(dwOptions | FOS_PICKFOLDERS)))
|
||||
if (!SUCCEEDED(fileDialog->SetOptions(dwOptions | FOS_PICKFOLDERS)))
|
||||
{
|
||||
NFDi_SetError("SetOptions for IFileDialog failed.");
|
||||
return NFD_ERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
// Show the dialog to the user
|
||||
const HRESULT result = pFileDialog->Show(NULL);
|
||||
if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED))
|
||||
result = fileDialog->Show(NULL);
|
||||
if ( SUCCEEDED(result) )
|
||||
{
|
||||
return NFD_CANCEL;
|
||||
// Get the folder name
|
||||
::IShellItem *shellItem(NULL);
|
||||
|
||||
result = fileDialog->GetResult(&shellItem);
|
||||
if ( !SUCCEEDED(result) )
|
||||
{
|
||||
NFDi_SetError("Could not get file path for selected.");
|
||||
shellItem->Release();
|
||||
goto end;
|
||||
}
|
||||
|
||||
wchar_t *path = NULL;
|
||||
result = shellItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &path);
|
||||
if ( !SUCCEEDED(result) )
|
||||
{
|
||||
NFDi_SetError("GetDisplayName for IShellItem failed.");
|
||||
shellItem->Release();
|
||||
goto end;
|
||||
}
|
||||
|
||||
CopyWCharToNFDChar(path, outPath);
|
||||
CoTaskMemFree(path);
|
||||
if ( !*outPath )
|
||||
{
|
||||
shellItem->Release();
|
||||
goto end;
|
||||
}
|
||||
|
||||
nfdResult = NFD_OKAY;
|
||||
shellItem->Release();
|
||||
}
|
||||
else if (!SUCCEEDED(result))
|
||||
else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
||||
{
|
||||
nfdResult = NFD_CANCEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
NFDi_SetError("Show for IFileDialog failed.");
|
||||
return NFD_ERROR;
|
||||
nfdResult = NFD_ERROR;
|
||||
}
|
||||
|
||||
// Get the shell item result
|
||||
ComPtr<IShellItem> pShellItem;
|
||||
if (!SUCCEEDED(pFileDialog->GetResult(&pShellItem)))
|
||||
{
|
||||
NFDi_SetError("Could not get shell item from dialog.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
end:
|
||||
|
||||
// Finally get the path
|
||||
wchar_t *path = NULL;
|
||||
if (!SUCCEEDED(pShellItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &path)))
|
||||
{
|
||||
NFDi_SetError("GetDisplayName for IShellItem failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
if (fileDialog)
|
||||
fileDialog->Release();
|
||||
|
||||
// Convert string
|
||||
CopyWCharToNFDChar(path, outPath);
|
||||
CoTaskMemFree(path);
|
||||
if (!*outPath)
|
||||
{
|
||||
// error is malloc-based, error message would be redundant
|
||||
return NFD_ERROR;
|
||||
}
|
||||
COMUninit(coResult);
|
||||
|
||||
return NFD_OKAY;
|
||||
return nfdResult;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ static nfdresult_t ZenityCommon(char** command, int commandLen, const char* defa
|
|||
{
|
||||
if(defaultPath != NULL)
|
||||
{
|
||||
char* prefix = "--filename";
|
||||
char* prefix = "--filename=";
|
||||
int len = strlen(prefix) + strlen(defaultPath) + 1;
|
||||
|
||||
char* tmp = (char*) calloc(len, 1);
|
||||
|
|
@ -133,10 +133,6 @@ static nfdresult_t ZenityCommon(char** command, int commandLen, const char* defa
|
|||
|
||||
static nfdresult_t AllocPathSet(char* zenityList, nfdpathset_t *pathSet )
|
||||
{
|
||||
size_t bufSize = 0;
|
||||
nfdchar_t *p_buf;
|
||||
size_t count = 0;
|
||||
|
||||
assert(zenityList);
|
||||
assert(pathSet);
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ int runCommandArray(char** stdOut, int* stdOutByteCount, int* returnCode, int in
|
|||
#include <stdarg.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define release_assert(x) do { int __release_assert_tmp__ = (x); assert(__release_assert_tmp__); } while(0)
|
||||
#define release_assert(exp) { if (!(exp)) { abort(); } }
|
||||
|
||||
enum PIPE_FILE_DESCRIPTORS
|
||||
{
|
||||
|
|
@ -70,6 +70,7 @@ int runCommandArray(char** stdOut, int* stdOutByteCount, int* returnCode, int in
|
|||
case -1:
|
||||
{
|
||||
release_assert(0 && "Fork failed");
|
||||
break;
|
||||
}
|
||||
|
||||
case 0: // child
|
||||
|
|
@ -96,7 +97,8 @@ int runCommandArray(char** stdOut, int* stdOutByteCount, int* returnCode, int in
|
|||
execvp(command, allArgs);
|
||||
|
||||
char err = 1;
|
||||
write(errPipe[WRITE_FD], &err, 1);
|
||||
ssize_t result = write(errPipe[WRITE_FD], &err, 1);
|
||||
release_assert(result != -1);
|
||||
|
||||
close(errPipe[WRITE_FD]);
|
||||
close(parentToChild[READ_FD]);
|
||||
|
|
@ -128,7 +130,8 @@ int runCommandArray(char** stdOut, int* stdOutByteCount, int* returnCode, int in
|
|||
release_assert(close(childToParent[READ_FD]) == 0);
|
||||
|
||||
char errChar = 0;
|
||||
read(errPipe[READ_FD], &errChar, 1);
|
||||
ssize_t result = read(errPipe[READ_FD], &errChar, 1);
|
||||
release_assert(result != -1);
|
||||
close(errPipe[READ_FD]);
|
||||
|
||||
if(errChar)
|
||||
|
|
@ -156,6 +159,7 @@ int runCommandArray(char** stdOut, int* stdOutByteCount, int* returnCode, int in
|
|||
case -1:
|
||||
{
|
||||
release_assert(0 && "read() failed");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue