Converted most of GTK launcher to use glib's string functions.

This commit is contained in:
Matthew Bowra-Dean
2010-12-30 16:04:47 +13:00
committed by Chris Forbes
parent 9739e7f51f
commit 0a1e6d16bd
5 changed files with 144 additions and 132 deletions

View File

@@ -22,11 +22,11 @@
int js_check_num_args(JSContextRef ctx, char const * func_name, int argc, int num_expected, JSValueRef * exception) int js_check_num_args(JSContextRef ctx, char const * func_name, int argc, int num_expected, JSValueRef * exception)
{ {
char buf[64]; GString * buf = g_string_new(NULL);
if (argc < num_expected) if (argc < num_expected)
{ {
sprintf(buf, "%s: Not enough args, expected %d got %d", func_name, num_expected, argc); g_string_printf(buf, "%s: Not enough args, expected %d got %d", func_name, num_expected, argc);
*exception = JSValueMakeString(ctx, JS_STR(buf)); *exception = JSValueMakeString(ctx, JS_STR(buf->str));
return 0; return 0;
} }
return 1; return 1;
@@ -101,8 +101,8 @@ JSValueRef js_exists_in_mod(JSContextRef ctx, JSObjectRef func,
fclose(f); fclose(f);
return_value = JSValueMakeNumber(ctx, 1); return_value = JSValueMakeNumber(ctx, 1);
} }
else
g_message("JS ExistsInMod: Not found"); g_message("JS ExistsInMod: Not found");
return return_value; return return_value;
} }
@@ -140,9 +140,8 @@ JSValueRef js_launch_mod(JSContextRef ctx, JSObjectRef func,
while (strlen(mod->requires) > 0) while (strlen(mod->requires) > 0)
{ {
char r[MOD_requires_MAX_LEN], * comma; gchar * r = g_strdup(mod->requires), * comma;
strcpy(r, mod->requires); if (NULL != (comma = g_strstr_len(r, -1, ",")))
if (NULL != (comma = strchr(r, ',')))
{ {
*comma = '\0'; *comma = '\0';
} }
@@ -160,10 +159,11 @@ JSValueRef js_launch_mod(JSContextRef ctx, JSObjectRef func,
mod_list = (char *)realloc(mod_list, offset + strlen(r) + 1); mod_list = (char *)realloc(mod_list, offset + strlen(r) + 1);
sprintf(mod_list + offset, ",%s", r); sprintf(mod_list + offset, ",%s", r);
offset += strlen(r) + 1; offset += strlen(r) + 1;
g_free(r);
} }
{ {
char * launch_args[] = { "mono", "OpenRA.Game.exe", NULL, NULL }; char * launch_args[] = { "mono", "OpenRA.Game.exe", NULL, "SupportDir=~/.openra", NULL };
char * game_mods_arg; char * game_mods_arg;
game_mods_arg = (char *)malloc(strlen(mod_list) + strlen("Game.Mods=") + 1); game_mods_arg = (char *)malloc(strlen(mod_list) + strlen("Game.Mods=") + 1);

View File

@@ -24,32 +24,43 @@ GtkTreeStore * tree_store;
GtkTreeView * tree; GtkTreeView * tree;
GdkPixbuf * generic_mod_icon; GdkPixbuf * generic_mod_icon;
static mod_t mods[MAX_NUM_MODS];
static int mod_count = 0;
void free_mod(mod_t * mod)
{
g_free(mod->key);
g_free(mod->title);
g_free(mod->version);
g_free(mod->author);
g_free(mod->description);
g_free(mod->requires);
}
gboolean window_delete(GtkWidget * widget, GdkEvent * event, gboolean window_delete(GtkWidget * widget, GdkEvent * event,
gpointer user_data) gpointer user_data)
{ {
int i;
server_teardown(); server_teardown();
for (i = 0; i < mod_count; i++)
free_mod(mods + i);
gtk_main_quit(); gtk_main_quit();
return FALSE; return FALSE;
} }
static mod_t mods[MAX_NUM_MODS]; typedef void ( * lines_callback ) (GString const * line, gpointer data);
static int mod_count = 0;
typedef void ( * lines_callback ) (char const * line, gpointer data);
//Splits console output into lines and passes each one to a callback //Splits console output into lines and passes each one to a callback
void process_lines(char * const lines, int len, lines_callback cb, gpointer data) void process_lines(GString * lines, lines_callback cb, gpointer data)
{ {
int prev = 0, current = 0; int prev = 0, current = 0;
while (current < len) while (current < lines->len)
{ {
if (lines[current] == '\n') if (lines->str[current] == '\n')
{ {
char * line = (char *)malloc(current - prev + 1); GString * line = g_string_new_len(lines->str + prev, current - prev);
memcpy(line, lines + prev, current - prev);
line[current - prev] = '\0';
cb(line, data); cb(line, data);
free(line); g_string_free(line, TRUE);
prev = current + 1; prev = current + 1;
} }
current++; current++;
@@ -57,49 +68,46 @@ void process_lines(char * const lines, int len, lines_callback cb, gpointer data
} }
#define ASSIGN_TO_MOD(FIELD) \ #define ASSIGN_TO_MOD(FIELD) \
strncpy(mod->FIELD, val_start + 2, MOD_##FIELD##_MAX_LEN - 1); \ mod->FIELD = g_strdup(val_start)
mod->FIELD[MOD_##FIELD##_MAX_LEN - 1] = '\0'
#define min(X, Y) X < Y ? X : Y void mod_metadata_line(GString const * line, gpointer data)
void mod_metadata_line(char const * line, gpointer data)
{ {
mod_t * mod = (mod_t *)data; mod_t * mod = (mod_t *)data;
char * val_start = strchr(line, ':'); gchar * val_start = g_strstr_len(line->str, -1, ":") + 2;
if (memcmp(line, "Mod:", 4) == 0) if (g_str_has_prefix(line->str, "Mod:"))
{ {
ASSIGN_TO_MOD(key); ASSIGN_TO_MOD(key);
} }
else if (memcmp(line, " Title:", min(strlen(line), 8)) == 0) else if (g_str_has_prefix(line->str, " Title:"))
{ {
ASSIGN_TO_MOD(title); ASSIGN_TO_MOD(title);
} }
else if (memcmp(line, " Version:", min(strlen(line), 10)) == 0) else if (g_str_has_prefix(line->str, " Version:"))
{ {
ASSIGN_TO_MOD(version); ASSIGN_TO_MOD(version);
} }
else if (memcmp(line, " Author:", min(strlen(line), 9)) == 0) else if (g_str_has_prefix(line->str, " Author:"))
{ {
ASSIGN_TO_MOD(author); ASSIGN_TO_MOD(author);
} }
else if (memcmp(line, " Description:", min(strlen(line), 14)) == 0) else if (g_str_has_prefix(line->str, " Description:"))
{ {
ASSIGN_TO_MOD(description); ASSIGN_TO_MOD(description);
} }
else if (memcmp(line, " Requires:", min(strlen(line), 11)) == 0) else if (g_str_has_prefix(line->str, " Requires:"))
{ {
ASSIGN_TO_MOD(requires); ASSIGN_TO_MOD(requires);
} }
else if (memcmp(line, " Standalone:", min(strlen(line), 13)) == 0) else if (g_str_has_prefix(line->str, " Standalone:"))
{ {
if (strcmp(val_start + 2, "True") == 0) if (strcmp(val_start, "True") == 0)
mod->standalone = TRUE; mod->standalone = TRUE;
else else
mod->standalone = FALSE; mod->standalone = FALSE;
} }
} }
mod_t * get_mod(char const * key) mod_t * get_mod(gchar const * key)
{ {
int i; int i;
for (i = 0; i < mod_count; i++) for (i = 0; i < mod_count; i++)
@@ -141,20 +149,27 @@ gboolean append_to_mod(GtkTreeModel * model, GtkTreePath * path,
void mod_metadata_callback(GPid pid, gint status, gpointer data) void mod_metadata_callback(GPid pid, gint status, gpointer data)
{ {
int out_len, * out_fd = (int *)data; int * out_fd = (int *)data;
char * msg = NULL; GString * msg = NULL;
mod_t * mod = mods + mod_count; mod_t * mod = mods + mod_count;
GtkTreeIter iter, mod_iter; GtkTreeIter iter, mod_iter;
mod_count = (mod_count + 1) % MAX_NUM_MODS; mod_count = (mod_count + 1) % MAX_NUM_MODS;
free_mod(mod);
memset(mod, 0, sizeof(mod_t)); memset(mod, 0, sizeof(mod_t));
msg = util_get_output(*out_fd, &out_len); msg = util_get_output(*out_fd);
process_lines(msg, out_len, mod_metadata_line, mod); close(*out_fd);
free(out_fd);
free(msg); if (!msg)
return;
process_lines(msg, mod_metadata_line, mod);
g_string_free(msg, TRUE);
gtk_tree_model_get_iter_first(GTK_TREE_MODEL(tree_store), &mod_iter); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(tree_store), &mod_iter);
@@ -185,14 +200,11 @@ void mod_metadata_callback(GPid pid, gint status, gpointer data)
{ {
gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), append_to_mod, mod); gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), append_to_mod, mod);
} }
close(*out_fd);
free(out_fd);
} }
typedef struct tree_node typedef struct tree_node
{ {
char const * key; gchar const * key;
gchar * node_path; gchar * node_path;
} tree_node; } tree_node;
@@ -222,23 +234,32 @@ gboolean find_mod(GtkTreeModel * model, GtkTreePath * path,
void last_mod_callback(GPid pid, gint status, gpointer data) void last_mod_callback(GPid pid, gint status, gpointer data)
{ {
int out_len, * out_fd = (int *)data; int * out_fd = (int *)data;
char * comma_pos = 0; gchar * comma_pos = 0, * newline_pos = 0;
char * msg = NULL; GString * msg = NULL;
tree_node n; tree_node n;
memset(&n, 0, sizeof(tree_node)); memset(&n, 0, sizeof(tree_node));
msg = util_get_output(*out_fd, &out_len); msg = util_get_output(*out_fd);
if (0 == memcmp(msg, "Error:", 6)) close(*out_fd);
memcpy(msg, "ra", 3); free(out_fd);
else if (NULL != (comma_pos = strchr(msg, ',')))
if (!msg)
return;
if (0 == strcmp(msg->str, "Error:"))
{ {
*comma_pos = '\0'; g_string_truncate(msg, 2);
g_string_overwrite(msg, 0, "ra");
} }
else if (NULL != (comma_pos = g_strstr_len(msg->str, -1, ",")))
*comma_pos = '\0';
else if (NULL != (newline_pos = g_strstr_len(msg->str, -1, "\n")))
*newline_pos = '\0';
n.key = msg; n.key = msg->str;
gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), find_mod, &n); gtk_tree_model_foreach(GTK_TREE_MODEL(tree_store), find_mod, &n);
@@ -254,31 +275,35 @@ void last_mod_callback(GPid pid, gint status, gpointer data)
g_free(n.node_path); g_free(n.node_path);
} }
free(msg); g_string_free(msg, TRUE);
} }
void mod_list_line(char const * mod, gpointer user) void mod_list_line(GString const * mod, gpointer user)
{ {
util_get_mod_metadata(mod, mod_metadata_callback); util_get_mod_metadata(mod->str, mod_metadata_callback);
} }
void mod_list_callback(GPid pid, gint status, gpointer data) void mod_list_callback(GPid pid, gint status, gpointer data)
{ {
int out_len, * out_fd = (int *)data; int * out_fd = (int *)data;
char * msg = NULL; GString * msg = NULL;
msg = util_get_output(*out_fd, &out_len); msg = util_get_output(*out_fd);
mod_count = 0;
process_lines(msg, out_len, mod_list_line, NULL);
util_get_setting("Game.Mods", last_mod_callback);
free(msg);
close(*out_fd); close(*out_fd);
free(out_fd); free(out_fd);
if (!msg)
return;
mod_count = 0;
process_lines(msg, mod_list_line, NULL);
util_get_setting("Game.Mods", last_mod_callback);
g_string_free(msg, TRUE);
g_spawn_close_pid(pid); g_spawn_close_pid(pid);
} }
@@ -287,7 +312,7 @@ void tree_view_selection_changed(GtkTreeView * tree_view, gpointer data)
GtkTreePath * path; GtkTreePath * path;
GtkTreeIter iter; GtkTreeIter iter;
gchar * key; gchar * key;
char url[256]; GString * url;
gtk_tree_view_get_cursor(tree_view, &path, NULL); gtk_tree_view_get_cursor(tree_view, &path, NULL);
@@ -306,12 +331,15 @@ void tree_view_selection_changed(GtkTreeView * tree_view, gpointer data)
return; return;
} }
sprintf(url, "http://localhost:%d/mods/%s/mod.html", WEBSERVER_PORT, key); url = g_string_new(NULL);
webkit_web_view_load_uri(browser, url); g_string_printf(url, "http://localhost:%d/mods/%s/mod.html", WEBSERVER_PORT, key);
webkit_web_view_load_uri(browser, url->str);
g_free(key); g_free(key);
gtk_tree_path_free(path); gtk_tree_path_free(path);
g_string_free(url, TRUE);
} }
void make_tree_view(void) void make_tree_view(void)

