X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=player%2Fcallbacks.c;h=94b9e5b3aaa0d8f547e2fe60dc78c7f01673a668;hb=0c5e51127206d26290a8e1e1349ab37d847d1d84;hp=479a5ce7425d14667bd4aa352e1ba38233666317;hpb=71bb42dc75907bd2acf2706ecec69acf57177221;p=projects%2Fchimara%2Fchimara.git diff --git a/player/callbacks.c b/player/callbacks.c index 479a5ce..94b9e5b 100644 --- a/player/callbacks.c +++ b/player/callbacks.c @@ -30,23 +30,267 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include +#include +#include #include +#include +#include #include "error.h" -void on_save(GtkAction *action, ChimaraGlk *glk) { +/* If a game is running in @glk, warn the user that they will quit the currently +running game if they open a new one. Returns TRUE if no game was running. +Returns FALSE if the user cancelled. Returns TRUE and shuts down the running +game if the user wishes to continue. */ +static gboolean +confirm_open_new_game(ChimaraGlk *glk) +{ + g_return_val_if_fail(glk && CHIMARA_IS_GLK(glk), FALSE); + + GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk))); + + if(chimara_glk_get_running(glk)) { + GtkWidget *dialog = gtk_message_dialog_new(window, + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_CANCEL, + _("Are you sure you want to open a new game?")); + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), + _("If you open a new game, you will quit the one you are currently playing.")); + gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OPEN, GTK_RESPONSE_OK); + gint response = gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + + if(response != GTK_RESPONSE_OK) + return FALSE; + + chimara_glk_stop(glk); + chimara_glk_wait(glk); + } + return TRUE; +} + +/* Internal function: See if there is a corresponding graphics file */ +static void +search_for_graphics_file(const char *filename, ChimaraIF *glk) +{ + + extern GSettings *prefs_settings; + + /* First get the name of the story file */ + char *scratch = g_path_get_basename(filename); + char *ext = strrchr(scratch, '.'); + if(strcmp(ext, ".zlb") == 0 || + strcmp(ext, ".zblorb") == 0 || + strcmp(ext, ".glb") == 0 || + strcmp(ext, ".gblorb") == 0 || + strcmp(ext, ".blorb") == 0 || + strcmp(ext, ".blb") == 0) + { + g_object_set(glk, "graphics-file", NULL, NULL); + return; + } + *ext = '\0'; + + /* Check in the stored resource path, if set */ + char *resource_path; + g_settings_get(prefs_settings, "resource-path", "ms", &resource_path); + + /* Otherwise check in the current directory */ + if(!resource_path) + resource_path = g_path_get_dirname(filename); + + char *blorbfile = g_strconcat(resource_path, "/", scratch, ".blb", NULL); + if(g_file_test(blorbfile, G_FILE_TEST_EXISTS)) + g_object_set(glk, "graphics-file", blorbfile, NULL); + + g_free(blorbfile); + g_free(scratch); + g_free(resource_path); +} + +void +on_open_activate(GtkAction *action, ChimaraGlk *glk) +{ + GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk))); + + if(!confirm_open_new_game(glk)) + return; + + GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Open Game"), + window, + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + /* Get last opened path */ + extern GSettings *state_settings; + gchar *path; + g_settings_get(state_settings, "last-open-path", "ms", &path); + if(path) { + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path); + g_free(path); + } + + if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { + GError *error = NULL; + extern GSettings *prefs_settings; + char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + + search_for_graphics_file(filename, CHIMARA_IF(glk)); + if(!chimara_if_run_game(CHIMARA_IF(glk), filename, &error)) { + error_dialog(window, error, _("Could not open game file '%s': "), filename); + g_free(filename); + gtk_widget_destroy(dialog); + return; + } + + path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog)); + if(path) { + g_settings_set(state_settings, "last-open-path", "ms", path); + g_free(path); + } + + /* Add file to recent files list */ + GtkRecentManager *manager = gtk_recent_manager_get_default(); + gchar *uri; + + if(!(uri = g_filename_to_uri(filename, NULL, &error))) + g_warning(_("Could not convert filename '%s' to URI: %s"), filename, error->message); + else { + if(!gtk_recent_manager_add_item(manager, uri)) + g_warning(_("Could not add URI '%s' to recent files list."), uri); + g_free(uri); + } + g_free(filename); + } + gtk_widget_destroy(dialog); +} + +void +on_recent_item_activated(GtkRecentChooser *chooser, ChimaraGlk *glk) +{ + GError *error = NULL; + GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk))); + gchar *uri = gtk_recent_chooser_get_current_uri(chooser); + gchar *filename; + if(!(filename = g_filename_from_uri(uri, NULL, &error))) { + error_dialog(window, error, _("Could not open game file '%s': "), uri); + goto finally; + } + + if(!confirm_open_new_game(glk)) + goto finally2; + + search_for_graphics_file(filename, CHIMARA_IF(glk)); + if(!chimara_if_run_game(CHIMARA_IF(glk), filename, &error)) { + error_dialog(window, error, _("Could not open game file '%s': "), filename); + goto finally2; + } + + /* Add file to recent files list again, this updates it to most recently used */ + GtkRecentManager *manager = gtk_recent_manager_get_default(); + if(!gtk_recent_manager_add_item(manager, uri)) + g_warning(_("Could not add URI '%s' to recent files list."), uri); + +finally2: + g_free(filename); +finally: + g_free(uri); +} + +void +on_stop_activate(GtkAction *action, ChimaraGlk *glk) +{ + chimara_glk_stop(glk); +} + +void +on_quit_chimara_activate(GtkAction *action, ChimaraGlk *glk) +{ + gtk_main_quit(); +} + +void +on_copy_activate(GtkAction *action, ChimaraGlk *glk) +{ + GtkWindow *toplevel = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk))); + GtkWidget *focus = gtk_window_get_focus(toplevel); + /* Call "copy clipboard" on any widget that defines it */ + if(GTK_IS_LABEL(focus) || GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus)) + g_signal_emit_by_name(focus, "copy-clipboard"); +} + +void +on_paste_activate(GtkAction *action, ChimaraGlk *glk) +{ + GtkWindow *toplevel = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk))); + GtkWidget *focus = gtk_window_get_focus(toplevel); + /* Call "paste clipboard" on any widget that defines it */ + if(GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus)) + g_signal_emit_by_name(focus, "paste-clipboard"); +} + +void +on_preferences_activate(GtkAction *action, ChimaraGlk *glk) +{ + extern GtkWidget *prefswindow; + gtk_window_present(GTK_WINDOW(prefswindow)); +} + +void +on_toolbar_toggled(GtkToggleAction *action, ChimaraGlk *glk) +{ + extern GtkWidget *toolbar; + + if(gtk_toggle_action_get_active(action)) + gtk_widget_show(toolbar); + else + gtk_widget_hide(toolbar); +} + +void +on_undo_activate(GtkAction *action, ChimaraGlk *glk) +{ + chimara_glk_feed_line_input(glk, "undo"); +} + +void +on_save_activate(GtkAction *action, ChimaraGlk *glk) +{ chimara_glk_feed_line_input(glk, "save"); } -void on_restore(GtkAction *action, ChimaraGlk *glk) { +void +on_restore_activate(GtkAction *action, ChimaraGlk *glk) +{ chimara_glk_feed_line_input(glk, "restore"); } -gboolean on_window_delete_event(GtkWidget *widget, GdkEvent *event, ChimaraGlk *glk) { - gtk_main_quit(); - return TRUE; +void +on_restart_activate(GtkAction *action, ChimaraGlk *glk) +{ + chimara_glk_feed_line_input(glk, "restart"); } -void on_quit(GtkAction *action, ChimaraGlk *glk) { +void +on_quit_activate(GtkAction *action, ChimaraGlk *glk) +{ + chimara_glk_feed_line_input(glk, "quit"); +} + +void +on_about_activate(GtkAction *action, ChimaraGlk *glk) +{ + extern GtkWidget *aboutwindow; + gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(aboutwindow), PACKAGE_VERSION); + gtk_window_present(GTK_WINDOW(aboutwindow)); +} + +gboolean +on_window_delete_event(GtkWidget *widget, GdkEvent *event, ChimaraGlk *glk) +{ gtk_main_quit(); + return TRUE; }