diff --git a/nfd/nfd_cocoa.m b/nfd/nfd_cocoa.m index d3fb4834..39a0931d 100644 --- a/nfd/nfd_cocoa.m +++ b/nfd/nfd_cocoa.m @@ -117,7 +117,7 @@ static nfdresult_t AllocPathSet( NSArray *urls, nfdpathset_t *pathset ) /* public */ -nfdresult_t NFD_OpenDialog( const char *filterList, +nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList, const nfdchar_t *defaultPath, nfdchar_t **outPath ) { @@ -146,6 +146,7 @@ nfdresult_t NFD_OpenDialog( const char *filterList, if ( !*outPath ) { [pool release]; + [keyWindow makeKeyAndOrderFront:nil]; return NFD_ERROR; } memcpy( *outPath, utf8Path, len+1 ); /* copy null term */ @@ -163,6 +164,7 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList, nfdpathset_t *outPaths ) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow]; NSOpenPanel *dialog = [NSOpenPanel openPanel]; [dialog setAllowsMultipleSelection:YES]; @@ -181,12 +183,14 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList, if ( [urls count] == 0 ) { [pool release]; + [keyWindow makeKeyAndOrderFront:nil]; return NFD_CANCEL; } if ( AllocPathSet( urls, outPaths ) == NFD_ERROR ) { [pool release]; + [keyWindow makeKeyAndOrderFront:nil]; return NFD_ERROR; } @@ -194,6 +198,7 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList, } [pool release]; + [keyWindow makeKeyAndOrderFront:nil]; return nfdResult; } @@ -203,7 +208,8 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, nfdchar_t **outPath ) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow]; + NSSavePanel *dialog = [NSSavePanel savePanel]; [dialog setExtensionHidden:NO]; @@ -225,6 +231,7 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, if ( !*outPath ) { [pool release]; + [keyWindow makeKeyAndOrderFront:nil]; return NFD_ERROR; } memcpy( *outPath, utf8Path, byteLen ); @@ -232,7 +239,7 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, } [pool release]; - + [keyWindow makeKeyAndOrderFront:nil]; return nfdResult; } @@ -241,7 +248,7 @@ nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath, { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow]; + NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow]; NSOpenPanel *dialog = [NSOpenPanel openPanel]; [dialog setAllowsMultipleSelection:NO]; [dialog setCanChooseDirectories:YES]; @@ -264,6 +271,7 @@ nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath, if ( !*outPath ) { [pool release]; + [keyWindow makeKeyAndOrderFront:nil]; return NFD_ERROR; } memcpy( *outPath, utf8Path, len+1 ); /* copy null term */ diff --git a/nfd/nfd_gtk.c b/nfd/nfd_gtk.c index 65bc41da..7a9958ed 100644 --- a/nfd/nfd_gtk.c +++ b/nfd/nfd_gtk.c @@ -165,7 +165,7 @@ static void WaitForCleanup(void) /* public */ -nfdresult_t NFD_OpenDialog( const char *filterList, +nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList, const nfdchar_t *defaultPath, nfdchar_t **outPath ) { diff --git a/nfd/nfd_win.cpp b/nfd/nfd_win.cpp index 37d9b774..f4c5e7a7 100644 --- a/nfd/nfd_win.cpp +++ b/nfd/nfd_win.cpp @@ -4,6 +4,10 @@ http://www.frogtoss.com/labs */ +#define _CRTDBG_MAP_ALLOC +#include +#include + /* only locally define UNICODE in this compilation unit */ #ifndef UNICODE #define UNICODE @@ -21,7 +25,7 @@ #include struct IUnknown; // Workaround for "combaseapi.h(229): error C2187: syntax error: 'identifier' was unexpected here" when using /permissive- -#include +#include #include "nfd_common.h" @@ -50,9 +54,9 @@ static void CopyWCharToNFDChar( const wchar_t *inStr, nfdchar_t **outStr ) /* includes NULL terminator byte in return */ static size_t GetUTF8ByteCountForWChar( const wchar_t *str ) { - int bytesNeeded = WideCharToMultiByte( CP_UTF8, 0, - str, -1, - NULL, 0, NULL, NULL ); + size_t bytesNeeded = WideCharToMultiByte( CP_UTF8, 0, + str, -1, + NULL, 0, NULL, NULL ); assert( bytesNeeded ); return bytesNeeded+1; } @@ -151,12 +155,12 @@ static nfdresult_t AddFiltersToDialog( ::IFileDialog *fileOpenDialog, const char } /* filterCount plus 1 because we hardcode the *.* wildcard after the while loop */ - COMDLG_FILTERSPEC *specList = (COMDLG_FILTERSPEC*)NFDi_Malloc( sizeof(COMDLG_FILTERSPEC) * (filterCount + 1) ); + COMDLG_FILTERSPEC *specList = (COMDLG_FILTERSPEC*)NFDi_Malloc( sizeof(COMDLG_FILTERSPEC) * ((size_t)filterCount + 1) ); if ( !specList ) { return NFD_ERROR; } - for (size_t i = 0; i < filterCount+1; ++i ) + for (UINT i = 0; i < filterCount+1; ++i ) { specList[i].pszName = NULL; specList[i].pszSpec = NULL; @@ -184,9 +188,8 @@ static nfdresult_t AddFiltersToDialog( ::IFileDialog *fileOpenDialog, const char if ( *p_filterList == ';' || *p_filterList == '\0' ) { /* end of filter -- add it to specList */ - - // Empty filter name -- Windows describes them by extension. - specList[specIdx].pszName = EMPTY_WSTR; + + CopyNFDCharToWChar( specbuf, (wchar_t**)&specList[specIdx].pszName ); CopyNFDCharToWChar( specbuf, (wchar_t**)&specList[specIdx].pszSpec ); memset( specbuf, 0, sizeof(char)*NFD_MAX_STRLEN ); @@ -206,7 +209,7 @@ static nfdresult_t AddFiltersToDialog( ::IFileDialog *fileOpenDialog, const char /* Add wildcard */ specList[specIdx].pszSpec = WILDCARD; - specList[specIdx].pszName = EMPTY_WSTR; + specList[specIdx].pszName = WILDCARD; fileOpenDialog->SetFileTypes( filterCount+1, specList ); @@ -273,6 +276,8 @@ static nfdresult_t AllocPathSet( IShellItemArray *shellItems, nfdpathset_t *path // Calculate length of name with UTF-8 encoding bufSize += GetUTF8ByteCountForWChar( name ); + + CoTaskMemFree(name); } assert(bufSize); @@ -307,6 +312,7 @@ static nfdresult_t AllocPathSet( IShellItemArray *shellItems, nfdpathset_t *path shellItem->GetDisplayName(SIGDN_FILESYSPATH, &name); int bytesWritten = CopyWCharToExistingNFDCharBuffer(name, p_buf); + CoTaskMemFree(name); ptrdiff_t index = p_buf - pathSet->buf; assert( index >= 0 ); @@ -356,29 +362,30 @@ static nfdresult_t SetDefaultPath( IFileDialog *dialog, const char *defaultPath /* public */ -nfdresult_t NFD_OpenDialog( const char *filterList, +nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList, const nfdchar_t *defaultPath, nfdchar_t **outPath ) { nfdresult_t nfdResult = NFD_ERROR; // Init COM library. - HRESULT result = ::CoInitializeEx(NULL, - ::COINIT_APARTMENTTHREADED | - ::COINIT_DISABLE_OLE1DDE ); + HRESULT coResult = ::CoInitializeEx(NULL, + ::COINIT_APARTMENTTHREADED | + ::COINIT_DISABLE_OLE1DDE ); ::IFileOpenDialog *fileOpenDialog(NULL); - if ( !SUCCEEDED(result)) + if ( !SUCCEEDED(coResult)) { + fileOpenDialog = NULL; NFDi_SetError("Could not initialize COM."); goto end; } // Create dialog - result = ::CoCreateInstance(::CLSID_FileOpenDialog, NULL, - CLSCTX_ALL, ::IID_IFileOpenDialog, - reinterpret_cast(&fileOpenDialog) ); + HRESULT result = ::CoCreateInstance(::CLSID_FileOpenDialog, NULL, + CLSCTX_ALL, ::IID_IFileOpenDialog, + reinterpret_cast(&fileOpenDialog) ); if ( !SUCCEEDED(result) ) { @@ -415,6 +422,7 @@ nfdresult_t NFD_OpenDialog( const char *filterList, if ( !SUCCEEDED(result) ) { NFDi_SetError("Could not get file path for selected."); + shellItem->Release(); goto end; } @@ -423,6 +431,7 @@ nfdresult_t NFD_OpenDialog( const char *filterList, if ( !*outPath ) { /* error is malloc-based, error message would be redundant */ + shellItem->Release(); goto end; } @@ -439,8 +448,12 @@ nfdresult_t NFD_OpenDialog( const char *filterList, nfdResult = NFD_ERROR; } - end: - ::CoUninitialize(); +end: + if (fileOpenDialog) + fileOpenDialog->Release(); + + if (SUCCEEDED(coResult)) + ::CoUninitialize(); return nfdResult; } @@ -452,10 +465,10 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList, nfdresult_t nfdResult = NFD_ERROR; // Init COM library. - HRESULT result = ::CoInitializeEx(NULL, - ::COINIT_APARTMENTTHREADED | - ::COINIT_DISABLE_OLE1DDE ); - if ( !SUCCEEDED(result)) + HRESULT coResult = ::CoInitializeEx(NULL, + ::COINIT_APARTMENTTHREADED | + ::COINIT_DISABLE_OLE1DDE ); + if ( !SUCCEEDED(coResult)) { NFDi_SetError("Could not initialize COM."); return NFD_ERROR; @@ -464,12 +477,13 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList, ::IFileOpenDialog *fileOpenDialog(NULL); // Create dialog - result = ::CoCreateInstance(::CLSID_FileOpenDialog, NULL, - CLSCTX_ALL, ::IID_IFileOpenDialog, - reinterpret_cast(&fileOpenDialog) ); + HRESULT result = ::CoCreateInstance(::CLSID_FileOpenDialog, NULL, + CLSCTX_ALL, ::IID_IFileOpenDialog, + reinterpret_cast(&fileOpenDialog) ); if ( !SUCCEEDED(result) ) { + fileOpenDialog = NULL; NFDi_SetError("Could not create dialog."); goto end; } @@ -515,6 +529,7 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList, if ( AllocPathSet( shellItems, outPaths ) == NFD_ERROR ) { + shellItems->Release(); goto end; } @@ -531,8 +546,12 @@ nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList, nfdResult = NFD_ERROR; } - end: - ::CoUninitialize(); +end: + if ( fileOpenDialog ) + fileOpenDialog->Release(); + + if (SUCCEEDED(coResult)) + ::CoUninitialize(); return nfdResult; } @@ -544,10 +563,10 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, nfdresult_t nfdResult = NFD_ERROR; // Init COM library. - HRESULT result = ::CoInitializeEx(NULL, - ::COINIT_APARTMENTTHREADED | - ::COINIT_DISABLE_OLE1DDE ); - if ( !SUCCEEDED(result)) + HRESULT coResult = ::CoInitializeEx(NULL, + ::COINIT_APARTMENTTHREADED | + ::COINIT_DISABLE_OLE1DDE ); + if ( !SUCCEEDED(coResult)) { NFDi_SetError("Could not initialize COM."); return NFD_ERROR; @@ -556,12 +575,13 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, ::IFileSaveDialog *fileSaveDialog(NULL); // Create dialog - result = ::CoCreateInstance(::CLSID_FileSaveDialog, NULL, - CLSCTX_ALL, ::IID_IFileSaveDialog, - reinterpret_cast(&fileSaveDialog) ); + HRESULT result = ::CoCreateInstance(::CLSID_FileSaveDialog, NULL, + CLSCTX_ALL, ::IID_IFileSaveDialog, + reinterpret_cast(&fileSaveDialog) ); if ( !SUCCEEDED(result) ) { + fileSaveDialog = NULL; NFDi_SetError("Could not create dialog."); goto end; } @@ -594,6 +614,7 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, result = shellItem->GetDisplayName(::SIGDN_FILESYSPATH, &filePath); if ( !SUCCEEDED(result) ) { + shellItem->Release(); NFDi_SetError("Could not get file path for selected."); goto end; } @@ -603,6 +624,7 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, if ( !*outPath ) { /* error is malloc-based, error message would be redundant */ + shellItem->Release(); goto end; } @@ -619,8 +641,12 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList, nfdResult = NFD_ERROR; } - end: - ::CoUninitialize(); +end: + if ( fileSaveDialog ) + fileSaveDialog->Release(); + + if (SUCCEEDED(coResult)) + ::CoUninitialize(); return nfdResult; } @@ -732,7 +758,8 @@ nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath, ComPtr pShellItem; if (!SUCCEEDED(pFileDialog->GetResult(&pShellItem))) { - return NFD_OKAY; + NFDi_SetError("Could not get shell item from dialog."); + return NFD_ERROR; } // Finally get the path