#include "SDL_internal.h"
#include "SDL_zenitymessagebox.h"
#define ZENITY_VERSION_LEN 32
#define MAX_BUTTONS 8
static bool parse_zenity_version(const char *version, int *major, int *minor)
{
const char *version_ptr = version;
char *end_ptr = NULL;
int tmp = (int) SDL_strtol(version_ptr, &end_ptr, 10);
if (tmp == 0 && end_ptr == version_ptr) {
return SDL_SetError("failed to get zenity major version number");
}
*major = tmp;
if (*end_ptr == '.') {
version_ptr = end_ptr + 1; tmp = (int) SDL_strtol(version_ptr, &end_ptr, 10);
if (tmp == 0 && end_ptr == version_ptr) {
return SDL_SetError("failed to get zenity minor version number");
}
*minor = tmp;
} else {
*minor = 0;
}
return true;
}
bool SDL_get_zenity_version(int *major, int *minor)
{
const char *argv[] = { "zenity", "--version", NULL };
bool result = false;
SDL_Process *process = SDL_CreateProcess(argv, true);
if (!process) {
return false;
}
char *output = SDL_ReadProcess(process, NULL, NULL);
if (output) {
result = parse_zenity_version(output, major, minor);
SDL_free(output);
}
SDL_DestroyProcess(process);
return result;
}
bool SDL_Zenity_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID)
{
int exit_code = -1;
int zenity_major = 0, zenity_minor = 0, output_len = 0;
int argc = 5, i;
const char *argv[5 + 2 + 2 + 2 + 2 * MAX_BUTTONS + 1 ] = {
"zenity", "--question", "--switch", "--no-wrap", "--no-markup"
};
SDL_Process *process;
if (messageboxdata->numbuttons > MAX_BUTTONS) {
return SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS);
}
if (!SDL_get_zenity_version(&zenity_major, &zenity_minor)) {
return false; }
argv[argc++] = zenity_major > 3 || (zenity_major == 3 && zenity_minor >= 90) ? "--icon" : "--icon-name";
switch (messageboxdata->flags & (SDL_MESSAGEBOX_ERROR | SDL_MESSAGEBOX_WARNING | SDL_MESSAGEBOX_INFORMATION)) {
case SDL_MESSAGEBOX_ERROR:
argv[argc++] = "dialog-error";
break;
case SDL_MESSAGEBOX_WARNING:
argv[argc++] = "dialog-warning";
break;
case SDL_MESSAGEBOX_INFORMATION:
default:
argv[argc++] = "dialog-information";
break;
}
if (messageboxdata->title && messageboxdata->title[0]) {
argv[argc++] = "--title";
argv[argc++] = messageboxdata->title;
} else {
argv[argc++] = "--title=";
}
if (messageboxdata->message && messageboxdata->message[0]) {
argv[argc++] = "--text";
argv[argc++] = messageboxdata->message;
} else {
argv[argc++] = "--text=";
}
for (i = 0; i < messageboxdata->numbuttons; ++i) {
if (messageboxdata->buttons[i].text && messageboxdata->buttons[i].text[0]) {
int len = SDL_strlen(messageboxdata->buttons[i].text);
if (len > output_len) {
output_len = len;
}
argv[argc++] = "--extra-button";
argv[argc++] = messageboxdata->buttons[i].text;
} else {
argv[argc++] = "--extra-button=";
}
}
if (messageboxdata->numbuttons == 0) {
argv[argc++] = "--extra-button=OK";
}
argv[argc] = NULL;
SDL_PropertiesID props = SDL_CreateProperties();
if (!props) {
return false;
}
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, argv);
if (buttonID) {
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
} else {
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_NULL);
}
process = SDL_CreateProcessWithProperties(props);
SDL_DestroyProperties(props);
if (!process) {
return false;
}
if (buttonID) {
char *output = SDL_ReadProcess(process, NULL, &exit_code);
if (exit_code < 0 || exit_code == 255) {
SDL_free(output);
} else if (output) {
char *tmp = SDL_strrchr(output, '\n');
if (tmp) {
*tmp = '\0';
}
for (i = 0; i < messageboxdata->numbuttons; i += 1) {
if (messageboxdata->buttons[i].text) {
if (SDL_strcmp(output, messageboxdata->buttons[i].text) == 0) {
*buttonID = messageboxdata->buttons[i].buttonID;
break;
}
}
}
SDL_free(output);
}
} else {
SDL_WaitProcess(process, true, &exit_code);
}
SDL_DestroyProcess(process);
return !(exit_code < 0 || exit_code == 255);
}