|
|
- /*
- Native File Dialog
-
- http://www.frogtoss.com/labs
- */
-
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <gtk/gtk.h>
- #include "nfd.h"
- #include "nfd_common.h"
-
-
- 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[] = ", ";
-
- size_t len = strlen(filterName);
- if ( len != 0 )
- {
- strncat( filterName, SEP, bufsize - len - 1 );
- len += strlen(SEP);
- }
-
- 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};
-
- if ( !filterList || strlen(filterList) == 0 )
- return;
-
- 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 );
-
- snprintf( typebufWildcard, NFD_MAX_STRLEN, "*.%s", typebuf );
- AddTypeToFilterName( typebuf, filterName, NFD_MAX_STRLEN );
-
- gtk_file_filter_add_pattern( filter, typebufWildcard );
-
- 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 */
-
- gtk_file_filter_set_name( filter, filterName );
- gtk_file_chooser_add_filter( GTK_FILE_CHOOSER(dialog), filter );
-
- filterName[0] = '\0';
-
- if ( *p_filterList == '\0' )
- break;
-
- filter = gtk_file_filter_new();
- }
-
- if ( !NFDi_IsFilterSegmentChar( *p_filterList ) )
- {
- *p_typebuf = *p_filterList;
- p_typebuf++;
- }
-
- p_filterList++;
- }
-
- /* 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 );
- }
-
- static void SetDefaultPath( GtkWidget *dialog, const char *defaultPath )
- {
- 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.
-
- 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;
- }
-
- static void WaitForCleanup(void)
- {
- while (gtk_events_pending())
- gtk_main_iteration();
- }
-
- /* public */
-
- nfdresult_t NFD_OpenDialog( const char *filterList,
- 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;
- }
-
-
- nfdresult_t NFD_OpenDialogMultiple( const nfdchar_t *filterList,
- 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;
- }
-
- nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
- 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;
- }
|