dialog/unix: reduce string allocations
Simplifies logic of spawning the zenity process by avoiding allocations of static strings
This commit is contained in:
committed by
Sam Lantinga
parent
ff82238172
commit
4c86511035
@@ -36,35 +36,25 @@ typedef struct
|
|||||||
bool allow_many;
|
bool allow_many;
|
||||||
SDL_FileDialogType type;
|
SDL_FileDialogType type;
|
||||||
/* Zenity only works with X11 handles apparently */
|
/* Zenity only works with X11 handles apparently */
|
||||||
Uint64 x11_window_handle;
|
char x11_window_handle[64];
|
||||||
const char *title;
|
const char *title;
|
||||||
const char *accept;
|
const char *accept;
|
||||||
const char *cancel;
|
const char *cancel;
|
||||||
} zenityArgs;
|
} zenityArgs;
|
||||||
|
|
||||||
#define CLEAR_AND_RETURN() \
|
typedef struct
|
||||||
{ \
|
{
|
||||||
while (--nextarg >= 0) { \
|
char **argv;
|
||||||
SDL_free(argv[nextarg]); \
|
int argc;
|
||||||
} \
|
|
||||||
SDL_free(argv); \
|
|
||||||
return NULL; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CHECK_OOM() \
|
char **filters_slice;
|
||||||
{ \
|
int nfilters;
|
||||||
if (!argv[nextarg - 1]) { \
|
} Args;
|
||||||
CLEAR_AND_RETURN() \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
if (nextarg > argc) { \
|
|
||||||
SDL_SetError("Zenity dialog problem: argc (%d) < nextarg (%d)", \
|
|
||||||
argc, nextarg); \
|
|
||||||
CLEAR_AND_RETURN() \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
char *zenity_clean_name(const char *name)
|
#define NULL_ARGS \
|
||||||
|
(Args) { NULL }
|
||||||
|
|
||||||
|
static char *zenity_clean_name(const char *name)
|
||||||
{
|
{
|
||||||
char *newname = SDL_strdup(name);
|
char *newname = SDL_strdup(name);
|
||||||
|
|
||||||
@@ -89,70 +79,31 @@ char *zenity_clean_name(const char *name)
|
|||||||
* [--cancel-label CANCEL]
|
* [--cancel-label CANCEL]
|
||||||
* [--file-filter=Filter Name | *.filt *.fn ...]...
|
* [--file-filter=Filter Name | *.filt *.fn ...]...
|
||||||
*/
|
*/
|
||||||
static char** generate_args(const zenityArgs* info)
|
static Args generate_args(const zenityArgs *info)
|
||||||
{
|
{
|
||||||
int argc = 3;
|
int argc = 0;
|
||||||
int nextarg = 0;
|
char **argv = SDL_malloc(
|
||||||
char **argv = NULL;
|
sizeof(*argv) * (3 /* zenity --file-selection --separator=\n */
|
||||||
|
+ 1 /* --multiple */
|
||||||
// ARGC PASS
|
+ 1 /* --directory */
|
||||||
if (info->allow_many) {
|
+ 2 /* --save --confirm-overwrite */
|
||||||
argc++;
|
+ 2 /* --filename [file] */
|
||||||
}
|
+ 3 /* --modal --attach [handle] */
|
||||||
|
+ 2 /* --title [title] */
|
||||||
switch (info->type) {
|
+ 2 /* --ok-label [label] */
|
||||||
case SDL_FILEDIALOG_OPENFILE:
|
+ 2 /* --cancel-label [label] */
|
||||||
break;
|
+ info->nfilters + 1 /* NULL */));
|
||||||
|
|
||||||
case SDL_FILEDIALOG_SAVEFILE:
|
|
||||||
argc += 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_FILEDIALOG_OPENFOLDER:
|
|
||||||
argc++;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (info->filename) {
|
|
||||||
argc += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->x11_window_handle) {
|
|
||||||
argc += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->title) {
|
|
||||||
argc += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->accept) {
|
|
||||||
argc += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->cancel) {
|
|
||||||
argc += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info->filters) {
|
|
||||||
argc += info->nfilters;
|
|
||||||
}
|
|
||||||
|
|
||||||
argv = SDL_malloc(sizeof(char *) * argc + 1);
|
|
||||||
if (!argv) {
|
if (!argv) {
|
||||||
return NULL;
|
return NULL_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARGV PASS
|
// ARGV PASS
|
||||||
argv[nextarg++] = SDL_strdup("zenity");
|
argv[argc++] = "zenity";
|
||||||
CHECK_OOM()
|
argv[argc++] = "--file-selection";
|
||||||
argv[nextarg++] = SDL_strdup("--file-selection");
|
argv[argc++] = "--separator=\n";
|
||||||
CHECK_OOM()
|
|
||||||
argv[nextarg++] = SDL_strdup("--separator=\n");
|
|
||||||
CHECK_OOM()
|
|
||||||
|
|
||||||
if (info->allow_many) {
|
if (info->allow_many) {
|
||||||
argv[nextarg++] = SDL_strdup("--multiple");
|
argv[argc++] = "--multiple";
|
||||||
CHECK_OOM()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (info->type) {
|
switch (info->type) {
|
||||||
@@ -160,61 +111,43 @@ static char** generate_args(const zenityArgs* info)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_FILEDIALOG_SAVEFILE:
|
case SDL_FILEDIALOG_SAVEFILE:
|
||||||
argv[nextarg++] = SDL_strdup("--save");
|
argv[argc++] = "--save";
|
||||||
/* Asking before overwriting while saving seems like a sane default */
|
/* Asking before overwriting while saving seems like a sane default */
|
||||||
argv[nextarg++] = SDL_strdup("--confirm-overwrite");
|
argv[argc++] = "--confirm-overwrite";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_FILEDIALOG_OPENFOLDER:
|
case SDL_FILEDIALOG_OPENFOLDER:
|
||||||
argv[nextarg++] = SDL_strdup("--directory");
|
argv[argc++] = "--directory";
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (info->filename) {
|
if (info->filename) {
|
||||||
argv[nextarg++] = SDL_strdup("--filename");
|
argv[argc++] = "--filename";
|
||||||
CHECK_OOM()
|
argv[argc++] = (char *)info->filename;
|
||||||
|
|
||||||
argv[nextarg++] = SDL_strdup(info->filename);
|
|
||||||
CHECK_OOM()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->x11_window_handle) {
|
if (info->x11_window_handle[0]) {
|
||||||
argv[nextarg++] = SDL_strdup("--modal");
|
argv[argc++] = "--modal";
|
||||||
CHECK_OOM()
|
argv[argc++] = "--attach";
|
||||||
|
argv[argc++] = (char *)info->x11_window_handle;
|
||||||
argv[nextarg++] = SDL_strdup("--attach");
|
|
||||||
CHECK_OOM()
|
|
||||||
|
|
||||||
argv[nextarg++] = SDL_malloc(64);
|
|
||||||
CHECK_OOM()
|
|
||||||
|
|
||||||
SDL_snprintf(argv[nextarg - 1], 64, "0x%" SDL_PRIx64, info->x11_window_handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->title) {
|
if (info->title) {
|
||||||
argv[nextarg++] = SDL_strdup("--title");
|
argv[argc++] = "--title";
|
||||||
CHECK_OOM()
|
argv[argc++] = (char *)info->title;
|
||||||
|
|
||||||
argv[nextarg++] = SDL_strdup(info->title);
|
|
||||||
CHECK_OOM()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->accept) {
|
if (info->accept) {
|
||||||
argv[nextarg++] = SDL_strdup("--ok-label");
|
argv[argc++] = "--ok-label";
|
||||||
CHECK_OOM()
|
argv[argc++] = (char *)info->accept;
|
||||||
|
|
||||||
argv[nextarg++] = SDL_strdup(info->accept);
|
|
||||||
CHECK_OOM()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->cancel) {
|
if (info->cancel) {
|
||||||
argv[nextarg++] = SDL_strdup("--cancel-label");
|
argv[argc++] = "--cancel-label";
|
||||||
CHECK_OOM()
|
argv[argc++] = (char *)info->cancel;
|
||||||
|
|
||||||
argv[nextarg++] = SDL_strdup(info->cancel);
|
|
||||||
CHECK_OOM()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char **filters_slice = &argv[argc];
|
||||||
if (info->filters) {
|
if (info->filters) {
|
||||||
for (int i = 0; i < info->nfilters; i++) {
|
for (int i = 0; i < info->nfilters; i++) {
|
||||||
char *filter_str = convert_filter(info->filters[i],
|
char *filter_str = convert_filter(info->filters[i],
|
||||||
@@ -223,29 +156,38 @@ static char** generate_args(const zenityArgs* info)
|
|||||||
"*.", " *.", "");
|
"*.", " *.", "");
|
||||||
|
|
||||||
if (!filter_str) {
|
if (!filter_str) {
|
||||||
CLEAR_AND_RETURN()
|
while (i--) {
|
||||||
|
SDL_free(filters_slice[i]);
|
||||||
|
}
|
||||||
|
SDL_free(argv);
|
||||||
|
return NULL_ARGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[nextarg++] = filter_str;
|
filters_slice[i] = filter_str;
|
||||||
CHECK_OOM()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[nextarg++] = NULL;
|
argc += info->nfilters;
|
||||||
|
argv[argc] = NULL;
|
||||||
|
|
||||||
return argv;
|
return (Args){
|
||||||
|
.argv = argv,
|
||||||
|
.argc = argc,
|
||||||
|
.filters_slice = filters_slice,
|
||||||
|
.nfilters = info->nfilters
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_args(char **argv)
|
static void free_args(Args args)
|
||||||
{
|
{
|
||||||
char **ptr = argv;
|
if (!args.argv) {
|
||||||
|
return;
|
||||||
while (*ptr) {
|
}
|
||||||
SDL_free(*ptr);
|
for (int i = 0; i < args.nfilters; i++) {
|
||||||
ptr++;
|
SDL_free(args.filters_slice[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(argv);
|
SDL_free(args.argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Zenity survives termination of the parent
|
// TODO: Zenity survives termination of the parent
|
||||||
@@ -255,7 +197,6 @@ static void run_zenity(zenityArgs* arg_struct)
|
|||||||
SDL_DialogFileCallback callback = arg_struct->callback;
|
SDL_DialogFileCallback callback = arg_struct->callback;
|
||||||
void* userdata = arg_struct->userdata;
|
void* userdata = arg_struct->userdata;
|
||||||
SDL_Process *process = NULL;
|
SDL_Process *process = NULL;
|
||||||
char **args = NULL;
|
|
||||||
SDL_Environment *env = NULL;
|
SDL_Environment *env = NULL;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
@@ -264,8 +205,8 @@ static void run_zenity(zenityArgs* arg_struct)
|
|||||||
char **array = NULL;
|
char **array = NULL;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
args = generate_args(arg_struct);
|
Args args = generate_args(arg_struct);
|
||||||
if (!args) {
|
if (!args.argv) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +225,7 @@ static void run_zenity(zenityArgs* arg_struct)
|
|||||||
SDL_SetEnvironmentVariable(env, "ZENITY_TIMEOUT", "2", true);
|
SDL_SetEnvironmentVariable(env, "ZENITY_TIMEOUT", "2", true);
|
||||||
|
|
||||||
SDL_PropertiesID props = SDL_CreateProperties();
|
SDL_PropertiesID props = SDL_CreateProperties();
|
||||||
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, args);
|
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, args.argv);
|
||||||
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, env);
|
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, env);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
|
||||||
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
|
||||||
@@ -372,7 +313,7 @@ void SDL_Zenity_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
|
|||||||
args->nfilters = SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0);
|
args->nfilters = SDL_GetNumberProperty(props, SDL_PROP_FILE_DIALOG_NFILTERS_NUMBER, 0);
|
||||||
args->allow_many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
|
args->allow_many = SDL_GetBooleanProperty(props, SDL_PROP_FILE_DIALOG_MANY_BOOLEAN, false);
|
||||||
args->type = type;
|
args->type = type;
|
||||||
args->x11_window_handle = 0;
|
args->x11_window_handle[0] = 0;
|
||||||
args->title = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_TITLE_STRING, NULL);
|
args->title = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_TITLE_STRING, NULL);
|
||||||
args->accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL);
|
args->accept = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_ACCEPT_STRING, NULL);
|
||||||
args->cancel = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_CANCEL_STRING, NULL);
|
args->cancel = SDL_GetStringProperty(props, SDL_PROP_FILE_DIALOG_CANCEL_STRING, NULL);
|
||||||
@@ -381,7 +322,10 @@ void SDL_Zenity_ShowFileDialogWithProperties(SDL_FileDialogType type, SDL_Dialog
|
|||||||
if (window) {
|
if (window) {
|
||||||
SDL_PropertiesID window_props = SDL_GetWindowProperties(window);
|
SDL_PropertiesID window_props = SDL_GetWindowProperties(window);
|
||||||
if (window_props) {
|
if (window_props) {
|
||||||
args->x11_window_handle = (Uint64) SDL_GetNumberProperty(window_props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
Uint64 handle = (Uint64)SDL_GetNumberProperty(window_props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||||
|
if (handle) {
|
||||||
|
SDL_snprintf(args->x11_window_handle, 64, "0x%" SDL_PRIx64, handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user