mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-18 09:18:14 +00:00
File dialog improvements
- Add a globally-accessible function to handle the parsing of filter extensions - Remove the ability of putting the wildcard ('*') among other patterns; it's either a list of patterns or a single '*' now - Add a hint to select between portals and Zenity on Unix
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
#include "./SDL_dialog.h"
|
||||
#include "../SDL_dialog_utils.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
@@ -65,6 +65,22 @@ typedef struct
|
||||
} \
|
||||
}
|
||||
|
||||
char *zenity_clean_name(const char *name)
|
||||
{
|
||||
char *newname = SDL_strdup(name);
|
||||
|
||||
/* Filter out "|", which Zenity considers a special character. Let's hope
|
||||
there aren't others. TODO: find something better. */
|
||||
for (char *c = newname; *c; c++) {
|
||||
if (*c == '|') {
|
||||
/* Zenity doesn't support escaping with \ */
|
||||
*c = '/';
|
||||
}
|
||||
}
|
||||
|
||||
return newname;
|
||||
}
|
||||
|
||||
/* Exec call format:
|
||||
*
|
||||
* /usr/bin/env zenity --file-selection --separator=\n [--multiple]
|
||||
@@ -147,68 +163,15 @@ static char** generate_args(const zenityArgs* info)
|
||||
const SDL_DialogFileFilter *filter_ptr = info->filters;
|
||||
|
||||
while (filter_ptr->name && filter_ptr->pattern) {
|
||||
/* *Normally*, no filter arg should exceed 4096 bytes. */
|
||||
char buffer[4096];
|
||||
char *filter_str = convert_filter(*filter_ptr, zenity_clean_name,
|
||||
"--file-filter=", " | ", "",
|
||||
"*.", " *.", "");
|
||||
|
||||
SDL_snprintf(buffer, 4096, "--file-filter=%s | *.", filter_ptr->name);
|
||||
size_t i_buf = SDL_strlen(buffer);
|
||||
|
||||
/* "|" is a special character for Zenity */
|
||||
for (char *c = buffer; *c; c++) {
|
||||
if (*c == '|') {
|
||||
*c = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i_pat = 0; i_buf < 4095 && filter_ptr->pattern[i_pat]; i_pat++) {
|
||||
const char *c = filter_ptr->pattern + i_pat;
|
||||
|
||||
if (*c == ';') {
|
||||
/* Disallow empty patterns (might bug Zenity) */
|
||||
int at_end = (c[1] == '\0');
|
||||
int at_mid = (c[1] == ';');
|
||||
int at_beg = (i_pat == 0);
|
||||
if (at_end || at_mid || at_beg) {
|
||||
const char *pos_str = "";
|
||||
|
||||
if (at_end) {
|
||||
pos_str = "end";
|
||||
} else if (at_mid) {
|
||||
pos_str = "middle";
|
||||
} else if (at_beg) {
|
||||
pos_str = "beginning";
|
||||
}
|
||||
|
||||
SDL_SetError("Empty pattern file extension (at %s of list)", pos_str);
|
||||
CLEAR_AND_RETURN()
|
||||
}
|
||||
|
||||
if (i_buf + 3 >= 4095) {
|
||||
i_buf += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[i_buf++] = ' ';
|
||||
buffer[i_buf++] = '*';
|
||||
buffer[i_buf++] = '.';
|
||||
} else if (*c == '*' && (c[1] == '\0' || c[1] == ';') && (i_pat == 0 || *(c - 1) == ';')) {
|
||||
buffer[i_buf++] = '*';
|
||||
} else if (!((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z') || (*c >= '0' && *c <= '9') || *c == '.' || *c == '_' || *c == '-')) {
|
||||
SDL_SetError("Illegal character in pattern name: %c (Only alphanumeric characters, periods, underscores and hyphens allowed)", *c);
|
||||
CLEAR_AND_RETURN()
|
||||
} else {
|
||||
buffer[i_buf++] = *c;
|
||||
}
|
||||
}
|
||||
|
||||
if (i_buf >= 4095) {
|
||||
SDL_SetError("Filter '%s' wouldn't fit in a 4096 byte buffer; please report your use case if you need filters that long", filter_ptr->name);
|
||||
if (!filter_str) {
|
||||
CLEAR_AND_RETURN()
|
||||
}
|
||||
|
||||
buffer[i_buf] = '\0';
|
||||
|
||||
argv[nextarg++] = SDL_strdup(buffer);
|
||||
argv[nextarg++] = filter_str;
|
||||
CHECK_OOM()
|
||||
|
||||
filter_ptr++;
|
||||
|
Reference in New Issue
Block a user