Code

apply patch 1498946 by zbsz (fixes #1492545 "PNG resolution value export")
[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_CANVAS,
122     SP_ARG_EXPORT_AREA_SNAP,
123     SP_ARG_EXPORT_WIDTH,
124     SP_ARG_EXPORT_HEIGHT,
125     SP_ARG_EXPORT_ID,
126     SP_ARG_EXPORT_ID_ONLY,
127     SP_ARG_EXPORT_USE_HINTS,
128     SP_ARG_EXPORT_BACKGROUND,
129     SP_ARG_EXPORT_BACKGROUND_OPACITY,
130     SP_ARG_EXPORT_SVG,
131     SP_ARG_EXPORT_PS,
132     SP_ARG_EXPORT_EPS,
133     SP_ARG_EXPORT_TEXT_TO_PATH,
134     SP_ARG_EXPORT_BBOX_PAGE,
135     SP_ARG_EXTENSIONDIR,
136     SP_ARG_SLIDESHOW,
137     SP_ARG_QUERY_X,
138     SP_ARG_QUERY_Y,
139     SP_ARG_QUERY_WIDTH,
140     SP_ARG_QUERY_HEIGHT,
141     SP_ARG_QUERY_ID,
142     SP_ARG_VERSION,
143     SP_ARG_NEW_GUI,
144     SP_ARG_VACUUM_DEFS,
145     SP_ARG_LAST
146 };
148 int sp_main_gui(int argc, char const **argv);
149 int sp_main_console(int argc, char const **argv);
150 static void sp_do_export_png(SPDocument *doc);
151 static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
152 static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
155 static gchar *sp_global_printer = NULL;
156 static gboolean sp_global_slideshow = FALSE;
157 static gchar *sp_export_png = NULL;
158 static gchar *sp_export_dpi = NULL;
159 static gchar *sp_export_area = NULL;
160 static gboolean sp_export_area_drawing = FALSE;
161 static gboolean sp_export_area_canvas = FALSE;
162 static gchar *sp_export_width = NULL;
163 static gchar *sp_export_height = NULL;
164 static gchar *sp_export_id = NULL;
165 static gchar *sp_export_background = NULL;
166 static gchar *sp_export_background_opacity = NULL;
167 static gboolean sp_export_area_snap = FALSE;
168 static gboolean sp_export_use_hints = FALSE;
169 static gboolean sp_export_id_only = FALSE;
170 static gchar *sp_export_svg = NULL;
171 static gchar *sp_export_ps = NULL;
172 static gchar *sp_export_eps = NULL;
173 static gboolean sp_export_text_to_path = FALSE;
174 static gboolean sp_export_bbox_page = FALSE;
175 static gboolean sp_query_x = FALSE;
176 static gboolean sp_query_y = FALSE;
177 static gboolean sp_query_width = FALSE;
178 static gboolean sp_query_height = FALSE;
179 static gchar *sp_query_id = NULL;
180 static int sp_new_gui = FALSE;
181 static gboolean sp_vacuum_defs = FALSE;
183 static gchar *sp_export_png_utf8 = NULL;
184 static gchar *sp_export_svg_utf8 = NULL;
185 static gchar *sp_global_printer_utf8 = NULL;
187 #ifdef WIN32
188 static bool replaceArgs( int& argc, char**& argv );
189 #endif
190 static GSList *sp_process_args(poptContext ctx);
191 struct poptOption options[] = {
192     {"version", 'V',
193      POPT_ARG_NONE, NULL, SP_ARG_VERSION,
194      N_("Print the Inkscape version number"),
195      NULL},
197     {"without-gui", 'z',
198      POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
199      N_("Do not use X server (only process files from console)"),
200      NULL},
202     {"with-gui", 'g',
203      POPT_ARG_NONE, NULL, SP_ARG_GUI,
204      N_("Try to use X server (even if $DISPLAY is not set)"),
205      NULL},
207     {"file", 'f',
208      POPT_ARG_STRING, NULL, SP_ARG_FILE,
209      N_("Open specified document(s) (option string may be excluded)"),
210      N_("FILENAME")},
212     {"print", 'p',
213      POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
214      N_("Print document(s) to specified output file (use '| program' for pipe)"),
215      N_("FILENAME")},
217     {"export-png", 'e',
218      POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
219      N_("Export document to a PNG file"),
220      N_("FILENAME")},
222     {"export-dpi", 'd',
223      POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
224      N_("The resolution used for exporting SVG into bitmap (default 90)"),
225      N_("DPI")},
227     {"export-area", 'a',
228      POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
229      N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
230      N_("x0:y0:x1:y1")},
232     {"export-area-drawing", 'D',
233      POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
234      N_("Exported area is the entire drawing (not canvas)"),
235      NULL},
237     {"export-area-canvas", 'C',
238      POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
239      N_("Exported area is the entire canvas"),
240      NULL},
242     {"export-area-snap", 0,
243      POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
244      N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
245      NULL},
247     {"export-width", 'w',
248      POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
249      N_("The width of exported bitmap in pixels (overrides export-dpi)"),
250      N_("WIDTH")},
252     {"export-height", 'h',
253      POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
254      N_("The height of exported bitmap in pixels (overrides export-dpi)"),
255      N_("HEIGHT")},
257     {"export-id", 'i',
258      POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
259      N_("The ID of the object to export"),
260      N_("ID")},
262     {"export-id-only", 'j',
263      POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
264      // TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
265      //  See "man inkscape" for details.
266      N_("Export just the object with export-id, hide all others (only with export-id)"),
267      NULL},
269     {"export-use-hints", 't',
270      POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
271      N_("Use stored filename and DPI hints when exporting (only with export-id)"),
272      NULL},
274     {"export-background", 'b',
275      POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
276      N_("Background color of exported bitmap (any SVG-supported color string)"),
277      N_("COLOR")},
279     {"export-background-opacity", 'y',
280      POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
281      N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"),
282      N_("VALUE")},
284     {"export-plain-svg", 'l',
285      POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
286      N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"),
287      N_("FILENAME")},
289     {"export-ps", 'P',
290      POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
291      N_("Export document to a PS file"),
292      N_("FILENAME")},
294     {"export-eps", 'E',
295      POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
296      N_("Export document to an EPS file"),
297      N_("FILENAME")},
299     {"export-text-to-path", 'T',
300      POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
301      N_("Convert text object to paths on export (EPS)"),
302      NULL},
304     {"export-bbox-page", 'B',
305      POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
306      N_("Export files with the bounding box set to the page size (EPS)"),
307      NULL},
309     {"query-x", 'X',
310      POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
311      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
312      N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
313      NULL},
315     {"query-y", 'Y',
316      POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
317      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
318      N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
319      NULL},
321     {"query-width", 'W',
322      POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
323      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
324      N_("Query the width of the drawing or, if specified, of the object with --query-id"),
325      NULL},
327     {"query-height", 'H',
328      POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
329      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
330      N_("Query the height of the drawing or, if specified, of the object with --query-id"),
331      NULL},
333     {"query-id", 'I',
334      POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
335      N_("The ID of the object whose dimensions are queried"),
336      N_("ID")},
338     {"extension-directory", 'x',
339      POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
340      // TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
341      N_("Print out the extension directory and exit"),
342      NULL},
344     {"slideshow", 's',
345      POPT_ARG_NONE, &sp_global_slideshow, SP_ARG_SLIDESHOW,
346      N_("Show given files one-by-one, switch to next on any key/mouse event"),
347      NULL},
349     {"new-gui", 'G',
350      POPT_ARG_NONE, &sp_new_gui, SP_ARG_NEW_GUI,
351      N_("Use the new Gtkmm GUI interface"),
352      NULL},
354     {"vacuum-defs", 0,
355      POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
356      N_("Remove unused definitions from the defs section(s) of the document"),
357      NULL},
359     POPT_AUTOHELP POPT_TABLEEND
360 };
362 static bool needToRecodeParams = true;
363 gchar* blankParam = "";
365 int
366 main(int argc, char **argv)
368 #ifdef HAVE_FPSETMASK
369     /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__.  It's probably
370        safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
371        the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
372     fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
373 #endif
375 #ifdef ENABLE_NLS
376 #ifdef WIN32
377     RegistryTool rt;
378     rt.setPathInfo();
379     gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
380     bindtextdomain(GETTEXT_PACKAGE, pathBuf);
381     g_free(pathBuf);
382 #else
383 #ifdef ENABLE_BINRELOC
384     bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
385 #else
386     bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
387 #endif
388 #endif
389 #endif
391     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
393 #ifdef ENABLE_NLS
394     textdomain(GETTEXT_PACKAGE);
395 #endif
397     LIBXML_TEST_VERSION
399     Inkscape::GC::init();
401     Inkscape::Debug::Logger::init();
403     gboolean use_gui;
404 #ifndef WIN32
405     use_gui = (getenv("DISPLAY") != NULL);
406 #else
407     /*
408       Set the current directory to the directory of the
409       executable.  This seems redundant, but is needed for
410       when inkscape.exe is executed from another directory.
411       We use relative paths on win32.
412       HKCR\svgfile\shell\open\command is a good example
413     */
414     /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
415     char *homedir = g_path_get_dirname(argv[0]);
416     SetCurrentDirectory(homedir);
417     g_free(homedir);
419     use_gui = TRUE;
420 #endif
421     /* Test whether with/without GUI is forced */
422     for (int i = 1; i < argc; i++) {
423         if (!strcmp(argv[i], "-z")
424             || !strcmp(argv[i], "--without-gui")
425             || !strcmp(argv[i], "-p")
426             || !strncmp(argv[i], "--print", 7)
427             || !strcmp(argv[i], "-e")
428             || !strncmp(argv[i], "--export-png", 12)
429             || !strcmp(argv[i], "-l")
430             || !strncmp(argv[i], "--export-plain-svg", 12)
431             || !strcmp(argv[i], "-i")
432             || !strncmp(argv[i], "--export-area-drawing", 21)
433             || !strcmp(argv[i], "-D")
434             || !strncmp(argv[i], "--export-area-canvas", 20)
435             || !strcmp(argv[i], "-C")
436             || !strncmp(argv[i], "--export-id", 12)
437             || !strcmp(argv[i], "-P")
438             || !strncmp(argv[i], "--export-ps", 11)
439             || !strcmp(argv[i], "-E")
440             || !strncmp(argv[i], "--export-eps", 12)
441             || !strcmp(argv[i], "-W")
442             || !strncmp(argv[i], "--query-width", 13)
443             || !strcmp(argv[i], "-H")
444             || !strncmp(argv[i], "--query-height", 14)
445             || !strcmp(argv[i], "-X")
446             || !strncmp(argv[i], "--query-x", 13)
447             || !strcmp(argv[i], "-Y")
448             || !strncmp(argv[i], "--query-y", 14)
449             || !strcmp(argv[i], "--vacuum-defs")
450            )
451         {
452             /* main_console handles any exports -- not the gui */
453             use_gui = FALSE;
454             break;
455         } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
456             use_gui = TRUE;
457             break;
458         } else if (!strcmp(argv[i], "-G") || !strcmp(argv[i], "--new-gui")) {
459             sp_new_gui = TRUE;
460             break;
461         }
462     }
464 #ifdef WIN32
465 #ifndef REPLACEARGS_ANSI
466     if ( PrintWin32::is_os_wide() )
467 #endif // REPLACEARGS_ANSI
468     {
469         // If the call fails, we'll need to convert charsets
470         needToRecodeParams = !replaceArgs( argc, argv );
471     }
472 #endif // WIN32
474     /// \todo  Should this be a static object (see inkscape.cpp)?
475     Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
477     return app.run();
480 void fixupSingleFilename( gchar **orig, gchar **spare )
482     if ( orig && *orig && **orig ) {
483         GError *error = NULL;
484         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
485         if ( newFileName )
486         {
487             *orig = newFileName;
488             if ( spare ) {
489                 *spare = newFileName;
490             }
491 //             g_message("Set a replacement fixup");
492         }
493     }
496 GSList *fixupFilenameEncoding( GSList* fl )
498     GSList *newFl = NULL;
499     while ( fl ) {
500         gchar *fn = static_cast<gchar*>(fl->data);
501         fl = g_slist_remove( fl, fl->data );
502         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
503         if ( newFileName ) {
505             if ( 0 )
506             {
507                 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
508                 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
509                 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
510                                                        "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
511                 gtk_dialog_run (GTK_DIALOG (w));
512                 gtk_widget_destroy (w);
513                 g_free(safeNewFn);
514                 g_free(safeFn);
515             }
517             g_free( fn );
518             fn = newFileName;
519             newFileName = 0;
520         }
521         else
522             if ( 0 )
523         {
524             gchar *safeFn = Inkscape::IO::sanitizeString(fn);
525             GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
526             gtk_dialog_run (GTK_DIALOG (w));
527             gtk_widget_destroy (w);
528             g_free(safeFn);
529         }
530         newFl = g_slist_append( newFl, fn );
531     }
532     return newFl;
535 int sp_common_main( int argc, char const **argv, GSList **flDest )
537     /// \todo fixme: Move these to some centralized location (Lauris)
538     sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
539     sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
542     // temporarily switch gettext encoding to locale, so that help messages can be output properly
543     gchar const *charset;
544     g_get_charset(&charset);
546     bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
548     poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
549     poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
550     g_return_val_if_fail(ctx != NULL, 1);
552     /* Collect own arguments */
553     GSList *fl = sp_process_args(ctx);
554     poptFreeContext(ctx);
556     // now switch gettext back to UTF-8 (for GUI)
557     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
559     // Now let's see if the file list still holds up
560     if ( needToRecodeParams )
561     {
562         fl = fixupFilenameEncoding( fl );
563     }
565     // Check the globals for filename-fixup
566     if ( needToRecodeParams )
567     {
568         fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
569         fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
570         fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
571     }
572     else
573     {
574         if ( sp_export_png )
575             sp_export_png_utf8 = g_strdup( sp_export_png );
576         if ( sp_export_svg )
577             sp_export_svg_utf8 = g_strdup( sp_export_svg );
578         if ( sp_global_printer )
579             sp_global_printer_utf8 = g_strdup( sp_global_printer );
580     }
582     // Return the list if wanted, else free it up.
583     if ( flDest ) {
584         *flDest = fl;
585         fl = 0;
586     } else {
587         while ( fl ) {
588             g_free( fl->data );
589             fl = g_slist_remove( fl, fl->data );
590         }
591     }
592     return 0;
595 int
596 sp_main_gui(int argc, char const **argv)
598     Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
600     GSList *fl = NULL;
601     int retVal = sp_common_main( argc, argv, &fl );
602     g_return_val_if_fail(retVal == 0, 1);
604     inkscape_gtk_stock_init();
606     /* Set default icon */
607     gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
608     if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
609         gtk_window_set_default_icon_from_file(filename, NULL);
610     }
611     g_free (filename);
612     filename = 0;
614     if (!sp_global_slideshow) {
615         gboolean create_new = TRUE;
617         /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
618         inkscape_application_init(argv[0], true);
620         while (fl) {
621             if (sp_file_open((gchar *)fl->data,NULL)) {
622                 create_new=FALSE;
623             }
624             fl = g_slist_remove(fl, fl->data);
625         }
626         if (create_new) {
627             sp_file_new_default();
628         }
629     } else {
630         if (fl) {
631             GtkWidget *ss;
632             /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
633             inkscape_application_init(argv[0], true);
634             ss = sp_slideshow_new(fl);
635             if (ss) gtk_widget_show(ss);
636         } else {
637             g_warning ("No slides to display");
638             exit(0);
639         }
640     }
642     main_instance.run();
644 #ifdef WIN32
645     //We might not need anything here
646     //sp_win32_finish(); <-- this is a NOP func
647 #endif
649     return 0;
652 int
653 sp_main_console(int argc, char const **argv)
655     /* We are started in text mode */
657     /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
658      * in a non-Gtk environment.  Used in libnrtype's
659      * FontInstance.cpp and FontFactory.cpp.
660      * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
661      */
662     g_type_init();
663     char **argv2 = const_cast<char **>(argv);
664     gtk_init_check( &argc, &argv2 );
665     //setlocale(LC_ALL, "");
667     GSList *fl = NULL;
668     int retVal = sp_common_main( argc, argv, &fl );
669     g_return_val_if_fail(retVal == 0, 1);
671     if (fl == NULL) {
672         g_print("Nothing to do!\n");
673         exit(0);
674     }
676     inkscape_application_init(argv[0], false);
678     while (fl) {
679         SPDocument *doc;
681         doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
682         if (doc == NULL) {
683             doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
684         }
685         if (doc == NULL) {
686             g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
687         } else {
688             if (sp_vacuum_defs) {
689                 vacuum_document(doc);
690             }
691             if (sp_vacuum_defs && !sp_export_svg) {
692                 // save under the name given in the command line
693                 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
694             }
695             if (sp_global_printer) {
696                 sp_print_document_to_file(doc, sp_global_printer);
697             }
698             if (sp_export_png || sp_export_id || sp_export_area_drawing) {
699                 sp_do_export_png(doc);
700             }
701             if (sp_export_svg) {
702                 Inkscape::XML::Document *rdoc;
703                 Inkscape::XML::Node *repr;
704                 rdoc = sp_repr_document_new("svg:svg");
705                 repr = rdoc->root();
706                 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
707                 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
708             }
709             if (sp_export_ps) {
710                 do_export_ps(doc, sp_export_ps, "image/x-postscript");
711             }
712             if (sp_export_eps) {
713                 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
714             }
715             if (sp_query_width || sp_query_height) {
716                 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
717             } else if (sp_query_x || sp_query_y) {
718                 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
719             }
720         }
721         fl = g_slist_remove(fl, fl->data);
722     }
724     inkscape_unref();
726     return 0;
729 static void
730 do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
732     SPObject *o = NULL;
734     if (id) {
735         o = doc->getObjectById(id);
736         if (o) {
737             if (!SP_IS_ITEM (o)) {
738                 g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
739                 return;
740             }
741         } else {
742             g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
743             return;
744         }
745     } else {
746         o = SP_DOCUMENT_ROOT(doc);
747     }
749     if (o) {
750         sp_document_ensure_up_to_date (doc);
751         SPItem *item = ((SPItem *) o);
752         NR::Rect area = item->invokeBbox(sp_item_i2doc_affine(item)); // "true" SVG bbox for scripting
754         Inkscape::SVGOStringStream os;
755         if (extent) {
756             os << area.extent(axis);
757         } else {
758             os << area.min()[axis];
759         }
760         g_print ("%s", os.str().c_str());
761     }
765 static void
766 sp_do_export_png(SPDocument *doc)
768     const gchar *filename = NULL;
769     gdouble dpi = 0.0;
771     if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
772         g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
773     }
775     GSList *items = NULL;
777     NRRect area;
778     if (sp_export_id || sp_export_area_drawing) {
780         SPObject *o = NULL;
781         SPObject *o_area = NULL;
782         if (sp_export_id && sp_export_area_drawing) {
783             o = doc->getObjectById(sp_export_id);
784             o_area = SP_DOCUMENT_ROOT (doc);
785         } else if (sp_export_id) {
786             o = doc->getObjectById(sp_export_id);
787             o_area = o;
788         } else if (sp_export_area_drawing) {
789             o = SP_DOCUMENT_ROOT (doc);
790             o_area = o;
791         } 
793         if (o) {
794             if (!SP_IS_ITEM (o)) {
795                 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
796                 return;
797             }
799             items = g_slist_prepend (items, SP_ITEM(o));
801             if (sp_export_id_only) {
802                 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
803             }
805             if (sp_export_use_hints) {
807                 // retrieve export filename hint
808                 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
809                 if (fn_hint) {
810                     if (sp_export_png) {
811                         g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
812                         filename = sp_export_png;
813                     } else {
814                         filename = fn_hint;
815                     }
816                 } else {
817                     g_warning ("Export filename hint not found for the object.");
818                     filename = sp_export_png;
819                 }
821                 // retrieve export dpi hints
822                 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
823                 if (dpi_hint) {
824                     if (sp_export_dpi || sp_export_width || sp_export_height) {
825                         g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
826                     } else {
827                         dpi = atof(dpi_hint);
828                     }
829                 } else {
830                     g_warning ("Export DPI hint not found for the object.");
831                 }
833             }
835             // write object bbox to area
836             sp_document_ensure_up_to_date (doc);
837             sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
838         } else {
839             g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
840             return;
841         }
842     }
843     
844     if (sp_export_area) {
845         /* Try to parse area (given in SVG pixels) */
846         if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
847             g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
848             return;
849         }
850         if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
851             g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
852             return;
853         }
854     } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
855         /* Export the whole canvas */
856         sp_document_ensure_up_to_date (doc);
857         area.x0 = SP_ROOT(doc->root)->x.computed;
858         area.y0 = SP_ROOT(doc->root)->y.computed;
859         area.x1 = area.x0 + sp_document_width (doc);
860         area.y1 = area.y0 + sp_document_height (doc);
861     }
863     // set filename and dpi from options, if not yet set from the hints
864     if (!filename) {
865         if (!sp_export_png) {
866             g_warning ("No export filename given and no filename hint. Nothing exported.");
867             return;
868         }
869         filename = sp_export_png;
870     }
872     if (sp_export_dpi && dpi == 0.0) {
873         dpi = atof(sp_export_dpi);
874         if ((dpi < 0.1) || (dpi > 10000.0)) {
875             g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
876             return;
877         }
878         g_print("DPI: %g\n", dpi);
879     }
881     if (sp_export_area_snap) {
882         area.x0 = std::floor (area.x0);
883         area.y0 = std::floor (area.y0);
884         area.x1 = std::ceil (area.x1);
885         area.y1 = std::ceil (area.y1);
886     }
888     // default dpi
889     if (dpi == 0.0)
890         dpi = PX_PER_IN;
892     gint width = 0;
893     gint height = 0;
895     if (sp_export_width) {
896         width = atoi(sp_export_width);
897         if ((width < 1) || (width > 65536)) {
898             g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
899             return;
900         }
901         dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
902     }
904     if (sp_export_height) {
905         height = atoi(sp_export_height);
906         if ((height < 1) || (height > 65536)) {
907             g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
908             return;
909         }
910         dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
911     }
913     if (!sp_export_width) {
914         width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
915     }
917     if (!sp_export_height) {
918         height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
919     }
921     guint32 bgcolor = 0x00000000;
922     if (sp_export_background) {
923         // override the page color
924         bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
925         bgcolor |= 0xff; // default is no opacity
926     } else {
927         // read from namedview
928         Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
929         if (nv && nv->attribute("pagecolor"))
930             bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
931         if (nv && nv->attribute("inkscape:pageopacity"))
932             bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
933     }
935     if (sp_export_background_opacity) {
936         // override opacity
937         gfloat value;
938         if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
939             if (value > 1.0) {
940                 value = CLAMP (value, 1.0f, 255.0f);
941                 bgcolor &= (guint32) 0xffffff00;
942                 bgcolor |= (guint32) floor(value);
943             } else {
944                 value = CLAMP (value, 0.0f, 1.0f);
945                 bgcolor &= (guint32) 0xffffff00;
946                 bgcolor |= SP_COLOR_F_TO_U(value);
947             }
948         }
949     }
951     g_print("Background RRGGBBAA: %08x\n", bgcolor);
953     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);
955     g_print("Bitmap saved as: %s\n", filename);
957     if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
958         sp_export_png_file(doc, filename, area.x0, area.y0, area.x1, area.y1, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
959     } else {
960         g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
961     }
963     g_slist_free (items);
967 /**
968  *  Perform an export of either PS or EPS.
969  *
970  *  \param doc Document to export.
971  *  \param uri URI to export to.
972  *  \param mime MIME type to export as.
973  */
975 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
977     /** \todo
978      * FIXME: I've no idea if this is the `proper' way to do this.
979      * If anyone feels qualified to say that it is, perhaps they
980      * could remove this comment.
981      */
983     Inkscape::Extension::DB::OutputList o;
984     Inkscape::Extension::db.get_output_list(o);
985     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
986     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
987         i++;
988     }
990     if (i == o.end())
991     {
992         g_warning ("Could not find an extension to export this file.");
993         return;
994     }
996     bool old_text_to_path = false;
997     bool old_bbox_page = false;
999     try {
1000         old_text_to_path = (*i)->get_param_bool("textToPath");
1001         (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1002     }
1003     catch (...) {
1004         g_warning ("Could not set export-text-to-path option for this export.");
1005     }
1007     try {
1008         old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1009         (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1010     }
1011     catch (...) {
1012         g_warning ("Could not set export-bbox-page option for this export.");
1013     }
1015     (*i)->save(doc, uri);
1017     try {
1018         (*i)->set_param_bool("textToPath", old_text_to_path);
1019         (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1020     }
1021     catch (...) {
1023     }
1026 #ifdef WIN32
1027 bool replaceArgs( int& argc, char**& argv )
1029     bool worked = false;
1031 #ifdef REPLACEARGS_DEBUG
1032     MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1033 #endif // REPLACEARGS_DEBUG
1035     wchar_t* line = GetCommandLineW();
1036     if ( line )
1037     {
1038 #ifdef REPLACEARGS_DEBUG
1039         {
1040             gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1041             if ( utf8Line )
1042             {
1043                 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1044                 {
1045                     char tmp[strlen(safe) + 32];
1046                     snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1047                     MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1048                 }
1049             }
1050         }
1051 #endif // REPLACEARGS_DEBUG
1053         int numArgs = 0;
1054         wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1056 #ifdef REPLACEARGS_ANSI
1057 // test code for trying things on Win95/98/ME
1058         if ( !parsed )
1059         {
1060 #ifdef REPLACEARGS_DEBUG
1061             MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1062 #endif // REPLACEARGS_DEBUG
1063             int lineLen = wcslen(line) + 1;
1064             wchar_t* lineDup = new wchar_t[lineLen];
1065             wcsncpy( lineDup, line, lineLen );
1067             int pos = 0;
1068             bool inQuotes = false;
1069             bool inWhitespace = true;
1070             std::vector<int> places;
1071             while ( lineDup[pos] )
1072             {
1073                 if ( inQuotes )
1074                 {
1075                     if ( lineDup[pos] == L'"' )
1076                     {
1077                         inQuotes = false;
1078                     }
1079                 }
1080                 else if ( lineDup[pos] == L'"' )
1081                 {
1082                     inQuotes = true;
1083                     inWhitespace = false;
1084                     places.push_back(pos);
1085                 }
1086                 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1087                 {
1088                     if ( !inWhitespace )
1089                     {
1090                         inWhitespace = true;
1091                         lineDup[pos] = 0;
1092                     }
1093                 }
1094                 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1095                 {
1096                     inWhitespace = false;
1097                     places.push_back(pos);
1098                 }
1099                 else
1100                 {
1101                     // consume
1102                 }
1103                 pos++;
1104             }
1105 #ifdef REPLACEARGS_DEBUG
1106             {
1107                 char tmp[256];
1108                 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1109                 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1110             }
1111 #endif // REPLACEARGS_DEBUG
1113             wchar_t** block = new wchar_t*[places.size()];
1114             int i = 0;
1115             for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1116             {
1117                 block[i++] = &lineDup[*it];
1118             }
1119             parsed = block;
1120             numArgs = places.size();
1121         }
1122 #endif // REPLACEARGS_ANSI
1124         if ( parsed )
1125         {
1126             std::vector<wchar_t*>expandedArgs;
1127             if ( numArgs > 0 )
1128             {
1129                 expandedArgs.push_back( parsed[0] );
1130             }
1132             for ( int i1 = 1; i1 < numArgs; i1++ )
1133             {
1134                 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1135                 wildcarded &= parsed[i1][0] != L'"';
1136                 wildcarded &= parsed[i1][0] != L'-';
1137                 if ( wildcarded )
1138                 {
1139 #ifdef REPLACEARGS_ANSI
1140                     WIN32_FIND_DATAA data = {0};
1141 #else
1142                     WIN32_FIND_DATAW data = {0};
1143 #endif // REPLACEARGS_ANSI
1145                     int baseLen = wcslen(parsed[i1]) + 2;
1146                     wchar_t* base = new wchar_t[baseLen];
1147                     wcsncpy( base, parsed[i1], baseLen );
1148                     wchar_t* last = wcsrchr( base, L'\\' );
1149                     if ( last )
1150                     {
1151                         last[1] = 0;
1152                     }
1153                     else
1154                     {
1155                         base[0] = 0;
1156                     }
1157                     baseLen = wcslen( base );
1159 #ifdef REPLACEARGS_ANSI
1160                     char target[MAX_PATH];
1161                     if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1162                     {
1163                         HANDLE hf = FindFirstFileA( target, &data );
1164 #else
1165                         HANDLE hf = FindFirstFileW( parsed[i1], &data );
1166 #endif // REPLACEARGS_ANSI
1167                         if ( hf != INVALID_HANDLE_VALUE )
1168                         {
1169                             BOOL found = TRUE;
1170                             do
1171                             {
1172 #ifdef REPLACEARGS_ANSI
1173                                 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1174                                 if ( howMany > 0 )
1175                                 {
1176                                     howMany += baseLen;
1177                                     wchar_t* tmp = new wchar_t[howMany + 1];
1178                                     wcsncpy( tmp, base, howMany + 1 );
1179                                     MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1180                                     expandedArgs.push_back( tmp );
1181                                     found = FindNextFileA( hf, &data );
1182                                 }
1183 #else
1184                                 int howMany = wcslen(data.cFileName) + baseLen;
1185                                 wchar_t* tmp = new wchar_t[howMany + 1];
1186                                 wcsncpy( tmp, base, howMany + 1 );
1187                                 wcsncat( tmp, data.cFileName, howMany + 1 );
1188                                 expandedArgs.push_back( tmp );
1189                                 found = FindNextFileW( hf, &data );
1190 #endif // REPLACEARGS_ANSI
1191                             } while ( found );
1193                             FindClose( hf );
1194                         }
1195                         else
1196                         {
1197                             expandedArgs.push_back( parsed[i1] );
1198                         }
1199 #ifdef REPLACEARGS_ANSI
1200                     }
1201 #endif // REPLACEARGS_ANSI
1203                     delete[] base;
1204                 }
1205                 else
1206                 {
1207                     expandedArgs.push_back( parsed[i1] );
1208                 }
1209             }
1211             {
1212                 wchar_t** block = new wchar_t*[expandedArgs.size()];
1213                 int iz = 0;
1214                 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1215                 {
1216                     block[iz++] = *it;
1217                 }
1218                 parsed = block;
1219                 numArgs = expandedArgs.size();
1220             }
1222             std::vector<gchar*> newArgs;
1223             for ( int i = 0; i < numArgs; i++ )
1224             {
1225                 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1226                 if ( replacement )
1227                 {
1228 #ifdef REPLACEARGS_DEBUG
1229                     gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1231                     if ( safe2 )
1232                     {
1233                         {
1234                             char tmp[1024];
1235                             snprintf( tmp, sizeof(tmp), "    [%2d] = '%s'", i, safe2 );
1236                             MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1237                         }
1238                         g_free( safe2 );
1239                     }
1240 #endif // REPLACEARGS_DEBUG
1242                     newArgs.push_back( replacement );
1243                 }
1244                 else
1245                 {
1246                     newArgs.push_back( blankParam );
1247                 }
1248             }
1250             // Now push our munged params to be the new argv and argc
1251             {
1252                 char** block = new char*[newArgs.size()];
1253                 int iz = 0;
1254                 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1255                 {
1256                     block[iz++] = *it;
1257                 }
1258                 argv = block;
1259                 argc = newArgs.size();
1260                 worked = true;
1261             }
1262         }
1263 #ifdef REPLACEARGS_DEBUG
1264         else
1265         {
1266             MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1267         }
1268 #endif // REPLACEARGS_DEBUG
1269     }
1270 #ifdef REPLACEARGS_DEBUG
1271     else
1272     {
1273         {
1274             MessageBoxA( NULL,  "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1275         }
1277         char* line2 = GetCommandLineA();
1278         if ( line2 )
1279         {
1280             gchar *safe = Inkscape::IO::sanitizeString(line2);
1281             {
1282                 {
1283                     char tmp[strlen(safe) + 32];
1284                     snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1285                     MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1286                 }
1287             }
1288         }
1289         else
1290         {
1291             MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1292         }
1293     }
1294 #endif // REPLACEARGS_DEBUG
1296     return worked;
1298 #endif // WIN32
1300 static GSList *
1301 sp_process_args(poptContext ctx)
1303     GSList *fl = NULL;
1305     gint a;
1306     while ((a = poptGetNextOpt(ctx)) >= 0) {
1307         switch (a) {
1308             case SP_ARG_FILE: {
1309                 gchar const *fn = poptGetOptArg(ctx);
1310                 if (fn != NULL) {
1311                     fl = g_slist_append(fl, g_strdup(fn));
1312                 }
1313                 break;
1314             }
1315             case SP_ARG_VERSION: {
1316                 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1317                 exit(0);
1318                 break;
1319             }
1320             case SP_ARG_EXTENSIONDIR: {
1321                 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1322                 exit(0);
1323                 break;
1324             }
1325             default: {
1326                 break;
1327             }
1328         }
1329     }
1331     gchar const ** const args = poptGetArgs(ctx);
1332     if (args != NULL) {
1333         for (unsigned i = 0; args[i] != NULL; i++) {
1334             fl = g_slist_append(fl, g_strdup(args[i]));
1335         }
1336     }
1338     return fl;
1342 /*
1343   Local Variables:
1344   mode:c++
1345   c-file-style:"stroustrup"
1346   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1347   indent-tabs-mode:nil
1348   fill-column:99
1349   End:
1350 */
1351 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :