613 lines
15 KiB
C
613 lines
15 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <libgnome/libgnome.h>
|
|
#include <libgnomevfs/gnome-vfs.h>
|
|
#include <libgnomeui/libgnomeui.h>
|
|
#include <strings.h>
|
|
#include <signal.h>
|
|
|
|
#include "widgets/gm-app-view.h"
|
|
#include "gm-world.h"
|
|
#include "gm-color-table.h"
|
|
|
|
#include "gm-app.h"
|
|
#include "gm-ansi.h"
|
|
#include "gm-debug.h"
|
|
#include "gm-pixbuf.h"
|
|
#include "gm-support.h"
|
|
#include "gm-scripts.h"
|
|
|
|
static gchar *debug_level = NULL;
|
|
static gboolean show_version = FALSE;
|
|
static gboolean recover = FALSE;
|
|
static gchar *load_worlds = NULL;
|
|
static GmApp *application;
|
|
|
|
struct poptOption poptions[] = {
|
|
{"debug", 'd', POPT_ARG_STRING, &debug_level, 0, N_("Enable debugging. "
|
|
"Specify multiple debug levels with a comma seperated list. "
|
|
"Available levels: default, mcp, all"), N_("DBGGLEVEL")},
|
|
{"version", 'v', POPT_ARG_NONE, &show_version, 0, N_("Show application "
|
|
"version"), NULL},
|
|
{"load", 'l', POPT_ARG_STRING, &load_worlds, 0, N_("Load specified worlds. "
|
|
"Specify multiple worlds with a comma separated list"),
|
|
N_("WORLDS")},
|
|
{"recover", 'r', POPT_ARG_NONE, &recover, 0, N_("Recover from previous "
|
|
"session (used with gnome session)"), NULL},
|
|
{NULL, '\0', 0, NULL, 0, NULL, NULL}
|
|
};
|
|
|
|
#define GM_APP_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE((object), \
|
|
GM_TYPE_APP, GmAppPrivate))
|
|
void gm_app_destroy_worlds(GmApp *app);
|
|
|
|
struct _GmAppPrivate {
|
|
gchar *path;
|
|
gchar *worlds_path;
|
|
gchar *options_path;
|
|
|
|
GmAppView *view;
|
|
GmOptions *options;
|
|
GmColorTable *color_table;
|
|
GnomeClient *client;
|
|
GList *worlds;
|
|
|
|
#ifdef HAVE_RUBY
|
|
GmScripts *scripts;
|
|
#endif
|
|
|
|
//tray_info tray;
|
|
};
|
|
|
|
/* Properties */
|
|
enum {
|
|
PROP_0,
|
|
|
|
PROP_WORLDS_PATH,
|
|
PROP_PATH,
|
|
PROP_OPTIONS,
|
|
PROP_WORLDS,
|
|
PROP_COLOR_TABLE
|
|
};
|
|
|
|
/* Signals */
|
|
|
|
enum {
|
|
WORLD_ADDED,
|
|
WORLD_REMOVED,
|
|
NUM_SIGNALS
|
|
};
|
|
|
|
static guint app_signals[NUM_SIGNALS] = {0};
|
|
|
|
G_DEFINE_TYPE(GmApp, gm_app, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
gm_app_get_property(GObject *object, guint prop_id, GValue *value,
|
|
GParamSpec *pspec) {
|
|
GmApp *app = GM_APP(object);
|
|
|
|
switch (prop_id) {
|
|
case PROP_WORLDS_PATH:
|
|
g_value_set_string(value, gm_app_worlds_path(app));
|
|
break;
|
|
case PROP_PATH:
|
|
g_value_set_string(value, gm_app_path(app));
|
|
break;
|
|
case PROP_OPTIONS:
|
|
g_value_set_object(value, gm_app_options(app));
|
|
break;
|
|
case PROP_COLOR_TABLE:
|
|
g_value_set_object(value, gm_app_color_table(app));
|
|
break;
|
|
case PROP_WORLDS:
|
|
g_value_set_pointer(value, gm_app_worlds(app));
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gm_app_finalize(GObject *object) {
|
|
GmApp *app = GM_APP(object);
|
|
|
|
gnome_vfs_shutdown();
|
|
|
|
#ifdef HAVE_RUBY
|
|
g_object_unref(app->priv->scripts);
|
|
#endif
|
|
|
|
gm_app_destroy_worlds(app);
|
|
gm_pixbuf_fini();
|
|
|
|
gm_options_save(app->priv->options);
|
|
g_object_unref(app->priv->options);
|
|
|
|
gm_color_table_save(app->priv->color_table);
|
|
g_object_unref(app->priv->color_table);
|
|
|
|
g_free(app->priv->path);
|
|
g_free(app->priv->worlds_path);
|
|
g_free(app->priv->options_path);
|
|
|
|
G_OBJECT_CLASS(gm_app_parent_class)->finalize(object);
|
|
}
|
|
|
|
static void
|
|
gm_app_class_init(GmAppClass *klass) {
|
|
GObjectClass *object_class = G_OBJECT_CLASS(klass);
|
|
|
|
object_class->finalize = gm_app_finalize;
|
|
object_class->get_property = gm_app_get_property;
|
|
|
|
g_object_class_install_property(object_class, PROP_PATH,
|
|
g_param_spec_string("path", "PATH", "The app path", NULL,
|
|
G_PARAM_READABLE));
|
|
|
|
g_object_class_install_property(object_class, PROP_WORLDS_PATH,
|
|
g_param_spec_string("worlds_path", "WORLDS_PATH", "The worlds path", NULL,
|
|
G_PARAM_READABLE));
|
|
|
|
g_object_class_install_property(object_class, PROP_OPTIONS,
|
|
g_param_spec_object("options", "OPTIONS", "Options object",
|
|
GM_TYPE_OPTIONS, G_PARAM_READABLE));
|
|
|
|
g_object_class_install_property(object_class, PROP_COLOR_TABLE,
|
|
g_param_spec_object("color_table", "COLOR_TABLE", "ColorTable object",
|
|
GM_TYPE_COLOR_TABLE, G_PARAM_READABLE));
|
|
|
|
g_object_class_install_property(object_class, PROP_WORLDS,
|
|
g_param_spec_pointer("worlds", "WORLDS", "Worlds list",
|
|
G_PARAM_READABLE));
|
|
|
|
app_signals[WORLD_ADDED] =
|
|
g_signal_new("world_added",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmAppClass, world_added),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_POINTER);
|
|
|
|
app_signals[WORLD_REMOVED] =
|
|
g_signal_new("world_removed",
|
|
G_OBJECT_CLASS_TYPE(object_class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET(GmAppClass, world_removed),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE,
|
|
1,
|
|
G_TYPE_POINTER);
|
|
|
|
g_type_class_add_private(object_class, sizeof(GmAppPrivate));
|
|
}
|
|
|
|
static void
|
|
gm_app_init(GmApp *app) {
|
|
app->priv = GM_APP_GET_PRIVATE(app);
|
|
|
|
app->priv->path = NULL;
|
|
app->priv->worlds_path = NULL;
|
|
app->priv->options_path = NULL;
|
|
app->priv->options = NULL;
|
|
app->priv->client = NULL;
|
|
app->priv->worlds = NULL;
|
|
}
|
|
|
|
/* Private functions */
|
|
void
|
|
gm_app_destroy_worlds(GmApp *app) {
|
|
GList *item;
|
|
|
|
for (item = app->priv->worlds; item; item = item->next) {
|
|
g_object_unref(GM_WORLD(item->data));
|
|
}
|
|
|
|
g_list_free(app->priv->worlds);
|
|
app->priv->worlds = NULL;
|
|
}
|
|
|
|
static void
|
|
on_gm_app_session_die(GnomeClient * client, gpointer client_data) {
|
|
gtk_main_quit();
|
|
}
|
|
|
|
static gboolean
|
|
on_gm_app_save_session(GnomeClient * client, gint phase,
|
|
GnomeSaveStyle save_style, gint is_shutdown,
|
|
GnomeInteractStyle interact_style, gint is_fast, gchar ** client_data) {
|
|
gchar **argv;
|
|
gint argc = sizeof(client_data) / sizeof(gchar *) + 1;
|
|
int i;
|
|
GString *ws = g_string_new("");
|
|
GList *elem, *list;
|
|
GmWorld *world;
|
|
|
|
argv = g_new(gchar *, argc);
|
|
argv[0] = client_data[0];
|
|
argv[1] = "--recover";
|
|
|
|
for (i = 1; i < argc - 1; i++) {
|
|
argv[i + 1] = client_data[i];
|
|
}
|
|
|
|
gnome_client_set_clone_command(client, argc, argv);
|
|
gnome_client_set_restart_command(client, argc, argv);
|
|
|
|
// Saving worlds state
|
|
list = gm_app_worlds(application);
|
|
|
|
for (elem = list; elem; elem = elem->next) {
|
|
world = (GmWorld *) (elem->data);
|
|
|
|
if (gm_world_loaded(world)) {
|
|
if (strlen(ws->str) != 0) {
|
|
ws = g_string_append_c(ws, ';');
|
|
}
|
|
|
|
ws = g_string_append(ws, gm_world_name(world));
|
|
}
|
|
}
|
|
|
|
g_list_free(list);
|
|
gm_options_set(gm_app_options(application), "worlds_saved_state", ws->str);
|
|
gm_options_save(gm_app_options(application));
|
|
g_string_free(ws, TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
gm_app_create_settings(GmApp *app) {
|
|
app->priv->options = gm_options_new();
|
|
|
|
gm_options_set(app->priv->options, "editor_alternative", "0");
|
|
gm_options_set(app->priv->options, "editor_embed", "0");
|
|
gm_options_set(app->priv->options, "editor_needs_terminal", "0");
|
|
gm_options_set(app->priv->options, "auto_check_syntax", "1");
|
|
gm_options_set(app->priv->options, "worlds_saved_state", "");
|
|
gm_options_set(app->priv->options, "search_direction_world", "1");
|
|
gm_options_set(app->priv->options, "search_direction", "0");
|
|
gm_options_set(app->priv->options, "search_sensitive", "0");
|
|
|
|
// Default logging settings
|
|
gm_options_set(app->priv->options, "logging_enable", "1");
|
|
gm_options_set(app->priv->options, "logging_in", "1");
|
|
gm_options_set(app->priv->options, "logging_out", "1");
|
|
gm_options_set(app->priv->options, "logging_status", "1");
|
|
gm_options_set(app->priv->options, "logging_mcp_in", "0");
|
|
gm_options_set(app->priv->options, "logging_mcp_out", "0");
|
|
gm_options_set(app->priv->options, "logging_mcp_status", "0");
|
|
|
|
// Default logging filter settings
|
|
gm_options_set(app->priv->options, "logging_filter_in", "1");
|
|
gm_options_set(app->priv->options, "logging_filter_out", "1");
|
|
gm_options_set(app->priv->options, "logging_filter_status", "1");
|
|
gm_options_set(app->priv->options, "logging_filter_mcp_in", "0");
|
|
gm_options_set(app->priv->options, "logging_filter_mcp_out", "0");
|
|
gm_options_set(app->priv->options, "logging_filter_mcp_status", "0");
|
|
}
|
|
|
|
void
|
|
gm_app_load_worlds(GmApp *app, gboolean autoload) {
|
|
GDir *handle = g_dir_open(app->priv->worlds_path, 0, NULL);
|
|
char *name, *path;
|
|
GmWorld *new_world;
|
|
|
|
if (handle != NULL) {
|
|
while ((name = (char *) g_dir_read_name(handle)) != NULL) {
|
|
path = g_strconcat(app->priv->worlds_path, G_DIR_SEPARATOR_S,
|
|
name, NULL);
|
|
|
|
if (g_file_test(path, G_FILE_TEST_IS_DIR)) {
|
|
new_world = gm_world_new(path);
|
|
|
|
if (new_world != NULL) {
|
|
gm_app_add_world(app, new_world);
|
|
|
|
if (autoload && gm_options_get_int(
|
|
gm_world_options(new_world), "autoload")) {
|
|
gm_world_load(new_world);
|
|
}
|
|
}
|
|
} else {
|
|
gm_debug_msg(DEBUG_ALWAYS, "Directory can't be opened: %s", path);
|
|
}
|
|
|
|
g_free(path);
|
|
}
|
|
|
|
g_dir_close(handle);
|
|
} else {
|
|
gm_debug_msg(DEBUG_DEFAULT, "GmApp.load_worlds: failed to open worlds "
|
|
"path %s", app->priv->path);
|
|
}
|
|
}
|
|
|
|
void
|
|
gm_app_convert_old_color_configuration(GmApp *app, gchar const *colors_path) {
|
|
guint i;
|
|
gchar const *color, *value;
|
|
FILE *f;
|
|
GmColorTable *table;
|
|
gboolean is_scheme = TRUE;
|
|
|
|
f = fopen(colors_path, "w");
|
|
|
|
if (!f) {
|
|
gm_debug_msg(DEBUG_DEFAULT, "Can't open colors file (%s) for writing!",
|
|
colors_path);
|
|
return;
|
|
}
|
|
|
|
// Create a template color table with the WHITE_ON_BLACK scheme
|
|
table = gm_color_table_new();
|
|
gm_color_table_load_scheme(table, SCHEME_WHITE_ON_BLACK);
|
|
|
|
// Copy every color related item from ->options_path to colors_path
|
|
for (i = 0; i < sizeof(ansi_colors) / sizeof(ansinamepair); ++i) {
|
|
color = ansi_colors[i].name;
|
|
value = gm_options_get(app->priv->options, color);
|
|
|
|
if (value) {
|
|
is_scheme = is_scheme && strcmp(value,
|
|
gm_color_table_get_hex(table, color)) == 0;
|
|
fprintf(f, "%s=%s\n", color, value);
|
|
|
|
gm_options_remove(app->priv->options, color);
|
|
}
|
|
}
|
|
|
|
value = gm_options_get(app->priv->options, "font-family");
|
|
|
|
if (value) {
|
|
fprintf(f, "font_family=%s\n", value);
|
|
}
|
|
|
|
gm_options_remove(app->priv->options, "font-family");
|
|
gm_options_remove(app->priv->options, "bold-colors");
|
|
gm_options_remove(app->priv->options, "background_transparancy");
|
|
gm_options_remove(app->priv->options, "background_transparent");
|
|
|
|
if (is_scheme) {
|
|
fputs("color_scheme=default\n", f);
|
|
} else {
|
|
fputs("color_scheme=user\n", f);
|
|
}
|
|
|
|
fclose(f);
|
|
g_object_unref(G_OBJECT(table));
|
|
}
|
|
|
|
void
|
|
gm_app_initialize(GmApp *app) {
|
|
gchar *colors_path;
|
|
|
|
gm_debug_set_level(debug_level);
|
|
|
|
app->priv->worlds_path = g_strconcat(app->priv->path, G_DIR_SEPARATOR_S,
|
|
"worlds", NULL);
|
|
app->priv->options_path = g_strconcat(app->priv->path, G_DIR_SEPARATOR_S,
|
|
"settings", NULL);
|
|
|
|
if (!g_file_test(app->priv->path, G_FILE_TEST_EXISTS)) {
|
|
mkdir(app->priv->path, 0755);
|
|
mkdir(app->priv->worlds_path, 0755);
|
|
}
|
|
|
|
#ifdef HAVE_RUBY
|
|
app->priv->scripts = gm_scripts_new();
|
|
#endif
|
|
|
|
gm_app_create_settings(app);
|
|
gm_options_load(app->priv->options, app->priv->options_path);
|
|
|
|
// Load color table
|
|
colors_path = g_strconcat(app->priv->path, G_DIR_SEPARATOR_S, "colors",
|
|
NULL);
|
|
|
|
if (!g_file_test(colors_path, G_FILE_TEST_EXISTS)) {
|
|
// There is no `new` color configuration yet. Copy from general options
|
|
gm_app_convert_old_color_configuration(app, colors_path);
|
|
}
|
|
|
|
app->priv->color_table = gm_color_table_new_from_options(colors_path);
|
|
g_free(colors_path);
|
|
}
|
|
|
|
void
|
|
gm_app_run(GmApp *app) {
|
|
gchar **wrlds;
|
|
const gchar *savedState;
|
|
int i = 0;
|
|
GmWorld *world;
|
|
|
|
app->priv->view = gm_app_view_new(app);
|
|
gtk_widget_show(GTK_WIDGET(app->priv->view));
|
|
|
|
#ifdef HAVE_RUBY
|
|
gm_scripts_load(app->priv->scripts);
|
|
#endif
|
|
|
|
gm_app_load_worlds(app, !(recover || load_worlds));
|
|
|
|
if (recover) {
|
|
savedState = gm_options_get(app->priv->options, "worlds_saved_state");
|
|
|
|
if (strlen(savedState) != 0) {
|
|
wrlds = g_strsplit(savedState, ";", -1);
|
|
|
|
for (i = 0; wrlds[i]; i++) {
|
|
if (strlen(wrlds[i]) != 0) {
|
|
world = gm_app_world_by_name(app, wrlds[i]);
|
|
|
|
if (world) {
|
|
gm_world_load(world);
|
|
}
|
|
}
|
|
}
|
|
|
|
g_strfreev(wrlds);
|
|
}
|
|
} else if (load_worlds) {
|
|
wrlds = g_strsplit(load_worlds, ",", -1);
|
|
|
|
for (i = 0; wrlds[i]; i++) {
|
|
world = gm_app_world_by_name(app, wrlds[i]);
|
|
|
|
if (world) {
|
|
gm_world_load(world);
|
|
}
|
|
}
|
|
|
|
g_strfreev(wrlds);
|
|
}
|
|
|
|
signal(SIGINT, SIG_DFL);
|
|
gtk_main();
|
|
}
|
|
|
|
/* Public functions */
|
|
GmApp *
|
|
gm_app_new(int argc, char *argv[]) {
|
|
GmApp *app = GM_APP(g_object_new(GM_TYPE_APP, NULL));
|
|
|
|
app->priv->path = gnome_util_home_file("gnoemoe");
|
|
|
|
if (!app->priv->path) {
|
|
printf(_("GnoeMoe Application: there is no application directory, "
|
|
"this is very bad!!!\n"));
|
|
return app;
|
|
}
|
|
|
|
bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
|
|
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
|
textdomain(GETTEXT_PACKAGE);
|
|
|
|
g_thread_init(NULL);
|
|
gtk_set_locale();
|
|
gtk_init(&argc, &argv);
|
|
|
|
gnome_program_init(PACKAGE, VERSION, LIBGNOMEUI_MODULE,
|
|
argc, argv, GNOME_PARAM_POPT_TABLE, poptions,
|
|
GNOME_PARAM_APP_DATADIR, PACKAGE_DATA_DIR, NULL);
|
|
|
|
app->priv->client = gnome_master_client();
|
|
|
|
gtk_signal_connect(GTK_OBJECT(app->priv->client), "save_yourself",
|
|
GTK_SIGNAL_FUNC(on_gm_app_save_session), argv);
|
|
gtk_signal_connect(GTK_OBJECT(app->priv->client), "die",
|
|
GTK_SIGNAL_FUNC(on_gm_app_session_die), NULL);
|
|
|
|
/* Initialize everything */
|
|
gnome_vfs_init();
|
|
glade_init();
|
|
gm_pixbuf_init();
|
|
gm_app_initialize(app);
|
|
|
|
if (show_version) {
|
|
g_object_unref(G_OBJECT(app));
|
|
printf(_("Current version of GnoeMoe is %s\n"), VERSION);
|
|
return NULL;
|
|
}
|
|
|
|
return app;
|
|
}
|
|
|
|
gint
|
|
gm_app_compare_worlds(GmWorld *world1, GmWorld *world2) {
|
|
return strcasecmp(gm_world_name(world1), gm_world_name(world2));
|
|
}
|
|
|
|
void
|
|
gm_app_add_world(GmApp *app, GmWorld *world) {
|
|
app->priv->worlds = g_list_insert_sorted(app->priv->worlds,
|
|
world, (GCompareFunc)(gm_app_compare_worlds));
|
|
g_signal_emit(app, app_signals[WORLD_ADDED], 0, world);
|
|
}
|
|
|
|
void
|
|
gm_app_remove_world(GmApp *app, GmWorld *world) {
|
|
// Only remove when not loaded
|
|
const gchar *path = gm_world_path(world);
|
|
|
|
if (!gm_world_loaded(world)) {
|
|
app->priv->worlds = g_list_remove(app->priv->worlds, world);
|
|
g_signal_emit(app, app_signals[WORLD_REMOVED], 0, world);
|
|
|
|
g_object_unref(world);
|
|
gm_directory_remove_all(path, TRUE);
|
|
}
|
|
}
|
|
|
|
GmWorld *
|
|
gm_app_world_by_name(GmApp *app, gchar *name) {
|
|
GList *elem;
|
|
const gchar *world_name;
|
|
|
|
for (elem = app->priv->worlds; elem; elem = elem->next) {
|
|
world_name = gm_world_name(GM_WORLD(elem->data));
|
|
|
|
if (!g_strcasecmp(name, world_name)) {
|
|
return GM_WORLD(elem->data);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
GmOptions *
|
|
gm_app_options(GmApp *app) {
|
|
return app->priv->options;
|
|
}
|
|
|
|
#ifdef HAVE_RUBY
|
|
GmScripts *
|
|
gm_app_scripts(GmApp *app) {
|
|
return app->priv->scripts;
|
|
}
|
|
#endif
|
|
|
|
const gchar *
|
|
gm_app_worlds_path(GmApp *app) {
|
|
return app->priv->worlds_path;
|
|
}
|
|
|
|
const gchar *
|
|
gm_app_path(GmApp *app) {
|
|
return app->priv->path;
|
|
}
|
|
|
|
GList *
|
|
gm_app_worlds(GmApp *app) {
|
|
return g_list_copy(app->priv->worlds);
|
|
}
|
|
|
|
GmColorTable *
|
|
gm_app_color_table(GmApp *app) {
|
|
return app->priv->color_table;
|
|
}
|
|
|
|
GmApp *
|
|
gm_app_instance() {
|
|
return application;
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[]) {
|
|
g_type_init();
|
|
application = gm_app_new(argc, argv);
|
|
|
|
if (application) {
|
|
gm_app_run(application);
|
|
g_object_unref(application);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|