Code

added commandline option ability and got timer ready for doing automatic
[inkscape.git] / src / inkview.cpp
1 #define __SPSVGVIEW_C__
3 /*
4  * Inkscape - an ambitious vector drawing program
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *   Frank Felfe <innerspace@iname.com>
9  *   Davide Puricelli <evo@debian.org>
10  *   Mitsuru Oka <oka326@parkcity.ne.jp>
11  *   Masatake YAMATO  <jet@gyve.org>
12  *   F.J.Franklin <F.J.Franklin@sheffield.ac.uk>
13  *   Michael Meeks <michael@helixcode.com>
14  *   Chema Celorio <chema@celorio.com>
15  *   Pawel Palucha
16  * ... and various people who have worked with various projects
17  *
18  * Copyright (C) 1999-2002 authors
19  * Copyright (C) 2001-2002 Ximian, Inc.
20  *
21  * Inkscape authors:
22  *   Johan Ceuppens
23  *
24  * Copyright (C) 2004 Inkscape authors
25  *
26  * Released under GNU GPL, read the file 'COPYING' for more information
27  */
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
34 #include <string.h>
35 #include <sys/stat.h>
36 #include <locale.h>
38 #include <glib/gmem.h>
39 #include <libnr/nr-macros.h>
41 // #include <stropts.h>
43 #include <libxml/tree.h>
44 #include <gdk/gdkkeysyms.h>
45 #include <gtk/gtkmain.h>
46 #include <gtk/gtkstock.h>
47 #include <gtk/gtkwindow.h>
48 #include <gtk/gtktable.h>
49 #include <gtk/gtkbutton.h>
51 #include "gc-core.h"
52 #include "preferences.h"
54 #include <glibmm/i18n.h>
55 #include "document.h"
56 #include "svg-view.h"
57 #include "svg-view-widget.h"
59 #ifdef WITH_INKJAR
60 #include "inkjar/jar.h"
61 #endif
63 #include "inkscape-private.h"
65 Inkscape::Application *inkscape;
67 #include <iostream>
69 #ifndef HAVE_BIND_TEXTDOMAIN_CODESET
70 #define bind_textdomain_codeset(p,c)
71 #endif
73 extern char *optarg;
74 extern int  optind, opterr;
76 struct SPSlideShow {
77     char **slides;
78     int size;
79     int length;
80     int current;
81     SPDocument *doc;
82     GtkWidget *view;
83     GtkWindow *window;
84     bool fullscreen;
85     int timer;
86 };
88 static GtkWidget *sp_svgview_control_show (struct SPSlideShow *ss);
89 static void sp_svgview_show_next (struct SPSlideShow *ss);
90 static void sp_svgview_show_prev (struct SPSlideShow *ss);
91 static void sp_svgview_goto_first (struct SPSlideShow *ss);
92 static void sp_svgview_goto_last (struct SPSlideShow *ss);
94 static int sp_svgview_show_next_cb (GtkWidget *widget, void *data);
95 static int sp_svgview_show_prev_cb (GtkWidget *widget, void *data);
96 static int sp_svgview_goto_first_cb (GtkWidget *widget, void *data);
97 static int sp_svgview_goto_last_cb (GtkWidget *widget, void *data);
98 #ifdef WITH_INKJAR
99 static bool is_jar(char const *filename);
100 #endif
101 static void usage();
103 static GtkWidget *ctrlwin = NULL;
105 /// Dummy functions to keep linker happy
106 int sp_main_gui (int, char const**) { return 0; }
107 int sp_main_console (int, char const**) { return 0; }
109 static int
110 sp_svgview_main_delete (GtkWidget *widget, GdkEvent *event, struct SPSlideShow *ss)
112     gtk_main_quit ();
113     return FALSE;
116 static int
117 sp_svgview_main_key_press (GtkWidget *widget, GdkEventKey *event, struct SPSlideShow *ss)
119     switch (event->keyval) {
120     case GDK_Up:
121         sp_svgview_goto_first(ss);
122         break;
123     case GDK_Down:
124         sp_svgview_goto_last(ss);
125         break;
126     case GDK_F11:
127 #ifdef HAVE_GTK_WINDOW_FULLSCREEN
128         if (ss->fullscreen) {
129             gtk_window_unfullscreen ((GtkWindow *) widget);
130             ss->fullscreen = false;
131         } else {
132             gtk_window_fullscreen ((GtkWindow *) widget);
133             ss->fullscreen = true;
134         }
135 #else
136         std::cout<<"Your GTK+ does not support fullscreen mode. Upgrade to 2.2."<<std::endl;
137 #endif
138         break;
139     case GDK_Return:
140         sp_svgview_control_show (ss);
141         break;
142     case GDK_KP_Page_Down:
143     case GDK_Page_Down:
144     case GDK_Right:
145     case GDK_space:
146         sp_svgview_show_next (ss);
147         break;
148     case GDK_KP_Page_Up:
149     case GDK_Page_Up:
150     case GDK_Left:
151         sp_svgview_show_prev (ss);
152         break;
153     case GDK_Escape:
154     case GDK_q:
155     case GDK_Q:
156         gtk_main_quit();
157         break;
158     default:
159         break;
160     }
161     gtk_window_set_title(GTK_WINDOW(widget), SP_DOCUMENT_NAME(ss->doc));
162     return FALSE;
165 int
166 main (int argc, const char **argv)
168     if (argc == 1) {
169         usage();
170     }
172     struct SPSlideShow ss;
174     int option,
175         num_parsed_options = 0;
177     // the list of arguments is in the net line
178     while ((option = getopt(argc, (char* const* )argv, "t:")) != -1) 
179     {
180         switch(option) {
181             case 't': // for timer
182                 // fprintf(stderr, "set timer arg %s\n", optarg );
183                 ss.timer = int(optarg); 
184                 num_parsed_options += 2; // 2 because of flag + option
185                 break;
186             case '?':
187             default:
188                 usage();
189         }       
190     }
191    
192     GtkWidget *w;
193     int i;
195     bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
196     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
197     textdomain (GETTEXT_PACKAGE);
199     LIBXML_TEST_VERSION
201     Inkscape::GC::init();
202     Inkscape::Preferences::loadSkeleton();
204     gtk_init (&argc, (char ***) &argv);
206 #ifdef lalaWITH_MODULES
207     g_warning ("Have to autoinit modules (lauris)");
208     sp_modulesys_init();
209 #endif /* WITH_MODULES */
211     /* We must set LC_NUMERIC to default, or otherwise */
212     /* we'll end with localised SVG files :-( */
214     setlocale (LC_NUMERIC, "C");
216     ss.size = 32;
217     ss.length = 0;
218     ss.current = 0;
219     ss.slides = g_new (char *, ss.size);
220     ss.current = 0;
221     ss.doc = NULL;
222     ss.view = NULL;
223     ss.fullscreen = false;
225     inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL);
226     Inkscape::Preferences::load();
227     
228     // starting at where the commandline options stopped parsing because
229     // we want all the files to be in the list
230     for (i = num_parsed_options + 1 ; i < argc; i++) {
231         struct stat st;
232         if (stat (argv[i], &st)
233               || !S_ISREG (st.st_mode)
234               || (st.st_size < 64)) {
235                 fprintf(stderr, "could not open file %s\n", argv[i]);
236         } else {
238 #ifdef WITH_INKJAR
239             if (is_jar(argv[i])) {
240                 Inkjar::JarFileReader jar_file_reader(argv[i]);
241                 for (;;) {
242                     GByteArray *gba = jar_file_reader.get_next_file();
243                     if (gba == NULL) {
244                         char *c_ptr;
245                         gchar *last_filename = jar_file_reader.get_last_filename();
246                         if (last_filename == NULL)
247                             break;
248                         if ((c_ptr = std::strrchr(last_filename, '/')) != NULL) {
249                             if (*(++c_ptr) == '\0') {
250                                 g_free(last_filename);
251                                 continue;
252                             }
253                         }
254                     } else if (gba->len > 0) {
255                         //::write(1, gba->data, gba->len);
256                         /* Append to list */
257                         if (ss.length >= ss.size) {
258                             /* Expand */
259                             ss.size <<= 1;
260                             ss.slides = g_renew (char *, ss.slides, ss.size);
261                         }
263                         ss.doc = sp_document_new_from_mem ((const gchar *)gba->data,
264                                                            gba->len,
265                                                            TRUE);
266                         gchar *last_filename = jar_file_reader.get_last_filename();
267                         if (ss.doc) {
268                             ss.slides[ss.length++] = strdup (last_filename);
269                             sp_document_set_uri (ss.doc, strdup(last_filename));
270                         }
271                         g_byte_array_free(gba, TRUE);
272                         g_free(last_filename);
273                     } else
274                         break;
275                 }
276             } else {
277 #endif /* WITH_INKJAR */
278                 /* Append to list */
279                 if (ss.length >= ss.size) {
280                     /* Expand */
281                     ss.size <<= 1;
282                     ss.slides = g_renew (char *, ss.slides, ss.size);
284                 }
286                 ss.slides[ss.length++] = strdup (argv[i]);
287                 ss.doc = sp_document_new (ss.slides[ss.current], TRUE, false);
289                 if (!ss.doc && ++ss.current >= ss.length) {
290                     /* No loadable documents */
291                     return 1;
292                 }
293 #ifdef WITH_INKJAR
294             }
295 #endif
296         }
297     }
299     if(!ss.doc)
300        return 1; /* none of the slides loadable */
302     w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
303     gtk_window_set_title (GTK_WINDOW (w), SP_DOCUMENT_NAME (ss.doc));
304     gtk_window_set_default_size (GTK_WINDOW (w),
305                                  MIN ((int)sp_document_width (ss.doc), (int)gdk_screen_width () - 64),
306                                  MIN ((int)sp_document_height (ss.doc), (int)gdk_screen_height () - 64));
307     gtk_window_set_policy (GTK_WINDOW (w), TRUE, TRUE, FALSE);
309     g_signal_connect (G_OBJECT (w), "delete_event", (GCallback) sp_svgview_main_delete, &ss);
310     g_signal_connect (G_OBJECT (w), "key_press_event", (GCallback) sp_svgview_main_key_press, &ss);
312     ss.view = sp_svg_view_widget_new (ss.doc);
313     sp_svg_view_widget_set_resize (SP_SVG_VIEW_WIDGET (ss.view), FALSE, sp_document_width (ss.doc), sp_document_height (ss.doc));
314     sp_document_ensure_up_to_date (ss.doc);
315     sp_document_unref (ss.doc);
316     gtk_widget_show (ss.view);
317     gtk_container_add (GTK_CONTAINER (w), ss.view);
319     gtk_widget_show (w);
321     gtk_main ();
323     return 0;
326 static int
327 sp_svgview_ctrlwin_delete (GtkWidget *widget, GdkEvent *event, void *data)
329     ctrlwin = NULL;
330     return FALSE;
333 static GtkWidget *
334 sp_svgview_control_show (struct SPSlideShow *ss)
336     if (!ctrlwin) {
337         GtkWidget *t, *b;
338         ctrlwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
339         g_signal_connect (G_OBJECT (ctrlwin), "delete_event", (GCallback) sp_svgview_ctrlwin_delete, NULL);
340         t = gtk_table_new (1, 4, TRUE);
341         gtk_container_add ((GtkContainer *) ctrlwin, t);
342         b = gtk_button_new_from_stock (GTK_STOCK_GOTO_FIRST);
343         gtk_table_attach ((GtkTable *) t, b, 0, 1, 0, 1,
344                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
345                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
346                           0, 0);
347         g_signal_connect ((GObject *) b, "clicked", (GCallback) sp_svgview_goto_first_cb, ss);
348         b = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
349         gtk_table_attach ((GtkTable *) t, b, 1, 2, 0, 1,
350                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
351                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
352                           0, 0);
353         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_prev_cb, ss);
354         b = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
355         gtk_table_attach ((GtkTable *) t, b, 2, 3, 0, 1,
356                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
357                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
358                           0, 0);
359         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_next_cb, ss);
360         b = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
361         gtk_table_attach ((GtkTable *) t, b, 3, 4, 0, 1,
362                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
363                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
364                           0, 0);
365         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_goto_last_cb, ss);
366         gtk_widget_show_all (ctrlwin);
367     } else {
368         gtk_window_present ((GtkWindow *) ctrlwin);
369     }
371     return NULL;
374 static int
375 sp_svgview_show_next_cb (GtkWidget *widget, void *data)
377     sp_svgview_show_next(static_cast<struct SPSlideShow *>(data));
378     return FALSE;
381 static int
382 sp_svgview_show_prev_cb (GtkWidget *widget, void *data)
384     sp_svgview_show_prev(static_cast<struct SPSlideShow *>(data));
385     return FALSE;
388 static int
389 sp_svgview_goto_first_cb (GtkWidget *widget, void *data)
391     sp_svgview_goto_first(static_cast<struct SPSlideShow *>(data));
392     return FALSE;
395 static int
396 sp_svgview_goto_last_cb (GtkWidget *widget, void *data)
398     sp_svgview_goto_last(static_cast<struct SPSlideShow *>(data));
399     return FALSE;
402 static void
403 sp_svgview_show_next (struct SPSlideShow *ss)
405     SPDocument *doc;
406     int current;
407     doc = NULL;
408     current = ss->current;
409     while (!doc && (current < ss->length - 1)) {
410         doc = sp_document_new (ss->slides[++current], TRUE, false);
411     }
412     if (doc) {
413         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
414         sp_document_ensure_up_to_date (doc);
415         ss->doc = doc;
416         ss->current = current;
417     }
420 static void
421 sp_svgview_show_prev (struct SPSlideShow *ss)
423     SPDocument *doc;
424     int current;
425     doc = NULL;
426     current = ss->current;
427     while (!doc && (current > 0)) {
428         doc = sp_document_new (ss->slides[--current], TRUE, false);
429     }
430     if (doc) {
431         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
432         sp_document_ensure_up_to_date (doc);
433         ss->doc = doc;
434         ss->current = current;
435     }
438 static void
439 sp_svgview_goto_first (struct SPSlideShow *ss)
441     SPDocument *doc = NULL;
442     int current = 0;
443     for ( ; !doc && (current < ss->length); current++) {
444         doc = sp_document_new (ss->slides[current], TRUE, false);
445     }
446     if (doc) {
447         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
448         sp_document_ensure_up_to_date (doc);
449         ss->doc = doc;
450         ss->current = current;
451     }
454 static void
455 sp_svgview_goto_last (struct SPSlideShow *ss)
457     SPDocument *doc = NULL;
458     int current = ss->length - 1;
459     for ( ; !doc && (current >= 0); current--) {
460         doc = sp_document_new (ss->slides[current], TRUE, false);
461     }
462     if (doc) {
463         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
464         sp_document_ensure_up_to_date (doc);
465         ss->doc = doc;
466         ss->current = current;
467     }
470 #ifdef WITH_INKJAR
471 static bool
472 is_jar(char const *filename)
474     /* fixme: Check MIME type or something.  /usr/share/misc/file/magic suggests that checking for
475        initial string "PK\003\004" in content should suffice. */
476     size_t const filename_len = strlen(filename);
477     if (filename_len < 5) {
478         return false;
479     }
480     char const *extension = filename + filename_len - 4;
481     return ((memcmp(extension, ".jar", 4) == 0) ||
482             (memcmp(extension, ".sxw", 4) == 0)   );
484 #endif /* WITH_INKJAR */
486 static void usage()
488     fprintf(stderr,
489             "Usage: inkview [OPTIONS...] [FILES ...]\n"
490             "\twhere FILES are SVG (.svg or .svgz)"
491 #ifdef WITH_INKJAR
492             " or archives of SVGs (.sxw, .jar)"
493 #endif
494             "\n\n"
495             "Available options:\n"
496             "\t-t\t\tTimer for automatically changing slides in seconds.\n"
497             "\n");
498     exit(1);
501 #ifdef XXX
502 /* TODO !!! make this temporary stub unnecessary */
503 Inkscape::Application *inkscape_get_instance() { return NULL; }
504 void inkscape_ref (void) {}
505 void inkscape_unref (void) {}
506 void inkscape_add_document (SPDocument *document) {}
507 void inkscape_remove_document (SPDocument *document) {}
508 Inkscape::XML::Node *inkscape_get_repr (Inkscape::Application *inkscape, const gchar *key) {return NULL;}
509 #endif
512 /*
513   Local Variables:
514   mode:c++
515   c-file-style:"stroustrup"
516   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
517   indent-tabs-mode:nil
518   fill-column:99
519   End:
520 */
521 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :