|
|
@@ -26,79 +26,79 @@ static char g_errorstr[NFD_MAX_STRLEN] = {0};
|
|
|
|
|
|
const char *NFD_GetError( void )
|
|
|
{
|
|
|
- return g_errorstr;
|
|
|
+ return g_errorstr;
|
|
|
}
|
|
|
|
|
|
size_t NFD_PathSet_GetCount( const nfdpathset_t *pathset )
|
|
|
{
|
|
|
- assert(pathset);
|
|
|
- return pathset->count;
|
|
|
+ assert(pathset);
|
|
|
+ return pathset->count;
|
|
|
}
|
|
|
|
|
|
nfdchar_t *NFD_PathSet_GetPath( const nfdpathset_t *pathset, size_t num )
|
|
|
{
|
|
|
- assert(pathset);
|
|
|
- assert(num < pathset->count);
|
|
|
+ assert(pathset);
|
|
|
+ assert(num < pathset->count);
|
|
|
|
|
|
- return pathset->buf + pathset->indices[num];
|
|
|
+ return pathset->buf + pathset->indices[num];
|
|
|
}
|
|
|
|
|
|
void NFD_PathSet_Free( nfdpathset_t *pathset )
|
|
|
{
|
|
|
- assert(pathset);
|
|
|
- NFDi_Free( pathset->indices );
|
|
|
- NFDi_Free( pathset->buf );
|
|
|
+ assert(pathset);
|
|
|
+ NFDi_Free( pathset->indices );
|
|
|
+ NFDi_Free( pathset->buf );
|
|
|
}
|
|
|
|
|
|
/* internal routines */
|
|
|
|
|
|
void *NFDi_Malloc( size_t bytes )
|
|
|
{
|
|
|
- void *ptr = malloc(bytes);
|
|
|
- if ( !ptr )
|
|
|
- NFDi_SetError("NFDi_Malloc failed.");
|
|
|
+ void *ptr = malloc(bytes);
|
|
|
+ if ( !ptr )
|
|
|
+ NFDi_SetError("NFDi_Malloc failed.");
|
|
|
|
|
|
- return ptr;
|
|
|
+ return ptr;
|
|
|
}
|
|
|
|
|
|
void NFDi_Free( void *ptr )
|
|
|
{
|
|
|
- assert(ptr);
|
|
|
- free(ptr);
|
|
|
+ assert(ptr);
|
|
|
+ free(ptr);
|
|
|
}
|
|
|
|
|
|
void NFDi_SetError( const char *msg )
|
|
|
{
|
|
|
- int bTruncate = NFDi_SafeStrncpy( g_errorstr, msg, NFD_MAX_STRLEN );
|
|
|
- assert( !bTruncate ); _NFD_UNUSED(bTruncate);
|
|
|
+ int bTruncate = NFDi_SafeStrncpy( g_errorstr, msg, NFD_MAX_STRLEN );
|
|
|
+ assert( !bTruncate ); _NFD_UNUSED(bTruncate);
|
|
|
}
|
|
|
|
|
|
|
|
|
int NFDi_SafeStrncpy( char *dst, const char *src, size_t maxCopy )
|
|
|
{
|
|
|
- size_t n = maxCopy;
|
|
|
- char *d = dst;
|
|
|
-
|
|
|
- assert( src );
|
|
|
- assert( dst );
|
|
|
-
|
|
|
- while ( n > 0 && *src != '\0' )
|
|
|
- {
|
|
|
- *d++ = *src++;
|
|
|
- --n;
|
|
|
- }
|
|
|
-
|
|
|
- /* Truncation case -
|
|
|
- terminate string and return true */
|
|
|
- if ( n == 0 )
|
|
|
- {
|
|
|
- dst[maxCopy-1] = '\0';
|
|
|
- return 1;
|
|
|
- }
|
|
|
-
|
|
|
- /* No truncation. Append a single NULL and return. */
|
|
|
- *d = '\0';
|
|
|
- return 0;
|
|
|
+ size_t n = maxCopy;
|
|
|
+ char *d = dst;
|
|
|
+
|
|
|
+ assert( src );
|
|
|
+ assert( dst );
|
|
|
+
|
|
|
+ while ( n > 0 && *src != '\0' )
|
|
|
+ {
|
|
|
+ *d++ = *src++;
|
|
|
+ --n;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Truncation case -
|
|
|
+ terminate string and return true */
|
|
|
+ if ( n == 0 )
|
|
|
+ {
|
|
|
+ dst[maxCopy-1] = '\0';
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* No truncation. Append a single NULL and return. */
|
|
|
+ *d = '\0';
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -124,22 +124,22 @@ int32_t NFDi_UTF8_Strlen( const nfdchar_t *str )
|
|
|
while(str[i])
|
|
|
{
|
|
|
if (str[i] >> 7 == 0)
|
|
|
- {
|
|
|
- /* If bit pattern begins with 0 we have ascii character. */
|
|
|
+ {
|
|
|
+ /* If bit pattern begins with 0 we have ascii character. */
|
|
|
++character_count;
|
|
|
- }
|
|
|
+ }
|
|
|
else if (str[i] >> 6 == 3)
|
|
|
- {
|
|
|
+ {
|
|
|
/* If bit pattern begins with 11 it is beginning of UTF-8 byte sequence. */
|
|
|
++character_count;
|
|
|
- }
|
|
|
+ }
|
|
|
else if (str[i] >> 6 == 2)
|
|
|
; /* If bit pattern begins with 10 it is middle of utf-8 byte sequence. */
|
|
|
else
|
|
|
- {
|
|
|
- /* In any other case this is not valid UTF-8. */
|
|
|
+ {
|
|
|
+ /* In any other case this is not valid UTF-8. */
|
|
|
return -1;
|
|
|
- }
|
|
|
+ }
|
|
|
++i;
|
|
|
}
|
|
|
|
|
|
@@ -148,7 +148,7 @@ int32_t NFDi_UTF8_Strlen( const nfdchar_t *str )
|
|
|
|
|
|
int NFDi_IsFilterSegmentChar( char ch )
|
|
|
{
|
|
|
- return (ch==','||ch==';'||ch=='\0');
|
|
|
+ return (ch==','||ch==';'||ch=='\0');
|
|
|
}
|
|
|
|
|
|
#ifdef IRON_LINUX
|
|
|
@@ -159,365 +159,365 @@ const char INIT_FAIL_MSG[] = "gtk_init_check failed to initilaize GTK+";
|
|
|
|
|
|
static void AddTypeToFilterName( const char *typebuf, char *filterName, size_t bufsize )
|
|
|
{
|
|
|
- const char SEP[] = ", ";
|
|
|
+ const char SEP[] = ", ";
|
|
|
|
|
|
- size_t len = strlen(filterName);
|
|
|
- if ( len != 0 )
|
|
|
- {
|
|
|
- strncat( filterName, SEP, bufsize - len - 1 );
|
|
|
- len += strlen(SEP);
|
|
|
- }
|
|
|
+ size_t len = strlen(filterName);
|
|
|
+ if ( len != 0 )
|
|
|
+ {
|
|
|
+ strncat( filterName, SEP, bufsize - len - 1 );
|
|
|
+ len += strlen(SEP);
|
|
|
+ }
|
|
|
|
|
|
- strncat( filterName, typebuf, bufsize - len - 1 );
|
|
|
+ strncat( filterName, typebuf, bufsize - len - 1 );
|
|
|
}
|
|
|
|
|
|
static void AddFiltersToDialog( GtkWidget *dialog, const char *filterList )
|
|
|
{
|
|
|
- GtkFileFilter *filter;
|
|
|
- char typebuf[NFD_MAX_STRLEN] = {0};
|
|
|
- const char *p_filterList = filterList;
|
|
|
- char *p_typebuf = typebuf;
|
|
|
- char filterName[NFD_MAX_STRLEN] = {0};
|
|
|
+ GtkFileFilter *filter;
|
|
|
+ char typebuf[NFD_MAX_STRLEN] = {0};
|
|
|
+ const char *p_filterList = filterList;
|
|
|
+ char *p_typebuf = typebuf;
|
|
|
+ char filterName[NFD_MAX_STRLEN] = {0};
|
|
|
|
|
|
- if ( !filterList || strlen(filterList) == 0 )
|
|
|
- return;
|
|
|
+ if ( !filterList || strlen(filterList) == 0 )
|
|
|
+ return;
|
|
|
|
|
|
- filter = gtk_file_filter_new();
|
|
|
- while ( 1 )
|
|
|
- {
|
|
|
+ filter = gtk_file_filter_new();
|
|
|
+ while ( 1 )
|
|
|
+ {
|
|
|
|
|
|
- if ( NFDi_IsFilterSegmentChar(*p_filterList) )
|
|
|
- {
|
|
|
- char typebufWildcard[NFD_MAX_STRLEN];
|
|
|
- /* add another type to the filter */
|
|
|
- assert( strlen(typebuf) > 0 );
|
|
|
- assert( strlen(typebuf) < NFD_MAX_STRLEN-1 );
|
|
|
+ if ( NFDi_IsFilterSegmentChar(*p_filterList) )
|
|
|
+ {
|
|
|
+ char typebufWildcard[NFD_MAX_STRLEN];
|
|
|
+ /* add another type to the filter */
|
|
|
+ assert( strlen(typebuf) > 0 );
|
|
|
+ assert( strlen(typebuf) < NFD_MAX_STRLEN-1 );
|
|
|
|
|
|
- snprintf( typebufWildcard, NFD_MAX_STRLEN, "*.%s", typebuf );
|
|
|
- AddTypeToFilterName( typebuf, filterName, NFD_MAX_STRLEN );
|
|
|
+ snprintf( typebufWildcard, NFD_MAX_STRLEN, "*.%s", typebuf );
|
|
|
+ AddTypeToFilterName( typebuf, filterName, NFD_MAX_STRLEN );
|
|
|
|
|
|
- gtk_file_filter_add_pattern( filter, typebufWildcard );
|
|
|
+ gtk_file_filter_add_pattern( filter, typebufWildcard );
|
|
|
|
|
|
- p_typebuf = typebuf;
|
|
|
- memset( typebuf, 0, sizeof(char) * NFD_MAX_STRLEN );
|
|
|
- }
|
|
|
+ p_typebuf = typebuf;
|
|
|
+ memset( typebuf, 0, sizeof(char) * NFD_MAX_STRLEN );
|
|
|
+ }
|
|
|
|
|
|
- if ( *p_filterList == ';' || *p_filterList == '\0' )
|
|
|
- {
|
|
|
- /* end of filter -- add it to the dialog */
|
|
|
+ if ( *p_filterList == ';' || *p_filterList == '\0' )
|
|
|
+ {
|
|
|
+ /* end of filter -- add it to the dialog */
|
|
|
|
|
|
- gtk_file_filter_set_name( filter, filterName );
|
|
|
- gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter );
|
|
|
+ gtk_file_filter_set_name( filter, filterName );
|
|
|
+ gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter );
|
|
|
|
|
|
- filterName[0] = '\0';
|
|
|
+ filterName[0] = '\0';
|
|
|
|
|
|
- if ( *p_filterList == '\0' )
|
|
|
- break;
|
|
|
+ if ( *p_filterList == '\0' )
|
|
|
+ break;
|
|
|
|
|
|
- filter = gtk_file_filter_new();
|
|
|
- }
|
|
|
+ filter = gtk_file_filter_new();
|
|
|
+ }
|
|
|
|
|
|
- if ( !NFDi_IsFilterSegmentChar( *p_filterList ) )
|
|
|
- {
|
|
|
- *p_typebuf = *p_filterList;
|
|
|
- p_typebuf++;
|
|
|
- }
|
|
|
+ if ( !NFDi_IsFilterSegmentChar( *p_filterList ) )
|
|
|
+ {
|
|
|
+ *p_typebuf = *p_filterList;
|
|
|
+ p_typebuf++;
|
|
|
+ }
|
|
|
|
|
|
- p_filterList++;
|
|
|
- }
|
|
|
+ p_filterList++;
|
|
|
+ }
|
|
|
|
|
|
- /* always append a wildcard option to the end*/
|
|
|
+ /* always append a wildcard option to the end*/
|
|
|
|
|
|
- filter = gtk_file_filter_new();
|
|
|
- gtk_file_filter_set_name( filter, "*.*" );
|
|
|
- gtk_file_filter_add_pattern( filter, "*" );
|
|
|
- gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter );
|
|
|
+ filter = gtk_file_filter_new();
|
|
|
+ gtk_file_filter_set_name( filter, "*.*" );
|
|
|
+ gtk_file_filter_add_pattern( filter, "*" );
|
|
|
+ gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter );
|
|
|
}
|
|
|
|
|
|
static void SetDefaultPath( GtkWidget *dialog, const char *defaultPath )
|
|
|
{
|
|
|
- if ( !defaultPath || strlen(defaultPath) == 0 )
|
|
|
- return;
|
|
|
+ if ( !defaultPath || strlen(defaultPath) == 0 )
|
|
|
+ return;
|
|
|
|
|
|
- /* GTK+ manual recommends not specifically setting the default path.
|
|
|
- We do it anyway in order to be consistent across platforms.
|
|
|
+ /* GTK+ manual recommends not specifically setting the default path.
|
|
|
+ We do it anyway in order to be consistent across platforms.
|
|
|
|
|
|
- If consistency with the native OS is preferred, this is the line
|
|
|
- to comment out. -ml */
|
|
|
- gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(dialog), defaultPath );
|
|
|
+ If consistency with the native OS is preferred, this is the line
|
|
|
+ to comment out. -ml */
|
|
|
+ gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER(dialog), defaultPath );
|
|
|
}
|
|
|
|
|
|
static nfdresult_t AllocPathSet( GSList *fileList, nfdpathset_t *pathSet )
|
|
|
{
|
|
|
- size_t bufSize = 0;
|
|
|
- GSList *node;
|
|
|
- nfdchar_t *p_buf;
|
|
|
- size_t count = 0;
|
|
|
-
|
|
|
- assert(fileList);
|
|
|
- assert(pathSet);
|
|
|
-
|
|
|
- pathSet->count = (size_t)g_slist_length( fileList );
|
|
|
- assert( pathSet->count > 0 );
|
|
|
-
|
|
|
- pathSet->indices = NFDi_Malloc( sizeof(size_t)*pathSet->count );
|
|
|
- if ( !pathSet->indices )
|
|
|
- {
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- /* count the total space needed for buf */
|
|
|
- for ( node = fileList; node; node = node->next )
|
|
|
- {
|
|
|
- assert(node->data);
|
|
|
- bufSize += strlen( (const gchar*)node->data ) + 1;
|
|
|
- }
|
|
|
-
|
|
|
- pathSet->buf = NFDi_Malloc( sizeof(nfdchar_t) * bufSize );
|
|
|
-
|
|
|
- /* fill buf */
|
|
|
- p_buf = pathSet->buf;
|
|
|
- for ( node = fileList; node; node = node->next )
|
|
|
- {
|
|
|
- nfdchar_t *path = (nfdchar_t*)(node->data);
|
|
|
- size_t byteLen = strlen(path)+1;
|
|
|
- ptrdiff_t index;
|
|
|
-
|
|
|
- memcpy( p_buf, path, byteLen );
|
|
|
- g_free(node->data);
|
|
|
-
|
|
|
- index = p_buf - pathSet->buf;
|
|
|
- assert( index >= 0 );
|
|
|
- pathSet->indices[count] = (size_t)index;
|
|
|
-
|
|
|
- p_buf += byteLen;
|
|
|
- ++count;
|
|
|
- }
|
|
|
-
|
|
|
- g_slist_free( fileList );
|
|
|
-
|
|
|
- return NFD_OKAY;
|
|
|
+ size_t bufSize = 0;
|
|
|
+ GSList *node;
|
|
|
+ nfdchar_t *p_buf;
|
|
|
+ size_t count = 0;
|
|
|
+
|
|
|
+ assert(fileList);
|
|
|
+ assert(pathSet);
|
|
|
+
|
|
|
+ pathSet->count = (size_t)g_slist_length( fileList );
|
|
|
+ assert( pathSet->count > 0 );
|
|
|
+
|
|
|
+ pathSet->indices = NFDi_Malloc( sizeof(size_t)*pathSet->count );
|
|
|
+ if ( !pathSet->indices )
|
|
|
+ {
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* count the total space needed for buf */
|
|
|
+ for ( node = fileList; node; node = node->next )
|
|
|
+ {
|
|
|
+ assert(node->data);
|
|
|
+ bufSize += strlen( (const gchar*)node->data ) + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ pathSet->buf = NFDi_Malloc( sizeof(nfdchar_t) * bufSize );
|
|
|
+
|
|
|
+ /* fill buf */
|
|
|
+ p_buf = pathSet->buf;
|
|
|
+ for ( node = fileList; node; node = node->next )
|
|
|
+ {
|
|
|
+ nfdchar_t *path = (nfdchar_t*)(node->data);
|
|
|
+ size_t byteLen = strlen(path)+1;
|
|
|
+ ptrdiff_t index;
|
|
|
+
|
|
|
+ memcpy( p_buf, path, byteLen );
|
|
|
+ g_free(node->data);
|
|
|
+
|
|
|
+ index = p_buf - pathSet->buf;
|
|
|
+ assert( index >= 0 );
|
|
|
+ pathSet->indices[count] = (size_t)index;
|
|
|
+
|
|
|
+ p_buf += byteLen;
|
|
|
+ ++count;
|
|
|
+ }
|
|
|
+
|
|
|
+ g_slist_free( fileList );
|
|
|
+
|
|
|
+ return NFD_OKAY;
|
|
|
}
|
|
|
|
|
|
static void WaitForCleanup(void)
|
|
|
{
|
|
|
- while (gtk_events_pending())
|
|
|
- gtk_main_iteration();
|
|
|
+ while (gtk_events_pending())
|
|
|
+ gtk_main_iteration();
|
|
|
}
|
|
|
|
|
|
/* public */
|
|
|
|
|
|
nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList,
|
|
|
- const nfdchar_t *defaultPath,
|
|
|
- nfdchar_t **outPath )
|
|
|
+ const nfdchar_t *defaultPath,
|
|
|
+ nfdchar_t **outPath )
|
|
|
{
|
|
|
- GtkWidget *dialog;
|
|
|
- nfdresult_t result;
|
|
|
-
|
|
|
- if ( !gtk_init_check( NULL, NULL ) )
|
|
|
- {
|
|
|
- NFDi_SetError(INIT_FAIL_MSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- dialog = gtk_file_chooser_dialog_new( "Open File",
|
|
|
- NULL,
|
|
|
- GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
|
- "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
- "_Open", GTK_RESPONSE_ACCEPT,
|
|
|
- NULL );
|
|
|
-
|
|
|
- /* Build the filter list */
|
|
|
- AddFiltersToDialog(dialog, filterList);
|
|
|
-
|
|
|
- /* Set the default path */
|
|
|
- SetDefaultPath(dialog, defaultPath);
|
|
|
-
|
|
|
- result = NFD_CANCEL;
|
|
|
- if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
- {
|
|
|
- char *filename;
|
|
|
-
|
|
|
- filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
|
-
|
|
|
- {
|
|
|
- size_t len = strlen(filename);
|
|
|
- *outPath = NFDi_Malloc( len + 1 );
|
|
|
- memcpy( *outPath, filename, len + 1 );
|
|
|
- if ( !*outPath )
|
|
|
- {
|
|
|
- g_free( filename );
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
- }
|
|
|
- g_free( filename );
|
|
|
-
|
|
|
- result = NFD_OKAY;
|
|
|
- }
|
|
|
-
|
|
|
- WaitForCleanup();
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- WaitForCleanup();
|
|
|
-
|
|
|
- return result;
|
|
|
+ GtkWidget *dialog;
|
|
|
+ nfdresult_t result;
|
|
|
+
|
|
|
+ if ( !gtk_init_check( NULL, NULL ) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(INIT_FAIL_MSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ dialog = gtk_file_chooser_dialog_new( "Open File",
|
|
|
+ NULL,
|
|
|
+ GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
|
+ "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
+ "_Open", GTK_RESPONSE_ACCEPT,
|
|
|
+ NULL );
|
|
|
+
|
|
|
+ /* Build the filter list */
|
|
|
+ AddFiltersToDialog(dialog, filterList);
|
|
|
+
|
|
|
+ /* Set the default path */
|
|
|
+ SetDefaultPath(dialog, defaultPath);
|
|
|
+
|
|
|
+ result = NFD_CANCEL;
|
|
|
+ if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
+ {
|
|
|
+ char *filename;
|
|
|
+
|
|
|
+ filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
|
+
|
|
|
+ {
|
|
|
+ size_t len = strlen(filename);
|
|
|
+ *outPath = NFDi_Malloc( len + 1 );
|
|
|
+ memcpy( *outPath, filename, len + 1 );
|
|
|
+ if ( !*outPath )
|
|
|
+ {
|
|
|
+ g_free( filename );
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ g_free( filename );
|
|
|
+
|
|
|
+ result = NFD_OKAY;
|
|
|
+ }
|
|
|
+
|
|
|
+ WaitForCleanup();
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ WaitForCleanup();
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
|
|
|
nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList,
|
|
|
- const nfdchar_t *defaultPath,
|
|
|
- nfdpathset_t *outPaths )
|
|
|
+ const nfdchar_t *defaultPath,
|
|
|
+ nfdpathset_t *outPaths )
|
|
|
{
|
|
|
- GtkWidget *dialog;
|
|
|
- nfdresult_t result;
|
|
|
-
|
|
|
- if ( !gtk_init_check( NULL, NULL ) )
|
|
|
- {
|
|
|
- NFDi_SetError(INIT_FAIL_MSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- dialog = gtk_file_chooser_dialog_new( "Open Files",
|
|
|
- NULL,
|
|
|
- GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
|
- "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
- "_Open", GTK_RESPONSE_ACCEPT,
|
|
|
- NULL );
|
|
|
- gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
-
|
|
|
- /* Build the filter list */
|
|
|
- AddFiltersToDialog(dialog, filterList);
|
|
|
-
|
|
|
- /* Set the default path */
|
|
|
- SetDefaultPath(dialog, defaultPath);
|
|
|
-
|
|
|
- result = NFD_CANCEL;
|
|
|
- if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
- {
|
|
|
- GSList *fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER(dialog) );
|
|
|
- if ( AllocPathSet( fileList, outPaths ) == NFD_ERROR )
|
|
|
- {
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- result = NFD_OKAY;
|
|
|
- }
|
|
|
-
|
|
|
- WaitForCleanup();
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- WaitForCleanup();
|
|
|
-
|
|
|
- return result;
|
|
|
+ GtkWidget *dialog;
|
|
|
+ nfdresult_t result;
|
|
|
+
|
|
|
+ if ( !gtk_init_check( NULL, NULL ) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(INIT_FAIL_MSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ dialog = gtk_file_chooser_dialog_new( "Open Files",
|
|
|
+ NULL,
|
|
|
+ GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
|
+ "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
+ "_Open", GTK_RESPONSE_ACCEPT,
|
|
|
+ NULL );
|
|
|
+ gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
+
|
|
|
+ /* Build the filter list */
|
|
|
+ AddFiltersToDialog(dialog, filterList);
|
|
|
+
|
|
|
+ /* Set the default path */
|
|
|
+ SetDefaultPath(dialog, defaultPath);
|
|
|
+
|
|
|
+ result = NFD_CANCEL;
|
|
|
+ if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
+ {
|
|
|
+ GSList *fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER(dialog) );
|
|
|
+ if ( AllocPathSet( fileList, outPaths ) == NFD_ERROR )
|
|
|
+ {
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ result = NFD_OKAY;
|
|
|
+ }
|
|
|
+
|
|
|
+ WaitForCleanup();
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ WaitForCleanup();
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
|
|
|
- const nfdchar_t *defaultPath,
|
|
|
- nfdchar_t **outPath )
|
|
|
+ const nfdchar_t *defaultPath,
|
|
|
+ nfdchar_t **outPath )
|
|
|
{
|
|
|
- GtkWidget *dialog;
|
|
|
- nfdresult_t result;
|
|
|
-
|
|
|
- if ( !gtk_init_check( NULL, NULL ) )
|
|
|
- {
|
|
|
- NFDi_SetError(INIT_FAIL_MSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- dialog = gtk_file_chooser_dialog_new( "Save File",
|
|
|
- NULL,
|
|
|
- GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
|
- "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
- "_Save", GTK_RESPONSE_ACCEPT,
|
|
|
- NULL );
|
|
|
- gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
-
|
|
|
- /* Build the filter list */
|
|
|
- AddFiltersToDialog(dialog, filterList);
|
|
|
-
|
|
|
- /* Set the default path */
|
|
|
- SetDefaultPath(dialog, defaultPath);
|
|
|
-
|
|
|
- result = NFD_CANCEL;
|
|
|
- if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
- {
|
|
|
- char *filename;
|
|
|
- filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
|
-
|
|
|
- {
|
|
|
- size_t len = strlen(filename);
|
|
|
- *outPath = NFDi_Malloc( len + 1 );
|
|
|
- memcpy( *outPath, filename, len + 1 );
|
|
|
- if ( !*outPath )
|
|
|
- {
|
|
|
- g_free( filename );
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
- }
|
|
|
- g_free(filename);
|
|
|
-
|
|
|
- result = NFD_OKAY;
|
|
|
- }
|
|
|
-
|
|
|
- WaitForCleanup();
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- WaitForCleanup();
|
|
|
-
|
|
|
- return result;
|
|
|
+ GtkWidget *dialog;
|
|
|
+ nfdresult_t result;
|
|
|
+
|
|
|
+ if ( !gtk_init_check( NULL, NULL ) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(INIT_FAIL_MSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ dialog = gtk_file_chooser_dialog_new( "Save File",
|
|
|
+ NULL,
|
|
|
+ GTK_FILE_CHOOSER_ACTION_SAVE,
|
|
|
+ "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
+ "_Save", GTK_RESPONSE_ACCEPT,
|
|
|
+ NULL );
|
|
|
+ gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
+
|
|
|
+ /* Build the filter list */
|
|
|
+ AddFiltersToDialog(dialog, filterList);
|
|
|
+
|
|
|
+ /* Set the default path */
|
|
|
+ SetDefaultPath(dialog, defaultPath);
|
|
|
+
|
|
|
+ result = NFD_CANCEL;
|
|
|
+ if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
+ {
|
|
|
+ char *filename;
|
|
|
+ filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
|
+
|
|
|
+ {
|
|
|
+ size_t len = strlen(filename);
|
|
|
+ *outPath = NFDi_Malloc( len + 1 );
|
|
|
+ memcpy( *outPath, filename, len + 1 );
|
|
|
+ if ( !*outPath )
|
|
|
+ {
|
|
|
+ g_free( filename );
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ g_free(filename);
|
|
|
+
|
|
|
+ result = NFD_OKAY;
|
|
|
+ }
|
|
|
+
|
|
|
+ WaitForCleanup();
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ WaitForCleanup();
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
|
|
|
- nfdchar_t **outPath)
|
|
|
+ nfdchar_t **outPath)
|
|
|
{
|
|
|
- GtkWidget *dialog;
|
|
|
- nfdresult_t result;
|
|
|
-
|
|
|
- if (!gtk_init_check(NULL, NULL))
|
|
|
- {
|
|
|
- NFDi_SetError(INIT_FAIL_MSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- dialog = gtk_file_chooser_dialog_new( "Select folder",
|
|
|
- NULL,
|
|
|
- GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
|
|
- "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
- "_Select", GTK_RESPONSE_ACCEPT,
|
|
|
- NULL );
|
|
|
- gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
-
|
|
|
-
|
|
|
- /* Set the default path */
|
|
|
- SetDefaultPath(dialog, defaultPath);
|
|
|
-
|
|
|
- result = NFD_CANCEL;
|
|
|
- if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
- {
|
|
|
- char *filename;
|
|
|
- filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
|
-
|
|
|
- {
|
|
|
- size_t len = strlen(filename);
|
|
|
- *outPath = NFDi_Malloc( len + 1 );
|
|
|
- memcpy( *outPath, filename, len + 1 );
|
|
|
- if ( !*outPath )
|
|
|
- {
|
|
|
- g_free( filename );
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
- }
|
|
|
- g_free(filename);
|
|
|
-
|
|
|
- result = NFD_OKAY;
|
|
|
- }
|
|
|
-
|
|
|
- WaitForCleanup();
|
|
|
- gtk_widget_destroy(dialog);
|
|
|
- WaitForCleanup();
|
|
|
-
|
|
|
- return result;
|
|
|
+ GtkWidget *dialog;
|
|
|
+ nfdresult_t result;
|
|
|
+
|
|
|
+ if (!gtk_init_check(NULL, NULL))
|
|
|
+ {
|
|
|
+ NFDi_SetError(INIT_FAIL_MSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ dialog = gtk_file_chooser_dialog_new( "Select folder",
|
|
|
+ NULL,
|
|
|
+ GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
|
|
+ "_Cancel", GTK_RESPONSE_CANCEL,
|
|
|
+ "_Select", GTK_RESPONSE_ACCEPT,
|
|
|
+ NULL );
|
|
|
+ gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE );
|
|
|
+
|
|
|
+
|
|
|
+ /* Set the default path */
|
|
|
+ SetDefaultPath(dialog, defaultPath);
|
|
|
+
|
|
|
+ result = NFD_CANCEL;
|
|
|
+ if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
|
|
+ {
|
|
|
+ char *filename;
|
|
|
+ filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
|
|
+
|
|
|
+ {
|
|
|
+ size_t len = strlen(filename);
|
|
|
+ *outPath = NFDi_Malloc( len + 1 );
|
|
|
+ memcpy( *outPath, filename, len + 1 );
|
|
|
+ if ( !*outPath )
|
|
|
+ {
|
|
|
+ g_free( filename );
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ g_free(filename);
|
|
|
+
|
|
|
+ result = NFD_OKAY;
|
|
|
+ }
|
|
|
+
|
|
|
+ WaitForCleanup();
|
|
|
+ gtk_widget_destroy(dialog);
|
|
|
+ WaitForCleanup();
|
|
|
+
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
#endif
|
|
|
@@ -549,73 +549,73 @@ nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
|
|
|
|
|
|
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);
|
|
|
+ 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);
|
|
|
+ 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();
|
|
|
+ // 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 )
|
|
|
{
|
|
|
- int inStrCharacterCount = (int)(wcslen(inStr));
|
|
|
- int bytesNeeded = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
- inStr, inStrCharacterCount,
|
|
|
- NULL, 0, NULL, NULL );
|
|
|
- assert( bytesNeeded );
|
|
|
- bytesNeeded += 1;
|
|
|
-
|
|
|
- *outStr = (nfdchar_t*)NFDi_Malloc( bytesNeeded );
|
|
|
- if ( !*outStr )
|
|
|
- return;
|
|
|
-
|
|
|
- int bytesWritten = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
- inStr, -1,
|
|
|
- *outStr, bytesNeeded,
|
|
|
- NULL, NULL );
|
|
|
- assert( bytesWritten ); _NFD_UNUSED( bytesWritten );
|
|
|
+ int inStrCharacterCount = (int)(wcslen(inStr));
|
|
|
+ int bytesNeeded = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
+ inStr, inStrCharacterCount,
|
|
|
+ NULL, 0, NULL, NULL );
|
|
|
+ assert( bytesNeeded );
|
|
|
+ bytesNeeded += 1;
|
|
|
+
|
|
|
+ *outStr = (nfdchar_t*)NFDi_Malloc( bytesNeeded );
|
|
|
+ if ( !*outStr )
|
|
|
+ return;
|
|
|
+
|
|
|
+ int bytesWritten = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
+ inStr, -1,
|
|
|
+ *outStr, bytesNeeded,
|
|
|
+ NULL, NULL );
|
|
|
+ assert( bytesWritten ); _NFD_UNUSED( bytesWritten );
|
|
|
}
|
|
|
|
|
|
/* includes NULL terminator byte in return */
|
|
|
static size_t GetUTF8ByteCountForWChar( const wchar_t *str )
|
|
|
{
|
|
|
- size_t bytesNeeded = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
- str, -1,
|
|
|
- NULL, 0, NULL, NULL );
|
|
|
- assert( bytesNeeded );
|
|
|
- return bytesNeeded+1;
|
|
|
+ size_t bytesNeeded = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
+ str, -1,
|
|
|
+ NULL, 0, NULL, NULL );
|
|
|
+ assert( bytesNeeded );
|
|
|
+ return bytesNeeded+1;
|
|
|
}
|
|
|
|
|
|
// write to outPtr -- no free() necessary.
|
|
|
static int CopyWCharToExistingNFDCharBuffer( const wchar_t *inStr, nfdchar_t *outPtr )
|
|
|
{
|
|
|
- int bytesNeeded = (int)(GetUTF8ByteCountForWChar( inStr ));
|
|
|
+ int bytesNeeded = (int)(GetUTF8ByteCountForWChar( inStr ));
|
|
|
|
|
|
- /* invocation copies null term */
|
|
|
- int bytesWritten = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
- inStr, -1,
|
|
|
- outPtr, bytesNeeded,
|
|
|
- NULL, 0 );
|
|
|
- assert( bytesWritten );
|
|
|
+ /* invocation copies null term */
|
|
|
+ int bytesWritten = WideCharToMultiByte( CP_UTF8, 0,
|
|
|
+ inStr, -1,
|
|
|
+ outPtr, bytesNeeded,
|
|
|
+ NULL, 0 );
|
|
|
+ assert( bytesWritten );
|
|
|
|
|
|
- return bytesWritten;
|
|
|
+ return bytesWritten;
|
|
|
|
|
|
}
|
|
|
|
|
|
@@ -623,653 +623,653 @@ static int CopyWCharToExistingNFDCharBuffer( const wchar_t *inStr, nfdchar_t *ou
|
|
|
// allocs the space in outStr -- call free()
|
|
|
static void CopyNFDCharToWChar( const nfdchar_t *inStr, wchar_t **outStr )
|
|
|
{
|
|
|
- int inStrByteCount = (int)(strlen(inStr));
|
|
|
- int charsNeeded = MultiByteToWideChar(CP_UTF8, 0,
|
|
|
- inStr, inStrByteCount,
|
|
|
- NULL, 0 );
|
|
|
- assert( charsNeeded );
|
|
|
- assert( !*outStr );
|
|
|
- charsNeeded += 1; // terminator
|
|
|
-
|
|
|
- *outStr = (wchar_t*)NFDi_Malloc( charsNeeded * sizeof(wchar_t) );
|
|
|
- if ( !*outStr )
|
|
|
- return;
|
|
|
-
|
|
|
- int ret = MultiByteToWideChar(CP_UTF8, 0,
|
|
|
- inStr, inStrByteCount,
|
|
|
- *outStr, charsNeeded);
|
|
|
- (*outStr)[charsNeeded-1] = '\0';
|
|
|
+ int inStrByteCount = (int)(strlen(inStr));
|
|
|
+ int charsNeeded = MultiByteToWideChar(CP_UTF8, 0,
|
|
|
+ inStr, inStrByteCount,
|
|
|
+ NULL, 0 );
|
|
|
+ assert( charsNeeded );
|
|
|
+ assert( !*outStr );
|
|
|
+ charsNeeded += 1; // terminator
|
|
|
+
|
|
|
+ *outStr = (wchar_t*)NFDi_Malloc( charsNeeded * sizeof(wchar_t) );
|
|
|
+ if ( !*outStr )
|
|
|
+ return;
|
|
|
+
|
|
|
+ int ret = MultiByteToWideChar(CP_UTF8, 0,
|
|
|
+ inStr, inStrByteCount,
|
|
|
+ *outStr, charsNeeded);
|
|
|
+ (*outStr)[charsNeeded-1] = '\0';
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
int inStrCharacterCount = (int)(NFDi_UTF8_Strlen(inStr));
|
|
|
- assert( ret == inStrCharacterCount );
|
|
|
+ assert( ret == inStrCharacterCount );
|
|
|
#else
|
|
|
- _NFD_UNUSED(ret);
|
|
|
+ _NFD_UNUSED(ret);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
/* ext is in format "jpg", no wildcards or separators */
|
|
|
static int AppendExtensionToSpecBuf( const char *ext, char *specBuf, size_t specBufLen )
|
|
|
{
|
|
|
- const char SEP[] = ";";
|
|
|
- assert( specBufLen > strlen(ext)+3 );
|
|
|
+ const char SEP[] = ";";
|
|
|
+ assert( specBufLen > strlen(ext)+3 );
|
|
|
|
|
|
- if ( strlen(specBuf) > 0 )
|
|
|
- {
|
|
|
- strncat( specBuf, SEP, specBufLen - strlen(specBuf) - 1 );
|
|
|
- specBufLen += strlen(SEP);
|
|
|
- }
|
|
|
+ if ( strlen(specBuf) > 0 )
|
|
|
+ {
|
|
|
+ strncat( specBuf, SEP, specBufLen - strlen(specBuf) - 1 );
|
|
|
+ specBufLen += strlen(SEP);
|
|
|
+ }
|
|
|
|
|
|
- char extWildcard[NFD_MAX_STRLEN];
|
|
|
- int bytesWritten = sprintf_s( extWildcard, NFD_MAX_STRLEN, "*.%s", ext );
|
|
|
- assert( bytesWritten == (int)(strlen(ext)+2) );
|
|
|
- _NFD_UNUSED(bytesWritten);
|
|
|
+ char extWildcard[NFD_MAX_STRLEN];
|
|
|
+ int bytesWritten = sprintf_s( extWildcard, NFD_MAX_STRLEN, "*.%s", ext );
|
|
|
+ assert( bytesWritten == (int)(strlen(ext)+2) );
|
|
|
+ _NFD_UNUSED(bytesWritten);
|
|
|
|
|
|
- strncat( specBuf, extWildcard, specBufLen - strlen(specBuf) - 1 );
|
|
|
+ strncat( specBuf, extWildcard, specBufLen - strlen(specBuf) - 1 );
|
|
|
|
|
|
- return NFD_OKAY;
|
|
|
+ return NFD_OKAY;
|
|
|
}
|
|
|
|
|
|
static nfdresult_t AddFiltersToDialog( IFileDialog *fileOpenDialog, const char *filterList )
|
|
|
{
|
|
|
- const wchar_t WILDCARD[] = L"*.*";
|
|
|
-
|
|
|
- if ( !filterList || strlen(filterList) == 0 )
|
|
|
- return NFD_OKAY;
|
|
|
-
|
|
|
- // Count rows to alloc
|
|
|
- UINT filterCount = 1; /* guaranteed to have one filter on a correct, non-empty parse */
|
|
|
- const char *p_filterList;
|
|
|
- for ( p_filterList = filterList; *p_filterList; ++p_filterList )
|
|
|
- {
|
|
|
- if ( *p_filterList == ';' )
|
|
|
- ++filterCount;
|
|
|
- }
|
|
|
-
|
|
|
- assert(filterCount);
|
|
|
- if ( !filterCount )
|
|
|
- {
|
|
|
- NFDi_SetError("Error parsing filters.");
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- /* filterCount plus 1 because we hardcode the *.* wildcard after the while loop */
|
|
|
- COMDLG_FILTERSPEC *specList = (COMDLG_FILTERSPEC*)NFDi_Malloc( sizeof(COMDLG_FILTERSPEC) * ((size_t)filterCount + 1) );
|
|
|
- if ( !specList )
|
|
|
- {
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
- for (UINT i = 0; i < filterCount+1; ++i )
|
|
|
- {
|
|
|
- specList[i].pszName = NULL;
|
|
|
- specList[i].pszSpec = NULL;
|
|
|
- }
|
|
|
-
|
|
|
- size_t specIdx = 0;
|
|
|
- p_filterList = filterList;
|
|
|
- char typebuf[NFD_MAX_STRLEN] = {0}; /* one per comma or semicolon */
|
|
|
- char *p_typebuf = typebuf;
|
|
|
-
|
|
|
- char specbuf[NFD_MAX_STRLEN] = {0}; /* one per semicolon */
|
|
|
-
|
|
|
- while ( 1 )
|
|
|
- {
|
|
|
- if ( NFDi_IsFilterSegmentChar(*p_filterList) )
|
|
|
- {
|
|
|
- /* append a type to the specbuf (pending filter) */
|
|
|
- AppendExtensionToSpecBuf( typebuf, specbuf, NFD_MAX_STRLEN );
|
|
|
-
|
|
|
- p_typebuf = typebuf;
|
|
|
- memset( typebuf, 0, sizeof(char)*NFD_MAX_STRLEN );
|
|
|
- }
|
|
|
-
|
|
|
- if ( *p_filterList == ';' || *p_filterList == '\0' )
|
|
|
- {
|
|
|
- /* end of filter -- add it to specList */
|
|
|
-
|
|
|
- CopyNFDCharToWChar( specbuf, (wchar_t**)&specList[specIdx].pszName );
|
|
|
- CopyNFDCharToWChar( specbuf, (wchar_t**)&specList[specIdx].pszSpec );
|
|
|
-
|
|
|
- memset( specbuf, 0, sizeof(char)*NFD_MAX_STRLEN );
|
|
|
- ++specIdx;
|
|
|
- if ( specIdx == filterCount )
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if ( !NFDi_IsFilterSegmentChar( *p_filterList ))
|
|
|
- {
|
|
|
- *p_typebuf = *p_filterList;
|
|
|
- ++p_typebuf;
|
|
|
- }
|
|
|
-
|
|
|
- ++p_filterList;
|
|
|
- }
|
|
|
-
|
|
|
- /* Add wildcard */
|
|
|
- specList[specIdx].pszSpec = WILDCARD;
|
|
|
- specList[specIdx].pszName = WILDCARD;
|
|
|
-
|
|
|
- fileOpenDialog->lpVtbl->SetFileTypes(fileOpenDialog, filterCount + 1, specList);
|
|
|
-
|
|
|
- /* free speclist */
|
|
|
- for ( size_t i = 0; i < filterCount; ++i )
|
|
|
- {
|
|
|
- NFDi_Free( (void*)specList[i].pszSpec );
|
|
|
- }
|
|
|
- NFDi_Free( specList );
|
|
|
-
|
|
|
- return NFD_OKAY;
|
|
|
+ const wchar_t WILDCARD[] = L"*.*";
|
|
|
+
|
|
|
+ if ( !filterList || strlen(filterList) == 0 )
|
|
|
+ return NFD_OKAY;
|
|
|
+
|
|
|
+ // Count rows to alloc
|
|
|
+ UINT filterCount = 1; /* guaranteed to have one filter on a correct, non-empty parse */
|
|
|
+ const char *p_filterList;
|
|
|
+ for ( p_filterList = filterList; *p_filterList; ++p_filterList )
|
|
|
+ {
|
|
|
+ if ( *p_filterList == ';' )
|
|
|
+ ++filterCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ assert(filterCount);
|
|
|
+ if ( !filterCount )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Error parsing filters.");
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* filterCount plus 1 because we hardcode the *.* wildcard after the while loop */
|
|
|
+ COMDLG_FILTERSPEC *specList = (COMDLG_FILTERSPEC*)NFDi_Malloc( sizeof(COMDLG_FILTERSPEC) * ((size_t)filterCount + 1) );
|
|
|
+ if ( !specList )
|
|
|
+ {
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+ for (UINT i = 0; i < filterCount+1; ++i )
|
|
|
+ {
|
|
|
+ specList[i].pszName = NULL;
|
|
|
+ specList[i].pszSpec = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ size_t specIdx = 0;
|
|
|
+ p_filterList = filterList;
|
|
|
+ char typebuf[NFD_MAX_STRLEN] = {0}; /* one per comma or semicolon */
|
|
|
+ char *p_typebuf = typebuf;
|
|
|
+
|
|
|
+ char specbuf[NFD_MAX_STRLEN] = {0}; /* one per semicolon */
|
|
|
+
|
|
|
+ while ( 1 )
|
|
|
+ {
|
|
|
+ if ( NFDi_IsFilterSegmentChar(*p_filterList) )
|
|
|
+ {
|
|
|
+ /* append a type to the specbuf (pending filter) */
|
|
|
+ AppendExtensionToSpecBuf( typebuf, specbuf, NFD_MAX_STRLEN );
|
|
|
+
|
|
|
+ p_typebuf = typebuf;
|
|
|
+ memset( typebuf, 0, sizeof(char)*NFD_MAX_STRLEN );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( *p_filterList == ';' || *p_filterList == '\0' )
|
|
|
+ {
|
|
|
+ /* end of filter -- add it to specList */
|
|
|
+
|
|
|
+ CopyNFDCharToWChar( specbuf, (wchar_t**)&specList[specIdx].pszName );
|
|
|
+ CopyNFDCharToWChar( specbuf, (wchar_t**)&specList[specIdx].pszSpec );
|
|
|
+
|
|
|
+ memset( specbuf, 0, sizeof(char)*NFD_MAX_STRLEN );
|
|
|
+ ++specIdx;
|
|
|
+ if ( specIdx == filterCount )
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( !NFDi_IsFilterSegmentChar( *p_filterList ))
|
|
|
+ {
|
|
|
+ *p_typebuf = *p_filterList;
|
|
|
+ ++p_typebuf;
|
|
|
+ }
|
|
|
+
|
|
|
+ ++p_filterList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Add wildcard */
|
|
|
+ specList[specIdx].pszSpec = WILDCARD;
|
|
|
+ specList[specIdx].pszName = WILDCARD;
|
|
|
+
|
|
|
+ fileOpenDialog->lpVtbl->SetFileTypes(fileOpenDialog, filterCount + 1, specList);
|
|
|
+
|
|
|
+ /* free speclist */
|
|
|
+ for ( size_t i = 0; i < filterCount; ++i )
|
|
|
+ {
|
|
|
+ NFDi_Free( (void*)specList[i].pszSpec );
|
|
|
+ }
|
|
|
+ NFDi_Free( specList );
|
|
|
+
|
|
|
+ return NFD_OKAY;
|
|
|
}
|
|
|
|
|
|
static nfdresult_t AllocPathSet( IShellItemArray *shellItems, nfdpathset_t *pathSet )
|
|
|
{
|
|
|
- const char ERRORMSG[] = "Error allocating pathset.";
|
|
|
+ const char ERRORMSG[] = "Error allocating pathset.";
|
|
|
|
|
|
- assert(shellItems);
|
|
|
- assert(pathSet);
|
|
|
+ assert(shellItems);
|
|
|
+ assert(pathSet);
|
|
|
|
|
|
- // How many items in shellItems?
|
|
|
- DWORD numShellItems;
|
|
|
+ // How many items in shellItems?
|
|
|
+ DWORD numShellItems;
|
|
|
HRESULT result = shellItems->lpVtbl->GetCount(shellItems, & numShellItems);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError(ERRORMSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- pathSet->count = (size_t)(numShellItems);
|
|
|
- assert( pathSet->count > 0 );
|
|
|
-
|
|
|
- pathSet->indices = (size_t*)NFDi_Malloc( sizeof(size_t)*pathSet->count );
|
|
|
- if ( !pathSet->indices )
|
|
|
- {
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- /* count the total bytes needed for buf */
|
|
|
- size_t bufSize = 0;
|
|
|
- for ( DWORD i = 0; i < numShellItems; ++i )
|
|
|
- {
|
|
|
- IShellItem *shellItem;
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(ERRORMSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ pathSet->count = (size_t)(numShellItems);
|
|
|
+ assert( pathSet->count > 0 );
|
|
|
+
|
|
|
+ pathSet->indices = (size_t*)NFDi_Malloc( sizeof(size_t)*pathSet->count );
|
|
|
+ if ( !pathSet->indices )
|
|
|
+ {
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* count the total bytes needed for buf */
|
|
|
+ size_t bufSize = 0;
|
|
|
+ for ( DWORD i = 0; i < numShellItems; ++i )
|
|
|
+ {
|
|
|
+ IShellItem *shellItem;
|
|
|
result = shellItems->lpVtbl->GetItemAt(shellItems, i, &shellItem);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError(ERRORMSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- // Confirm SFGAO_FILESYSTEM is true for this shellitem, or ignore it.
|
|
|
- SFGAOF attribs;
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(ERRORMSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Confirm SFGAO_FILESYSTEM is true for this shellitem, or ignore it.
|
|
|
+ SFGAOF attribs;
|
|
|
result = shellItem->lpVtbl->GetAttributes(shellItem, SFGAO_FILESYSTEM, &attribs);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError(ERRORMSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
- if ( !(attribs & SFGAO_FILESYSTEM) )
|
|
|
- continue;
|
|
|
-
|
|
|
- LPWSTR name;
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(ERRORMSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+ if ( !(attribs & SFGAO_FILESYSTEM) )
|
|
|
+ continue;
|
|
|
+
|
|
|
+ LPWSTR name;
|
|
|
shellItem->lpVtbl->GetDisplayName(shellItem, SIGDN_FILESYSPATH, &name);
|
|
|
|
|
|
- // Calculate length of name with UTF-8 encoding
|
|
|
- bufSize += GetUTF8ByteCountForWChar( name );
|
|
|
+ // Calculate length of name with UTF-8 encoding
|
|
|
+ bufSize += GetUTF8ByteCountForWChar( name );
|
|
|
|
|
|
- CoTaskMemFree(name);
|
|
|
- }
|
|
|
+ CoTaskMemFree(name);
|
|
|
+ }
|
|
|
|
|
|
- assert(bufSize);
|
|
|
+ assert(bufSize);
|
|
|
|
|
|
- pathSet->buf = (nfdchar_t*)NFDi_Malloc( sizeof(nfdchar_t) * bufSize );
|
|
|
- memset( pathSet->buf, 0, sizeof(nfdchar_t) * bufSize );
|
|
|
+ pathSet->buf = (nfdchar_t*)NFDi_Malloc( sizeof(nfdchar_t) * bufSize );
|
|
|
+ memset( pathSet->buf, 0, sizeof(nfdchar_t) * bufSize );
|
|
|
|
|
|
- /* fill buf */
|
|
|
- nfdchar_t *p_buf = pathSet->buf;
|
|
|
- for (DWORD i = 0; i < numShellItems; ++i )
|
|
|
- {
|
|
|
- IShellItem *shellItem;
|
|
|
+ /* fill buf */
|
|
|
+ nfdchar_t *p_buf = pathSet->buf;
|
|
|
+ for (DWORD i = 0; i < numShellItems; ++i )
|
|
|
+ {
|
|
|
+ IShellItem *shellItem;
|
|
|
result = shellItems->lpVtbl->GetItemAt(shellItems, i, &shellItem);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError(ERRORMSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- // Confirm SFGAO_FILESYSTEM is true for this shellitem, or ignore it.
|
|
|
- SFGAOF attribs;
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(ERRORMSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Confirm SFGAO_FILESYSTEM is true for this shellitem, or ignore it.
|
|
|
+ SFGAOF attribs;
|
|
|
result = shellItem->lpVtbl->GetAttributes(shellItem, SFGAO_FILESYSTEM, &attribs);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError(ERRORMSG);
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
- if ( !(attribs & SFGAO_FILESYSTEM) )
|
|
|
- continue;
|
|
|
-
|
|
|
- LPWSTR name;
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError(ERRORMSG);
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+ if ( !(attribs & SFGAO_FILESYSTEM) )
|
|
|
+ continue;
|
|
|
+
|
|
|
+ LPWSTR name;
|
|
|
shellItem->lpVtbl->GetDisplayName(shellItem, SIGDN_FILESYSPATH, &name);
|
|
|
|
|
|
- int bytesWritten = CopyWCharToExistingNFDCharBuffer(name, p_buf);
|
|
|
- CoTaskMemFree(name);
|
|
|
+ int bytesWritten = CopyWCharToExistingNFDCharBuffer(name, p_buf);
|
|
|
+ CoTaskMemFree(name);
|
|
|
|
|
|
- ptrdiff_t index = p_buf - pathSet->buf;
|
|
|
- assert( index >= 0 );
|
|
|
- pathSet->indices[i] = (size_t)(index);
|
|
|
+ ptrdiff_t index = p_buf - pathSet->buf;
|
|
|
+ assert( index >= 0 );
|
|
|
+ pathSet->indices[i] = (size_t)(index);
|
|
|
|
|
|
- p_buf += bytesWritten;
|
|
|
- }
|
|
|
+ p_buf += bytesWritten;
|
|
|
+ }
|
|
|
|
|
|
- return NFD_OKAY;
|
|
|
+ return NFD_OKAY;
|
|
|
}
|
|
|
|
|
|
static nfdresult_t SetDefaultPath( IFileDialog *dialog, const char *defaultPath )
|
|
|
{
|
|
|
- if ( !defaultPath || strlen(defaultPath) == 0 )
|
|
|
- return NFD_OKAY;
|
|
|
+ if ( !defaultPath || strlen(defaultPath) == 0 )
|
|
|
+ return NFD_OKAY;
|
|
|
|
|
|
- wchar_t *defaultPathW = {0};
|
|
|
- CopyNFDCharToWChar( defaultPath, &defaultPathW );
|
|
|
+ wchar_t *defaultPathW = {0};
|
|
|
+ CopyNFDCharToWChar( defaultPath, &defaultPathW );
|
|
|
|
|
|
- IShellItem *folder;
|
|
|
+ IShellItem *folder;
|
|
|
HRESULT result = SHCreateItemFromParsingName(defaultPathW, NULL, &IID_IShellItem, (void **)&folder);
|
|
|
|
|
|
- // Valid non results.
|
|
|
- if ( result == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || result == HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE) )
|
|
|
- {
|
|
|
- NFDi_Free( defaultPathW );
|
|
|
- return NFD_OKAY;
|
|
|
- }
|
|
|
-
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Error creating ShellItem");
|
|
|
- NFDi_Free( defaultPathW );
|
|
|
- return NFD_ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- // Could also call SetDefaultFolder(), but this guarantees defaultPath -- more consistency across API.
|
|
|
+ // Valid non results.
|
|
|
+ if ( result == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || result == HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE) )
|
|
|
+ {
|
|
|
+ NFDi_Free( defaultPathW );
|
|
|
+ return NFD_OKAY;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Error creating ShellItem");
|
|
|
+ NFDi_Free( defaultPathW );
|
|
|
+ return NFD_ERROR;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Could also call SetDefaultFolder(), but this guarantees defaultPath -- more consistency across API.
|
|
|
dialog->lpVtbl->SetFolder(dialog, folder);
|
|
|
|
|
|
- NFDi_Free( defaultPathW );
|
|
|
+ NFDi_Free( defaultPathW );
|
|
|
folder->lpVtbl->Release(folder);
|
|
|
|
|
|
- return NFD_OKAY;
|
|
|
+ return NFD_OKAY;
|
|
|
}
|
|
|
|
|
|
/* public */
|
|
|
|
|
|
nfdresult_t NFD_OpenDialog( const nfdchar_t *filterList,
|
|
|
- const nfdchar_t *defaultPath,
|
|
|
- nfdchar_t **outPath )
|
|
|
+ const nfdchar_t *defaultPath,
|
|
|
+ nfdchar_t **outPath )
|
|
|
{
|
|
|
- nfdresult_t nfdResult = NFD_ERROR;
|
|
|
-
|
|
|
-
|
|
|
- HRESULT coResult = COMInit();
|
|
|
- if (!COMIsInitialized(coResult))
|
|
|
- {
|
|
|
- NFDi_SetError("Could not initialize COM.");
|
|
|
- return nfdResult;
|
|
|
- }
|
|
|
-
|
|
|
- // Create dialog
|
|
|
- IFileOpenDialog *fileOpenDialog;
|
|
|
- HRESULT result = CoCreateInstance(&CLSID_FileOpenDialog, NULL,
|
|
|
- CLSCTX_ALL, &IID_IFileOpenDialog,
|
|
|
- (void**)(&fileOpenDialog) );
|
|
|
-
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not create dialog.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Build the filter list
|
|
|
- if ( !AddFiltersToDialog( fileOpenDialog, filterList ) )
|
|
|
- {
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Set the default path
|
|
|
- if ( !SetDefaultPath( fileOpenDialog, defaultPath ) )
|
|
|
- {
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Show the dialog.
|
|
|
+ nfdresult_t nfdResult = NFD_ERROR;
|
|
|
+
|
|
|
+
|
|
|
+ HRESULT coResult = COMInit();
|
|
|
+ if (!COMIsInitialized(coResult))
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not initialize COM.");
|
|
|
+ return nfdResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create dialog
|
|
|
+ IFileOpenDialog *fileOpenDialog;
|
|
|
+ HRESULT result = CoCreateInstance(&CLSID_FileOpenDialog, NULL,
|
|
|
+ CLSCTX_ALL, &IID_IFileOpenDialog,
|
|
|
+ (void**)(&fileOpenDialog) );
|
|
|
+
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not create dialog.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Build the filter list
|
|
|
+ if ( !AddFiltersToDialog( fileOpenDialog, filterList ) )
|
|
|
+ {
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set the default path
|
|
|
+ if ( !SetDefaultPath( fileOpenDialog, defaultPath ) )
|
|
|
+ {
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Show the dialog.
|
|
|
result = fileOpenDialog->lpVtbl->Show(fileOpenDialog, NULL);
|
|
|
- if ( SUCCEEDED(result) )
|
|
|
- {
|
|
|
- // Get the file name
|
|
|
- IShellItem *shellItem;
|
|
|
+ if ( SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ // Get the file name
|
|
|
+ IShellItem *shellItem;
|
|
|
result = fileOpenDialog->lpVtbl->GetResult(fileOpenDialog , & shellItem);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not get shell item from dialog.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
- wchar_t *filePath;
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not get shell item from dialog.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ wchar_t *filePath;
|
|
|
result = shellItem->lpVtbl->GetDisplayName(shellItem, SIGDN_FILESYSPATH, &filePath);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not get file path for selected.");
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not get file path for selected.");
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- CopyWCharToNFDChar( filePath, outPath );
|
|
|
- CoTaskMemFree(filePath);
|
|
|
- if ( !*outPath )
|
|
|
- {
|
|
|
- /* error is malloc-based, error message would be redundant */
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ CopyWCharToNFDChar( filePath, outPath );
|
|
|
+ CoTaskMemFree(filePath);
|
|
|
+ if ( !*outPath )
|
|
|
+ {
|
|
|
+ /* error is malloc-based, error message would be redundant */
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- nfdResult = NFD_OKAY;
|
|
|
+ nfdResult = NFD_OKAY;
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- }
|
|
|
- else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
- {
|
|
|
- nfdResult = NFD_CANCEL;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- NFDi_SetError("File dialog box show failed.");
|
|
|
- nfdResult = NFD_ERROR;
|
|
|
- }
|
|
|
+ }
|
|
|
+ else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
+ {
|
|
|
+ nfdResult = NFD_CANCEL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ NFDi_SetError("File dialog box show failed.");
|
|
|
+ nfdResult = NFD_ERROR;
|
|
|
+ }
|
|
|
|
|
|
end:
|
|
|
- if (fileOpenDialog)
|
|
|
+ if (fileOpenDialog)
|
|
|
fileOpenDialog->lpVtbl->Release(fileOpenDialog);
|
|
|
|
|
|
- COMUninit(coResult);
|
|
|
+ COMUninit(coResult);
|
|
|
|
|
|
- return nfdResult;
|
|
|
+ return nfdResult;
|
|
|
}
|
|
|
|
|
|
nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList,
|
|
|
- const nfdchar_t *defaultPath,
|
|
|
- nfdpathset_t *outPaths )
|
|
|
+ const nfdchar_t *defaultPath,
|
|
|
+ nfdpathset_t *outPaths )
|
|
|
{
|
|
|
- nfdresult_t nfdResult = NFD_ERROR;
|
|
|
-
|
|
|
-
|
|
|
- HRESULT coResult = COMInit();
|
|
|
- if (!COMIsInitialized(coResult))
|
|
|
- {
|
|
|
- NFDi_SetError("Could not initialize COM.");
|
|
|
- return nfdResult;
|
|
|
- }
|
|
|
-
|
|
|
- // Create dialog
|
|
|
- IFileOpenDialog *fileOpenDialog;
|
|
|
- HRESULT result = CoCreateInstance(&CLSID_FileOpenDialog, NULL,
|
|
|
- CLSCTX_ALL, &IID_IFileOpenDialog,
|
|
|
- (void**)(&fileOpenDialog) );
|
|
|
-
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- fileOpenDialog = NULL;
|
|
|
- NFDi_SetError("Could not create dialog.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Build the filter list
|
|
|
- if ( !AddFiltersToDialog( fileOpenDialog, filterList ) )
|
|
|
- {
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Set the default path
|
|
|
- if ( !SetDefaultPath( fileOpenDialog, defaultPath ) )
|
|
|
- {
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Set a flag for multiple options
|
|
|
- DWORD dwFlags;
|
|
|
+ nfdresult_t nfdResult = NFD_ERROR;
|
|
|
+
|
|
|
+
|
|
|
+ HRESULT coResult = COMInit();
|
|
|
+ if (!COMIsInitialized(coResult))
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not initialize COM.");
|
|
|
+ return nfdResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create dialog
|
|
|
+ IFileOpenDialog *fileOpenDialog;
|
|
|
+ HRESULT result = CoCreateInstance(&CLSID_FileOpenDialog, NULL,
|
|
|
+ CLSCTX_ALL, &IID_IFileOpenDialog,
|
|
|
+ (void**)(&fileOpenDialog) );
|
|
|
+
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ fileOpenDialog = NULL;
|
|
|
+ NFDi_SetError("Could not create dialog.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Build the filter list
|
|
|
+ if ( !AddFiltersToDialog( fileOpenDialog, filterList ) )
|
|
|
+ {
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set the default path
|
|
|
+ if ( !SetDefaultPath( fileOpenDialog, defaultPath ) )
|
|
|
+ {
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set a flag for multiple options
|
|
|
+ DWORD dwFlags;
|
|
|
result = fileOpenDialog->lpVtbl->GetOptions(fileOpenDialog , & dwFlags);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not get options.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not get options.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
result = fileOpenDialog->lpVtbl->SetOptions(fileOpenDialog, dwFlags | FOS_ALLOWMULTISELECT);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not set options.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not set options.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- // Show the dialog.
|
|
|
+ // Show the dialog.
|
|
|
result = fileOpenDialog->lpVtbl->Show(fileOpenDialog, NULL);
|
|
|
- if ( SUCCEEDED(result) )
|
|
|
- {
|
|
|
- IShellItemArray *shellItems;
|
|
|
+ if ( SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ IShellItemArray *shellItems;
|
|
|
result = fileOpenDialog->lpVtbl->GetResults(fileOpenDialog, & shellItems);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not get shell items.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- if ( AllocPathSet( shellItems, outPaths ) == NFD_ERROR )
|
|
|
- {
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not get shell items.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( AllocPathSet( shellItems, outPaths ) == NFD_ERROR )
|
|
|
+ {
|
|
|
shellItems->lpVtbl->Release(shellItems);
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- shellItems->lpVtbl->Release(shellItems);
|
|
|
- nfdResult = NFD_OKAY;
|
|
|
- }
|
|
|
- else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
- {
|
|
|
- nfdResult = NFD_CANCEL;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- NFDi_SetError("File dialog box show failed.");
|
|
|
- nfdResult = NFD_ERROR;
|
|
|
- }
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ shellItems->lpVtbl->Release(shellItems);
|
|
|
+ nfdResult = NFD_OKAY;
|
|
|
+ }
|
|
|
+ else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
+ {
|
|
|
+ nfdResult = NFD_CANCEL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ NFDi_SetError("File dialog box show failed.");
|
|
|
+ nfdResult = NFD_ERROR;
|
|
|
+ }
|
|
|
|
|
|
end:
|
|
|
- if ( fileOpenDialog )
|
|
|
+ if ( fileOpenDialog )
|
|
|
fileOpenDialog->lpVtbl->Release(fileOpenDialog);
|
|
|
|
|
|
- COMUninit(coResult);
|
|
|
+ COMUninit(coResult);
|
|
|
|
|
|
- return nfdResult;
|
|
|
+ return nfdResult;
|
|
|
}
|
|
|
|
|
|
nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
|
|
|
- const nfdchar_t *defaultPath,
|
|
|
- nfdchar_t **outPath )
|
|
|
+ const nfdchar_t *defaultPath,
|
|
|
+ nfdchar_t **outPath )
|
|
|
{
|
|
|
- nfdresult_t nfdResult = NFD_ERROR;
|
|
|
-
|
|
|
- HRESULT coResult = COMInit();
|
|
|
- if (!COMIsInitialized(coResult))
|
|
|
- {
|
|
|
- NFDi_SetError("Could not initialize COM.");
|
|
|
- return nfdResult;
|
|
|
- }
|
|
|
-
|
|
|
- // Create dialog
|
|
|
- IFileSaveDialog *fileSaveDialog;
|
|
|
- HRESULT result = CoCreateInstance(&CLSID_FileSaveDialog, NULL,
|
|
|
- CLSCTX_ALL, &IID_IFileSaveDialog,
|
|
|
- (void**)(&fileSaveDialog) );
|
|
|
-
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- fileSaveDialog = NULL;
|
|
|
- NFDi_SetError("Could not create dialog.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Build the filter list
|
|
|
- if ( !AddFiltersToDialog( fileSaveDialog, filterList ) )
|
|
|
- {
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Set the default path
|
|
|
- if ( !SetDefaultPath( fileSaveDialog, defaultPath ) )
|
|
|
- {
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Show the dialog.
|
|
|
+ nfdresult_t nfdResult = NFD_ERROR;
|
|
|
+
|
|
|
+ HRESULT coResult = COMInit();
|
|
|
+ if (!COMIsInitialized(coResult))
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not initialize COM.");
|
|
|
+ return nfdResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create dialog
|
|
|
+ IFileSaveDialog *fileSaveDialog;
|
|
|
+ HRESULT result = CoCreateInstance(&CLSID_FileSaveDialog, NULL,
|
|
|
+ CLSCTX_ALL, &IID_IFileSaveDialog,
|
|
|
+ (void**)(&fileSaveDialog) );
|
|
|
+
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ fileSaveDialog = NULL;
|
|
|
+ NFDi_SetError("Could not create dialog.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Build the filter list
|
|
|
+ if ( !AddFiltersToDialog( fileSaveDialog, filterList ) )
|
|
|
+ {
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set the default path
|
|
|
+ if ( !SetDefaultPath( fileSaveDialog, defaultPath ) )
|
|
|
+ {
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Show the dialog.
|
|
|
result = fileSaveDialog->lpVtbl->Show(fileSaveDialog, NULL);
|
|
|
- if ( SUCCEEDED(result) )
|
|
|
- {
|
|
|
- // Get the file name
|
|
|
- IShellItem *shellItem;
|
|
|
+ if ( SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ // Get the file name
|
|
|
+ IShellItem *shellItem;
|
|
|
result = fileSaveDialog->lpVtbl->GetResult(fileSaveDialog , & shellItem);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not get shell item from dialog.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
- wchar_t *filePath;
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not get shell item from dialog.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+ wchar_t *filePath;
|
|
|
result = shellItem->lpVtbl->GetDisplayName(shellItem, SIGDN_FILESYSPATH, &filePath);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- NFDi_SetError("Could not get file path for selected.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- CopyWCharToNFDChar( filePath, outPath );
|
|
|
- CoTaskMemFree(filePath);
|
|
|
- if ( !*outPath )
|
|
|
- {
|
|
|
- /* error is malloc-based, error message would be redundant */
|
|
|
+ NFDi_SetError("Could not get file path for selected.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ CopyWCharToNFDChar( filePath, outPath );
|
|
|
+ CoTaskMemFree(filePath);
|
|
|
+ if ( !*outPath )
|
|
|
+ {
|
|
|
+ /* error is malloc-based, error message would be redundant */
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- nfdResult = NFD_OKAY;
|
|
|
+ nfdResult = NFD_OKAY;
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- }
|
|
|
- else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
- {
|
|
|
- nfdResult = NFD_CANCEL;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- NFDi_SetError("File dialog box show failed.");
|
|
|
- nfdResult = NFD_ERROR;
|
|
|
- }
|
|
|
+ }
|
|
|
+ else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
+ {
|
|
|
+ nfdResult = NFD_CANCEL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ NFDi_SetError("File dialog box show failed.");
|
|
|
+ nfdResult = NFD_ERROR;
|
|
|
+ }
|
|
|
|
|
|
end:
|
|
|
- if ( fileSaveDialog )
|
|
|
+ if ( fileSaveDialog )
|
|
|
fileSaveDialog->lpVtbl->Release(fileSaveDialog);
|
|
|
|
|
|
- COMUninit(coResult);
|
|
|
+ COMUninit(coResult);
|
|
|
|
|
|
- return nfdResult;
|
|
|
+ return nfdResult;
|
|
|
}
|
|
|
|
|
|
nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
|
|
|
- nfdchar_t **outPath)
|
|
|
+ nfdchar_t **outPath)
|
|
|
{
|
|
|
- nfdresult_t nfdResult = NFD_ERROR;
|
|
|
- DWORD dwOptions = 0;
|
|
|
-
|
|
|
- HRESULT coResult = COMInit();
|
|
|
- if (!COMIsInitialized(coResult))
|
|
|
- {
|
|
|
- NFDi_SetError("CoInitializeEx failed.");
|
|
|
- return nfdResult;
|
|
|
- }
|
|
|
-
|
|
|
- // Create dialog
|
|
|
- IFileOpenDialog *fileDialog;
|
|
|
- HRESULT result = CoCreateInstance(&CLSID_FileOpenDialog,
|
|
|
- NULL,
|
|
|
- CLSCTX_ALL, &IID_IFileOpenDialog, (void **)&fileDialog);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("CoCreateInstance for CLSID_FileOpenDialog failed.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Set the default path
|
|
|
- if (SetDefaultPath(fileDialog, defaultPath) != NFD_OKAY)
|
|
|
- {
|
|
|
- NFDi_SetError("SetDefaultPath failed.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
-
|
|
|
- // Get the dialogs options
|
|
|
+ nfdresult_t nfdResult = NFD_ERROR;
|
|
|
+ DWORD dwOptions = 0;
|
|
|
+
|
|
|
+ HRESULT coResult = COMInit();
|
|
|
+ if (!COMIsInitialized(coResult))
|
|
|
+ {
|
|
|
+ NFDi_SetError("CoInitializeEx failed.");
|
|
|
+ return nfdResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create dialog
|
|
|
+ IFileOpenDialog *fileDialog;
|
|
|
+ HRESULT result = CoCreateInstance(&CLSID_FileOpenDialog,
|
|
|
+ NULL,
|
|
|
+ CLSCTX_ALL, &IID_IFileOpenDialog, (void **)&fileDialog);
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("CoCreateInstance for CLSID_FileOpenDialog failed.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Set the default path
|
|
|
+ if (SetDefaultPath(fileDialog, defaultPath) != NFD_OKAY)
|
|
|
+ {
|
|
|
+ NFDi_SetError("SetDefaultPath failed.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the dialogs options
|
|
|
if (!SUCCEEDED(fileDialog->lpVtbl->GetOptions(fileDialog , & dwOptions)))
|
|
|
- {
|
|
|
- NFDi_SetError("GetOptions for IFileDialog failed.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ {
|
|
|
+ NFDi_SetError("GetOptions for IFileDialog failed.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- // Add in FOS_PICKFOLDERS which hides files and only allows selection of folders
|
|
|
+ // Add in FOS_PICKFOLDERS which hides files and only allows selection of folders
|
|
|
if (!SUCCEEDED(fileDialog->lpVtbl->SetOptions(fileDialog, dwOptions | FOS_PICKFOLDERS)))
|
|
|
- {
|
|
|
- NFDi_SetError("SetOptions for IFileDialog failed.");
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ {
|
|
|
+ NFDi_SetError("SetOptions for IFileDialog failed.");
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- // Show the dialog to the user
|
|
|
+ // Show the dialog to the user
|
|
|
result = fileDialog->lpVtbl->Show(fileDialog, NULL);
|
|
|
- if ( SUCCEEDED(result) )
|
|
|
- {
|
|
|
- // Get the folder name
|
|
|
- IShellItem *shellItem;
|
|
|
-
|
|
|
- result = fileDialog->lpVtbl->GetResult(fileDialog , & shellItem);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("Could not get file path for selected.");
|
|
|
+ if ( SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ // Get the folder name
|
|
|
+ IShellItem *shellItem;
|
|
|
+
|
|
|
+ result = fileDialog->lpVtbl->GetResult(fileDialog , & shellItem);
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("Could not get file path for selected.");
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- wchar_t *path = NULL;
|
|
|
+ wchar_t *path = NULL;
|
|
|
result = shellItem->lpVtbl->GetDisplayName(shellItem, SIGDN_DESKTOPABSOLUTEPARSING, &path);
|
|
|
- if ( !SUCCEEDED(result) )
|
|
|
- {
|
|
|
- NFDi_SetError("GetDisplayName for IShellItem failed.");
|
|
|
+ if ( !SUCCEEDED(result) )
|
|
|
+ {
|
|
|
+ NFDi_SetError("GetDisplayName for IShellItem failed.");
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- CopyWCharToNFDChar(path, outPath);
|
|
|
- CoTaskMemFree(path);
|
|
|
- if ( !*outPath )
|
|
|
- {
|
|
|
+ CopyWCharToNFDChar(path, outPath);
|
|
|
+ CoTaskMemFree(path);
|
|
|
+ if ( !*outPath )
|
|
|
+ {
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- goto end;
|
|
|
- }
|
|
|
+ goto end;
|
|
|
+ }
|
|
|
|
|
|
- nfdResult = NFD_OKAY;
|
|
|
+ nfdResult = NFD_OKAY;
|
|
|
shellItem->lpVtbl->Release(shellItem);
|
|
|
- }
|
|
|
- else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
- {
|
|
|
- nfdResult = NFD_CANCEL;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- NFDi_SetError("Show for IFileDialog failed.");
|
|
|
- nfdResult = NFD_ERROR;
|
|
|
- }
|
|
|
+ }
|
|
|
+ else if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
|
|
+ {
|
|
|
+ nfdResult = NFD_CANCEL;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ NFDi_SetError("Show for IFileDialog failed.");
|
|
|
+ nfdResult = NFD_ERROR;
|
|
|
+ }
|
|
|
|
|
|
end:
|
|
|
|
|
|
- if (fileDialog)
|
|
|
+ if (fileDialog)
|
|
|
fileDialog->lpVtbl->Release(fileDialog);
|
|
|
|
|
|
- COMUninit(coResult);
|
|
|
+ COMUninit(coResult);
|
|
|
|
|
|
- return nfdResult;
|
|
|
+ return nfdResult;
|
|
|
}
|
|
|
|
|
|
#endif
|