#ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include "gm-app-view.h" #include "gm-world.h" #include "gm-color-table.h" //#include "mcp/mcp.h" #include "gm-app.h" //#include "editor.h" #include "debug.h" #include "gm-pixbuf.h" #include "gm-support.h" #include "gm-scripts.h" static int debug_level = 0; static gboolean show_version = FALSE; static gboolean recover = FALSE; static gchar *load_worlds = NULL; static GmApp *application; //static void gm_app_tray_create(tray_info *t); //gboolean on_gm_app_tray_button_press(GtkWidget *widget, GdkEventButton *event, // gpointer user_data); //gboolean on_gm_app_tray_destroy(GtkWidget *widget, gpointer user_data); void on_gm_app_view_size_allocate(GmAppView *view, GtkAllocation *allocation, GmApp *app); struct poptOption poptions[] = { { "debug", 'd', POPT_ARG_INT, &debug_level, 0, N_ ("Enable debugging. Debugging can be done in different depth levels, each " "level inherits all messages from the levels below: " "0 = None, 1 = Default and 2 = MCP"), 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, seperated by a `,'"), 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; }; /* 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_finalize(GObject *object) { GmApp *app = GM_APP(object); gnome_vfs_shutdown(); //mcp_fini(); //editor_fini(); #ifdef HAVE_RUBY g_object_unref(app->priv->scripts); #endif //mcpconsole_fini(); gm_app_destroy_worlds(app); gm_pixbuf_fini(); gm_options_save(app->priv->options); g_object_unref(app->priv->options); 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; 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; //gm_app_tray_create(&(app->priv->tray)); } /* Private functions */ void gm_app_destroy_worlds(GmApp *app) { // TODO } static void on_gm_app_session_die(GnomeClient * client, gpointer client_data) { gtk_main_quit(); } /*static void gm_app_tray_create(tray_info *t) { t->flash_timeout = 0; t->icon = egg_tray_icon_new(_("GnoeMoe Gnome MOO Client")); t->event_box = gtk_event_box_new(); t->iconnr = TRAY_ICON_DEFAULT; t->image = gtk_image_new_from_pixbuf( gnoe_pixbuf_get("tray/default.svg")); gtk_container_add(GTK_CONTAINER(t->event_box), t->image); t->tooltips = gtk_tooltips_new(); gtk_widget_show(t->event_box); gtk_widget_show(t->image); gtk_container_add(GTK_CONTAINER(t->icon), t->event_box); gtk_widget_show(GTK_WIDGET(t->icon)); gtk_widget_add_events(GTK_WIDGET(t->icon), GDK_BUTTON_PRESS_MASK); g_signal_connect(t->icon, "button_press_event", G_CALLBACK(on_gm_app_tray_button_press), NULL); // Handles when the area is removed from the panel. g_signal_connect(t->icon, "destroy", G_CALLBACK(on_gm_app_tray_destroy), t->event_box); }*/ 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, "font-family", "Monospace 8"); gm_options_set(app->priv->options, "worlds_saved_state", ""); gm_options_set(app->priv->options, "search_direction", "1"); } 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 { debug_msg(0, "Nee: %s", path); } g_free(path); } g_dir_close(handle); } else { debug_msg(1, "GmApp.load_worlds: failed to open worlds path %s", app->priv->path); } } void gm_app_initialize(GmApp *app) { 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 /* Create the main view */ gm_app_create_settings(app); gm_options_load(app->priv->options, app->priv->options_path); app->priv->color_table = gm_color_table_new_from_options(app->priv->options); } void gm_app_run(GmApp *app) { gchar **wrlds; const gchar *savedState; int i = 0; GmWorld *world; int width, height; app->priv->view = gm_app_view_new(app); width = gm_options_get_int(app->priv->options, "width"); height = gm_options_get_int(app->priv->options, "height"); if (height > 10 && width > 10) { gtk_window_set_default_size(GTK_WINDOW(app->priv->view), width, height); } gtk_widget_show(GTK_WIDGET(app->priv->view)); //mcpconsole_init(); g_signal_connect(app->priv->view, "size_allocate", G_CALLBACK(on_gm_app_view_size_allocate), app); #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); } 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; } #ifdef ENABLE_NLS bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); textdomain(GETTEXT_PACKAGE); #endif 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); if (show_version) { printf(_("Current version of GnoeMoe is %s\n"), VERSION); return app; } 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(); //mcp_init(); gm_pixbuf_init(); gm_app_initialize(app); //editor_init(); return app; } void gm_app_add_world(GmApp *app, GmWorld *world) { app->priv->worlds = g_list_append(app->priv->worlds, g_object_ref(world)); 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); gm_app_run(application); g_object_unref(application); return 0; } /* Callbacks */ void on_gm_app_view_size_allocate(GmAppView *view, GtkAllocation *allocation, GmApp *app) { gm_options_set_int(app->priv->options, "width", allocation->width); gm_options_set_int(app->priv->options, "height", allocation->height); } /*gboolean on_gm_app_tray_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { return FALSE; } switch (event->button) { case 1: if_main_show_hide(!GTK_WIDGET_VISIBLE(wndMain)); break; default: return FALSE; } return TRUE; } gboolean on_gm_app_tray_destroy(GtkWidget *widget, gpointer user_data) { gtk_widget_destroy(GTK_WIDGET(app_tray_info.icon)); app_tray_info.icon = NULL; app_tray_info.event_box = NULL; app_tray_info.image = NULL; app_tray_info.tooltips = NULL; if (app_tray_info.flash_timeout != 0) { g_source_remove(app_tray_info.flash_timeout); } tray_create(&app_tray_info); if (!have_tray()) { gtk_widget_show(if_main_get_widget("wndMain")); } return TRUE; }*/