From 4e0db5657472f31b95cb20bd4b42ac40093c983d Mon Sep 17 00:00:00 2001 From: Bernard Teo Date: Sat, 3 Feb 2024 16:34:37 +0800 Subject: [PATCH] Add versioned API --- src/include/nfd.h | 168 ++++++++++++++++++++++++++++- src/nfd_cocoa.m | 80 ++++++++++++-- src/nfd_gtk.cpp | 76 +++++++++++-- src/nfd_portal.cpp | 76 +++++++++++-- src/nfd_win.cpp | 143 +++++++++++++++++++----- test/CMakeLists.txt | 8 +- test/test_opendialog_native_with.c | 52 +++++++++ test/test_opendialog_with.c | 39 +++++++ test/test_pickfolder_native_with.c | 43 ++++++++ test/test_pickfolder_with.c | 34 ++++++ test/test_savedialog_native_with.c | 59 ++++++++++ test/test_savedialog_with.c | 40 +++++++ 12 files changed, 762 insertions(+), 56 deletions(-) create mode 100644 test/test_opendialog_native_with.c create mode 100644 test/test_opendialog_with.c create mode 100644 test/test_pickfolder_native_with.c create mode 100644 test/test_pickfolder_with.c create mode 100644 test/test_savedialog_native_with.c create mode 100644 test/test_savedialog_with.c diff --git a/src/include/nfd.h b/src/include/nfd.h index 6ce848f..bb54040 100644 --- a/src/include/nfd.h +++ b/src/include/nfd.h @@ -93,6 +93,59 @@ typedef struct { typedef nfdu8filteritem_t nfdnfilteritem_t; #endif // _WIN32 +typedef size_t nfdversion_t; + +typedef struct { + const nfdu8filteritem_t* filterList; + nfdfiltersize_t filterCount; + const nfdu8char_t* defaultPath; +} nfdopendialogu8args_t; + +#ifdef _WIN32 +typedef struct { + const nfdnfilteritem_t* filterList; + nfdfiltersize_t filterCount; + const nfdnchar_t* defaultPath; +} nfdopendialognargs_t; +#else +typedef nfdopendialogu8args_t nfdopendialognargs_t; +#endif // _WIN32 + +typedef struct { + const nfdu8filteritem_t* filterList; + nfdfiltersize_t filterCount; + const nfdu8char_t* defaultPath; + const nfdu8char_t* defaultName; +} nfdsavedialogu8args_t; + +#ifdef _WIN32 +typedef struct { + const nfdnfilteritem_t* filterList; + nfdfiltersize_t filterCount; + const nfdnchar_t* defaultPath; + const nfdnchar_t* defaultName; +} nfdsavedialognargs_t; +#else +typedef nfdsavedialogu8args_t nfdsavedialognargs_t; +#endif // _WIN32 + +typedef struct { + const nfdu8char_t* defaultPath; +} nfdpickfolderu8args_t; + +#ifdef _WIN32 +typedef struct { + const nfdnchar_t* defaultPath; +} nfdpickfoldernargs_t; +#else +typedef nfdpickfolderu8args_t nfdpickfoldernargs_t; +#endif // _WIN32 + +// This is a unique identifier tagged to all the NFD_*With() function calls, for backward +// compatibility purposes. There is usually no need to use this directly, unless you want to use +// NFD differently depending on the version you're building with. +#define NFD_INTERFACE_VERSION 1 + /** Free a file path that was returned by the dialogs. * * Note: use NFD_PathSet_FreePathN() to free path from pathset instead of this function. */ @@ -134,6 +187,33 @@ NFD_API nfdresult_t NFD_OpenDialogU8(nfdu8char_t** outPath, nfdfiltersize_t filterCount, const nfdu8char_t* defaultPath); +/** This function is a library implementation detail. Please use NFD_OpenDialogN_With() instead. */ +NFD_API nfdresult_t NFD_OpenDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdopendialognargs_t* args); + +/** Single file open dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPath` via NFD_FreePathN() if this function + * returns NFD_OKAY. See documentation of nfdopendialognargs_t for details. */ +inline nfdresult_t NFD_OpenDialogN_With(nfdnchar_t** outPath, nfdopendialognargs_t args) { + return NFD_OpenDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +/** This function is a library implementation detail. Please use NFD_OpenDialogU8_With() instead. + */ +NFD_API nfdresult_t NFD_OpenDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdopendialogu8args_t* args); + +/** Single file open dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPath` via NFD_FreePathU8() if this function + * returns NFD_OKAY. See documentation of nfdopendialogu8args_t for details. */ +inline nfdresult_t NFD_OpenDialogU8_With(nfdu8char_t** outPath, nfdopendialogu8args_t args) { + return NFD_OpenDialogU8_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + /** Multiple file open dialog * * It is the caller's responsibility to free `outPaths` via NFD_PathSet_FreeN() if this function @@ -158,6 +238,36 @@ NFD_API nfdresult_t NFD_OpenDialogMultipleU8(const nfdpathset_t** outPaths, nfdfiltersize_t filterCount, const nfdu8char_t* defaultPath); +/** This function is a library implementation detail. Please use NFD_OpenDialogMultipleN_With() + * instead. */ +NFD_API nfdresult_t NFD_OpenDialogMultipleN_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialognargs_t* args); + +/** Multiple file open dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPaths` via NFD_PathSet_FreeN() if this function + * returns NFD_OKAY. See documentation of nfdopendialognargs_t for details. */ +inline nfdresult_t NFD_OpenDialogMultipleN_With(const nfdpathset_t** outPaths, + nfdopendialognargs_t args) { + return NFD_OpenDialogMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &args); +} + +/** This function is a library implementation detail. Please use NFD_OpenDialogU8_With() instead. + */ +NFD_API nfdresult_t NFD_OpenDialogMultipleU8_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialogu8args_t* args); + +/** Multiple file open dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPaths` via NFD_PathSet_FreeU8() if this function + * returns NFD_OKAY. See documentation of nfdopendialogu8args_t for details. */ +inline nfdresult_t NFD_OpenDialogMultipleU8_With(const nfdpathset_t** outPaths, + nfdopendialogu8args_t args) { + return NFD_OpenDialogMultipleU8_With_Impl(NFD_INTERFACE_VERSION, outPaths, &args); +} + /** Save dialog * * It is the caller's responsibility to free `outPath` via NFD_FreePathN() if this function returns @@ -184,7 +294,34 @@ NFD_API nfdresult_t NFD_SaveDialogU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPath, const nfdu8char_t* defaultName); -/** Select folder dialog +/** This function is a library implementation detail. Please use NFD_SaveDialogN_With() instead. */ +NFD_API nfdresult_t NFD_SaveDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdsavedialognargs_t* args); + +/** Single file save dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPath` via NFD_FreePathN() if this function + * returns NFD_OKAY. See documentation of nfdsavedialognargs_t for details. */ +inline nfdresult_t NFD_SaveDialogN_With(nfdnchar_t** outPath, nfdsavedialognargs_t args) { + return NFD_SaveDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +/** This function is a library implementation detail. Please use NFD_SaveDialogU8_With() instead. + */ +NFD_API nfdresult_t NFD_SaveDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdsavedialogu8args_t* args); + +/** Single file save dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPath` via NFD_FreePathU8() if this function + * returns NFD_OKAY. See documentation of nfdsavedialogu8args_t for details. */ +inline nfdresult_t NFD_SaveDialogU8_With(nfdu8char_t** outPath, nfdsavedialogu8args_t args) { + return NFD_SaveDialogU8_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +/** Select single folder dialog * * It is the caller's responsibility to free `outPath` via NFD_FreePathN() if this function returns * NFD_OKAY. @@ -192,7 +329,7 @@ NFD_API nfdresult_t NFD_SaveDialogU8(nfdu8char_t** outPath, * @param defaultPath If null, the operating system will decide. */ NFD_API nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath); -/** Select folder dialog +/** Select single folder dialog * * It is the caller's responsibility to free `outPath` via NFD_FreePathU8() if this function * returns NFD_OKAY. @@ -200,6 +337,33 @@ NFD_API nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defa * @param defaultPath If null, the operating system will decide. */ NFD_API nfdresult_t NFD_PickFolderU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPath); +/** This function is a library implementation detail. Please use NFD_PickFolderN_With() instead. */ +NFD_API nfdresult_t NFD_PickFolderN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdpickfoldernargs_t* args); + +/** Select single folder dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPath` via NFD_FreePathN() if this function + * returns NFD_OKAY. See documentation of nfdpickfoldernargs_t for details. */ +inline nfdresult_t NFD_PickFolderN_With(nfdnchar_t** outPath, nfdpickfoldernargs_t args) { + return NFD_PickFolderN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +/** This function is a library implementation detail. Please use NFD_PickFolderU8_With() instead. + */ +NFD_API nfdresult_t NFD_PickFolderU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdpickfolderu8args_t* args); + +/** Select single folder dialog, with additional parameters. + * + * It is the caller's responsibility to free `outPath` via NFD_FreePathU8() if this function + * returns NFD_OKAY. See documentation of nfdpickfolderu8args_t for details. */ +inline nfdresult_t NFD_PickFolderU8_With(nfdu8char_t** outPath, nfdpickfolderu8args_t args) { + return NFD_PickFolderU8_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + /** Get the last error * * This is set when a function returns NFD_ERROR. diff --git a/src/nfd_cocoa.m b/src/nfd_cocoa.m index babd6d4..6337fcd 100644 --- a/src/nfd_cocoa.m +++ b/src/nfd_cocoa.m @@ -215,6 +215,16 @@ nfdresult_t NFD_OpenDialogN(nfdnchar_t** outPath, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { + const nfdopendialognargs_t args = {filterList, filterCount, defaultPath}; + return NFD_OpenDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_OpenDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + nfdresult_t result = NFD_CANCEL; @autoreleasepool { NSWindow* keyWindow = [[NSApplication sharedApplication] keyWindow]; @@ -223,10 +233,10 @@ nfdresult_t NFD_OpenDialogN(nfdnchar_t** outPath, [dialog setAllowsMultipleSelection:NO]; // Build the filter list - AddFilterListToDialog(dialog, filterList, filterCount); + AddFilterListToDialog(dialog, args->filterList, args->filterCount); // Set the starting directory - SetDefaultPath(dialog, defaultPath); + SetDefaultPath(dialog, args->defaultPath); if ([dialog runModal] == NSModalResponseOK) { const NSURL* url = [dialog URL]; @@ -247,10 +257,26 @@ nfdresult_t NFD_OpenDialogU8(nfdu8char_t** outPath, return NFD_OpenDialogN(outPath, filterList, filterCount, defaultPath); } +nfdresult_t NFD_OpenDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdopendialogu8args_t* args) { + return NFD_OpenDialogN_With_Impl(version, outPath, args); +} + nfdresult_t NFD_OpenDialogMultipleN(const nfdpathset_t** outPaths, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { + const nfdopendialognargs_t args = {filterList, filterCount, defaultPath}; + return NFD_OpenDialogMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &args); +} + +nfdresult_t NFD_OpenDialogMultipleN_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + nfdresult_t result = NFD_CANCEL; @autoreleasepool { NSWindow* keyWindow = [[NSApplication sharedApplication] keyWindow]; @@ -259,10 +285,10 @@ nfdresult_t NFD_OpenDialogMultipleN(const nfdpathset_t** outPaths, [dialog setAllowsMultipleSelection:YES]; // Build the filter list - AddFilterListToDialog(dialog, filterList, filterCount); + AddFilterListToDialog(dialog, args->filterList, args->filterCount); // Set the starting directory - SetDefaultPath(dialog, defaultPath); + SetDefaultPath(dialog, args->defaultPath); if ([dialog runModal] == NSModalResponseOK) { const NSArray* urls = [dialog URLs]; @@ -288,11 +314,27 @@ nfdresult_t NFD_OpenDialogMultipleU8(const nfdpathset_t** outPaths, return NFD_OpenDialogMultipleN(outPaths, filterList, filterCount, defaultPath); } +nfdresult_t NFD_OpenDialogMultipleU8_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialogu8args_t* args) { + return NFD_OpenDialogMultipleN_With_Impl(version, outPaths, args); +} + nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath, const nfdnchar_t* defaultName) { + const nfdsavedialognargs_t args = {filterList, filterCount, defaultPath, defaultName}; + return NFD_SaveDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_SaveDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdsavedialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + nfdresult_t result = NFD_CANCEL; @autoreleasepool { NSWindow* keyWindow = [[NSApplication sharedApplication] keyWindow]; @@ -304,13 +346,13 @@ nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, [dialog setAllowsOtherFileTypes:TRUE]; // Build the filter list - AddFilterListToDialog(dialog, filterList, filterCount); + AddFilterListToDialog(dialog, args->filterList, args->filterCount); // Set the starting directory - SetDefaultPath(dialog, defaultPath); + SetDefaultPath(dialog, args->defaultPath); // Set the default file name - SetDefaultName(dialog, defaultName); + SetDefaultName(dialog, args->defaultName); if ([dialog runModal] == NSModalResponseOK) { const NSURL* url = [dialog URL]; @@ -332,7 +374,23 @@ nfdresult_t NFD_SaveDialogU8(nfdu8char_t** outPath, return NFD_SaveDialogN(outPath, filterList, filterCount, defaultPath, defaultName); } +nfdresult_t NFD_SaveDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdsavedialogu8args_t* args) { + return NFD_SaveDialogN_With_Impl(version, outPath, args); +} + nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) { + const nfdpickfoldernargs_t args = {defaultPath}; + return NFD_PickFolderN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_PickFolderN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdpickfoldernargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + nfdresult_t result = NFD_CANCEL; @autoreleasepool { NSWindow* keyWindow = [[NSApplication sharedApplication] keyWindow]; @@ -344,7 +402,7 @@ nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) [dialog setCanChooseFiles:NO]; // Set the starting directory - SetDefaultPath(dialog, defaultPath); + SetDefaultPath(dialog, args->defaultPath); if ([dialog runModal] == NSModalResponseOK) { const NSURL* url = [dialog URL]; @@ -362,6 +420,12 @@ nfdresult_t NFD_PickFolderU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPa return NFD_PickFolderN(outPath, defaultPath); } +nfdresult_t NFD_PickFolderU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdpickfolderu8args_t* args) { + return NFD_PickFolderN_With_Impl(version, outPath, args); +} + nfdresult_t NFD_PathSet_GetCount(const nfdpathset_t* pathSet, nfdpathsetsize_t* count) { const NSArray* urls = (const NSArray*)pathSet; *count = [urls count]; diff --git a/src/nfd_gtk.cpp b/src/nfd_gtk.cpp index cb1696d..3ff84ca 100644 --- a/src/nfd_gtk.cpp +++ b/src/nfd_gtk.cpp @@ -416,6 +416,16 @@ nfdresult_t NFD_OpenDialogN(nfdnchar_t** outPath, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { + const nfdopendialognargs_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_OpenDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + GtkWidget* widget = gtk_file_chooser_dialog_new("Open File", nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, @@ -429,10 +439,10 @@ nfdresult_t NFD_OpenDialogN(nfdnchar_t** outPath, Widget_Guard widgetGuard(widget); /* Build the filter list */ - AddFiltersToDialog(GTK_FILE_CHOOSER(widget), filterList, filterCount); + AddFiltersToDialog(GTK_FILE_CHOOSER(widget), args->filterList, args->filterCount); /* Set the default path */ - SetDefaultPath(GTK_FILE_CHOOSER(widget), defaultPath); + SetDefaultPath(GTK_FILE_CHOOSER(widget), args->defaultPath); if (RunDialogWithFocus(GTK_DIALOG(widget)) == GTK_RESPONSE_ACCEPT) { // write out the file name @@ -450,10 +460,25 @@ nfdresult_t NFD_OpenDialogU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPath) __attribute__((alias("NFD_OpenDialogN"))); +nfdresult_t NFD_OpenDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdopendialogu8args_t* args) + __attribute__((alias("NFD_OpenDialogN_With_Impl"))); + nfdresult_t NFD_OpenDialogMultipleN(const nfdpathset_t** outPaths, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { + const nfdopendialognargs_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &args); +} + +nfdresult_t NFD_OpenDialogMultipleN_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + GtkWidget* widget = gtk_file_chooser_dialog_new("Open Files", nullptr, GTK_FILE_CHOOSER_ACTION_OPEN, @@ -470,10 +495,10 @@ nfdresult_t NFD_OpenDialogMultipleN(const nfdpathset_t** outPaths, gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(widget), TRUE); /* Build the filter list */ - AddFiltersToDialog(GTK_FILE_CHOOSER(widget), filterList, filterCount); + AddFiltersToDialog(GTK_FILE_CHOOSER(widget), args->filterList, args->filterCount); /* Set the default path */ - SetDefaultPath(GTK_FILE_CHOOSER(widget), defaultPath); + SetDefaultPath(GTK_FILE_CHOOSER(widget), args->defaultPath); if (RunDialogWithFocus(GTK_DIALOG(widget)) == GTK_RESPONSE_ACCEPT) { // write out the file name @@ -492,11 +517,26 @@ nfdresult_t NFD_OpenDialogMultipleU8(const nfdpathset_t** outPaths, const nfdu8char_t* defaultPath) __attribute__((alias("NFD_OpenDialogMultipleN"))); +nfdresult_t NFD_OpenDialogMultipleU8_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialogu8args_t* args) + __attribute__((alias("NFD_OpenDialogMultipleN_With_Impl"))); + nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath, const nfdnchar_t* defaultName) { + const nfdsavedialognargs_t args{filterList, filterCount, defaultPath, defaultName}; + return NFD_SaveDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_SaveDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdsavedialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + GtkWidget* widget = gtk_file_chooser_dialog_new("Save File", nullptr, GTK_FILE_CHOOSER_ACTION_SAVE, @@ -516,13 +556,13 @@ nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, ButtonClickedArgs buttonClickedArgs; buttonClickedArgs.chooser = GTK_FILE_CHOOSER(widget); buttonClickedArgs.map = - AddFiltersToDialogWithMap(GTK_FILE_CHOOSER(widget), filterList, filterCount); + AddFiltersToDialogWithMap(GTK_FILE_CHOOSER(widget), args->filterList, args->filterCount); /* Set the default path */ - SetDefaultPath(GTK_FILE_CHOOSER(widget), defaultPath); + SetDefaultPath(GTK_FILE_CHOOSER(widget), args->defaultPath); /* Set the default file name */ - SetDefaultName(GTK_FILE_CHOOSER(widget), defaultName); + SetDefaultName(GTK_FILE_CHOOSER(widget), args->defaultName); /* set the handler to add file extension */ gulong handlerID = g_signal_connect(G_OBJECT(saveButton), @@ -555,7 +595,22 @@ nfdresult_t NFD_SaveDialogU8(nfdu8char_t** outPath, const nfdu8char_t* defaultName) __attribute__((alias("NFD_SaveDialogN"))); +nfdresult_t NFD_SaveDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdsavedialogu8args_t* args) + __attribute__((alias("NFD_SaveDialogN_With_Impl"))); + nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) { + const nfdpickfoldernargs_t args{defaultPath}; + return NFD_PickFolderN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_PickFolderN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdpickfoldernargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + GtkWidget* widget = gtk_file_chooser_dialog_new("Select folder", nullptr, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, @@ -569,7 +624,7 @@ nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) Widget_Guard widgetGuard(widget); /* Set the default path */ - SetDefaultPath(GTK_FILE_CHOOSER(widget), defaultPath); + SetDefaultPath(GTK_FILE_CHOOSER(widget), args->defaultPath); if (RunDialogWithFocus(GTK_DIALOG(widget)) == GTK_RESPONSE_ACCEPT) { // write out the file name @@ -584,6 +639,11 @@ nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) nfdresult_t NFD_PickFolderU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPath) __attribute__((alias("NFD_PickFolderN"))); +nfdresult_t NFD_PickFolderU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdpickfolderu8args_t* args) + __attribute__((alias("NFD_PickFolderN_With_Impl"))); + nfdresult_t NFD_PathSet_GetCount(const nfdpathset_t* pathSet, nfdpathsetsize_t* count) { assert(pathSet); // const_cast because methods on GSList aren't const, but it should act diff --git a/src/nfd_portal.cpp b/src/nfd_portal.cpp index 655dcb8..6f279cf 100644 --- a/src/nfd_portal.cpp +++ b/src/nfd_portal.cpp @@ -1377,10 +1377,20 @@ nfdresult_t NFD_OpenDialogN(nfdnchar_t** outPath, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { + const nfdopendialognargs_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_OpenDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + DBusMessage* msg; { - const nfdresult_t res = - NFD_DBus_OpenFile(msg, filterList, filterCount, defaultPath); + const nfdresult_t res = NFD_DBus_OpenFile( + msg, args->filterList, args->filterCount, args->defaultPath); if (res != NFD_OKAY) { return res; } @@ -1404,14 +1414,29 @@ nfdresult_t NFD_OpenDialogU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPath) __attribute__((alias("NFD_OpenDialogN"))); +nfdresult_t NFD_OpenDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdopendialogu8args_t* args) + __attribute__((alias("NFD_OpenDialogN_With_Impl"))); + nfdresult_t NFD_OpenDialogMultipleN(const nfdpathset_t** outPaths, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { + const nfdopendialognargs_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &args); +} + +nfdresult_t NFD_OpenDialogMultipleN_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + DBusMessage* msg; { - const nfdresult_t res = - NFD_DBus_OpenFile(msg, filterList, filterCount, defaultPath); + const nfdresult_t res = NFD_DBus_OpenFile( + msg, args->filterList, args->filterCount, args->defaultPath); if (res != NFD_OKAY) { return res; } @@ -1434,15 +1459,30 @@ nfdresult_t NFD_OpenDialogMultipleU8(const nfdpathset_t** outPaths, const nfdu8char_t* defaultPath) __attribute__((alias("NFD_OpenDialogMultipleN"))); +nfdresult_t NFD_OpenDialogMultipleU8_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialogu8args_t* args) + __attribute__((alias("NFD_OpenDialogMultipleN_With_Impl"))); + nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath, const nfdnchar_t* defaultName) { + const nfdsavedialognargs_t args{filterList, filterCount, defaultPath, defaultName}; + return NFD_SaveDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_SaveDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdsavedialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + DBusMessage* msg; { - const nfdresult_t res = - NFD_DBus_SaveFile(msg, filterList, filterCount, defaultPath, defaultName); + const nfdresult_t res = NFD_DBus_SaveFile( + msg, args->filterList, args->filterCount, args->defaultPath, args->defaultName); if (res != NFD_OKAY) { return res; } @@ -1480,8 +1520,23 @@ nfdresult_t NFD_SaveDialogU8(nfdu8char_t** outPath, const nfdu8char_t* defaultName) __attribute__((alias("NFD_SaveDialogN"))); +nfdresult_t NFD_SaveDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdsavedialogu8args_t* args) + __attribute__((alias("NFD_SaveDialogN_With_Impl"))); + nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) { - (void)defaultPath; // Default path not supported for portal backend + const nfdpickfoldernargs_t args{defaultPath}; + return NFD_PickFolderN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_PickFolderN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdpickfoldernargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + + (void)args; // Default path not supported for portal backend { dbus_uint32_t version; @@ -1501,7 +1556,7 @@ nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) DBusMessage* msg; { - const nfdresult_t res = NFD_DBus_OpenFile(msg, nullptr, 0, defaultPath); + const nfdresult_t res = NFD_DBus_OpenFile(msg, nullptr, 0, args->defaultPath); if (res != NFD_OKAY) { return res; } @@ -1522,6 +1577,11 @@ nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) nfdresult_t NFD_PickFolderU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPath) __attribute__((alias("NFD_PickFolderN"))); +nfdresult_t NFD_PickFolderU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdpickfolderu8args_t* args) + __attribute__((alias("NFD_PickFolderN_With_Impl"))); + nfdresult_t NFD_PathSet_GetCount(const nfdpathset_t* pathSet, nfdpathsetsize_t* count) { assert(pathSet); DBusMessage* msg = const_cast(static_cast(pathSet)); diff --git a/src/nfd_win.cpp b/src/nfd_win.cpp index 66ef596..9889f55 100644 --- a/src/nfd_win.cpp +++ b/src/nfd_win.cpp @@ -334,6 +334,16 @@ nfdresult_t NFD_OpenDialogN(nfdnchar_t** outPath, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { + const nfdopendialognargs_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_OpenDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + ::IFileOpenDialog* fileOpenDialog; // Create dialog @@ -352,17 +362,17 @@ nfdresult_t NFD_OpenDialogN(nfdnchar_t** outPath, Release_Guard<::IFileOpenDialog> fileOpenDialogGuard(fileOpenDialog); // Build the filter list - if (!AddFiltersToDialog(fileOpenDialog, filterList, filterCount)) { + if (!AddFiltersToDialog(fileOpenDialog, args->filterList, args->filterCount)) { return NFD_ERROR; } // Set auto-completed default extension - if (!SetDefaultExtension(fileOpenDialog, filterList, filterCount)) { + if (!SetDefaultExtension(fileOpenDialog, args->filterList, args->filterCount)) { return NFD_ERROR; } // Set the default path - if (!SetDefaultPath(fileOpenDialog, defaultPath)) { + if (!SetDefaultPath(fileOpenDialog, args->defaultPath)) { return NFD_ERROR; } @@ -405,7 +415,17 @@ nfdresult_t NFD_OpenDialogMultipleN(const nfdpathset_t** outPaths, const nfdnfilteritem_t* filterList, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath) { - ::IFileOpenDialog* fileOpenDialog(nullptr); + const nfdopendialognargs_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &args); +} + +nfdresult_t NFD_OpenDialogMultipleN_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + + ::IFileOpenDialog* fileOpenDialog; // Create dialog HRESULT result = ::CoCreateInstance(::CLSID_FileOpenDialog, @@ -423,17 +443,17 @@ nfdresult_t NFD_OpenDialogMultipleN(const nfdpathset_t** outPaths, Release_Guard<::IFileOpenDialog> fileOpenDialogGuard(fileOpenDialog); // Build the filter list - if (!AddFiltersToDialog(fileOpenDialog, filterList, filterCount)) { + if (!AddFiltersToDialog(fileOpenDialog, args->filterList, args->filterCount)) { return NFD_ERROR; } // Set auto-completed default extension - if (!SetDefaultExtension(fileOpenDialog, filterList, filterCount)) { + if (!SetDefaultExtension(fileOpenDialog, args->filterList, args->filterCount)) { return NFD_ERROR; } // Set the default path - if (!SetDefaultPath(fileOpenDialog, defaultPath)) { + if (!SetDefaultPath(fileOpenDialog, args->defaultPath)) { return NFD_ERROR; } @@ -469,6 +489,16 @@ nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, nfdfiltersize_t filterCount, const nfdnchar_t* defaultPath, const nfdnchar_t* defaultName) { + const nfdsavedialognargs_t args{filterList, filterCount, defaultPath, defaultName}; + return NFD_SaveDialogN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_SaveDialogN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdsavedialognargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + ::IFileSaveDialog* fileSaveDialog; // Create dialog @@ -487,22 +517,22 @@ nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, Release_Guard<::IFileSaveDialog> fileSaveDialogGuard(fileSaveDialog); // Build the filter list - if (!AddFiltersToDialog(fileSaveDialog, filterList, filterCount)) { + if (!AddFiltersToDialog(fileSaveDialog, args->filterList, args->filterCount)) { return NFD_ERROR; } // Set default extension - if (!SetDefaultExtension(fileSaveDialog, filterList, filterCount)) { + if (!SetDefaultExtension(fileSaveDialog, args->filterList, args->filterCount)) { return NFD_ERROR; } // Set the default path - if (!SetDefaultPath(fileSaveDialog, defaultPath)) { + if (!SetDefaultPath(fileSaveDialog, args->defaultPath)) { return NFD_ERROR; } // Set the default name - if (!SetDefaultName(fileSaveDialog, defaultName)) { + if (!SetDefaultName(fileSaveDialog, args->defaultName)) { return NFD_ERROR; } @@ -542,6 +572,16 @@ nfdresult_t NFD_SaveDialogN(nfdnchar_t** outPath, } nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) { + const nfdpickfoldernargs_t args{defaultPath}; + return NFD_PickFolderN_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_PickFolderN_With_Impl(nfdversion_t version, + nfdnchar_t** outPath, + const nfdpickfoldernargs_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + ::IFileOpenDialog* fileOpenDialog; // Create dialog @@ -557,7 +597,7 @@ nfdresult_t NFD_PickFolderN(nfdnchar_t** outPath, const nfdnchar_t* defaultPath) Release_Guard<::IFileOpenDialog> fileOpenDialogGuard(fileOpenDialog); // Set the default path - if (!SetDefaultPath(fileOpenDialog, defaultPath)) { + if (!SetDefaultPath(fileOpenDialog, args->defaultPath)) { return NFD_ERROR; } @@ -810,23 +850,34 @@ void NFD_FreePathU8(nfdu8char_t* outPath) { nfdresult_t NFD_OpenDialogU8(nfdu8char_t** outPath, const nfdu8filteritem_t* filterList, - nfdfiltersize_t count, + nfdfiltersize_t filterCount, const nfdu8char_t* defaultPath) { + const nfdopendialogu8args_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogU8_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_OpenDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdopendialogu8args_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + // populate the real nfdnfilteritem_t FilterItem_Guard filterItemsNGuard; - if (!CopyFilterItem(filterList, count, filterItemsNGuard)) { + if (!CopyFilterItem(args->filterList, args->filterCount, filterItemsNGuard)) { return NFD_ERROR; } // convert and normalize the default path, but only if it is not nullptr FreeCheck_Guard defaultPathNGuard; - ConvertU8ToNative(defaultPath, defaultPathNGuard); + ConvertU8ToNative(args->defaultPath, defaultPathNGuard); NormalizePathSeparator(defaultPathNGuard.data); // call the native function nfdnchar_t* outPathN; - nfdresult_t res = - NFD_OpenDialogN(&outPathN, filterItemsNGuard.data, count, defaultPathNGuard.data); + const nfdopendialognargs_t argsN{ + filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data}; + nfdresult_t res = NFD_OpenDialogN_With_Impl(NFD_INTERFACE_VERSION, &outPathN, &argsN); if (res != NFD_OKAY) { return res; @@ -845,21 +896,33 @@ nfdresult_t NFD_OpenDialogU8(nfdu8char_t** outPath, * returns NFD_OKAY */ nfdresult_t NFD_OpenDialogMultipleU8(const nfdpathset_t** outPaths, const nfdu8filteritem_t* filterList, - nfdfiltersize_t count, + nfdfiltersize_t filterCount, const nfdu8char_t* defaultPath) { + const nfdopendialogu8args_t args{filterList, filterCount, defaultPath}; + return NFD_OpenDialogMultipleU8_With_Impl(NFD_INTERFACE_VERSION, outPaths, &args); +} + +nfdresult_t NFD_OpenDialogMultipleU8_With_Impl(nfdversion_t version, + const nfdpathset_t** outPaths, + const nfdopendialogu8args_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + // populate the real nfdnfilteritem_t FilterItem_Guard filterItemsNGuard; - if (!CopyFilterItem(filterList, count, filterItemsNGuard)) { + if (!CopyFilterItem(args->filterList, args->filterCount, filterItemsNGuard)) { return NFD_ERROR; } // convert and normalize the default path, but only if it is not nullptr FreeCheck_Guard defaultPathNGuard; - ConvertU8ToNative(defaultPath, defaultPathNGuard); + ConvertU8ToNative(args->defaultPath, defaultPathNGuard); NormalizePathSeparator(defaultPathNGuard.data); // call the native function - return NFD_OpenDialogMultipleN(outPaths, filterItemsNGuard.data, count, defaultPathNGuard.data); + const nfdopendialognargs_t argsN{ + filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data}; + return NFD_OpenDialogMultipleN_With_Impl(NFD_INTERFACE_VERSION, outPaths, &argsN); } /* save dialog */ @@ -867,28 +930,39 @@ nfdresult_t NFD_OpenDialogMultipleU8(const nfdpathset_t** outPaths, * NFD_OKAY */ nfdresult_t NFD_SaveDialogU8(nfdu8char_t** outPath, const nfdu8filteritem_t* filterList, - nfdfiltersize_t count, + nfdfiltersize_t filterCount, const nfdu8char_t* defaultPath, const nfdu8char_t* defaultName) { + const nfdsavedialogu8args_t args{filterList, filterCount, defaultPath, defaultName}; + return NFD_SaveDialogU8_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_SaveDialogU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdsavedialogu8args_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + // populate the real nfdnfilteritem_t FilterItem_Guard filterItemsNGuard; - if (!CopyFilterItem(filterList, count, filterItemsNGuard)) { + if (!CopyFilterItem(args->filterList, args->filterCount, filterItemsNGuard)) { return NFD_ERROR; } // convert and normalize the default path, but only if it is not nullptr FreeCheck_Guard defaultPathNGuard; - ConvertU8ToNative(defaultPath, defaultPathNGuard); + ConvertU8ToNative(args->defaultPath, defaultPathNGuard); NormalizePathSeparator(defaultPathNGuard.data); // convert the default name, but only if it is not nullptr FreeCheck_Guard defaultNameNGuard; - ConvertU8ToNative(defaultName, defaultNameNGuard); + ConvertU8ToNative(args->defaultName, defaultNameNGuard); // call the native function nfdnchar_t* outPathN; - nfdresult_t res = NFD_SaveDialogN( - &outPathN, filterItemsNGuard.data, count, defaultPathNGuard.data, defaultNameNGuard.data); + const nfdsavedialognargs_t argsN{ + filterItemsNGuard.data, args->filterCount, defaultPathNGuard.data, defaultNameNGuard.data}; + nfdresult_t res = NFD_SaveDialogN_With_Impl(NFD_INTERFACE_VERSION, &outPathN, &argsN); if (res != NFD_OKAY) { return res; @@ -906,14 +980,25 @@ nfdresult_t NFD_SaveDialogU8(nfdu8char_t** outPath, /* It is the caller's responsibility to free `outPath` via NFD_FreePathU8() if this function returns * NFD_OKAY */ nfdresult_t NFD_PickFolderU8(nfdu8char_t** outPath, const nfdu8char_t* defaultPath) { + const nfdpickfolderu8args_t args{defaultPath}; + return NFD_PickFolderU8_With_Impl(NFD_INTERFACE_VERSION, outPath, &args); +} + +nfdresult_t NFD_PickFolderU8_With_Impl(nfdversion_t version, + nfdu8char_t** outPath, + const nfdpickfolderu8args_t* args) { + // We haven't needed to bump the interface version yet. + (void)version; + // convert and normalize the default path, but only if it is not nullptr FreeCheck_Guard defaultPathNGuard; - ConvertU8ToNative(defaultPath, defaultPathNGuard); + ConvertU8ToNative(args->defaultPath, defaultPathNGuard); NormalizePathSeparator(defaultPathNGuard.data); // call the native function nfdnchar_t* outPathN; - nfdresult_t res = NFD_PickFolderN(&outPathN, defaultPathNGuard.data); + const nfdpickfoldernargs_t argsN{defaultPathNGuard.data}; + nfdresult_t res = NFD_PickFolderN_With_Impl(NFD_INTERFACE_VERSION, &outPathN, &argsN); if (res != NFD_OKAY) { return res; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f965826..dfe29f3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,6 +3,8 @@ set(TEST_LIST test_opendialog.c test_opendialog_cpp.cpp test_opendialog_native.c + test_opendialog_with.c + test_opendialog_native_with.c test_opendialogmultiple.c test_opendialogmultiple_cpp.cpp test_opendialogmultiple_native.c @@ -11,8 +13,12 @@ set(TEST_LIST test_pickfolder.c test_pickfolder_cpp.cpp test_pickfolder_native.c + test_pickfolder_with.c + test_pickfolder_native_with.c test_savedialog.c - test_savedialog_native.c) + test_savedialog_native.c + test_savedialog_with.c + test_savedialog_native_with.c) foreach (TEST ${TEST_LIST}) string(REPLACE "." "_" CLEAN_TEST_NAME ${TEST}) diff --git a/test/test_opendialog_native_with.c b/test/test_opendialog_native_with.c new file mode 100644 index 0000000..0b2bae6 --- /dev/null +++ b/test/test_opendialog_native_with.c @@ -0,0 +1,52 @@ +#define NFD_NATIVE +#include + +#include +#include + +/* this test should compile on all supported platforms */ + +int main(void) { + // initialize NFD + // either call NFD_Init at the start of your program and NFD_Quit at the end of your program, + // or before/after every time you want to show a file dialog. + NFD_Init(); + + nfdchar_t* outPath; + + // prepare filters for the dialog +#ifdef _WIN32 + nfdfilteritem_t filterItem[2] = {{L"Source code", L"c,cpp,cc"}, {L"Headers", L"h,hpp"}}; +#else + nfdfilteritem_t filterItem[2] = {{"Source code", "c,cpp,cc"}, {"Headers", "h,hpp"}}; +#endif + + // show the dialog + nfdopendialognargs_t args = {0}; + args.filterList = filterItem; + args.filterCount = 2; + nfdresult_t result = NFD_OpenDialogN_With(&outPath, args); + if (result == NFD_OKAY) { + puts("Success!"); +#ifdef _WIN32 +#ifdef _MSC_VER + _putws(outPath); +#else + fputws(outPath, stdin); +#endif +#else + puts(outPath); +#endif + // remember to free the memory (since NFD_OKAY is returned) + NFD_FreePath(outPath); + } else if (result == NFD_CANCEL) { + puts("User pressed cancel."); + } else { + printf("Error: %s\n", NFD_GetError()); + } + + // Quit NFD + NFD_Quit(); + + return 0; +} diff --git a/test/test_opendialog_with.c b/test/test_opendialog_with.c new file mode 100644 index 0000000..6c05f13 --- /dev/null +++ b/test/test_opendialog_with.c @@ -0,0 +1,39 @@ +#include + +#include +#include + +/* this test should compile on all supported platforms */ + +int main(void) { + // initialize NFD + // either call NFD_Init at the start of your program and NFD_Quit at the end of your program, + // or before/after every time you want to show a file dialog. + NFD_Init(); + + nfdchar_t* outPath; + + // prepare filters for the dialog + nfdfilteritem_t filterItem[2] = {{"Source code", "c,cpp,cc"}, {"Headers", "h,hpp"}}; + + // show the dialog + nfdopendialogu8args_t args = {0}; + args.filterList = filterItem; + args.filterCount = 2; + nfdresult_t result = NFD_OpenDialogU8_With(&outPath, args); + if (result == NFD_OKAY) { + puts("Success!"); + puts(outPath); + // remember to free the memory (since NFD_OKAY is returned) + NFD_FreePath(outPath); + } else if (result == NFD_CANCEL) { + puts("User pressed cancel."); + } else { + printf("Error: %s\n", NFD_GetError()); + } + + // Quit NFD + NFD_Quit(); + + return 0; +} diff --git a/test/test_pickfolder_native_with.c b/test/test_pickfolder_native_with.c new file mode 100644 index 0000000..ac439c3 --- /dev/null +++ b/test/test_pickfolder_native_with.c @@ -0,0 +1,43 @@ +#define NFD_NATIVE +#include + +#include +#include + +/* this test should compile on all supported platforms */ + +int main(void) { + // initialize NFD + // either call NFD_Init at the start of your program and NFD_Quit at the end of your program, + // or before/after every time you want to show a file dialog. + NFD_Init(); + + nfdchar_t* outPath; + + // show the dialog + nfdpickfoldernargs_t args = {0}; + nfdresult_t result = NFD_PickFolderN_With(&outPath, args); + if (result == NFD_OKAY) { + puts("Success!"); +#ifdef _WIN32 +#ifdef _MSC_VER + _putws(outPath); +#else + fputws(outPath, stdin); +#endif +#else + puts(outPath); +#endif + // remember to free the memory (since NFD_OKAY is returned) + NFD_FreePath(outPath); + } else if (result == NFD_CANCEL) { + puts("User pressed cancel."); + } else { + printf("Error: %s\n", NFD_GetError()); + } + + // Quit NFD + NFD_Quit(); + + return 0; +} diff --git a/test/test_pickfolder_with.c b/test/test_pickfolder_with.c new file mode 100644 index 0000000..5d6af30 --- /dev/null +++ b/test/test_pickfolder_with.c @@ -0,0 +1,34 @@ +#include + +#include +#include + +/* this test should compile on all supported platforms */ + +int main(void) { + // initialize NFD + // either call NFD_Init at the start of your program and NFD_Quit at the end of your program, + // or before/after every time you want to show a file dialog. + NFD_Init(); + + nfdchar_t* outPath; + + // show the dialog + nfdpickfolderu8args_t args = {0}; + nfdresult_t result = NFD_PickFolderU8_With(&outPath, args); + if (result == NFD_OKAY) { + puts("Success!"); + puts(outPath); + // remember to free the memory (since NFD_OKAY is returned) + NFD_FreePath(outPath); + } else if (result == NFD_CANCEL) { + puts("User pressed cancel."); + } else { + printf("Error: %s\n", NFD_GetError()); + } + + // Quit NFD + NFD_Quit(); + + return 0; +} diff --git a/test/test_savedialog_native_with.c b/test/test_savedialog_native_with.c new file mode 100644 index 0000000..3a87867 --- /dev/null +++ b/test/test_savedialog_native_with.c @@ -0,0 +1,59 @@ +#define NFD_NATIVE +#include + +#include +#include + +/* this test should compile on all supported platforms */ + +int main(void) { + // initialize NFD + // either call NFD_Init at the start of your program and NFD_Quit at the end of your program, + // or before/after every time you want to show a file dialog. + NFD_Init(); + + nfdchar_t* savePath; + + // prepare filters for the dialog +#ifdef _WIN32 + nfdfilteritem_t filterItem[2] = {{L"Source code", L"c,cpp,cc"}, {L"Headers", L"h,hpp"}}; +#else + nfdfilteritem_t filterItem[2] = {{"Source code", "c,cpp,cc"}, {"Headers", "h,hpp"}}; +#endif + +#ifdef _WIN32 + const wchar_t* defaultPath = L"Untitled.c"; +#else + const char* defaultPath = "Untitled.c"; +#endif + + // show the dialog + nfdsavedialognargs_t args = {0}; + args.filterList = filterItem; + args.filterCount = 2; + args.defaultName = defaultPath; + nfdresult_t result = NFD_SaveDialogN_With(&savePath, args); + if (result == NFD_OKAY) { + puts("Success!"); +#ifdef _WIN32 +#ifdef _MSC_VER + _putws(savePath); +#else + fputws(savePath, stdin); +#endif +#else + puts(savePath); +#endif + // remember to free the memory (since NFD_OKAY is returned) + NFD_FreePath(savePath); + } else if (result == NFD_CANCEL) { + puts("User pressed cancel."); + } else { + printf("Error: %s\n", NFD_GetError()); + } + + // Quit NFD + NFD_Quit(); + + return 0; +} diff --git a/test/test_savedialog_with.c b/test/test_savedialog_with.c new file mode 100644 index 0000000..a3c4d2e --- /dev/null +++ b/test/test_savedialog_with.c @@ -0,0 +1,40 @@ +#include + +#include +#include + +/* this test should compile on all supported platforms */ + +int main(void) { + // initialize NFD + // either call NFD_Init at the start of your program and NFD_Quit at the end of your program, + // or before/after every time you want to show a file dialog. + NFD_Init(); + + nfdchar_t* savePath; + + // prepare filters for the dialog + nfdfilteritem_t filterItem[2] = {{"Source code", "c,cpp,cc"}, {"Header", "h,hpp"}}; + + // show the dialog + nfdsavedialogu8args_t args = {0}; + args.filterList = filterItem; + args.filterCount = 2; + args.defaultName = "Untitled.c"; + nfdresult_t result = NFD_SaveDialogU8_With(&savePath, args); + if (result == NFD_OKAY) { + puts("Success!"); + puts(savePath); + // remember to free the memory (since NFD_OKAY is returned) + NFD_FreePath(savePath); + } else if (result == NFD_CANCEL) { + puts("User pressed cancel."); + } else { + printf("Error: %s\n", NFD_GetError()); + } + + // Quit NFD + NFD_Quit(); + + return 0; +}