View File

@@ -16,26 +16,19 @@ enum
N_COLUMNS N_COLUMNS
}; };
#define MOD_key_MAX_LEN 16
#define MOD_title_MAX_LEN 32
#define MOD_version_MAX_LEN 16
#define MOD_author_MAX_LEN 32
#define MOD_description_MAX_LEN 128
#define MOD_requires_MAX_LEN 32
#define MAX_NUM_MODS 64 #define MAX_NUM_MODS 64
typedef struct mod_t typedef struct mod_t
{ {
char key[MOD_key_MAX_LEN]; gchar * key;
char title[MOD_title_MAX_LEN]; gchar * title;
char version[MOD_version_MAX_LEN]; gchar * version;
char author[MOD_author_MAX_LEN]; gchar * author;
char description[MOD_description_MAX_LEN]; gchar * description;
char requires[MOD_requires_MAX_LEN]; gchar * requires;
int standalone; int standalone;
} mod_t; } mod_t;
mod_t * get_mod(char const * key); mod_t * get_mod(gchar const * key);
#endif #endif

View File

@@ -12,11 +12,11 @@
#include <glib.h> #include <glib.h>
#include <sys/wait.h> #include <sys/wait.h>
int util_do_command_async(char * command, GChildWatchFunc callback) gboolean util_do_command_async(gchar * command, GChildWatchFunc callback)
{ {
GPid child_pid; GPid child_pid;
gint * out_fd = (gint *)malloc(sizeof(gint)); gint * out_fd = (gint *)malloc(sizeof(gint));
char * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL }; gchar * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL };
gboolean result; gboolean result;
result = g_spawn_async_with_pipes(NULL, spawn_args, NULL, result = g_spawn_async_with_pipes(NULL, spawn_args, NULL,
@@ -33,17 +33,17 @@ int util_do_command_async(char * command, GChildWatchFunc callback)
return TRUE; return TRUE;
} }
int util_get_mod_list (GChildWatchFunc callback) gboolean util_get_mod_list (GChildWatchFunc callback)
{ {
return util_do_command_async("-l", callback); return util_do_command_async("-l", callback);
} }
int util_do_command_blocking(char * command, GChildWatchFunc callback) gboolean util_do_command_blocking(gchar * command, GChildWatchFunc callback)
{ {
GPid child_pid; GPid child_pid;
int status; int status;
gint * out_fd = (gint *)malloc(sizeof(gint)); gint * out_fd = (gint *)g_malloc(sizeof(gint));
char * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL }; gchar * spawn_args[] = { "mono", "OpenRA.Utility.exe", command, NULL };
gboolean result; gboolean result;
result = g_spawn_async_with_pipes(NULL, spawn_args, NULL, result = g_spawn_async_with_pipes(NULL, spawn_args, NULL,
@@ -55,7 +55,6 @@ int util_do_command_blocking(char * command, GChildWatchFunc callback)
return FALSE; return FALSE;
} }
//g_child_watch_add(child_pid, callback, out_fd);
waitpid(child_pid, &status, 0); waitpid(child_pid, &status, 0);
callback(child_pid, status, out_fd); callback(child_pid, status, out_fd);
@@ -63,47 +62,44 @@ int util_do_command_blocking(char * command, GChildWatchFunc callback)
return TRUE; return TRUE;
} }
int util_get_mod_metadata(char const * mod, GChildWatchFunc callback) gboolean util_get_mod_metadata(gchar const * mod, GChildWatchFunc callback)
{ {
char * util_args; GString * util_args = g_string_new(NULL);
int return_val; gboolean return_val;
util_args = (char *)malloc(strlen(mod) + strlen("-i=") + 1); g_string_printf(util_args, "-i=%s", mod);
sprintf(util_args, "-i=%s", mod); return_val = util_do_command_blocking(util_args->str, callback);
return_val = util_do_command_blocking(util_args, callback); g_string_free(util_args, TRUE);
free(util_args);
return return_val; return return_val;
} }
int util_get_setting(const char * setting, GChildWatchFunc callback) gboolean util_get_setting(gchar const * setting, GChildWatchFunc callback)
{ {
char * command; GString * command = g_string_new(NULL);
int return_val; gboolean return_val;
command = (char *)malloc(strlen(setting) + strlen("--settings-value=~/.openra,") + 1); g_string_printf(command, "--settings-value=~/.openra,%s", setting);
sprintf(command, "--settings-value=~/.openra,%s", setting); return_val = util_do_command_blocking(command->str, callback);
return_val = util_do_command_blocking(command, callback); g_string_free(command, TRUE);
free(command);
return return_val; return return_val;
} }
int util_spawn_with_command(const char * command, const char * arg1, const char * arg2, GPid * pid) gint util_spawn_with_command(gchar const * command, gchar const * arg1, gchar const * arg2, GPid * pid)
{ {
char * complete_command; GString * complete_command = g_string_new(NULL);
int out_fd; gint out_fd;
gboolean result; gboolean result;
char * launch_args[] = { "mono", "OpenRA.Utility.exe", NULL, NULL }; gchar * launch_args[] = { "mono", "OpenRA.Utility.exe", NULL, NULL };
complete_command = (char *)malloc(strlen(command) + strlen(arg1) + strlen(arg2) + 2); g_string_printf(complete_command, "%s%s,%s", command, arg1, arg2);
sprintf(complete_command, "%s%s,%s", command, arg1, arg2);
launch_args[2] = complete_command; launch_args[2] = complete_command->str;
result = g_spawn_async_with_pipes(NULL, launch_args, NULL, G_SPAWN_SEARCH_PATH, result = g_spawn_async_with_pipes(NULL, launch_args, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, pid, NULL, &out_fd, NULL, NULL); NULL, NULL, pid, NULL, &out_fd, NULL, NULL);
free(complete_command); g_string_free(complete_command, TRUE);
if (!result) if (!result)
{ {
@@ -113,39 +109,34 @@ int util_spawn_with_command(const char * command, const char * arg1, const char
return out_fd; return out_fd;
} }
int util_do_download(const char * url, const char * dest, GPid * pid) gint util_do_download(gchar const * url, gchar const * dest, GPid * pid)
{ {
return util_spawn_with_command("--download-url=", url, dest, pid); return util_spawn_with_command("--download-url=", url, dest, pid);
} }
int util_do_extract(const char * target, const char * dest, GPid * pid) gint util_do_extract(gchar const * target, gchar const * dest, GPid * pid)
{ {
return util_spawn_with_command("--extract-zip=", target, dest, pid); return util_spawn_with_command("--extract-zip=", target, dest, pid);
} }
char * util_get_output(int fd, int * output_len) GString * util_get_output(int fd)
{ {
char buffer[1024], * msg = NULL; char buffer[1024];
GString * msg = g_string_new(NULL);
int read_bytes = 0; int read_bytes = 0;
*output_len = 0;
while (0 != (read_bytes = read(fd, buffer, 1024))) while (0 != (read_bytes = read(fd, buffer, 1024)))
{ {
if (-1 == read_bytes) if (-1 == read_bytes)
{ {
g_error("Error reading from command output"); g_error("Error reading from command output");
free(msg); g_string_free(msg, TRUE);
*output_len = 0;
return NULL; return NULL;
} }
*output_len += read_bytes; g_string_append_len(msg, buffer, read_bytes);
msg = (char *)realloc(msg, *output_len + 1);
memcpy(msg + (*output_len - read_bytes), buffer, read_bytes);
} }
msg[*output_len] = '\0'; g_string_append_c(msg, '\0');
return msg; return msg;
} }

View File

@@ -6,9 +6,9 @@
* see LICENSE. * see LICENSE.
*/ */
int util_get_mod_list (GChildWatchFunc); gboolean util_get_mod_list (GChildWatchFunc);
int util_get_mod_metadata(char const *, GChildWatchFunc); gboolean util_get_mod_metadata(gchar const *, GChildWatchFunc);
int util_get_setting(const char *, GChildWatchFunc); gboolean util_get_setting(gchar const *, GChildWatchFunc);
int util_do_download(const char *, const char *, GPid *); gint util_do_download(gchar const *, gchar const *, GPid *);
int util_do_extract(const char *, const char *, GPid *); gint util_do_extract(gchar const *, gchar const *, GPid *);
char * util_get_output(int, int *); GString * util_get_output(int);