From 691cc5bb5e95b4c101d874b29dd112bced86e598 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Thu, 1 May 2025 18:11:36 -0400 Subject: [PATCH] dialog: Cocoa shouldn't crash if there's a '.' in the filters. So something like "index.pb" will now accept any file with a ".pb" extension, to make macOS happy. This seems like a reasonable tradeoff. Other minor cleanups. Fixes #12778. --- src/dialog/cocoa/SDL_cocoadialog.m | 35 ++++++++++++++++++++---------- test/testdialog.c | 8 +++---- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/dialog/cocoa/SDL_cocoadialog.m b/src/dialog/cocoa/SDL_cocoadialog.m index fb9c5ad88f..a6054a6eba 100644 --- a/src/dialog/cocoa/SDL_cocoadialog.m +++ b/src/dialog/cocoa/SDL_cocoadialog.m @@ -27,6 +27,26 @@ #import #import +static void AddFileExtensionType(NSMutableArray *types, const char *pattern_ptr) +{ + if (!*pattern_ptr) { + return; // in case the string had an extra ';' at the end. + } + + // -[UTType typeWithFilenameExtension] will return nil if there's a period in the string. It's better to + // allow too many files than not allow the one the user actually needs, so just take the part after the '.' + const char *dot = SDL_strrchr(pattern_ptr, '.'); + NSString *extstr = [NSString stringWithFormat: @"%s", dot ? (dot + 1) : pattern_ptr]; + if (@available(macOS 11.0, *)) { + UTType *uttype = [UTType typeWithFilenameExtension:extstr]; + if (uttype) { // still failed? Don't add the pattern. This is what the pre-macOS11 path does internally anyhow. + [types addObject:uttype]; + } + } else { + [types addObject:extstr]; + } +} + void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFileCallback callback, void *userdata, SDL_PropertiesID props) { SDL_Window* window = SDL_GetPointerProperty(props, SDL_PROP_FILE_DIALOG_WINDOW_POINTER, NULL); @@ -87,7 +107,7 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil if (filters) { // On macOS 11.0 and up, this is an array of UTType. Prior to that, it's an array of NSString - NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters ]; + NSMutableArray *types = [[NSMutableArray alloc] initWithCapacity:nfilters]; int has_all_files = 0; for (int i = 0; i < nfilters; i++) { @@ -102,21 +122,14 @@ void SDL_SYS_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_DialogFil for (char *c = pattern; *c; c++) { if (*c == ';') { *c = '\0'; - if(@available(macOS 11.0, *)) { - [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; - } else { - [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; - } + AddFileExtensionType(types, pattern_ptr); pattern_ptr = c + 1; } else if (*c == '*') { has_all_files = 1; } } - if(@available(macOS 11.0, *)) { - [types addObject: [UTType typeWithFilenameExtension:[NSString stringWithFormat: @"%s", pattern_ptr]]]; - } else { - [types addObject: [NSString stringWithFormat: @"%s", pattern_ptr]]; - } + + AddFileExtensionType(types, pattern_ptr); // get the last piece of the string. SDL_free(pattern); } diff --git a/test/testdialog.c b/test/testdialog.c index 3d19fb9416..dcff5bd9f0 100644 --- a/test/testdialog.c +++ b/test/testdialog.c @@ -15,8 +15,9 @@ #include #include -const SDL_DialogFileFilter filters[3] = { +const SDL_DialogFileFilter filters[] = { { "All files", "*" }, + { "SVI Session Indexes", "index;svi-index;index.pb" }, { "JPG images", "jpg;jpeg" }, { "PNG images", "png" } }; @@ -54,7 +55,6 @@ int main(int argc, char *argv[]) const SDL_FRect open_folder_rect = { 370, 50, 220, 140 }; int i; const char *initial_path = NULL; - const int nfilters = sizeof(filters) / sizeof(*filters); /* Initialize test framework */ state = SDLTest_CommonCreateState(argv, 0); @@ -112,11 +112,11 @@ int main(int argc, char *argv[]) * - Nonzero if the user is allowed to choose multiple entries (not for SDL_ShowSaveFileDialog) */ if (SDL_PointInRectFloat(&p, &open_file_rect)) { - SDL_ShowOpenFileDialog(callback, NULL, w, filters, nfilters, initial_path, 1); + SDL_ShowOpenFileDialog(callback, NULL, w, filters, SDL_arraysize(filters), initial_path, 1); } else if (SDL_PointInRectFloat(&p, &open_folder_rect)) { SDL_ShowOpenFolderDialog(callback, NULL, w, initial_path, 1); } else if (SDL_PointInRectFloat(&p, &save_file_rect)) { - SDL_ShowSaveFileDialog(callback, NULL, w, filters, nfilters, initial_path); + SDL_ShowSaveFileDialog(callback, NULL, w, filters, SDL_arraysize(filters), initial_path); } } }