Skip to content

Commit

Permalink
Add versioned API
Browse files Browse the repository at this point in the history
  • Loading branch information
btzy committed May 12, 2024
1 parent 17b6e8c commit 4e0db56
Show file tree
Hide file tree
Showing 12 changed files with 762 additions and 56 deletions.
168 changes: 166 additions & 2 deletions src/include/nfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -184,22 +294,76 @@ 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.
* @param[out] 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.
* @param[out] outPath
* @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.
Expand Down
80 changes: 72 additions & 8 deletions src/nfd_cocoa.m
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand Down
Loading

0 comments on commit 4e0db56

Please sign in to comment.