Code

add HAVE_GETOPT_H
[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 #ifdef HAVE_GETOPT_H
35 #include <getopt.h>
36 #endif
38 #include <string.h>
39 #include <sys/stat.h>
40 #include <locale.h>
42 #include <glib/gmem.h>
43 #include <libnr/nr-macros.h>
45 // #include <stropts.h>
47 #include <libxml/tree.h>
48 #include <gdk/gdkkeysyms.h>
49 #include <gtk/gtkmain.h>
50 #include <gtk/gtkstock.h>
51 #include <gtk/gtkwindow.h>
52 #include <gtk/gtktable.h>
53 #include <gtk/gtkbutton.h>
55 #include "gc-core.h"
56 #include "preferences.h"
58 #include <glibmm/i18n.h>
59 #include "document.h"
60 #include "svg-view.h"
61 #include "svg-view-widget.h"
63 #ifdef WITH_INKJAR
64 #include "inkjar/jar.h"
65 #endif
67 #include "inkscape-private.h"
69 Inkscape::Application *inkscape;
71 #include <iostream>
73 #ifndef HAVE_BIND_TEXTDOMAIN_CODESET
74 #define bind_textdomain_codeset(p,c)
75 #endif
77 extern char *optarg;
78 extern int  optind, opterr;
80 struct SPSlideShow {
81     char **slides;
82     int size;
83     int length;
84     int current;
85     SPDocument *doc;
86     GtkWidget *view;
87     GtkWindow *window;
88     bool fullscreen;
89     int timer;
90 };
92 static GtkWidget *sp_svgview_control_show (struct SPSlideShow *ss);
93 static void sp_svgview_show_next (struct SPSlideShow *ss);
94 static void sp_svgview_show_prev (struct SPSlideShow *ss);
95 static void sp_svgview_goto_first (struct SPSlideShow *ss);
96 static void sp_svgview_goto_last (struct SPSlideShow *ss);
98 static int sp_svgview_show_next_cb (GtkWidget *widget, void *data);
99 static int sp_svgview_show_prev_cb (GtkWidget *widget, void *data);
100 static int sp_svgview_goto_first_cb (GtkWidget *widget, void *data);
101 static int sp_svgview_goto_last_cb (GtkWidget *widget, void *data);
102 #ifdef WITH_INKJAR
103 static bool is_jar(char const *filename);
104 #endif
105 static void usage();
107 static GtkWidget *ctrlwin = NULL;
109 /// Dummy functions to keep linker happy
110 int sp_main_gui (int, char const**) { return 0; }
111 int sp_main_console (int, char const**) { return 0; }
113 static int
114 sp_svgview_main_delete (GtkWidget *widget, GdkEvent *event, struct SPSlideShow *ss)
116     gtk_main_quit ();
117     return FALSE;
120 static int
121 sp_svgview_main_key_press (GtkWidget *widget, GdkEventKey *event, struct SPSlideShow *ss)
123     switch (event->keyval) {
124     case GDK_Up:
125         sp_svgview_goto_first(ss);
126         break;
127     case GDK_Down:
128         sp_svgview_goto_last(ss);
129         break;
130     case GDK_F11:
131 #ifdef HAVE_GTK_WINDOW_FULLSCREEN
132         if (ss->fullscreen) {
133             gtk_window_unfullscreen ((GtkWindow *) widget);
134             ss->fullscreen = false;
135         } else {
136             gtk_window_fullscreen ((GtkWindow *) widget);
137             ss->fullscreen = true;
138         }
139 #else
140         std::cout<<"Your GTK+ does not support fullscreen mode. Upgrade to 2.2."<<std::endl;
141 #endif
142         break;
143     case GDK_Return:
144         sp_svgview_control_show (ss);
145         break;
146     case GDK_KP_Page_Down:
147     case GDK_Page_Down:
148     case GDK_Right:
149     case GDK_space:
150         sp_svgview_show_next (ss);
151         break;
152     case GDK_KP_Page_Up:
153     case GDK_Page_Up:
154     case GDK_Left:
155         sp_svgview_show_prev (ss);
156         break;
157     case GDK_Escape:
158     case GDK_q:
159     case GDK_Q:
160         gtk_main_quit();
161         break;
162     default:
163         break;
164     }
165     gtk_window_set_title(GTK_WINDOW(widget), SP_DOCUMENT_NAME(ss->doc));
166     return FALSE;
169 int
170 main (int argc, const char **argv)
172     if (argc == 1) {
173         usage();
174     }
176     struct SPSlideShow ss;
178     int option,
179         num_parsed_options = 0;
181     // the list of arguments is in the net line
182     while ((option = getopt(argc, (char* const* )argv, "t:")) != -1) 
183     {
184         switch(option) {
185             case 't': // for timer
186                 // fprintf(stderr, "set timer arg %s\n", optarg );
187                 ss.timer = int(optarg); 
188                 num_parsed_options += 2; // 2 because of flag + option
189                 break;
190             case '?':
191             default:
192                 usage();
193         }       
194     }
195    
196     GtkWidget *w;
197     int i;
199     bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
200     bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
201     textdomain (GETTEXT_PACKAGE);
203     LIBXML_TEST_VERSION
205     Inkscape::GC::init();
206     Inkscape::Preferences::loadSkeleton();
208     gtk_init (&argc, (char ***) &argv);
210 #ifdef lalaWITH_MODULES
211     g_warning ("Have to autoinit modules (lauris)");
212     sp_modulesys_init();
213 #endif /* WITH_MODULES */
215     /* We must set LC_NUMERIC to default, or otherwise */
216     /* we'll end with localised SVG files :-( */
218     setlocale (LC_NUMERIC, "C");
220     ss.size = 32;
221     ss.length = 0;
222     ss.current = 0;
223     ss.slides = g_new (char *, ss.size);
224     ss.current = 0;
225     ss.doc = NULL;
226     ss.view = NULL;
227     ss.fullscreen = false;
229     inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL);
230     Inkscape::Preferences::load();
231     
232     // starting at where the commandline options stopped parsing because
233     // we want all the files to be in the list
234     for (i = num_parsed_options + 1 ; i < argc; i++) {
235         struct stat st;
236         if (stat (argv[i], &st)
237               || !S_ISREG (st.st_mode)
238               || (st.st_size < 64)) {
239                 fprintf(stderr, "could not open file %s\n", argv[i]);
240         } else {
242 #ifdef WITH_INKJAR
243             if (is_jar(argv[i])) {
244                 Inkjar::JarFileReader jar_file_reader(argv[i]);
245                 for (;;) {
246                     GByteArray *gba = jar_file_reader.get_next_file();
247                     if (gba == NULL) {
248                         char *c_ptr;
249                         gchar *last_filename = jar_file_reader.get_last_filename();
250                         if (last_filename == NULL)
251                             break;
252                         if ((c_ptr = std::strrchr(last_filename, '/')) != NULL) {
253                             if (*(++c_ptr) == '\0') {
254                                 g_free(last_filename);
255                                 continue;
256                             }
257                         }
258                     } else if (gba->len > 0) {
259                         //::write(1, gba->data, gba->len);
260                         /* Append to list */
261                         if (ss.length >= ss.size) {
262                             /* Expand */
263                             ss.size <<= 1;
264                             ss.slides = g_renew (char *, ss.slides, ss.size);
265                         }
267                         ss.doc = sp_document_new_from_mem ((const gchar *)gba->data,
268                                                            gba->len,
269                                                            TRUE);
270                         gchar *last_filename = jar_file_reader.get_last_filename();
271                         if (ss.doc) {
272                             ss.slides[ss.length++] = strdup (last_filename);
273                             sp_document_set_uri (ss.doc, strdup(last_filename));
274                         }
275                         g_byte_array_free(gba, TRUE);
276                         g_free(last_filename);
277                     } else
278                         break;
279                 }
280             } else {
281 #endif /* WITH_INKJAR */
282                 /* Append to list */
283                 if (ss.length >= ss.size) {
284                     /* Expand */
285                     ss.size <<= 1;
286                     ss.slides = g_renew (char *, ss.slides, ss.size);
288                 }
290                 ss.slides[ss.length++] = strdup (argv[i]);
291                 ss.doc = sp_document_new (ss.slides[ss.current], TRUE, false);
293                 if (!ss.doc && ++ss.current >= ss.length) {
294                     /* No loadable documents */
295                     return 1;
296                 }
297 #ifdef WITH_INKJAR
298             }
299 #endif
300         }
301     }
303     if(!ss.doc)
304        return 1; /* none of the slides loadable */
306     w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
307     gtk_window_set_title (GTK_WINDOW (w), SP_DOCUMENT_NAME (ss.doc));
308     gtk_window_set_default_size (GTK_WINDOW (w),
309                                  MIN ((int)sp_document_width (ss.doc), (int)gdk_screen_width () - 64),
310                                  MIN ((int)sp_document_height (ss.doc), (int)gdk_screen_height () - 64));
311     gtk_window_set_policy (GTK_WINDOW (w), TRUE, TRUE, FALSE);
313     g_signal_connect (G_OBJECT (w), "delete_event", (GCallback) sp_svgview_main_delete, &ss);
314     g_signal_connect (G_OBJECT (w), "key_press_event", (GCallback) sp_svgview_main_key_press, &ss);
316     ss.view = sp_svg_view_widget_new (ss.doc);
317     sp_svg_view_widget_set_resize (SP_SVG_VIEW_WIDGET (ss.view), FALSE, sp_document_width (ss.doc), sp_document_height (ss.doc));
318     sp_document_ensure_up_to_date (ss.doc);
319     sp_document_unref (ss.doc);
320     gtk_widget_show (ss.view);
321     gtk_container_add (GTK_CONTAINER (w), ss.view);
323     gtk_widget_show (w);
325     gtk_main ();
327     return 0;
330 static int
331 sp_svgview_ctrlwin_delete (GtkWidget *widget, GdkEvent *event, void *data)
333     ctrlwin = NULL;
334     return FALSE;
337 static GtkWidget *
338 sp_svgview_control_show (struct SPSlideShow *ss)
340     if (!ctrlwin) {
341         GtkWidget *t, *b;
342         ctrlwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
343         g_signal_connect (G_OBJECT (ctrlwin), "delete_event", (GCallback) sp_svgview_ctrlwin_delete, NULL);
344         t = gtk_table_new (1, 4, TRUE);
345         gtk_container_add ((GtkContainer *) ctrlwin, t);
346         b = gtk_button_new_from_stock (GTK_STOCK_GOTO_FIRST);
347         gtk_table_attach ((GtkTable *) t, b, 0, 1, 0, 1,
348                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
349                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
350                           0, 0);
351         g_signal_connect ((GObject *) b, "clicked", (GCallback) sp_svgview_goto_first_cb, ss);
352         b = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
353         gtk_table_attach ((GtkTable *) t, b, 1, 2, 0, 1,
354                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
355                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
356                           0, 0);
357         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_prev_cb, ss);
358         b = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
359         gtk_table_attach ((GtkTable *) t, b, 2, 3, 0, 1,
360                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
361                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
362                           0, 0);
363         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_show_next_cb, ss);
364         b = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
365         gtk_table_attach ((GtkTable *) t, b, 3, 4, 0, 1,
366                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
367                           (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
368                           0, 0);
369         g_signal_connect (G_OBJECT(b), "clicked", (GCallback) sp_svgview_goto_last_cb, ss);
370         gtk_widget_show_all (ctrlwin);
371     } else {
372         gtk_window_present ((GtkWindow *) ctrlwin);
373     }
375     return NULL;
378 static int
379 sp_svgview_show_next_cb (GtkWidget *widget, void *data)
381     sp_svgview_show_next(static_cast<struct SPSlideShow *>(data));
382     return FALSE;
385 static int
386 sp_svgview_show_prev_cb (GtkWidget *widget, void *data)
388     sp_svgview_show_prev(static_cast<struct SPSlideShow *>(data));
389     return FALSE;
392 static int
393 sp_svgview_goto_first_cb (GtkWidget *widget, void *data)
395     sp_svgview_goto_first(static_cast<struct SPSlideShow *>(data));
396     return FALSE;
399 static int
400 sp_svgview_goto_last_cb (GtkWidget *widget, void *data)
402     sp_svgview_goto_last(static_cast<struct SPSlideShow *>(data));
403     return FALSE;
406 static void
407 sp_svgview_show_next (struct SPSlideShow *ss)
409     SPDocument *doc;
410     int current;
411     doc = NULL;
412     current = ss->current;
413     while (!doc && (current < ss->length - 1)) {
414         doc = sp_document_new (ss->slides[++current], TRUE, false);
415     }
416     if (doc) {
417         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
418         sp_document_ensure_up_to_date (doc);
419         ss->doc = doc;
420         ss->current = current;
421     }
424 static void
425 sp_svgview_show_prev (struct SPSlideShow *ss)
427     SPDocument *doc;
428     int current;
429     doc = NULL;
430     current = ss->current;
431     while (!doc && (current > 0)) {
432         doc = sp_document_new (ss->slides[--current], TRUE, false);
433     }
434     if (doc) {
435         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
436         sp_document_ensure_up_to_date (doc);
437         ss->doc = doc;
438         ss->current = current;
439     }
442 static void
443 sp_svgview_goto_first (struct SPSlideShow *ss)
445     SPDocument *doc = NULL;
446     int current = 0;
447     for ( ; !doc && (current < ss->length); current++) {
448         doc = sp_document_new (ss->slides[current], TRUE, false);
449     }
450     if (doc) {
451         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
452         sp_document_ensure_up_to_date (doc);
453         ss->doc = doc;
454         ss->current = current;
455     }
458 static void
459 sp_svgview_goto_last (struct SPSlideShow *ss)
461     SPDocument *doc = NULL;
462     int current = ss->length - 1;
463     for ( ; !doc && (current >= 0); current--) {
464         doc = sp_document_new (ss->slides[current], TRUE, false);
465     }
466     if (doc) {
467         reinterpret_cast<SPSVGView*>(SP_VIEW_WIDGET_VIEW (ss->view))->setDocument (doc);
468         sp_document_ensure_up_to_date (doc);
469         ss->doc = doc;
470         ss->current = current;
471     }
474 #ifdef WITH_INKJAR
475 static bool
476 is_jar(char const *filename)
478     /* fixme: Check MIME type or something.  /usr/share/misc/file/magic suggests that checking for
479        initial string "PK\003\004" in content should suffice. */
480     size_t const filename_len = strlen(filename);
481     if (filename_len < 5) {
482         return false;
483     }
484     char const *extension = filename + filename_len - 4;
485     return ((memcmp(extension, ".jar", 4) == 0) ||
486             (memcmp(extension, ".sxw", 4) == 0)   );
488 #endif /* WITH_INKJAR */
490 static void usage()
492     fprintf(stderr,
493             "Usage: inkview [OPTIONS...] [FILES ...]\n"
494             "\twhere FILES are SVG (.svg or .svgz)"
495 #ifdef WITH_INKJAR
496             " or archives of SVGs (.sxw, .jar)"
497 #endif
498             "\n\n"
499             "Available options:\n"
500             "\t-t\t\tTimer for automatically changing slides in seconds.\n"
501             "\n");
502     exit(1);
505 #ifdef XXX
506 /* TODO !!! make this temporary stub unnecessary */
507 Inkscape::Application *inkscape_get_instance() { return NULL; }
508 void inkscape_ref (void) {}
509 void inkscape_unref (void) {}
510 void inkscape_add_document (SPDocument *document) {}
511 void inkscape_remove_document (SPDocument *document) {}
512 Inkscape::XML::Node *inkscape_get_repr (Inkscape::Application *inkscape, const gchar *key) {return NULL;}
513 #endif
516 /*
517   Local Variables:
518   mode:c++
519   c-file-style:"stroustrup"
520   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
521   indent-tabs-mode:nil
522   fill-column:99
523   End:
524 */
525 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :