20130427
[gdash.git] / src / main.cpp
blob5864fc13baf1cbd04d34817500f42d89ef3dac8c
1 /*
2 * Copyright (c) 2007-2013, Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
19 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include "config.h"
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <fstream>
30 #ifdef HAVE_GTK
31 #include <gtk/gtk.h>
32 #endif
34 #ifdef HAVE_SDL
35 /* on windows, sdl does some hack on the main function.
36 * therefore we need to include this file, even if it seems
37 * to do nothing. */
38 #include <SDL/SDL.h>
39 #endif
41 #include "cave/caveset.hpp"
42 #include "sound/sound.hpp"
43 #include "misc/util.hpp"
44 #include "misc/logger.hpp"
45 #include "misc/about.hpp"
46 #include "settings.hpp"
47 #include "framework/commands.hpp"
48 #include "fileops/loadfile.hpp"
49 #include "fileops/highscore.hpp"
50 #include "fileops/binaryimport.hpp"
51 #include "input/joystick.hpp"
53 #ifdef HAVE_GTK
54 #include "editor/editor.hpp"
55 #include "editor/editorcellrenderer.hpp"
56 #include "editor/exporthtml.hpp"
57 #include "gtk/gtkpixbuffactory.hpp"
58 #include "gtk/gtkscreen.hpp"
59 #include "gtk/gtkui.hpp"
60 #include "misc/helphtml.hpp"
61 #endif
63 #include "mainwindow.hpp"
65 /* includes cavesets built in to the executable */
66 #include "levels.cpp"
70 int main(int argc, char *argv[]) {
71 CaveSet caveset;
72 int quit = 0;
73 #ifdef HAVE_GTK
74 gboolean editor = FALSE;
75 #endif
76 char *gallery_filename = NULL;
77 char *png_filename = NULL, *png_size = NULL;
78 char *save_cave_name = NULL, *save_gds_name = NULL;
79 #ifdef HAVE_GTK
80 int save_doc_lang = -1;
81 #endif
83 GError *error = NULL;
84 GOptionEntry entries[] = {
85 #ifdef HAVE_GTK
86 {"editor", 'e', 0, G_OPTION_ARG_NONE, &editor, N_("Start editor")},
87 {"save-gallery", 'g', 0, G_OPTION_ARG_FILENAME, &gallery_filename, N_("Save caveset in a HTML gallery")},
88 {"stylesheet", 0, 0, G_OPTION_ARG_STRING /* not filename! */, &gd_html_stylesheet_filename, N_("Link stylesheet from file to a HTML gallery, eg. \"../style.css\"")},
89 {"favicon", 0, 0, G_OPTION_ARG_STRING /* not filename! */, &gd_html_favicon_filename, N_("Link shortcut icon to a HTML gallery, eg. \"../favicon.ico\"")},
90 {"save-png", 'p', 0, G_OPTION_ARG_FILENAME, &png_filename, N_("Save image of first cave to PNG")},
91 {"png-size", 0, 0, G_OPTION_ARG_STRING, &png_size, N_("Set PNG image size. Default is 128x96, set to 0x0 for unscaled")},
92 #endif
93 {"save-bdcff", 's', 0, G_OPTION_ARG_FILENAME, &save_cave_name, N_("Save caveset in a BDCFF file")},
94 {"save-gds", 'd', 0, G_OPTION_ARG_FILENAME, &save_gds_name, N_("Save imported binary data to a GDS file. An input file name is required.")},
95 #ifdef HAVE_GTK
96 {"save-docs", 0, 0, G_OPTION_ARG_INT, &save_doc_lang, N_("Save documentation in HTML, in the given language identified by an integer.")},
97 #endif
98 {"quit", 'q', 0, G_OPTION_ARG_NONE, &quit, N_("Batch mode: quit after specified tasks")},
99 {NULL}
102 GOptionContext *context = gd_option_context_new();
103 g_option_context_add_main_entries(context, entries, PACKAGE); /* gdash (gtk version) parameters */
104 #ifdef HAVE_GTK
105 g_option_context_add_group(context, gtk_get_option_group(FALSE)); /* add gtk parameters */
106 #endif
107 g_option_context_parse(context, &argc, &argv, &error);
108 g_option_context_free(context);
109 if (error) {
110 gd_warning(error->message);
111 g_error_free(error);
114 /* show license? */
115 if (gd_param_license) {
116 /* print license and quit. */
117 g_print("%s %s\n\n%s\n\n", PACKAGE_NAME, PACKAGE_VERSION, About::copyright);
118 std::vector<std::string> wrapped_license = gd_wrap_text(About::license, 72);
119 for (unsigned i = 0; i < wrapped_license.size(); ++i)
120 g_print("%s\n", wrapped_license[i].c_str());
121 return 0;
124 Logger global_logger;
126 gd_settings_init();
127 gd_settings_init_dirs();
128 if (!gd_param_load_default_settings)
129 gd_load_settings();
130 gd_settings_set_locale();
131 gd_settings_init_translation();
133 #ifdef HAVE_GTK
134 /* init gtk and set gtk default icon */
135 gboolean force_quit_no_gtk = FALSE;
136 if (!gtk_init_check(&argc, &argv))
137 force_quit_no_gtk = TRUE;
138 GdkPixbuf *logo = gd_icon();
139 gtk_window_set_default_icon(logo);
140 g_object_unref(logo);
141 #endif
143 gd_cave_types_init();
144 gd_cave_objects_init();
145 Joystick::init();
147 /* if memory snapshot -> gds file conversion requested */
148 if (save_gds_name != NULL) {
149 Logger thislogger;
150 if (gd_param_cavenames == NULL || g_str_equal(gd_param_cavenames, "")) {
151 g_print("An input filename must be given for GDS conversion.\n");
152 return 1;
154 std::vector<unsigned char> file = load_file_to_vector(gd_param_cavenames[0]);
155 /* -1 because the file loader adds a terminating zero */
156 std::vector<unsigned char> memory = load_memory_dump(&file[0], file.size() - 1);
157 std::vector<unsigned char> gds = gdash_binary_import(memory);
158 std::fstream os(save_gds_name, std::ios::out | std::ios::binary);
159 os.write((char *) &gds[0], gds.size());
161 thislogger.clear();
164 /* LOAD A CAVESET FROM A FILE, OR AN INTERNAL ONE */
165 /* if remaining arguments, they are filenames */
166 try {
167 if (gd_param_cavenames && gd_param_cavenames[0]) {
168 caveset = load_caveset_from_file(gd_param_cavenames[0]);
169 load_highscore(caveset);
170 } else {
171 /* if nothing requested, load default */
172 caveset = create_from_buffer(level_pointers[0], -1);
173 caveset.name = level_names[0];
174 load_highscore(caveset);
176 } catch (std::exception &e) {
177 /// @todo show error to the screen
178 gd_critical(e.what());
181 #ifdef HAVE_GTK
182 /* see if generating a gallery. */
183 /* but only if there are any caves at all. */
184 if (caveset.has_caves() && gallery_filename)
185 gd_save_html(gallery_filename, NULL, caveset);
187 /* save cave png */
188 if (png_filename) {
189 unsigned int size_x = 128, size_y = 96; /* default size */
191 if (png_size && (sscanf(png_size, "%ux%u", &size_x, &size_y) != 2))
192 gd_warning(CPrintf(_("Invalid image size: %s")) % png_size);
193 if (size_x < 1 || size_y < 1) {
194 size_x = 0;
195 size_y = 0;
198 /* rendering cave for png: seed=0 */
199 CaveRendered renderedcave(caveset.cave(0), 0, 0);
200 GTKPixbufFactory pf;
201 GTKScreen scr(pf, NULL);
202 EditorCellRenderer cr(scr, gd_theme);
204 GdkPixbuf *pixbuf = gd_drawcave_to_pixbuf(&renderedcave, cr, size_x, size_y, true, false);
205 GError *error = NULL;
206 if (!gdk_pixbuf_save(pixbuf, png_filename, "png", &error, "compression", "9", NULL)) {
207 gd_critical(CPrintf("Error saving PNG image %s: %s") % png_filename % error->message);
208 g_error_free(error);
210 g_object_unref(pixbuf);
212 #endif
214 if (save_cave_name)
215 caveset.save_to_file(save_cave_name);
217 #ifdef HAVE_GTK
218 gd_register_stock_icons();
220 if (save_doc_lang != -1) {
221 if (save_doc_lang < 1 || save_doc_lang >= (int)g_strv_length((gchar **) gd_languages_names)) {
222 gd_critical("No such language");
223 return 1;
225 /* switch to the doc language requested */
226 int language_previous = gd_language;
227 gd_language = save_doc_lang;
228 gd_settings_set_locale();
229 gd_settings_init_translation();
231 /* the html saver needs a realized widget to render gtk icons, so create a toplevel window,
232 * realize it, but do not show it */
233 GtkWidget *widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
234 gtk_widget_realize(widget);
235 save_help_to_html(CPrintf("Doc-%s.html") % gd_languages_names[save_doc_lang], widget);
236 gtk_widget_destroy(widget);
238 /* switch back to original language */
239 gd_language = language_previous;
240 gd_settings_set_locale();
241 gd_settings_init_translation();
243 #endif
245 /* if batch mode, quit now */
246 if (quit) {
247 global_logger.clear();
248 return 0;
250 #ifdef HAVE_GTK
251 if (force_quit_no_gtk) {
252 gd_critical("Cannot initialize GTK+");
253 return 1;
255 #endif
257 #ifdef HAVE_SDL
258 if (SDL_Init(0) == -1) {
259 gd_critical("Cannot initialize SDL");
260 return 1;
262 #endif
264 /* select first action */
265 NextAction na = StartTitle;
266 #ifdef HAVE_GTK
267 if (editor)
268 na = StartEditor;
269 #endif
271 restart_from_here:
273 gd_sound_init();
274 gd_sound_set_music_volume();
275 gd_sound_set_chunk_volumes();
277 while (na != Quit && na != Restart) {
278 switch (na) {
279 case StartTitle:
280 main_window_run_title_screen(&caveset, na);
281 break;
282 #ifdef HAVE_GTK
283 case StartEditor:
284 na = StartTitle;
285 gd_cave_editor_run(&caveset);
286 break;
287 #endif
288 case Restart:
289 case Quit:
290 break;
294 gd_sound_close();
296 if (na == Restart) {
297 na = StartTitle;
298 goto restart_from_here;
301 save_highscore(caveset);
303 gd_save_settings();
305 global_logger.clear();
307 #ifdef HAVE_SDL
308 SDL_Quit();
309 #endif
311 /* free the stuff created by the option context */
312 g_free(gallery_filename);
313 g_free(gd_html_stylesheet_filename);
314 g_free(gd_html_favicon_filename);
315 g_free(png_filename);
316 g_free(png_size);
317 g_free(save_gds_name);
319 return 0;