Ver Fonte

3rdparty: update nativefiledialog

Daniele Bartolini há 6 anos atrás
pai
commit
6232523ee8

+ 3 - 1
3rdparty/nativefiledialog/src/nfd_cocoa.m

@@ -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;

+ 3 - 3
3rdparty/nativefiledialog/src/nfd_common.c

@@ -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. */

+ 3 - 1
3rdparty/nativefiledialog/src/nfd_common.h

@@ -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

+ 126 - 144
3rdparty/nativefiledialog/src/nfd_win.cpp

@@ -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) )
+    {
+        // 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 (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
     {
-        return NFD_CANCEL;
+        nfdResult = NFD_CANCEL;
     }
-    else if (!SUCCEEDED(result))
+    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;
 }

+ 1 - 5
3rdparty/nativefiledialog/src/nfd_zenity.c

@@ -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);
     

+ 7 - 3
3rdparty/nativefiledialog/src/simple_exec.h

@@ -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: