From 5a079a2d114f96d4847d1ee305d5b7c16eeec50e Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 27 Dec 2025 12:03:39 -0800 Subject: Initial commit --- contrib/SDL-3.2.8/src/dialog/SDL_dialog_utils.c | 256 ++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 contrib/SDL-3.2.8/src/dialog/SDL_dialog_utils.c (limited to 'contrib/SDL-3.2.8/src/dialog/SDL_dialog_utils.c') diff --git a/contrib/SDL-3.2.8/src/dialog/SDL_dialog_utils.c b/contrib/SDL-3.2.8/src/dialog/SDL_dialog_utils.c new file mode 100644 index 0000000..8d2b186 --- /dev/null +++ b/contrib/SDL-3.2.8/src/dialog/SDL_dialog_utils.c @@ -0,0 +1,256 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2025 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_internal.h" + +#include "SDL_dialog_utils.h" + +char *convert_filters(const SDL_DialogFileFilter *filters, int nfilters, + NameTransform ntf, const char *prefix, + const char *separator, const char *suffix, + const char *filt_prefix, const char *filt_separator, + const char *filt_suffix, const char *ext_prefix, + const char *ext_separator, const char *ext_suffix) +{ + char *combined; + char *new_combined; + char *converted; + const char *terminator; + size_t new_length; + int i; + + if (!filters) { + SDL_SetError("Called convert_filters() with NULL filters (SDL bug)"); + return NULL; + } + + combined = SDL_strdup(prefix); + + if (!combined) { + return NULL; + } + + for (i = 0; i < nfilters; i++) { + const SDL_DialogFileFilter *f = &filters[i]; + + converted = convert_filter(*f, ntf, filt_prefix, filt_separator, + filt_suffix, ext_prefix, ext_separator, + ext_suffix); + + if (!converted) { + SDL_free(combined); + return NULL; + } + + terminator = ((i + 1) < nfilters) ? separator : suffix; + new_length = SDL_strlen(combined) + SDL_strlen(converted) + + SDL_strlen(terminator) + 1; + + new_combined = (char *)SDL_realloc(combined, new_length); + + if (!new_combined) { + SDL_free(converted); + SDL_free(combined); + return NULL; + } + + combined = new_combined; + + SDL_strlcat(combined, converted, new_length); + SDL_strlcat(combined, terminator, new_length); + SDL_free(converted); + } + + new_length = SDL_strlen(combined) + SDL_strlen(suffix) + 1; + + new_combined = (char *)SDL_realloc(combined, new_length); + + if (!new_combined) { + SDL_free(combined); + return NULL; + } + + combined = new_combined; + + SDL_strlcat(combined, suffix, new_length); + + return combined; +} + +char *convert_filter(SDL_DialogFileFilter filter, NameTransform ntf, + const char *prefix, const char *separator, + const char *suffix, const char *ext_prefix, + const char *ext_separator, const char *ext_suffix) +{ + char *converted; + char *name_filtered; + size_t total_length; + char *list; + + list = convert_ext_list(filter.pattern, ext_prefix, ext_separator, + ext_suffix); + + if (!list) { + return NULL; + } + + if (ntf) { + name_filtered = ntf(filter.name); + } else { + // Useless strdup, but easier to read and maintain code this way + name_filtered = SDL_strdup(filter.name); + } + + if (!name_filtered) { + SDL_free(list); + return NULL; + } + + total_length = SDL_strlen(prefix) + SDL_strlen(name_filtered) + + SDL_strlen(separator) + SDL_strlen(list) + + SDL_strlen(suffix) + 1; + + converted = (char *) SDL_malloc(total_length); + + if (!converted) { + SDL_free(list); + SDL_free(name_filtered); + return NULL; + } + + SDL_snprintf(converted, total_length, "%s%s%s%s%s", prefix, name_filtered, + separator, list, suffix); + + SDL_free(list); + SDL_free(name_filtered); + + return converted; +} + +char *convert_ext_list(const char *list, const char *prefix, + const char *separator, const char *suffix) +{ + char *converted; + int semicolons; + size_t total_length; + + semicolons = 0; + + for (const char *c = list; *c; c++) { + semicolons += (*c == ';'); + } + + total_length = + SDL_strlen(list) - semicolons // length of list contents + + semicolons * SDL_strlen(separator) // length of separators + + SDL_strlen(prefix) + SDL_strlen(suffix) // length of prefix/suffix + + 1; // terminating null byte + + converted = (char *) SDL_malloc(total_length); + + if (!converted) { + return NULL; + } + + *converted = '\0'; + + SDL_strlcat(converted, prefix, total_length); + + /* Some platforms may prefer to handle the asterisk manually, but this + function offers to handle it for ease of use. */ + if (SDL_strcmp(list, "*") == 0) { + SDL_strlcat(converted, "*", total_length); + } else { + for (const char *c = list; *c; c++) { + if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') + || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_' + || *c == '.') { + char str[2]; + str[0] = *c; + str[1] = '\0'; + SDL_strlcat(converted, str, total_length); + } else if (*c == ';') { + if (c == list || c[-1] == ';') { + SDL_SetError("Empty pattern not allowed"); + SDL_free(converted); + return NULL; + } + + SDL_strlcat(converted, separator, total_length); + } else { + SDL_SetError("Invalid character '%c' in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)", *c); + SDL_free(converted); + return NULL; + } + } + } + + if (list[SDL_strlen(list) - 1] == ';') { + SDL_SetError("Empty pattern not allowed"); + SDL_free(converted); + return NULL; + } + + SDL_strlcat(converted, suffix, total_length); + + return converted; +} + +const char *validate_filters(const SDL_DialogFileFilter *filters, int nfilters) +{ + if (filters) { + for (int i = 0; i < nfilters; i++) { + const char *msg = validate_list(filters[i].pattern); + + if (msg) { + return msg; + } + } + } + + return NULL; +} + +const char *validate_list(const char *list) +{ + if (SDL_strcmp(list, "*") == 0) { + return NULL; + } else { + for (const char *c = list; *c; c++) { + if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') + || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_' + || *c == '.') { + continue; + } else if (*c == ';') { + if (c == list || c[-1] == ';') { + return "Empty pattern not allowed"; + } + } else { + return "Invalid character in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)"; + } + } + } + + if (list[SDL_strlen(list) - 1] == ';') { + return "Empty pattern not allowed"; + } + + return NULL; +} -- cgit v1.2.3