Made ChimaraPlayer class
[projects/chimara/chimara.git] / player / callbacks.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * callbacks.c
4  * Copyright (C) Philip en Marijn 2008 <>
5  * 
6  * callbacks.c is free software copyrighted by Philip en Marijn.
7  * 
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name ``Philip en Marijn'' nor the name of any other
17  *    contributor may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  * 
20  * callbacks.c IS PROVIDED BY Philip en Marijn ``AS IS'' AND ANY EXPRESS
21  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL Philip en Marijn OR ANY OTHER CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <glib.h>
34 #include <glib/gi18n.h>
35 #include <gtk/gtk.h>
36 #include <libchimara/chimara-glk.h>
37 #include <libchimara/chimara-if.h>
38 #include <config.h>
39 #include "error.h"
40 #include "player.h"
41
42 /* If a game is running in @glk, warn the user that they will quit the currently
43 running game if they open a new one. Returns TRUE if no game was running.
44 Returns FALSE if the user cancelled. Returns TRUE and shuts down the running
45 game if the user wishes to continue. */
46 static gboolean
47 confirm_open_new_game(ChimaraGlk *glk)
48 {
49         g_return_val_if_fail(glk && CHIMARA_IS_GLK(glk), FALSE);
50         
51         GtkWindow *window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(glk)));
52         
53         if(chimara_glk_get_running(glk)) {
54                 GtkWidget *dialog = gtk_message_dialog_new(window,
55                     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
56                     GTK_MESSAGE_WARNING,
57                     GTK_BUTTONS_CANCEL,
58                     _("Are you sure you want to open a new game?"));
59                 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
60                     _("If you open a new game, you will quit the one you are currently playing."));
61                 gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OPEN, GTK_RESPONSE_OK);
62                 gint response = gtk_dialog_run(GTK_DIALOG(dialog));
63                 gtk_widget_destroy(dialog);
64                 
65                 if(response != GTK_RESPONSE_OK)
66                         return FALSE;
67
68                 chimara_glk_stop(glk);
69                 chimara_glk_wait(glk);
70         }
71         return TRUE;
72 }
73
74 /* Internal function: See if there is a corresponding graphics file */
75 static void
76 search_for_graphics_file(const char *filename, ChimaraIF *glk)
77 {
78
79         extern GSettings *prefs_settings;
80
81         /* First get the name of the story file */
82         char *scratch = g_path_get_basename(filename);
83         *(strrchr(scratch, '.')) = '\0';
84
85         /* Check in the stored resource path, if set */
86         char *resource_path;
87         g_settings_get(prefs_settings, "resource-path", "ms", &resource_path);
88
89         /* Otherwise check in the current directory */
90         if(!resource_path)
91                 resource_path = g_path_get_dirname(filename);
92
93         char *blorbfile = g_strconcat(resource_path, "/", scratch, ".blb", NULL);
94         if(g_file_test(blorbfile, G_FILE_TEST_EXISTS))
95                 g_object_set(glk, "graphics-file", blorbfile, NULL);
96
97         g_free(blorbfile);
98         g_free(scratch);
99         g_free(resource_path);
100 }
101
102 void
103 on_open_activate(GtkAction *action, ChimaraPlayer *player)
104 {
105         if(!confirm_open_new_game(CHIMARA_GLK(player->glk)))
106                 return;
107
108         GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Open Game"),
109             GTK_WINDOW(player),
110             GTK_FILE_CHOOSER_ACTION_OPEN,
111             GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
112             GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
113             NULL);
114
115         /* Get last opened path */
116         //extern GSettings *state_settings;
117         //gchar *path;
118         //g_settings_get(state_settings, "last-open-path", "ms", &path);
119         //if(path) {
120         //      gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), path);
121         //      g_free(path);
122         //}
123
124         if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
125                 GError *error = NULL;
126                 extern GSettings *prefs_settings;
127                 char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
128
129                 search_for_graphics_file(filename, CHIMARA_IF(player->glk));
130                 if(!chimara_if_run_game(CHIMARA_IF(player->glk), filename, &error)) {
131                         error_dialog(GTK_WINDOW(player), error, _("Could not open game file '%s': "), filename);
132                         g_free(filename);
133                         gtk_widget_destroy(dialog);
134                         return;
135                 }
136                 
137                 //path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
138                 //if(path) {
139                 //      g_settings_set(state_settings, "last-open-path", "ms", path);
140                 //      g_free(path);
141                 //}
142
143                 /* Add file to recent files list */
144                 GtkRecentManager *manager = gtk_recent_manager_get_default();
145                 gchar *uri;
146                 
147                 if(!(uri = g_filename_to_uri(filename, NULL, &error)))
148                         g_warning(_("Could not convert filename '%s' to URI: %s"), filename, error->message);
149                 else {
150                         if(!gtk_recent_manager_add_item(manager, uri))
151                                 g_warning(_("Could not add URI '%s' to recent files list."), uri);
152                         g_free(uri);
153                 }
154                 g_free(filename);
155         }
156         gtk_widget_destroy(dialog);
157 }
158
159 void
160 on_recent_item_activated(GtkRecentChooser *chooser, ChimaraPlayer *player)
161 {
162         GError *error = NULL;
163         gchar *uri = gtk_recent_chooser_get_current_uri(chooser);
164         gchar *filename;
165         if(!(filename = g_filename_from_uri(uri, NULL, &error))) {
166                 error_dialog(GTK_WINDOW(player), error, _("Could not open game file '%s': "), uri);
167                 goto finally;
168         }
169         
170         if(!confirm_open_new_game(CHIMARA_GLK(player->glk)))
171                 goto finally2;
172         
173         search_for_graphics_file(filename, CHIMARA_IF(player->glk));
174         if(!chimara_if_run_game(CHIMARA_IF(player->glk), filename, &error)) {
175                 error_dialog(GTK_WINDOW(player), error, _("Could not open game file '%s': "), filename);
176                 goto finally2;
177         }
178         
179         /* Add file to recent files list again, this updates it to most recently used */
180         GtkRecentManager *manager = gtk_recent_manager_get_default();
181         if(!gtk_recent_manager_add_item(manager, uri))
182                 g_warning(_("Could not add URI '%s' to recent files list."), uri);
183
184 finally2:
185         g_free(filename);
186 finally:
187         g_free(uri);
188 }
189
190 void
191 on_stop_activate(GtkAction *action, ChimaraPlayer *player)
192 {
193         chimara_glk_stop(CHIMARA_GLK(player->glk));
194 }
195
196 void 
197 on_quit_chimara_activate(GtkAction *action, ChimaraPlayer *player)
198 {
199         gtk_main_quit();
200 }
201
202 void
203 on_copy_activate(GtkAction *action, ChimaraPlayer *player)
204 {
205         GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
206         /* Call "copy clipboard" on any widget that defines it */
207         if(GTK_IS_LABEL(focus) || GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
208                 g_signal_emit_by_name(focus, "copy-clipboard");
209 }
210
211 void
212 on_paste_activate(GtkAction *action, ChimaraPlayer *player)
213 {
214         GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(player));
215         /* Call "paste clipboard" on any widget that defines it */
216         if(GTK_IS_ENTRY(focus) || GTK_IS_TEXT_VIEW(focus))
217                 g_signal_emit_by_name(focus, "paste-clipboard");
218 }
219
220 void
221 on_preferences_activate(GtkAction *action, ChimaraPlayer *player)
222 {
223         //extern GtkWidget *prefswindow;
224         //gtk_window_present(GTK_WINDOW(prefswindow));
225 }
226
227 void
228 on_toolbar_toggled(GtkToggleAction *action, ChimaraPlayer *player)
229 {
230         if(gtk_toggle_action_get_active(action))
231                 gtk_widget_show(player->toolbar);
232         else
233                 gtk_widget_hide(player->toolbar);
234 }
235
236 void
237 on_undo_activate(GtkAction *action, ChimaraPlayer *player)
238 {
239         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "undo");
240 }
241
242 void 
243 on_save_activate(GtkAction *action, ChimaraPlayer *player)
244 {
245         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "save");
246 }
247
248 void 
249 on_restore_activate(GtkAction *action, ChimaraPlayer *player)
250 {
251         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restore");
252 }
253
254 void 
255 on_restart_activate(GtkAction *action, ChimaraPlayer *player)
256 {
257         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "restart");
258 }
259
260 void 
261 on_quit_activate(GtkAction *action, ChimaraPlayer *player)
262 {
263         chimara_glk_feed_line_input(CHIMARA_GLK(player->glk), "quit");
264 }
265
266 void
267 on_about_activate(GtkAction *action, ChimaraPlayer *player)
268 {
269         extern GtkWidget *aboutwindow;
270         gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(aboutwindow), PACKAGE_VERSION);
271         gtk_window_present(GTK_WINDOW(aboutwindow));
272 }
273
274 gboolean 
275 on_window_delete_event(GtkWidget *widget, GdkEvent *event, ChimaraPlayer *player) 
276 {
277         gtk_main_quit();
278         return TRUE;
279 }