Atlas - SDL_dialog_utils.c
Home / ext / SDL / src / dialog Lines: 1 | Size: 7528 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#include "SDL_dialog_utils.h" 24 25char *convert_filters(const SDL_DialogFileFilter *filters, int nfilters, 26 NameTransform ntf, const char *prefix, 27 const char *separator, const char *suffix, 28 const char *filt_prefix, const char *filt_separator, 29 const char *filt_suffix, const char *ext_prefix, 30 const char *ext_separator, const char *ext_suffix) 31{ 32 char *combined; 33 char *new_combined; 34 char *converted; 35 const char *terminator; 36 size_t new_length; 37 int i; 38 39 if (!filters) { 40 SDL_SetError("Called convert_filters() with NULL filters (SDL bug)"); 41 return NULL; 42 } 43 44 combined = SDL_strdup(prefix); 45 46 if (!combined) { 47 return NULL; 48 } 49 50 for (i = 0; i < nfilters; i++) { 51 const SDL_DialogFileFilter *f = &filters[i]; 52 53 converted = convert_filter(*f, ntf, filt_prefix, filt_separator, 54 filt_suffix, ext_prefix, ext_separator, 55 ext_suffix); 56 57 if (!converted) { 58 SDL_free(combined); 59 return NULL; 60 } 61 62 terminator = ((i + 1) < nfilters) ? separator : suffix; 63 new_length = SDL_strlen(combined) + SDL_strlen(converted) 64 + SDL_strlen(terminator) + 1; 65 66 new_combined = (char *)SDL_realloc(combined, new_length); 67 68 if (!new_combined) { 69 SDL_free(converted); 70 SDL_free(combined); 71 return NULL; 72 } 73 74 combined = new_combined; 75 76 SDL_strlcat(combined, converted, new_length); 77 SDL_strlcat(combined, terminator, new_length); 78 SDL_free(converted); 79 } 80 81 new_length = SDL_strlen(combined) + SDL_strlen(suffix) + 1; 82 83 new_combined = (char *)SDL_realloc(combined, new_length); 84 85 if (!new_combined) { 86 SDL_free(combined); 87 return NULL; 88 } 89 90 combined = new_combined; 91 92 SDL_strlcat(combined, suffix, new_length); 93 94 return combined; 95} 96 97char *convert_filter(SDL_DialogFileFilter filter, NameTransform ntf, 98 const char *prefix, const char *separator, 99 const char *suffix, const char *ext_prefix, 100 const char *ext_separator, const char *ext_suffix) 101{ 102 char *converted; 103 char *name_filtered; 104 size_t total_length; 105 char *list; 106 107 list = convert_ext_list(filter.pattern, ext_prefix, ext_separator, 108 ext_suffix); 109 110 if (!list) { 111 return NULL; 112 } 113 114 if (ntf) { 115 name_filtered = ntf(filter.name); 116 } else { 117 // Useless strdup, but easier to read and maintain code this way 118 name_filtered = SDL_strdup(filter.name); 119 } 120 121 if (!name_filtered) { 122 SDL_free(list); 123 return NULL; 124 } 125 126 total_length = SDL_strlen(prefix) + SDL_strlen(name_filtered) 127 + SDL_strlen(separator) + SDL_strlen(list) 128 + SDL_strlen(suffix) + 1; 129 130 converted = (char *) SDL_malloc(total_length); 131 132 if (!converted) { 133 SDL_free(list); 134 SDL_free(name_filtered); 135 return NULL; 136 } 137 138 SDL_snprintf(converted, total_length, "%s%s%s%s%s", prefix, name_filtered, 139 separator, list, suffix); 140 141 SDL_free(list); 142 SDL_free(name_filtered); 143 144 return converted; 145} 146 147char *convert_ext_list(const char *list, const char *prefix, 148 const char *separator, const char *suffix) 149{ 150 char *converted; 151 int semicolons; 152 size_t total_length; 153 154 semicolons = 0; 155 156 for (const char *c = list; *c; c++) { 157 semicolons += (*c == ';'); 158 } 159 160 total_length = 161 SDL_strlen(list) - semicolons // length of list contents 162 + semicolons * SDL_strlen(separator) // length of separators 163 + SDL_strlen(prefix) + SDL_strlen(suffix) // length of prefix/suffix 164 + 1; // terminating null byte 165 166 converted = (char *) SDL_malloc(total_length); 167 168 if (!converted) { 169 return NULL; 170 } 171 172 *converted = '\0'; 173 174 SDL_strlcat(converted, prefix, total_length); 175 176 /* Some platforms may prefer to handle the asterisk manually, but this 177 function offers to handle it for ease of use. */ 178 if (SDL_strcmp(list, "*") == 0) { 179 SDL_strlcat(converted, "*", total_length); 180 } else { 181 for (const char *c = list; *c; c++) { 182 if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') 183 || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_' 184 || *c == '.') { 185 char str[2]; 186 str[0] = *c; 187 str[1] = '\0'; 188 SDL_strlcat(converted, str, total_length); 189 } else if (*c == ';') { 190 if (c == list || c[-1] == ';') { 191 SDL_SetError("Empty pattern not allowed"); 192 SDL_free(converted); 193 return NULL; 194 } 195 196 SDL_strlcat(converted, separator, total_length); 197 } else { 198 SDL_SetError("Invalid character '%c' in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)", *c); 199 SDL_free(converted); 200 return NULL; 201 } 202 } 203 } 204 205 if (list[SDL_strlen(list) - 1] == ';') { 206 SDL_SetError("Empty pattern not allowed"); 207 SDL_free(converted); 208 return NULL; 209 } 210 211 SDL_strlcat(converted, suffix, total_length); 212 213 return converted; 214} 215 216const char *validate_filters(const SDL_DialogFileFilter *filters, int nfilters) 217{ 218 if (filters) { 219 for (int i = 0; i < nfilters; i++) { 220 const char *msg = validate_list(filters[i].pattern); 221 222 if (msg) { 223 return msg; 224 } 225 } 226 } 227 228 return NULL; 229} 230 231const char *validate_list(const char *list) 232{ 233 if (SDL_strcmp(list, "*") == 0) { 234 return NULL; 235 } else { 236 for (const char *c = list; *c; c++) { 237 if ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') 238 || (*c >= '0' && *c <= '9') || *c == '-' || *c == '_' 239 || *c == '.') { 240 continue; 241 } else if (*c == ';') { 242 if (c == list || c[-1] == ';') { 243 return "Empty pattern not allowed"; 244 } 245 } else { 246 return "Invalid character in pattern (Only [a-zA-Z0-9_.-] allowed, or a single *)"; 247 } 248 } 249 } 250 251 if (list[SDL_strlen(list) - 1] == ';') { 252 return "Empty pattern not allowed"; 253 } 254 255 return NULL; 256} 257[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.