Code

Split SPCanvasItem and SPCanvasGroup to individual .h files. Removed forward header.
[inkscape.git] / src / inkview.cpp
1 /*
2  * Inkscape - an ambitious vector drawing program
3  *
4  * Authors:
5  *   Lauris Kaplinski <lauris@kaplinski.com>
6  *   Frank Felfe <innerspace@iname.com>
7  *   Davide Puricelli <evo@debian.org>
8  *   Mitsuru Oka <oka326@parkcity.ne.jp>
9  *   Masatake YAMATO  <jet@gyve.org>
10  *   F.J.Franklin <F.J.Franklin@sheffield.ac.uk>
11  *   Michael Meeks <michael@helixcode.com>
12  *   Chema Celorio <chema@celorio.com>
13  *   Pawel Palucha
14  * ... and various people who have worked with various projects
15  *   Abhishek Sharma
16  *
17  * Copyright (C) 1999-2002 authors
18  * Copyright (C) 2001-2002 Ximian, Inc.
19  *
20  * Inkscape authors:
21  *   Johan Ceuppens
22  *
23  * Copyright (C) 2004 Inkscape authors
24  *
25  * Released under GNU GPL, read the file 'COPYING' for more information
26  */
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
33 #ifdef HAVE_GETOPT_H
34 #include <getopt.h>
35 #endif
37 #include <string.h>
38 #include <sys/stat.h>
39 #include <locale.h>
41 #include <glib/gmem.h>
42 #include <libnr/nr-macros.h>
44 // #include <stropts.h>
46 #include <libxml/tree.h>
47 #include <gdk/gdkkeysyms.h>
48 #include <gtk/gtkmain.h>
49 #include <gtk/gtkstock.h>
50 #include <gtk/gtkwindow.h>
51 #include <gtk/gtktable.h>
52 #include <gtk/gtkbutton.h>
54 #include <gtkmm/main.h>
56 #include "gc-core.h"
57 #include "preferences.h"
59 #include <glibmm/i18n.h>
60 #include "document.h"
61 #include "svg-view.h"
62 #include "svg-view-widget.h"
64 #ifdef WITH_INKJAR
65 #include "io/inkjar.h"
66 #endif
68 #include "inkscape-private.h"
70 Inkscape::Application *inkscape;
72 #include <iostream>
74 #ifndef HAVE_BIND_TEXTDOMAIN_CODESET
75 #define bind_textdomain_codeset(p,c)
76 #endif
78 extern char *optarg;
79 extern int  optind, opterr;
81 struct SPSlideShow {
82     char **slides;
83     int size;
84     int length;
85     int current;
86     SPDocument *doc;
87     GtkWidget *view;
88     GtkWidget *window;
89     bool fullscreen;
90     int timer;
91 };
93 static GtkWidget *sp_svgview_control_show (struct SPSlideShow *ss);
94 static void sp_svgview_show_next (struct SPSlideShow *ss);
95 static void sp_svgview_show_prev (struct SPSlideShow *ss);
96 static void sp_svgview_goto_first (struct SPSlideShow *ss);
97 static void sp_svgview_goto_last (struct SPSlideShow *ss);
99 static int sp_svgview_show_next_cb (GtkWidget *widget, void *data);
100 static int sp_svgview_show_prev_cb (GtkWidget *widget, void *data);
101 static int sp_svgview_goto_first_cb (GtkWidget *widget, void *data);
102 static int sp_svgview_goto_last_cb (GtkWidget *widget, void *data);
103 #ifdef WITH_INKJAR
104 static bool is_jar(char const *filename);
105 #endif
106 static void usage();
108 static GtkWidget *ctrlwin = NULL;
110 /// Dummy functions to keep linker happy
111 int sp_main_gui (int, char const**) { return 0; }
112 int sp_main_console (int, char const**) { return 0; }
114 static int
115 sp_svgview_main_delete (GtkWidget */*widget*/, GdkEvent */*event*/, struct SPSlideShow */*ss*/)
117     gtk_main_quit ();
118     return FALSE;
121 static int
122 sp_svgview_main_key_press (GtkWidget */*widget*/, GdkEventKey *event, struct SPSlideShow *ss)
124     switch (event->keyval) {
125     case GDK_Up:
126     case GDK_Home:
127         sp_svgview_goto_first(ss);
128         break;
129     case GDK_Down:
130     case GDK_End:
131         sp_svgview_goto_last(ss);
132         break;
133     case GDK_F11:
134 #ifdef HAVE_GTK_WINDOW_FULLSCREEN
135         if (ss->fullscreen) {
136             gtk_window_unfullscreen (GTK_WINDOW(ss->window));
137             ss->fullscreen = false;
138         } else {
139             gtk_window_fullscreen (GTK_WINDOW(ss->window));
140             ss->fullscreen = true;
141         }
142 #else
143         std::cout<<"Your GTK+ does not support fullscreen mode. Upgrade to 2.2."<<std::endl;
144 #endif
145         break;
146     case GDK_Return:
147         sp_svgview_control_show (ss);
148         break;
149     case GDK_KP_Page_Down:
150     case GDK_Page_Down:
151     case GDK_Right:
152     case GDK_space:
153         sp_svgview_show_next (ss);
154         break;
155     case GDK_KP_Page_Up:
156     case GDK_Page_Up:
157     case GDK_Left:
158     case GDK_BackSpace:
159         sp_svgview_show_prev (ss);
160         break;
161     case GDK_Escape:
162     case GDK_q:
163     case GDK_Q:
164         gtk_main_quit();
165         break;
166     default:
167         break;
168     }
169     gtk_window_set_title(GTK_WINDOW(ss->window), ss->doc->getName());
170     return TRUE;
173 int
174 main (int argc, const char **argv)
176     if (argc == 1) {
177         usage();
178     }
180     // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
181     Gtk::Main::init_gtkmm_internals();
183     Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
185     struct SPSlideShow ss;
187     int option,
188         num_parsed_options = 0;
190     // the list of arguments is in the net line
191     while ((option = getopt(argc, (char* const* )argv, "t:")) != -1)
192     {
193         switch(option) {
194             case 't': // for timer
195                 // fprintf(stderr, "set timer arg %s\n", optarg );
196                 ss.timer = atoi(optarg);
197                 num_parsed_options += 2; // 2 because of flag + option
198                 break;
199             case '?':
200             default:
201                 usage();
202         }
203     }
205     GtkWidget *w;
206     int i;
208     bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
209     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
210     textdomain (GETTEXT_PACKAGE);
212     LIBXML_TEST_VERSION
214     Inkscape::GC::init();
215     Inkscape::Preferences::get(); // ensure preferences are initialized
217     gtk_init (&argc, (char ***) &argv);
219 #ifdef lalaWITH_MODULES
220     g_warning ("Have to autoinit modules (lauris)");
221     sp_modulesys_init();
222 #endif /* WITH_MODULES */
224     /* We must set LC_NUMERIC to default, or otherwise */
225     /* we'll end with localised SVG files :-( */
227     setlocale (LC_NUMERIC, "C");
229     ss.size = 32;
230     ss.length = 0;
231     ss.current = 0;
232     ss.slides = g_new (char *, ss.size);
233     ss.current = 0;
234     ss.doc = NULL;
235     ss.view = NULL;
236     ss.fullscreen = false;
238     inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL);
240     // starting at where the commandline options stopped parsing because
241     // we want all the files to be in the list
242     for (i = num_parsed_options + 1 ; i < argc; i++) {
243         struct stat st;
244         if (stat (argv[i], &st)
245               || !S_ISREG (st.st_mode)
246               || (st.st_size < 64)) {
247                 fprintf(stderr, "could not open file %s\n", argv[i]);
248         } else {
250 #ifdef WITH_INKJAR
251             if (is_jar(argv[i])) {
252                 Inkjar::JarFileReader jar_file_reader(argv[i]);
253                 for (;;) {
254                     GByteArray *gba = jar_file_reader.get_next_file();
255                     if (gba == NULL) {
256                         char *c_ptr;
257                         gchar *last_filename = jar_file_reader.get_last_filename();
258                         if (last_filename == NULL)
259                             break;
260                         if ((c_ptr = std::strrchr(last_filename, '/')) != NULL) {
261                             if (*(++c_ptr) == '\0') {
262                                 g_free(last_filename);
263                                 continue;
264                             }
265                         }
266                     } else if (gba->len > 0) {
267                         //::write(1, gba->data, gba->len);
268                         /* Append to list */
269                         if (ss.length >= ss.size) {
270                             /* Expand */
271                             ss.size <<= 1;
272                             ss.slides = g_renew (char *, ss.slides, ss.size);
273                         }
275                         ss.doc = SPDocument::createNewDocFromMem ((const gchar *)gba->data,
276                                                            gba->len,
277                                                            TRUE);
278                         gchar *last_filename = jar_file_reader.get_last_filename();
279                         if (ss.doc) {
280                             ss.slides[ss.length++] = strdup (last_filename);
281                             (ss.doc)->setUri (strdup(last_filename));
282                         }
283                         g_byte_array_free(gba, TRUE);
284                         g_free(last_filename);
285                     } else
286                         break;
287                 }
288             } else {
289 #endif /* WITH_INKJAR */
290                 /* Append to list */
291                 if (ss.length >= ss.size) {
292                     /* Expand */
293                     ss.size <<= 1;
294                     ss.slides = g_renew (char *, ss.slides, ss.size);
296                 }
298                 ss.slides[ss.length++] = strdup (argv[i]);
300                 if (!ss.doc) {
301                     ss.doc = SPDocument::createNewDoc (ss.slides[ss.current], TRUE, false);
302                     if (!ss.doc)
303                         ++ss.current;
304                 }
305 #ifdef WITH_INKJAR
306             }
307 #endif
308         }
309     }
311     if(!ss.doc)
312        return 1; /* none of the slides loadable */
314     w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
315     gtk_window_set_title( GTK_WINDOW(w), ss.doc->getName() );
316     gtk_window_set_default_size (GTK_WINDOW (w),
317                                  MIN ((int)(ss.doc)->getWidth (), (int)gdk_screen_width () - 64),
318                                  MIN ((int)(ss.doc)->getHeight (), (int)gdk_screen_height () - 64));
319     gtk_window_set_policy (GTK_WINDOW (w), TRUE, TRUE, FALSE);
320     ss.window = w;
322     g_signal_connect (G_OBJECT (w), "delete_event", (GCallback) sp_svgview_main_delete, &ss);
323     g_signal_connect (G_OBJECT (w), "key_press_event", (GCallback) sp_svgview_main_key_press, &ss);
325     (ss.doc)->ensureUpToDate();
326     ss.view = sp_svg_view_widget_new (ss.doc);
327     (ss.doc)->doUnref ();
328     SP_SVG_VIEW_WIDGET(ss.view)->setResize( false, ss.doc->getWidth(), ss.doc->getHeight() );
329     gtk_widget_show (ss.view);
330     gtk_container_add (GTK_CONTAINER (w), ss.view);
332     gtk_widget_show (w);
334     gtk_main ();
336     return 0;
339 static int
340 sp_svgview_ctrlwin_delete (GtkWidget */*widget*/, GdkEvent */*event*/, void */*data*/)
342     ctrlwin = NULL;
343     return FALSE;
346 static GtkWidget *
347 sp_svgview_control_show (struct SPSlideShow *ss)
349     if (!ctrlwin) {
350         GtkWidget *t, *b;
351         ctrlwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
352     gtk_window_set_transient_for (GTK_WINDOW(ctrlwin), GTK_WINDOW(ss->window));
353     g_signal_connect (G_OBJECT (ctrlwin), "key_press_event", (GCallback) sp_svgview_main_key_press, ss);
354         g_signal_connect (G_OBJECT (ctrlwin), "delete_event", (GCallback) sp_svgview_ctrlwin_delete, NULL);
355         t = gtk_table_new (1, 4, TRUE);
356         gtk_container_add ((GtkContainer *) ctrlwin, t);
357         b = gtk_button_new_from_stock (GTK_STOCK_GOTO_FIRST);
358         gtk_table_attach ((GtkTable *) t, b, 0, 1, 0, 1,
359                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
360                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
361                           0, 0);
362         g_signal_connect ((GObject *) b, "clicked", (GCallback) sp_svgview_goto_first_cb, ss);
363         b = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
364         gtk_table_attach ((GtkTable *) t, b, 1, 2, 0, 1,
365                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
366                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
367                           0, 0);
368         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_prev_cb, ss);
369         b = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
370         gtk_table_attach ((GtkTable *) t, b, 2, 3, 0, 1,
371                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
372                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
373                           0, 0);
374         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_next_cb, ss);
375         b = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
376         gtk_table_attach ((GtkTable *) t, b, 3, 4, 0, 1,
377                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
378                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
379                           0, 0);
380         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_goto_last_cb, ss);
381         gtk_widget_show_all (ctrlwin);
382     } else {
383         gtk_window_present ((GtkWindow *) ctrlwin);
384     }
386     return NULL;
389 static int
390 sp_svgview_show_next_cb (GtkWidget */*widget*/, void *data)
392     sp_svgview_show_next(static_cast<struct SPSlideShow *>(data));
393     return FALSE;
396 static int
397 sp_svgview_show_prev_cb (GtkWidget */*widget*/, void *data)
399     sp_svgview_show_prev(static_cast<struct SPSlideShow *>(data));
400     return FALSE;
403 static int
404 sp_svgview_goto_first_cb (GtkWidget */*widget*/, void *data)
406     sp_svgview_goto_first(static_cast<struct SPSlideShow *>(data));
407     return FALSE;
410 static int
411 sp_svgview_goto_last_cb (GtkWidget */*widget*/, void *data)
413     sp_svgview_goto_last(static_cast<struct SPSlideShow *>(data));
414     return FALSE;
417 static void
418 sp_svgview_waiting_cursor(struct SPSlideShow *ss)
420     GdkCursor *waiting = gdk_cursor_new(GDK_WATCH);
421     gdk_window_set_cursor(GTK_WIDGET(ss->window)->window, waiting);
422     gdk_cursor_unref(waiting);
423     if (ctrlwin) {
424         GdkCursor *waiting = gdk_cursor_new(GDK_WATCH);
425         gdk_window_set_cursor(GTK_WIDGET(ctrlwin)->window, waiting);
426         gdk_cursor_unref(waiting);
427     }
428     while(gtk_events_pending())
429        gtk_main_iteration();
432 static void
433 sp_svgview_normal_cursor(struct SPSlideShow *ss)
435    gdk_window_set_cursor(GTK_WIDGET(ss->window)->window, NULL);
436     if (ctrlwin) {
437         gdk_window_set_cursor(GTK_WIDGET(ctrlwin)->window, NULL);
438     }
441 static void
442 sp_svgview_set_document(struct SPSlideShow *ss, SPDocument *doc, int current)
444     if (doc && doc != ss->doc) {
445         doc->ensureUpToDate();
446         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
447         ss->doc = doc;
448         ss->current = current;
449     }
452 static void
453 sp_svgview_show_next (struct SPSlideShow *ss)
455     sp_svgview_waiting_cursor(ss);
457     SPDocument *doc = NULL;
458     int current = ss->current;
459     while (!doc && (current < ss->length - 1)) {
460         doc = SPDocument::createNewDoc (ss->slides[++current], TRUE, false);
461     }
463     sp_svgview_set_document(ss, doc, current);
465     sp_svgview_normal_cursor(ss);
468 static void
469 sp_svgview_show_prev (struct SPSlideShow *ss)
471     sp_svgview_waiting_cursor(ss);
473     SPDocument *doc = NULL;
474     int current = ss->current;
475     while (!doc && (current > 0)) {
476         doc = SPDocument::createNewDoc (ss->slides[--current], TRUE, false);
477     }
479     sp_svgview_set_document(ss, doc, current);
481     sp_svgview_normal_cursor(ss);
484 static void
485 sp_svgview_goto_first (struct SPSlideShow *ss)
487     sp_svgview_waiting_cursor(ss);
489     SPDocument *doc = NULL;
490     int current = 0;
491     while ( !doc && (current < ss->length - 1)) {
492         if (current == ss->current)
493             break;
494         doc = SPDocument::createNewDoc (ss->slides[current++], TRUE, false);
495     }
497     sp_svgview_set_document(ss, doc, current - 1);
499     sp_svgview_normal_cursor(ss);
502 static void
503 sp_svgview_goto_last (struct SPSlideShow *ss)
505     sp_svgview_waiting_cursor(ss);
507     SPDocument *doc = NULL;
508     int current = ss->length - 1;
509     while (!doc && (current >= 0)) {
510         if (current == ss->current)
511             break;
512         doc = SPDocument::createNewDoc (ss->slides[current--], TRUE, false);
513     }
515     sp_svgview_set_document(ss, doc, current + 1);
517     sp_svgview_normal_cursor(ss);
520 #ifdef WITH_INKJAR
521 static bool
522 is_jar(char const *filename)
524     /* fixme: Check MIME type or something.  /usr/share/misc/file/magic suggests that checking for
525        initial string "PK\003\004" in content should suffice. */
526     size_t const filename_len = strlen(filename);
527     if (filename_len < 5) {
528         return false;
529     }
530     char const *extension = filename + filename_len - 4;
531     return ((memcmp(extension, ".jar", 4) == 0) ||
532             (memcmp(extension, ".sxw", 4) == 0)   );
534 #endif /* WITH_INKJAR */
536 static void usage()
538     fprintf(stderr,
539             "Usage: inkview [OPTIONS...] [FILES ...]\n"
540             "\twhere FILES are SVG (.svg or .svgz)"
541 #ifdef WITH_INKJAR
542             " or archives of SVGs (.sxw, .jar)"
543 #endif
544             "\n");
545     exit(1);
548 #ifdef XXX
549 /* TODO !!! make this temporary stub unnecessary */
550 Inkscape::Application *inkscape_get_instance() { return NULL; }
551 void inkscape_ref (void) {}
552 void inkscape_unref (void) {}
553 void inkscape_add_document (SPDocument *document) {}
554 void inkscape_remove_document (SPDocument *document) {}
555 #endif
558 /*
559   Local Variables:
560   mode:c++
561   c-file-style:"stroustrup"
562   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
563   indent-tabs-mode:nil
564   fill-column:99
565   End:
566 */
567 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :