Code

#include svg/svg-color.h instead of or as well as (as appropriate) svg/svg.h.
[inkscape.git] / src / main.cpp
1 #define __MAIN_C__
3 /** \file
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  *   Bryce Harrington <bryce@bryceharrington.com>
17  * ... and various people who have worked with various projects
18  *
19  * Copyright (C) 1999-2004 authors
20  * Copyright (C) 2001-2002 Ximian, Inc.
21  *
22  * Released under GNU GPL, read the file 'COPYING' for more information
23  */
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29 #include "path-prefix.h"
31 #include <gtk/gtkmessagedialog.h>
33 #ifdef HAVE_IEEEFP_H
34 #include <ieeefp.h>
35 #endif
36 #include <string.h>
37 #include <locale.h>
39 #include <popt.h>
40 #ifndef POPT_TABLEEND
41 #define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
42 #endif /* Not def: POPT_TABLEEND */
44 #include <libxml/tree.h>
45 #include <glib-object.h>
46 #include <gtk/gtkmain.h>
47 #include <gtk/gtksignal.h>
48 #include <gtk/gtkwindow.h>
49 #include <gtk/gtkbox.h>
51 #include <gtk/gtkmain.h>
53 #include "gc-core.h"
55 #include "macros.h"
56 #include "file.h"
57 #include "document.h"
58 #include "sp-object.h"
59 #include "interface.h"
60 #include "print.h"
61 #include "slideshow.h"
62 #include "color.h"
63 #include "sp-item.h"
64 #include "sp-root.h"
65 #include "unit-constants.h"
67 #include "svg/svg.h"
68 #include "svg/svg-color.h"
69 #include "svg/stringstream.h"
71 #include "inkscape-private.h"
72 #include "inkscape-stock.h"
73 #include "inkscape_version.h"
75 #include "sp-namedview.h"
76 #include "sp-guide.h"
77 #include "sp-object-repr.h"
78 #include "xml/repr.h"
80 #include "io/sys.h"
82 #include "debug/logger.h"
84 #include <extension/extension.h>
85 #include <extension/system.h>
86 #include <extension/db.h>
87 #include <extension/output.h>
89 #ifdef WIN32
90 //#define REPLACEARGS_ANSI
91 //#define REPLACEARGS_DEBUG
93 #include "registrytool.h"
95 #include "extension/internal/win32.h"
96 using Inkscape::Extension::Internal::PrintWin32;
98 #endif // WIN32
100 #include "extension/init.h"
102 #include <glibmm/i18n.h>
103 #include <gtkmm/main.h>
105 #ifndef HAVE_BIND_TEXTDOMAIN_CODESET
106 #define bind_textdomain_codeset(p,c)
107 #endif
109 #include "application/application.h"
111 enum {
112     SP_ARG_NONE,
113     SP_ARG_NOGUI,
114     SP_ARG_GUI,
115     SP_ARG_FILE,
116     SP_ARG_PRINT,
117     SP_ARG_EXPORT_PNG,
118     SP_ARG_EXPORT_DPI,
119     SP_ARG_EXPORT_AREA,
120     SP_ARG_EXPORT_AREA_DRAWING,
121     SP_ARG_EXPORT_AREA_SNAP,
122     SP_ARG_EXPORT_WIDTH,
123     SP_ARG_EXPORT_HEIGHT,
124     SP_ARG_EXPORT_ID,
125     SP_ARG_EXPORT_ID_ONLY,
126     SP_ARG_EXPORT_USE_HINTS,
127     SP_ARG_EXPORT_BACKGROUND,
128     SP_ARG_EXPORT_BACKGROUND_OPACITY,
129     SP_ARG_EXPORT_SVG,
130     SP_ARG_EXPORT_PS,
131     SP_ARG_EXPORT_EPS,
132     SP_ARG_EXPORT_TEXT_TO_PATH,
133     SP_ARG_EXPORT_BBOX_PAGE,
134     SP_ARG_EXTENSIONDIR,
135     SP_ARG_SLIDESHOW,
136     SP_ARG_QUERY_X,
137     SP_ARG_QUERY_Y,
138     SP_ARG_QUERY_WIDTH,
139     SP_ARG_QUERY_HEIGHT,
140     SP_ARG_QUERY_ID,
141     SP_ARG_VERSION,
142     SP_ARG_NEW_GUI,
143     SP_ARG_VACUUM_DEFS,
144     SP_ARG_LAST
145 };
147 int sp_main_gui(int argc, char const **argv);
148 int sp_main_console(int argc, char const **argv);
149 static void sp_do_export_png(SPDocument *doc);
150 static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
151 static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
154 static gchar *sp_global_printer = NULL;
155 static gboolean sp_global_slideshow = FALSE;
156 static gchar *sp_export_png = NULL;
157 static gchar *sp_export_dpi = NULL;
158 static gchar *sp_export_area = NULL;
159 static gboolean sp_export_area_drawing = FALSE;
160 static gchar *sp_export_width = NULL;
161 static gchar *sp_export_height = NULL;
162 static gchar *sp_export_id = NULL;
163 static gchar *sp_export_background = NULL;
164 static gchar *sp_export_background_opacity = NULL;
165 static gboolean sp_export_area_snap = FALSE;
166 static gboolean sp_export_use_hints = FALSE;
167 static gboolean sp_export_id_only = FALSE;
168 static gchar *sp_export_svg = NULL;
169 static gchar *sp_export_ps = NULL;
170 static gchar *sp_export_eps = NULL;
171 static gboolean sp_export_text_to_path = FALSE;
172 static gboolean sp_export_bbox_page = FALSE;
173 static gboolean sp_query_x = FALSE;
174 static gboolean sp_query_y = FALSE;
175 static gboolean sp_query_width = FALSE;
176 static gboolean sp_query_height = FALSE;
177 static gchar *sp_query_id = NULL;
178 static int sp_new_gui = FALSE;
179 static gboolean sp_vacuum_defs = FALSE;
181 static gchar *sp_export_png_utf8 = NULL;
182 static gchar *sp_export_svg_utf8 = NULL;
183 static gchar *sp_global_printer_utf8 = NULL;
185 #ifdef WIN32
186 static bool replaceArgs( int& argc, char**& argv );
187 #endif
188 static GSList *sp_process_args(poptContext ctx);
189 struct poptOption options[] = {
190     {"version", 'V',
191      POPT_ARG_NONE, NULL, SP_ARG_VERSION,
192      N_("Print the Inkscape version number"),
193      NULL},
195     {"without-gui", 'z',
196      POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
197      N_("Do not use X server (only process files from console)"),
198      NULL},
200     {"with-gui", 'g',
201      POPT_ARG_NONE, NULL, SP_ARG_GUI,
202      N_("Try to use X server (even if $DISPLAY is not set)"),
203      NULL},
205     {"file", 'f',
206      POPT_ARG_STRING, NULL, SP_ARG_FILE,
207      N_("Open specified document(s) (option string may be excluded)"),
208      N_("FILENAME")},
210     {"print", 'p',
211      POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
212      N_("Print document(s) to specified output file (use '| program' for pipe)"),
213      N_("FILENAME")},
215     {"export-png", 'e',
216      POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
217      N_("Export document to a PNG file"),
218      N_("FILENAME")},
220     {"export-dpi", 'd',
221      POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
222      N_("The resolution used for exporting SVG into bitmap (default 90)"),
223      N_("DPI")},
225     {"export-area", 'a',
226      POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
227      N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
228      N_("x0:y0:x1:y1")},
230     {"export-area-drawing", 'D',
231      POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
232      N_("Exported area is the entire drawing (not canvas)"),
233      NULL},
235     {"export-area-snap", 0,
236      POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
237      N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
238      NULL},
240     {"export-width", 'w',
241      POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
242      N_("The width of exported bitmap in pixels (overrides export-dpi)"),
243      N_("WIDTH")},
245     {"export-height", 'h',
246      POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
247      N_("The height of exported bitmap in pixels (overrides export-dpi)"),
248      N_("HEIGHT")},
250     {"export-id", 'i',
251      POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
252      N_("The ID of the object to export (overrides export-area)"),
253      N_("ID")},
255     {"export-id-only", 'j',
256      POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
257      // TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
258      //  See "man inkscape" for details.
259      N_("Export just the object with export-id, hide all others (only with export-id)"),
260      NULL},
262     {"export-use-hints", 't',
263      POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
264      N_("Use stored filename and DPI hints when exporting (only with export-id)"),
265      NULL},
267     {"export-background", 'b',
268      POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
269      N_("Background color of exported bitmap (any SVG-supported color string)"),
270      N_("COLOR")},
272     {"export-background-opacity", 'y',
273      POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
274      N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"),
275      N_("VALUE")},
277     {"export-plain-svg", 'l',
278      POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
279      N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"),
280      N_("FILENAME")},
282     {"export-ps", 'P',
283      POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
284      N_("Export document to a PS file"),
285      N_("FILENAME")},
287     {"export-eps", 'E',
288      POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
289      N_("Export document to an EPS file"),
290      N_("FILENAME")},
292     {"export-text-to-path", 'T',
293      POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
294      N_("Convert text object to paths on export (EPS)"),
295      NULL},
297     {"export-bbox-page", 'B',
298      POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
299      N_("Export files with the bounding box set to the page size (EPS)"),
300      NULL},
302     {"query-x", 'X',
303      POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
304      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
305      N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
306      NULL},
308     {"query-y", 'Y',
309      POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
310      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
311      N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
312      NULL},
314     {"query-width", 'W',
315      POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
316      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
317      N_("Query the width of the drawing or, if specified, of the object with --query-id"),
318      NULL},
320     {"query-height", 'H',
321      POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
322      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
323      N_("Query the height of the drawing or, if specified, of the object with --query-id"),
324      NULL},
326     {"query-id", 'I',
327      POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
328      N_("The ID of the object whose dimensions are queried"),
329      N_("ID")},
331     {"extension-directory", 'x',
332      POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
333      // TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
334      N_("Print out the extension directory and exit"),
335      NULL},
337     {"slideshow", 's',
338      POPT_ARG_NONE, &sp_global_slideshow, SP_ARG_SLIDESHOW,
339      N_("Show given files one-by-one, switch to next on any key/mouse event"),
340      NULL},
342     {"new-gui", 'G',
343      POPT_ARG_NONE, &sp_new_gui, SP_ARG_NEW_GUI,
344      N_("Use the new Gtkmm GUI interface"),
345      NULL},
347     {"vacuum-defs", 0,
348      POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
349      N_("Remove unused definitions from the defs section(s) of the document"),
350      NULL},
352     POPT_AUTOHELP POPT_TABLEEND
353 };
355 static bool needToRecodeParams = true;
356 gchar* blankParam = "";
358 int
359 main(int argc, char **argv)
361 #ifdef HAVE_FPSETMASK
362     /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__.  It's probably
363        safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
364        the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
365     fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
366 #endif
368 #ifdef ENABLE_NLS
369 #ifdef WIN32
370     RegistryTool rt;
371     rt.setPathInfo();
372     gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
373     bindtextdomain(GETTEXT_PACKAGE, pathBuf);
374     g_free(pathBuf);
375 #else
376 #ifdef ENABLE_BINRELOC
377     bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
378 #else
379     bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
380 #endif
381 #endif
382 #endif
384     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
386 #ifdef ENABLE_NLS
387     textdomain(GETTEXT_PACKAGE);
388 #endif
390     LIBXML_TEST_VERSION
392     Inkscape::GC::init();
394     Inkscape::Debug::Logger::init();
396     gboolean use_gui;
397 #ifndef WIN32
398     use_gui = (getenv("DISPLAY") != NULL);
399 #else
400     /*
401       Set the current directory to the directory of the
402       executable.  This seems redundant, but is needed for
403       when inkscape.exe is executed from another directory.
404       We use relative paths on win32.
405       HKCR\svgfile\shell\open\command is a good example
406     */
407     /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
408     char *homedir = g_path_get_dirname(argv[0]);
409     SetCurrentDirectory(homedir);
410     g_free(homedir);
412     use_gui = TRUE;
413 #endif
414     /* Test whether with/without GUI is forced */
415     for (int i = 1; i < argc; i++) {
416         if (!strcmp(argv[i], "-z")
417             || !strcmp(argv[i], "--without-gui")
418             || !strcmp(argv[i], "-p")
419             || !strncmp(argv[i], "--print", 7)
420             || !strcmp(argv[i], "-e")
421             || !strncmp(argv[i], "--export-png", 12)
422             || !strcmp(argv[i], "-l")
423             || !strncmp(argv[i], "--export-plain-svg", 12)
424             || !strcmp(argv[i], "-i")
425             || !strncmp(argv[i], "--export-area-drawing", 21)
426             || !strcmp(argv[i], "-D")
427             || !strncmp(argv[i], "--export-id", 12)
428             || !strcmp(argv[i], "-P")
429             || !strncmp(argv[i], "--export-ps", 11)
430             || !strcmp(argv[i], "-E")
431             || !strncmp(argv[i], "--export-eps", 12)
432             || !strcmp(argv[i], "-W")
433             || !strncmp(argv[i], "--query-width", 13)
434             || !strcmp(argv[i], "-H")
435             || !strncmp(argv[i], "--query-height", 14)
436             || !strcmp(argv[i], "-X")
437             || !strncmp(argv[i], "--query-x", 13)
438             || !strcmp(argv[i], "-Y")
439             || !strncmp(argv[i], "--query-y", 14)
440             || !strcmp(argv[i], "--vacuum-defs")
441            )
442         {
443             /* main_console handles any exports -- not the gui */
444             use_gui = FALSE;
445             break;
446         } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
447             use_gui = TRUE;
448             break;
449         } else if (!strcmp(argv[i], "-G") || !strcmp(argv[i], "--new-gui")) {
450             sp_new_gui = TRUE;
451             break;
452         }
453     }
455 #ifdef WIN32
456 #ifndef REPLACEARGS_ANSI
457     if ( PrintWin32::is_os_wide() )
458 #endif // REPLACEARGS_ANSI
459     {
460         // If the call fails, we'll need to convert charsets
461         needToRecodeParams = !replaceArgs( argc, argv );
462     }
463 #endif // WIN32
465     /// \todo  Should this be a static object (see inkscape.cpp)?
466     Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
468     return app.run();
471 void fixupSingleFilename( gchar **orig, gchar **spare )
473     if ( orig && *orig && **orig ) {
474         GError *error = NULL;
475         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
476         if ( newFileName )
477         {
478             *orig = newFileName;
479             if ( spare ) {
480                 *spare = newFileName;
481             }
482 //             g_message("Set a replacement fixup");
483         }
484     }
487 GSList *fixupFilenameEncoding( GSList* fl )
489     GSList *newFl = NULL;
490     while ( fl ) {
491         gchar *fn = static_cast<gchar*>(fl->data);
492         fl = g_slist_remove( fl, fl->data );
493         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
494         if ( newFileName ) {
496             if ( 0 )
497             {
498                 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
499                 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
500                 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
501                                                        "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
502                 gtk_dialog_run (GTK_DIALOG (w));
503                 gtk_widget_destroy (w);
504                 g_free(safeNewFn);
505                 g_free(safeFn);
506             }
508             g_free( fn );
509             fn = newFileName;
510             newFileName = 0;
511         }
512         else
513             if ( 0 )
514         {
515             gchar *safeFn = Inkscape::IO::sanitizeString(fn);
516             GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
517             gtk_dialog_run (GTK_DIALOG (w));
518             gtk_widget_destroy (w);
519             g_free(safeFn);
520         }
521         newFl = g_slist_append( newFl, fn );
522     }
523     return newFl;
526 int sp_common_main( int argc, char const **argv, GSList **flDest )
528     /// \todo fixme: Move these to some centralized location (Lauris)
529     sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
530     sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
533     // temporarily switch gettext encoding to locale, so that help messages can be output properly
534     gchar const *charset;
535     g_get_charset(&charset);
537     bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
539     poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
540     poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
541     g_return_val_if_fail(ctx != NULL, 1);
543     /* Collect own arguments */
544     GSList *fl = sp_process_args(ctx);
545     poptFreeContext(ctx);
547     // now switch gettext back to UTF-8 (for GUI)
548     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
550     // Now let's see if the file list still holds up
551     if ( needToRecodeParams )
552     {
553         fl = fixupFilenameEncoding( fl );
554     }
556     // Check the globals for filename-fixup
557     if ( needToRecodeParams )
558     {
559         fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
560         fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
561         fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
562     }
563     else
564     {
565         if ( sp_export_png )
566             sp_export_png_utf8 = g_strdup( sp_export_png );
567         if ( sp_export_svg )
568             sp_export_svg_utf8 = g_strdup( sp_export_svg );
569         if ( sp_global_printer )
570             sp_global_printer_utf8 = g_strdup( sp_global_printer );
571     }
573     // Return the list if wanted, else free it up.
574     if ( flDest ) {
575         *flDest = fl;
576         fl = 0;
577     } else {
578         while ( fl ) {
579             g_free( fl->data );
580             fl = g_slist_remove( fl, fl->data );
581         }
582     }
583     return 0;
586 int
587 sp_main_gui(int argc, char const **argv)
589     Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
591     GSList *fl = NULL;
592     int retVal = sp_common_main( argc, argv, &fl );
593     g_return_val_if_fail(retVal == 0, 1);
595     inkscape_gtk_stock_init();
597     /* Set default icon */
598     gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
599     if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
600         gtk_window_set_default_icon_from_file(filename, NULL);
601     }
602     g_free (filename);
603     filename = 0;
605     if (!sp_global_slideshow) {
606         gboolean create_new = TRUE;
608         /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
609         inkscape_application_init(argv[0], true);
611         while (fl) {
612             if (sp_file_open((gchar *)fl->data,NULL)) {
613                 create_new=FALSE;
614             }
615             fl = g_slist_remove(fl, fl->data);
616         }
617         if (create_new) {
618             sp_file_new_default();
619         }
620     } else {
621         if (fl) {
622             GtkWidget *ss;
623             /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
624             inkscape_application_init(argv[0], true);
625             ss = sp_slideshow_new(fl);
626             if (ss) gtk_widget_show(ss);
627         } else {
628             g_warning ("No slides to display");
629             exit(0);
630         }
631     }
633     main_instance.run();
635 #ifdef WIN32
636     //We might not need anything here
637     //sp_win32_finish(); <-- this is a NOP func
638 #endif
640     return 0;
643 int
644 sp_main_console(int argc, char const **argv)
646     /* We are started in text mode */
648     /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
649      * in a non-Gtk environment.  Used in libnrtype's
650      * FontInstance.cpp and FontFactory.cpp.
651      * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
652      */
653     g_type_init();
654     char **argv2 = const_cast<char **>(argv);
655     gtk_init_check( &argc, &argv2 );
656     //setlocale(LC_ALL, "");
658     GSList *fl = NULL;
659     int retVal = sp_common_main( argc, argv, &fl );
660     g_return_val_if_fail(retVal == 0, 1);
662     if (fl == NULL) {
663         g_print("Nothing to do!\n");
664         exit(0);
665     }
667     inkscape_application_init(argv[0], false);
669     while (fl) {
670         SPDocument *doc;
672         doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
673         if (doc == NULL) {
674             doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
675         }
676         if (doc == NULL) {
677             g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
678         } else {
679             if (sp_vacuum_defs) {
680                 vacuum_document(doc);
681             }
682             if (sp_vacuum_defs && !sp_export_svg) {
683                 // save under the name given in the command line
684                 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
685             }
686             if (sp_global_printer) {
687                 sp_print_document_to_file(doc, sp_global_printer);
688             }
689             if (sp_export_png || sp_export_id || sp_export_area_drawing) {
690                 sp_do_export_png(doc);
691             }
692             if (sp_export_svg) {
693                 Inkscape::XML::Document *rdoc;
694                 Inkscape::XML::Node *repr;
695                 rdoc = sp_repr_document_new("svg:svg");
696                 repr = rdoc->root();
697                 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
698                 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
699             }
700             if (sp_export_ps) {
701                 do_export_ps(doc, sp_export_ps, "image/x-postscript");
702             }
703             if (sp_export_eps) {
704                 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
705             }
706             if (sp_query_width || sp_query_height) {
707                 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
708             } else if (sp_query_x || sp_query_y) {
709                 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
710             }
711         }
712         fl = g_slist_remove(fl, fl->data);
713     }
715     inkscape_unref();
717     return 0;
720 static void
721 do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
723     SPObject *o = NULL;
725     if (id) {
726         o = doc->getObjectById(id);
727         if (o) {
728             if (!SP_IS_ITEM (o)) {
729                 g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
730                 return;
731             }
732         } else {
733             g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
734             return;
735         }
736     } else {
737         o = SP_DOCUMENT_ROOT(doc);
738     }
740     if (o) {
741         sp_document_ensure_up_to_date (doc);
742         SPItem *item = ((SPItem *) o);
743         NR::Rect area = item->invokeBbox(sp_item_i2doc_affine(item)); // "true" SVG bbox for scripting
745         Inkscape::SVGOStringStream os;
746         if (extent) {
747             os << area.extent(axis);
748         } else {
749             os << area.min()[axis];
750         }
751         g_print ("%s", os.str().c_str());
752     }
756 static void
757 sp_do_export_png(SPDocument *doc)
759     const gchar *filename = NULL;
760     gdouble dpi = 0.0;
762     if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
763         g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
764     }
766     GSList *items = NULL;
768     NRRect area;
769     if (sp_export_id || sp_export_area_drawing) {
771         SPObject *o = NULL;
772         if (sp_export_id) {
773             o = doc->getObjectById(sp_export_id);
774         } else if (sp_export_area_drawing) {
775             o = SP_DOCUMENT_ROOT (doc);
776         }
778         if (o) {
779             if (!SP_IS_ITEM (o)) {
780                 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
781                 return;
782             }
783             if (sp_export_area) {
784                 g_warning ("Object with id=\"%s\" is being exported; --export-area is ignored.", sp_export_id);
785             }
787             items = g_slist_prepend (items, SP_ITEM(o));
789             if (sp_export_id_only) {
790                 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
791             }
793             if (sp_export_use_hints) {
795                 // retrieve export filename hint
796                 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
797                 if (fn_hint) {
798                     if (sp_export_png) {
799                         g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
800                         filename = sp_export_png;
801                     } else {
802                         filename = fn_hint;
803                     }
804                 } else {
805                     g_warning ("Export filename hint not found for the object.");
806                     filename = sp_export_png;
807                 }
809                 // retrieve export dpi hints
810                 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
811                 if (dpi_hint) {
812                     if (sp_export_dpi || sp_export_width || sp_export_height) {
813                         g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
814                     } else {
815                         dpi = atof(dpi_hint);
816                     }
817                 } else {
818                     g_warning ("Export DPI hint not found for the object.");
819                 }
821             }
823             // write object bbox to area
824             sp_document_ensure_up_to_date (doc);
825             sp_item_invoke_bbox((SPItem *) o, &area, sp_item_i2r_affine((SPItem *) o), TRUE);
826         } else {
827             g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
828             return;
829         }
830     } else if (sp_export_area) {
831         /* Try to parse area (given in SVG pixels) */
832         if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
833             g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
834             return;
835         }
836         if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
837             g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
838             return;
839         }
840     } else {
841         /* Export the whole canvas */
842         sp_document_ensure_up_to_date (doc);
843         area.x0 = SP_ROOT(doc->root)->x.computed;
844         area.y0 = SP_ROOT(doc->root)->y.computed;
845         area.x1 = area.x0 + sp_document_width (doc);
846         area.y1 = area.y0 + sp_document_height (doc);
847     }
849     // set filename and dpi from options, if not yet set from the hints
850     if (!filename) {
851         if (!sp_export_png) {
852             g_warning ("No export filename given and no filename hint. Nothing exported.");
853             return;
854         }
855         filename = sp_export_png;
856     }
858     if (sp_export_dpi && dpi == 0.0) {
859         dpi = atof(sp_export_dpi);
860         if ((dpi < 0.1) || (dpi > 10000.0)) {
861             g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
862             return;
863         }
864         g_print("DPI: %g\n", dpi);
865     }
867     if (sp_export_area_snap) {
868         area.x0 = std::floor (area.x0);
869         area.y0 = std::floor (area.y0);
870         area.x1 = std::ceil (area.x1);
871         area.y1 = std::ceil (area.y1);
872     }
874     // default dpi
875     if (dpi == 0.0)
876         dpi = PX_PER_IN;
878     gint width = 0;
879     gint height = 0;
881     if (sp_export_width) {
882         width = atoi(sp_export_width);
883         if ((width < 1) || (width > 65536)) {
884             g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
885             return;
886         }
887         dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
888     }
890     if (sp_export_height) {
891         height = atoi(sp_export_height);
892         if ((height < 1) || (height > 65536)) {
893             g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
894             return;
895         }
896         dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
897     }
899     if (!sp_export_width) {
900         width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
901     }
903     if (!sp_export_height) {
904         height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
905     }
907     guint32 bgcolor = 0x00000000;
908     if (sp_export_background) {
909         // override the page color
910         bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
911         bgcolor |= 0xff; // default is no opacity
912     } else {
913         // read from namedview
914         Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
915         if (nv && nv->attribute("pagecolor"))
916             bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
917         if (nv && nv->attribute("inkscape:pageopacity"))
918             bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
919     }
921     if (sp_export_background_opacity) {
922         // override opacity
923         gfloat value;
924         if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
925             if (value > 1.0) {
926                 value = CLAMP (value, 1.0f, 255.0f);
927                 bgcolor &= (guint32) 0xffffff00;
928                 bgcolor |= (guint32) floor(value);
929             } else {
930                 value = CLAMP (value, 0.0f, 1.0f);
931                 bgcolor &= (guint32) 0xffffff00;
932                 bgcolor |= SP_COLOR_F_TO_U(value);
933             }
934         }
935     }
937     g_print("Background RRGGBBAA: %08x\n", bgcolor);
939     g_print("Area %g:%g:%g:%g exported to %d x %d pixels (%g dpi)\n", area.x0, area.y0, area.x1, area.y1, width, height, dpi);
941     g_print("Bitmap saved as: %s\n", filename);
943     if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
944         sp_export_png_file(doc, filename, area.x0, area.y0, area.x1, area.y1, width, height, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
945     } else {
946         g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
947     }
949     g_slist_free (items);
953 /**
954  *  Perform an export of either PS or EPS.
955  *
956  *  \param doc Document to export.
957  *  \param uri URI to export to.
958  *  \param mime MIME type to export as.
959  */
961 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
963     /** \todo
964      * FIXME: I've no idea if this is the `proper' way to do this.
965      * If anyone feels qualified to say that it is, perhaps they
966      * could remove this comment.
967      */
969     Inkscape::Extension::DB::OutputList o;
970     Inkscape::Extension::db.get_output_list(o);
971     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
972     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
973         i++;
974     }
976     if (i == o.end())
977     {
978         g_warning ("Could not find an extension to export this file.");
979         return;
980     }
982     bool old_text_to_path = false;
983     bool old_bbox_page = false;
985     try {
986         old_text_to_path = (*i)->get_param_bool("textToPath");
987         (*i)->set_param_bool("textToPath", sp_export_text_to_path);
988     }
989     catch (...) {
990         g_warning ("Could not set export-text-to-path option for this export.");
991     }
993     try {
994         old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
995         (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
996     }
997     catch (...) {
998         g_warning ("Could not set export-bbox-page option for this export.");
999     }
1001     (*i)->save(doc, uri);
1003     try {
1004         (*i)->set_param_bool("textToPath", old_text_to_path);
1005         (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1006     }
1007     catch (...) {
1009     }
1012 #ifdef WIN32
1013 bool replaceArgs( int& argc, char**& argv )
1015     bool worked = false;
1017 #ifdef REPLACEARGS_DEBUG
1018     MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1019 #endif // REPLACEARGS_DEBUG
1021     wchar_t* line = GetCommandLineW();
1022     if ( line )
1023     {
1024 #ifdef REPLACEARGS_DEBUG
1025         {
1026             gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1027             if ( utf8Line )
1028             {
1029                 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1030                 {
1031                     char tmp[strlen(safe) + 32];
1032                     snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1033                     MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1034                 }
1035             }
1036         }
1037 #endif // REPLACEARGS_DEBUG
1039         int numArgs = 0;
1040         wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1042 #ifdef REPLACEARGS_ANSI
1043 // test code for trying things on Win95/98/ME
1044         if ( !parsed )
1045         {
1046 #ifdef REPLACEARGS_DEBUG
1047             MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1048 #endif // REPLACEARGS_DEBUG
1049             int lineLen = wcslen(line) + 1;
1050             wchar_t* lineDup = new wchar_t[lineLen];
1051             wcsncpy( lineDup, line, lineLen );
1053             int pos = 0;
1054             bool inQuotes = false;
1055             bool inWhitespace = true;
1056             std::vector<int> places;
1057             while ( lineDup[pos] )
1058             {
1059                 if ( inQuotes )
1060                 {
1061                     if ( lineDup[pos] == L'"' )
1062                     {
1063                         inQuotes = false;
1064                     }
1065                 }
1066                 else if ( lineDup[pos] == L'"' )
1067                 {
1068                     inQuotes = true;
1069                     inWhitespace = false;
1070                     places.push_back(pos);
1071                 }
1072                 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1073                 {
1074                     if ( !inWhitespace )
1075                     {
1076                         inWhitespace = true;
1077                         lineDup[pos] = 0;
1078                     }
1079                 }
1080                 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1081                 {
1082                     inWhitespace = false;
1083                     places.push_back(pos);
1084                 }
1085                 else
1086                 {
1087                     // consume
1088                 }
1089                 pos++;
1090             }
1091 #ifdef REPLACEARGS_DEBUG
1092             {
1093                 char tmp[256];
1094                 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1095                 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1096             }
1097 #endif // REPLACEARGS_DEBUG
1099             wchar_t** block = new wchar_t*[places.size()];
1100             int i = 0;
1101             for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1102             {
1103                 block[i++] = &lineDup[*it];
1104             }
1105             parsed = block;
1106             numArgs = places.size();
1107         }
1108 #endif // REPLACEARGS_ANSI
1110         if ( parsed )
1111         {
1112             std::vector<wchar_t*>expandedArgs;
1113             if ( numArgs > 0 )
1114             {
1115                 expandedArgs.push_back( parsed[0] );
1116             }
1118             for ( int i1 = 1; i1 < numArgs; i1++ )
1119             {
1120                 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1121                 wildcarded &= parsed[i1][0] != L'"';
1122                 wildcarded &= parsed[i1][0] != L'-';
1123                 if ( wildcarded )
1124                 {
1125 #ifdef REPLACEARGS_ANSI
1126                     WIN32_FIND_DATAA data = {0};
1127 #else
1128                     WIN32_FIND_DATAW data = {0};
1129 #endif // REPLACEARGS_ANSI
1131                     int baseLen = wcslen(parsed[i1]) + 2;
1132                     wchar_t* base = new wchar_t[baseLen];
1133                     wcsncpy( base, parsed[i1], baseLen );
1134                     wchar_t* last = wcsrchr( base, L'\\' );
1135                     if ( last )
1136                     {
1137                         last[1] = 0;
1138                     }
1139                     else
1140                     {
1141                         base[0] = 0;
1142                     }
1143                     baseLen = wcslen( base );
1145 #ifdef REPLACEARGS_ANSI
1146                     char target[MAX_PATH];
1147                     if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1148                     {
1149                         HANDLE hf = FindFirstFileA( target, &data );
1150 #else
1151                         HANDLE hf = FindFirstFileW( parsed[i1], &data );
1152 #endif // REPLACEARGS_ANSI
1153                         if ( hf != INVALID_HANDLE_VALUE )
1154                         {
1155                             BOOL found = TRUE;
1156                             do
1157                             {
1158 #ifdef REPLACEARGS_ANSI
1159                                 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1160                                 if ( howMany > 0 )
1161                                 {
1162                                     howMany += baseLen;
1163                                     wchar_t* tmp = new wchar_t[howMany + 1];
1164                                     wcsncpy( tmp, base, howMany + 1 );
1165                                     MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1166                                     expandedArgs.push_back( tmp );
1167                                     found = FindNextFileA( hf, &data );
1168                                 }
1169 #else
1170                                 int howMany = wcslen(data.cFileName) + baseLen;
1171                                 wchar_t* tmp = new wchar_t[howMany + 1];
1172                                 wcsncpy( tmp, base, howMany + 1 );
1173                                 wcsncat( tmp, data.cFileName, howMany + 1 );
1174                                 expandedArgs.push_back( tmp );
1175                                 found = FindNextFileW( hf, &data );
1176 #endif // REPLACEARGS_ANSI
1177                             } while ( found );
1179                             FindClose( hf );
1180                         }
1181                         else
1182                         {
1183                             expandedArgs.push_back( parsed[i1] );
1184                         }
1185 #ifdef REPLACEARGS_ANSI
1186                     }
1187 #endif // REPLACEARGS_ANSI
1189                     delete[] base;
1190                 }
1191                 else
1192                 {
1193                     expandedArgs.push_back( parsed[i1] );
1194                 }
1195             }
1197             {
1198                 wchar_t** block = new wchar_t*[expandedArgs.size()];
1199                 int iz = 0;
1200                 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1201                 {
1202                     block[iz++] = *it;
1203                 }
1204                 parsed = block;
1205                 numArgs = expandedArgs.size();
1206             }
1208             std::vector<gchar*> newArgs;
1209             for ( int i = 0; i < numArgs; i++ )
1210             {
1211                 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1212                 if ( replacement )
1213                 {
1214 #ifdef REPLACEARGS_DEBUG
1215                     gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1217                     if ( safe2 )
1218                     {
1219                         {
1220                             char tmp[1024];
1221                             snprintf( tmp, sizeof(tmp), "    [%2d] = '%s'", i, safe2 );
1222                             MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1223                         }
1224                         g_free( safe2 );
1225                     }
1226 #endif // REPLACEARGS_DEBUG
1228                     newArgs.push_back( replacement );
1229                 }
1230                 else
1231                 {
1232                     newArgs.push_back( blankParam );
1233                 }
1234             }
1236             // Now push our munged params to be the new argv and argc
1237             {
1238                 char** block = new char*[newArgs.size()];
1239                 int iz = 0;
1240                 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1241                 {
1242                     block[iz++] = *it;
1243                 }
1244                 argv = block;
1245                 argc = newArgs.size();
1246                 worked = true;
1247             }
1248         }
1249 #ifdef REPLACEARGS_DEBUG
1250         else
1251         {
1252             MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1253         }
1254 #endif // REPLACEARGS_DEBUG
1255     }
1256 #ifdef REPLACEARGS_DEBUG
1257     else
1258     {
1259         {
1260             MessageBoxA( NULL,  "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1261         }
1263         char* line2 = GetCommandLineA();
1264         if ( line2 )
1265         {
1266             gchar *safe = Inkscape::IO::sanitizeString(line2);
1267             {
1268                 {
1269                     char tmp[strlen(safe) + 32];
1270                     snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1271                     MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1272                 }
1273             }
1274         }
1275         else
1276         {
1277             MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1278         }
1279     }
1280 #endif // REPLACEARGS_DEBUG
1282     return worked;
1284 #endif // WIN32
1286 static GSList *
1287 sp_process_args(poptContext ctx)
1289     GSList *fl = NULL;
1291     gint a;
1292     while ((a = poptGetNextOpt(ctx)) >= 0) {
1293         switch (a) {
1294             case SP_ARG_FILE: {
1295                 gchar const *fn = poptGetOptArg(ctx);
1296                 if (fn != NULL) {
1297                     fl = g_slist_append(fl, g_strdup(fn));
1298                 }
1299                 break;
1300             }
1301             case SP_ARG_VERSION: {
1302                 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1303                 exit(0);
1304                 break;
1305             }
1306             case SP_ARG_EXTENSIONDIR: {
1307                 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1308                 exit(0);
1309                 break;
1310             }
1311             default: {
1312                 break;
1313             }
1314         }
1315     }
1317     gchar const ** const args = poptGetArgs(ctx);
1318     if (args != NULL) {
1319         for (unsigned i = 0; args[i] != NULL; i++) {
1320             fl = g_slist_append(fl, g_strdup(args[i]));
1321         }
1322     }
1324     return fl;
1328 /*
1329   Local Variables:
1330   mode:c++
1331   c-file-style:"stroustrup"
1332   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1333   indent-tabs-mode:nil
1334   fill-column:99
1335   End:
1336 */
1337 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :