Code

Change tool switch message for paint bucket
[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 "gc-core.h"
53 #include "macros.h"
54 #include "file.h"
55 #include "document.h"
56 #include "sp-object.h"
57 #include "interface.h"
58 #include "print.h"
59 #include "color.h"
60 #include "sp-item.h"
61 #include "sp-root.h"
62 #include "unit-constants.h"
64 #include "svg/svg.h"
65 #include "svg/svg-color.h"
66 #include "svg/stringstream.h"
68 #include "inkscape-private.h"
69 #include "inkscape-stock.h"
70 #include "inkscape_version.h"
72 #include "sp-namedview.h"
73 #include "sp-guide.h"
74 #include "sp-object-repr.h"
75 #include "xml/repr.h"
77 #include "io/sys.h"
79 #include "debug/logger.h"
81 #include "helper/png-write.h"
83 #include <extension/extension.h>
84 #include <extension/system.h>
85 #include <extension/db.h>
86 #include <extension/output.h>
88 #ifdef WIN32
89 //#define REPLACEARGS_ANSI
90 //#define REPLACEARGS_DEBUG
92 #include "registrytool.h"
94 #include "extension/internal/win32.h"
95 using Inkscape::Extension::Internal::PrintWin32;
97 #endif // WIN32
99 #include "extension/init.h"
101 #include <glibmm/i18n.h>
102 #include <gtkmm/main.h>
104 #ifndef HAVE_BIND_TEXTDOMAIN_CODESET
105 #define bind_textdomain_codeset(p,c)
106 #endif
108 #include "application/application.h"
110 #include "main-cmdlineact.h"
112 enum {
113     SP_ARG_NONE,
114     SP_ARG_NOGUI,
115     SP_ARG_GUI,
116     SP_ARG_FILE,
117     SP_ARG_PRINT,
118     SP_ARG_EXPORT_PNG,
119     SP_ARG_EXPORT_DPI,
120     SP_ARG_EXPORT_AREA,
121     SP_ARG_EXPORT_AREA_DRAWING,
122     SP_ARG_EXPORT_AREA_CANVAS,
123     SP_ARG_EXPORT_AREA_SNAP,
124     SP_ARG_EXPORT_WIDTH,
125     SP_ARG_EXPORT_HEIGHT,
126     SP_ARG_EXPORT_ID,
127     SP_ARG_EXPORT_ID_ONLY,
128     SP_ARG_EXPORT_USE_HINTS,
129     SP_ARG_EXPORT_BACKGROUND,
130     SP_ARG_EXPORT_BACKGROUND_OPACITY,
131     SP_ARG_EXPORT_SVG,
132     SP_ARG_EXPORT_PS,
133     SP_ARG_EXPORT_EPS,
134     SP_ARG_EXPORT_PDF,
135     SP_ARG_EXPORT_TEXT_TO_PATH,
136     SP_ARG_EXPORT_FONT,
137     SP_ARG_EXPORT_BBOX_PAGE,
138     SP_ARG_EXTENSIONDIR,
139     SP_ARG_FIT_PAGE_TO_DRAWING,
140     SP_ARG_QUERY_X,
141     SP_ARG_QUERY_Y,
142     SP_ARG_QUERY_WIDTH,
143     SP_ARG_QUERY_HEIGHT,
144     SP_ARG_QUERY_ID,
145     SP_ARG_VERSION,
146     SP_ARG_VACUUM_DEFS,
147     SP_ARG_VERB_LIST,
148     SP_ARG_VERB,
149     SP_ARG_SELECT,
150     SP_ARG_LAST
151 };
153 int sp_main_gui(int argc, char const **argv);
154 int sp_main_console(int argc, char const **argv);
155 static void sp_do_export_png(SPDocument *doc);
156 static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
157 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const *mime);
158 static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
161 static gchar *sp_global_printer = NULL;
162 static gchar *sp_export_png = NULL;
163 static gchar *sp_export_dpi = NULL;
164 static gchar *sp_export_area = NULL;
165 static gboolean sp_export_area_drawing = FALSE;
166 static gboolean sp_export_area_canvas = FALSE;
167 static gchar *sp_export_width = NULL;
168 static gchar *sp_export_height = NULL;
169 static gchar *sp_export_id = NULL;
170 static gchar *sp_export_background = NULL;
171 static gchar *sp_export_background_opacity = NULL;
172 static gboolean sp_export_area_snap = FALSE;
173 static gboolean sp_export_use_hints = FALSE;
174 static gboolean sp_export_id_only = FALSE;
175 static gchar *sp_export_svg = NULL;
176 static gchar *sp_export_ps = NULL;
177 static gchar *sp_export_eps = NULL;
178 static gchar *sp_export_pdf = NULL;
179 static gboolean sp_export_text_to_path = FALSE;
180 static gboolean sp_export_font = FALSE;
181 static gboolean sp_export_bbox_page = FALSE;
182 static gboolean sp_query_x = FALSE;
183 static gboolean sp_query_y = FALSE;
184 static gboolean sp_query_width = FALSE;
185 static gboolean sp_query_height = FALSE;
186 static gchar *sp_query_id = NULL;
187 static int sp_new_gui = FALSE;
188 static gboolean sp_vacuum_defs = FALSE;
190 static gchar *sp_export_png_utf8 = NULL;
191 static gchar *sp_export_svg_utf8 = NULL;
192 static gchar *sp_global_printer_utf8 = NULL;
194 #ifdef WIN32
195 static bool replaceArgs( int& argc, char**& argv );
196 #endif
197 static GSList *sp_process_args(poptContext ctx);
198 struct poptOption options[] = {
199     {"version", 'V',
200      POPT_ARG_NONE, NULL, SP_ARG_VERSION,
201      N_("Print the Inkscape version number"),
202      NULL},
204     {"without-gui", 'z',
205      POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
206      N_("Do not use X server (only process files from console)"),
207      NULL},
209     {"with-gui", 'g',
210      POPT_ARG_NONE, NULL, SP_ARG_GUI,
211      N_("Try to use X server (even if $DISPLAY is not set)"),
212      NULL},
214     {"file", 'f',
215      POPT_ARG_STRING, NULL, SP_ARG_FILE,
216      N_("Open specified document(s) (option string may be excluded)"),
217      N_("FILENAME")},
219     {"print", 'p',
220      POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
221      N_("Print document(s) to specified output file (use '| program' for pipe)"),
222      N_("FILENAME")},
224     {"export-png", 'e',
225      POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
226      N_("Export document to a PNG file"),
227      N_("FILENAME")},
229     {"export-dpi", 'd',
230      POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
231      N_("The resolution used for exporting SVG into bitmap (default 90)"),
232      N_("DPI")},
234     {"export-area", 'a',
235      POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
236      N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
237      N_("x0:y0:x1:y1")},
239     {"export-area-drawing", 'D',
240      POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
241      N_("Exported area is the entire drawing (not canvas)"),
242      NULL},
244     {"export-area-canvas", 'C',
245      POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
246      N_("Exported area is the entire canvas"),
247      NULL},
249     {"export-area-snap", 0,
250      POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
251      N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
252      NULL},
254     {"export-width", 'w',
255      POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
256      N_("The width of exported bitmap in pixels (overrides export-dpi)"),
257      N_("WIDTH")},
259     {"export-height", 'h',
260      POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
261      N_("The height of exported bitmap in pixels (overrides export-dpi)"),
262      N_("HEIGHT")},
264     {"export-id", 'i',
265      POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
266      N_("The ID of the object to export"),
267      N_("ID")},
269     {"export-id-only", 'j',
270      POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
271      // TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
272      //  See "man inkscape" for details.
273      N_("Export just the object with export-id, hide all others (only with export-id)"),
274      NULL},
276     {"export-use-hints", 't',
277      POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
278      N_("Use stored filename and DPI hints when exporting (only with export-id)"),
279      NULL},
281     {"export-background", 'b',
282      POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
283      N_("Background color of exported bitmap (any SVG-supported color string)"),
284      N_("COLOR")},
286     {"export-background-opacity", 'y',
287      POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
288      N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"),
289      N_("VALUE")},
291     {"export-plain-svg", 'l',
292      POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
293      N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"),
294      N_("FILENAME")},
296     {"export-ps", 'P',
297      POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
298      N_("Export document to a PS file"),
299      N_("FILENAME")},
301     {"export-eps", 'E',
302      POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
303      N_("Export document to an EPS file"),
304      N_("FILENAME")},
306     {"export-pdf", 'A',
307      POPT_ARG_STRING, &sp_export_pdf, SP_ARG_EXPORT_PDF,
308      N_("Export document to a PDF file"),
309      N_("FILENAME")},
311     {"export-text-to-path", 'T',
312      POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
313      N_("Convert text object to paths on export (EPS)"),
314      NULL},
316     {"export-embed-fonts", 'F',
317      POPT_ARG_NONE, &sp_export_font, SP_ARG_EXPORT_FONT,
318      N_("Embed fonts on export (Type 1 only) (EPS)"),
319      NULL},
321     {"export-bbox-page", 'B',
322      POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
323      N_("Export files with the bounding box set to the page size (EPS)"),
324      NULL},
326     {"query-x", 'X',
327      POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
328      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
329      N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
330      NULL},
332     {"query-y", 'Y',
333      POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
334      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
335      N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
336      NULL},
338     {"query-width", 'W',
339      POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
340      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
341      N_("Query the width of the drawing or, if specified, of the object with --query-id"),
342      NULL},
344     {"query-height", 'H',
345      POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
346      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
347      N_("Query the height of the drawing or, if specified, of the object with --query-id"),
348      NULL},
350     {"query-id", 'I',
351      POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
352      N_("The ID of the object whose dimensions are queried"),
353      N_("ID")},
355     {"extension-directory", 'x',
356      POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
357      // TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
358      N_("Print out the extension directory and exit"),
359      NULL},
361     {"vacuum-defs", 0,
362      POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
363      N_("Remove unused definitions from the defs section(s) of the document"),
364      NULL},
366     {"verb-list", 0,
367      POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
368      N_("List the IDs of all the verbs in Inkscape"),
369      NULL},
371     {"verb", 0,
372      POPT_ARG_STRING, NULL, SP_ARG_VERB,
373      N_("Verb to call when Inkscape opens."),
374      N_("VERB-ID")},
376     {"select", 0,
377      POPT_ARG_STRING, NULL, SP_ARG_SELECT,
378      N_("Object ID to select when Inkscape opens."),
379      N_("OBJECT-ID")},
381     POPT_AUTOHELP POPT_TABLEEND
382 };
384 static bool needToRecodeParams = true;
385 gchar* blankParam = "";
387 int
388 main(int argc, char **argv)
390 #ifdef HAVE_FPSETMASK
391     /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__.  It's probably
392        safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
393        the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
394     fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
395 #endif
397 #ifdef ENABLE_NLS
398 #ifdef WIN32
399     RegistryTool rt;
400     rt.setPathInfo();
401     gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
402     bindtextdomain(GETTEXT_PACKAGE, pathBuf);
403     g_free(pathBuf);
404 #else
405 #ifdef ENABLE_BINRELOC
406     bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
407 #else
408     bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
409 #endif
410 #endif
411     // Allow the user to override the locale directory by setting 
412     // the environment variable INKSCAPE_LOCALEDIR.
413     char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
414     if (inkscape_localedir != NULL) {
415         bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
416     }
417 #endif
419     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
421 #ifdef ENABLE_NLS
422     textdomain(GETTEXT_PACKAGE);
423 #endif
425     LIBXML_TEST_VERSION
427     Inkscape::GC::init();
429     Inkscape::Debug::Logger::init();
431     gboolean use_gui;
432 #ifndef WIN32
433     use_gui = (getenv("DISPLAY") != NULL);
434 #else
435     /*
436       Set the current directory to the directory of the
437       executable.  This seems redundant, but is needed for
438       when inkscape.exe is executed from another directory.
439       We use relative paths on win32.
440       HKCR\svgfile\shell\open\command is a good example
441     */
442     /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
443     char *homedir = g_path_get_dirname(argv[0]);
444     SetCurrentDirectory(homedir);
445     g_free(homedir);
447     use_gui = TRUE;
448 #endif
449     /* Test whether with/without GUI is forced */
450     for (int i = 1; i < argc; i++) {
451         if (!strcmp(argv[i], "-z")
452             || !strcmp(argv[i], "--without-gui")
453             || !strcmp(argv[i], "-p")
454             || !strncmp(argv[i], "--print", 7)
455             || !strcmp(argv[i], "-e")
456             || !strncmp(argv[i], "--export-png", 12)
457             || !strcmp(argv[i], "-l")
458             || !strncmp(argv[i], "--export-plain-svg", 12)
459             || !strcmp(argv[i], "-i")
460             || !strncmp(argv[i], "--export-area-drawing", 21)
461             || !strcmp(argv[i], "-D")
462             || !strncmp(argv[i], "--export-area-canvas", 20)
463             || !strcmp(argv[i], "-C")
464             || !strncmp(argv[i], "--export-id", 12)
465             || !strcmp(argv[i], "-P")
466             || !strncmp(argv[i], "--export-ps", 11)
467             || !strcmp(argv[i], "-E")
468             || !strncmp(argv[i], "--export-eps", 12)
469             || !strcmp(argv[i], "-A")
470             || !strncmp(argv[i], "--export-pdf", 12)
471             || !strcmp(argv[i], "-W")
472             || !strncmp(argv[i], "--query-width", 13)
473             || !strcmp(argv[i], "-H")
474             || !strncmp(argv[i], "--query-height", 14)
475             || !strcmp(argv[i], "-X")
476             || !strncmp(argv[i], "--query-x", 13)
477             || !strcmp(argv[i], "-Y")
478             || !strncmp(argv[i], "--query-y", 14)
479             || !strcmp(argv[i], "--vacuum-defs")
480            )
481         {
482             /* main_console handles any exports -- not the gui */
483             use_gui = FALSE;
484             break;
485         } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
486             use_gui = TRUE;
487             break;
488         }
489     }
491 #ifdef WIN32
492 #ifndef REPLACEARGS_ANSI
493     if ( PrintWin32::is_os_wide() )
494 #endif // REPLACEARGS_ANSI
495     {
496         // If the call fails, we'll need to convert charsets
497         needToRecodeParams = !replaceArgs( argc, argv );
498     }
499 #endif // WIN32
501     /// \todo  Should this be a static object (see inkscape.cpp)?
502     Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
504     return app.run();
507 void fixupSingleFilename( gchar **orig, gchar **spare )
509     if ( orig && *orig && **orig ) {
510         GError *error = NULL;
511         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
512         if ( newFileName )
513         {
514             *orig = newFileName;
515             if ( spare ) {
516                 *spare = newFileName;
517             }
518 //             g_message("Set a replacement fixup");
519         }
520     }
523 GSList *fixupFilenameEncoding( GSList* fl )
525     GSList *newFl = NULL;
526     while ( fl ) {
527         gchar *fn = static_cast<gchar*>(fl->data);
528         fl = g_slist_remove( fl, fl->data );
529         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
530         if ( newFileName ) {
532             if ( 0 )
533             {
534                 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
535                 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
536                 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
537                                                        "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
538                 gtk_dialog_run (GTK_DIALOG (w));
539                 gtk_widget_destroy (w);
540                 g_free(safeNewFn);
541                 g_free(safeFn);
542             }
544             g_free( fn );
545             fn = newFileName;
546             newFileName = 0;
547         }
548         else
549             if ( 0 )
550         {
551             gchar *safeFn = Inkscape::IO::sanitizeString(fn);
552             GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
553             gtk_dialog_run (GTK_DIALOG (w));
554             gtk_widget_destroy (w);
555             g_free(safeFn);
556         }
557         newFl = g_slist_append( newFl, fn );
558     }
559     return newFl;
562 int sp_common_main( int argc, char const **argv, GSList **flDest )
564     /// \todo fixme: Move these to some centralized location (Lauris)
565     sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
566     sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
569     // temporarily switch gettext encoding to locale, so that help messages can be output properly
570     gchar const *charset;
571     g_get_charset(&charset);
573     bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
575     poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
576     poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
577     g_return_val_if_fail(ctx != NULL, 1);
579     /* Collect own arguments */
580     GSList *fl = sp_process_args(ctx);
581     poptFreeContext(ctx);
583     // now switch gettext back to UTF-8 (for GUI)
584     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
586     // Now let's see if the file list still holds up
587     if ( needToRecodeParams )
588     {
589         fl = fixupFilenameEncoding( fl );
590     }
592     // Check the globals for filename-fixup
593     if ( needToRecodeParams )
594     {
595         fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
596         fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
597         fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
598     }
599     else
600     {
601         if ( sp_export_png )
602             sp_export_png_utf8 = g_strdup( sp_export_png );
603         if ( sp_export_svg )
604             sp_export_svg_utf8 = g_strdup( sp_export_svg );
605         if ( sp_global_printer )
606             sp_global_printer_utf8 = g_strdup( sp_global_printer );
607     }
609     // Return the list if wanted, else free it up.
610     if ( flDest ) {
611         *flDest = fl;
612         fl = 0;
613     } else {
614         while ( fl ) {
615             g_free( fl->data );
616             fl = g_slist_remove( fl, fl->data );
617         }
618     }
619     return 0;
622 int
623 sp_main_gui(int argc, char const **argv)
625     Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
627     GSList *fl = NULL;
628     int retVal = sp_common_main( argc, argv, &fl );
629     g_return_val_if_fail(retVal == 0, 1);
631     inkscape_gtk_stock_init();
633     /* Set default icon */
634     gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
635     if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
636         gtk_window_set_default_icon_from_file(filename, NULL);
637     }
638     g_free (filename);
639     filename = 0;
641     gboolean create_new = TRUE;
643     /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
644     inkscape_application_init(argv[0], true);
646     while (fl) {
647         if (sp_file_open((gchar *)fl->data,NULL)) {
648             create_new=FALSE;
649         }
650         fl = g_slist_remove(fl, fl->data);
651     }
652     if (create_new) {
653         sp_file_new_default();
654     }
656     Glib::signal_idle().connect(sigc::ptr_fun(&Inkscape::CmdLineAction::idle));
657     main_instance.run();
659 #ifdef WIN32
660     //We might not need anything here
661     //sp_win32_finish(); <-- this is a NOP func
662 #endif
664     return 0;
667 int
668 sp_main_console(int argc, char const **argv)
670     /* We are started in text mode */
672     /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
673      * in a non-Gtk environment.  Used in libnrtype's
674      * FontInstance.cpp and FontFactory.cpp.
675      * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
676      */
677     g_type_init();
678     char **argv2 = const_cast<char **>(argv);
679     gtk_init_check( &argc, &argv2 );
680     //setlocale(LC_ALL, "");
682     GSList *fl = NULL;
683     int retVal = sp_common_main( argc, argv, &fl );
684     g_return_val_if_fail(retVal == 0, 1);
686     if (fl == NULL) {
687         g_print("Nothing to do!\n");
688         exit(0);
689     }
691     inkscape_application_init(argv[0], false);
693     while (fl) {
694         SPDocument *doc;
696         doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
697         if (doc == NULL) {
698             doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
699         }
700         if (doc == NULL) {
701             g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
702         } else {
703             if (sp_vacuum_defs) {
704                 vacuum_document(doc);
705             }
706             if (sp_vacuum_defs && !sp_export_svg) {
707                 // save under the name given in the command line
708                 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
709             }
710             if (sp_global_printer) {
711                 sp_print_document_to_file(doc, sp_global_printer);
712             }
713             if (sp_export_png || sp_export_id || sp_export_area_drawing) {
714                 sp_do_export_png(doc);
715             }
716             if (sp_export_svg) {
717                 Inkscape::XML::Document *rdoc;
718                 Inkscape::XML::Node *repr;
719                 rdoc = sp_repr_document_new("svg:svg");
720                 repr = rdoc->root();
721                 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
722                 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
723             }
724             if (sp_export_ps) {
725                 do_export_ps(doc, sp_export_ps, "image/x-postscript");
726             }
727             if (sp_export_eps) {
728                 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
729             }
730             if (sp_export_pdf) {
731                 do_export_pdf(doc, sp_export_pdf, "application/pdf");
732             }
733             if (sp_query_width || sp_query_height) {
734                 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
735             } else if (sp_query_x || sp_query_y) {
736                 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
737             }
738         }
740         fl = g_slist_remove(fl, fl->data);
741     }
743     inkscape_unref();
745     return 0;
748 static void
749 do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
751     SPObject *o = NULL;
753     if (id) {
754         o = doc->getObjectById(id);
755         if (o) {
756             if (!SP_IS_ITEM (o)) {
757                 g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
758                 return;
759             }
760         } else {
761             g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
762             return;
763         }
764     } else {
765         o = SP_DOCUMENT_ROOT(doc);
766     }
768     if (o) {
769         sp_document_ensure_up_to_date (doc);
770         SPItem *item = ((SPItem *) o);
772         // "true" SVG bbox for scripting
773         NR::Maybe<NR::Rect> area = item->getBounds(sp_item_i2doc_affine(item));
774         if (area) {
775             Inkscape::SVGOStringStream os;
776             if (extent) {
777                 os << area->extent(axis);
778             } else {
779                 os << area->min()[axis];
780             }
781             g_print ("%s", os.str().c_str());
782         } else {
783             g_print("0");
784         }
785     }
789 static void
790 sp_do_export_png(SPDocument *doc)
792     const gchar *filename = NULL;
793     gdouble dpi = 0.0;
795     if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
796         g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
797     }
799     GSList *items = NULL;
801     NRRect area;
802     if (sp_export_id || sp_export_area_drawing) {
804         SPObject *o = NULL;
805         SPObject *o_area = NULL;
806         if (sp_export_id && sp_export_area_drawing) {
807             o = doc->getObjectById(sp_export_id);
808             o_area = SP_DOCUMENT_ROOT (doc);
809         } else if (sp_export_id) {
810             o = doc->getObjectById(sp_export_id);
811             o_area = o;
812         } else if (sp_export_area_drawing) {
813             o = SP_DOCUMENT_ROOT (doc);
814             o_area = o;
815         } 
817         if (o) {
818             if (!SP_IS_ITEM (o)) {
819                 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
820                 return;
821             }
823             items = g_slist_prepend (items, SP_ITEM(o));
825             if (sp_export_id_only) {
826                 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
827             }
829             if (sp_export_use_hints) {
831                 // retrieve export filename hint
832                 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
833                 if (fn_hint) {
834                     if (sp_export_png) {
835                         g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
836                         filename = sp_export_png;
837                     } else {
838                         filename = fn_hint;
839                     }
840                 } else {
841                     g_warning ("Export filename hint not found for the object.");
842                     filename = sp_export_png;
843                 }
845                 // retrieve export dpi hints
846                 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
847                 if (dpi_hint) {
848                     if (sp_export_dpi || sp_export_width || sp_export_height) {
849                         g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
850                     } else {
851                         dpi = atof(dpi_hint);
852                     }
853                 } else {
854                     g_warning ("Export DPI hint not found for the object.");
855                 }
857             }
859             // write object bbox to area
860             sp_document_ensure_up_to_date (doc);
861             sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
862         } else {
863             g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
864             return;
865         }
866     }
867     
868     if (sp_export_area) {
869         /* Try to parse area (given in SVG pixels) */
870         if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
871             g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
872             return;
873         }
874         if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
875             g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
876             return;
877         }
878     } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
879         /* Export the whole canvas */
880         sp_document_ensure_up_to_date (doc);
881         area.x0 = SP_ROOT(doc->root)->x.computed;
882         area.y0 = SP_ROOT(doc->root)->y.computed;
883         area.x1 = area.x0 + sp_document_width (doc);
884         area.y1 = area.y0 + sp_document_height (doc);
885     }
887     // set filename and dpi from options, if not yet set from the hints
888     if (!filename) {
889         if (!sp_export_png) {
890             g_warning ("No export filename given and no filename hint. Nothing exported.");
891             return;
892         }
893         filename = sp_export_png;
894     }
896     if (sp_export_dpi && dpi == 0.0) {
897         dpi = atof(sp_export_dpi);
898         if ((dpi < 0.1) || (dpi > 10000.0)) {
899             g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
900             return;
901         }
902         g_print("DPI: %g\n", dpi);
903     }
905     if (sp_export_area_snap) {
906         area.x0 = std::floor (area.x0);
907         area.y0 = std::floor (area.y0);
908         area.x1 = std::ceil (area.x1);
909         area.y1 = std::ceil (area.y1);
910     }
912     // default dpi
913     if (dpi == 0.0)
914         dpi = PX_PER_IN;
916     gint width = 0;
917     gint height = 0;
919     if (sp_export_width) {
920         width = atoi(sp_export_width);
921         if ((width < 1) || (width > 65536)) {
922             g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
923             return;
924         }
925         dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
926     }
928     if (sp_export_height) {
929         height = atoi(sp_export_height);
930         if ((height < 1) || (height > 65536)) {
931             g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
932             return;
933         }
934         dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
935     }
937     if (!sp_export_width) {
938         width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
939     }
941     if (!sp_export_height) {
942         height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
943     }
945     guint32 bgcolor = 0x00000000;
946     if (sp_export_background) {
947         // override the page color
948         bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
949         bgcolor |= 0xff; // default is no opacity
950     } else {
951         // read from namedview
952         Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
953         if (nv && nv->attribute("pagecolor"))
954             bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
955         if (nv && nv->attribute("inkscape:pageopacity"))
956             bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
957     }
959     if (sp_export_background_opacity) {
960         // override opacity
961         gfloat value;
962         if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
963             if (value > 1.0) {
964                 value = CLAMP (value, 1.0f, 255.0f);
965                 bgcolor &= (guint32) 0xffffff00;
966                 bgcolor |= (guint32) floor(value);
967             } else {
968                 value = CLAMP (value, 0.0f, 1.0f);
969                 bgcolor &= (guint32) 0xffffff00;
970                 bgcolor |= SP_COLOR_F_TO_U(value);
971             }
972         }
973     }
975     g_print("Background RRGGBBAA: %08x\n", bgcolor);
977     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);
979     g_print("Bitmap saved as: %s\n", filename);
981     if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
982         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);
983     } else {
984         g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
985     }
987     g_slist_free (items);
991 /**
992  *  Perform an export of either PS or EPS.
993  *
994  *  \param doc Document to export.
995  *  \param uri URI to export to.
996  *  \param mime MIME type to export as.
997  */
999 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
1001     Inkscape::Extension::DB::OutputList o;
1002     Inkscape::Extension::db.get_output_list(o);
1003     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1004     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1005         i++;
1006     }
1008     if (i == o.end())
1009     {
1010         g_warning ("Could not find an extension to export this file.");
1011         return;
1012     }
1014     bool old_text_to_path = false;
1015     bool old_font_embedded = false;
1016     bool old_bbox_page = false;
1018     try {
1019         old_text_to_path = (*i)->get_param_bool("textToPath");
1020         (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1021     }
1022     catch (...) {
1023         g_warning ("Could not set export-text-to-path option for this export.");
1024     }
1026     try {
1027         old_font_embedded = (*i)->get_param_bool("fontEmbedded");
1028         (*i)->set_param_bool("fontEmbedded", sp_export_font);
1029     }
1030     catch (...) {
1031         g_warning ("Could not set export-font option for this export.");
1032     }
1034     try {
1035         old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1036         (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1037     }
1038     catch (...) {
1039         g_warning ("Could not set export-bbox-page option for this export.");
1040     }
1042     (*i)->save(doc, uri);
1044     try {
1045         (*i)->set_param_bool("textToPath", old_text_to_path);
1046         (*i)->set_param_bool("fontEmbedded", old_font_embedded);
1047         (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1048     }
1049     catch (...) {
1051     }
1054 /**
1055  *  Perform a PDF export
1056  *
1057  *  \param doc Document to export.
1058  *  \param uri URI to export to.
1059  *  \param mime MIME type to export as.
1060  */
1062 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
1064     Inkscape::Extension::DB::OutputList o;
1065     Inkscape::Extension::db.get_output_list(o);
1066     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1067     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1068         i++;
1069     }
1071     if (i == o.end())
1072     {
1073         g_warning ("Could not find an extension to export this file.");
1074         return;
1075     }
1077     (*i)->save(doc, uri);
1080 #ifdef WIN32
1081 bool replaceArgs( int& argc, char**& argv )
1083     bool worked = false;
1085 #ifdef REPLACEARGS_DEBUG
1086     MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1087 #endif // REPLACEARGS_DEBUG
1089     wchar_t* line = GetCommandLineW();
1090     if ( line )
1091     {
1092 #ifdef REPLACEARGS_DEBUG
1093         {
1094             gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1095             if ( utf8Line )
1096             {
1097                 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1098                 {
1099                     char tmp[strlen(safe) + 32];
1100                     snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1101                     MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1102                 }
1103             }
1104         }
1105 #endif // REPLACEARGS_DEBUG
1107         int numArgs = 0;
1108         wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1110 #ifdef REPLACEARGS_ANSI
1111 // test code for trying things on Win95/98/ME
1112         if ( !parsed )
1113         {
1114 #ifdef REPLACEARGS_DEBUG
1115             MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1116 #endif // REPLACEARGS_DEBUG
1117             int lineLen = wcslen(line) + 1;
1118             wchar_t* lineDup = new wchar_t[lineLen];
1119             wcsncpy( lineDup, line, lineLen );
1121             int pos = 0;
1122             bool inQuotes = false;
1123             bool inWhitespace = true;
1124             std::vector<int> places;
1125             while ( lineDup[pos] )
1126             {
1127                 if ( inQuotes )
1128                 {
1129                     if ( lineDup[pos] == L'"' )
1130                     {
1131                         inQuotes = false;
1132                     }
1133                 }
1134                 else if ( lineDup[pos] == L'"' )
1135                 {
1136                     inQuotes = true;
1137                     inWhitespace = false;
1138                     places.push_back(pos);
1139                 }
1140                 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1141                 {
1142                     if ( !inWhitespace )
1143                     {
1144                         inWhitespace = true;
1145                         lineDup[pos] = 0;
1146                     }
1147                 }
1148                 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1149                 {
1150                     inWhitespace = false;
1151                     places.push_back(pos);
1152                 }
1153                 else
1154                 {
1155                     // consume
1156                 }
1157                 pos++;
1158             }
1159 #ifdef REPLACEARGS_DEBUG
1160             {
1161                 char tmp[256];
1162                 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1163                 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1164             }
1165 #endif // REPLACEARGS_DEBUG
1167             wchar_t** block = new wchar_t*[places.size()];
1168             int i = 0;
1169             for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1170             {
1171                 block[i++] = &lineDup[*it];
1172             }
1173             parsed = block;
1174             numArgs = places.size();
1175         }
1176 #endif // REPLACEARGS_ANSI
1178         if ( parsed )
1179         {
1180             std::vector<wchar_t*>expandedArgs;
1181             if ( numArgs > 0 )
1182             {
1183                 expandedArgs.push_back( parsed[0] );
1184             }
1186             for ( int i1 = 1; i1 < numArgs; i1++ )
1187             {
1188                 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1189                 wildcarded &= parsed[i1][0] != L'"';
1190                 wildcarded &= parsed[i1][0] != L'-';
1191                 if ( wildcarded )
1192                 {
1193 #ifdef REPLACEARGS_ANSI
1194                     WIN32_FIND_DATAA data = {0};
1195 #else
1196                     WIN32_FIND_DATAW data = {0};
1197 #endif // REPLACEARGS_ANSI
1199                     int baseLen = wcslen(parsed[i1]) + 2;
1200                     wchar_t* base = new wchar_t[baseLen];
1201                     wcsncpy( base, parsed[i1], baseLen );
1202                     wchar_t* last = wcsrchr( base, L'\\' );
1203                     if ( last )
1204                     {
1205                         last[1] = 0;
1206                     }
1207                     else
1208                     {
1209                         base[0] = 0;
1210                     }
1211                     baseLen = wcslen( base );
1213 #ifdef REPLACEARGS_ANSI
1214                     char target[MAX_PATH];
1215                     if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1216                     {
1217                         HANDLE hf = FindFirstFileA( target, &data );
1218 #else
1219                         HANDLE hf = FindFirstFileW( parsed[i1], &data );
1220 #endif // REPLACEARGS_ANSI
1221                         if ( hf != INVALID_HANDLE_VALUE )
1222                         {
1223                             BOOL found = TRUE;
1224                             do
1225                             {
1226 #ifdef REPLACEARGS_ANSI
1227                                 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1228                                 if ( howMany > 0 )
1229                                 {
1230                                     howMany += baseLen;
1231                                     wchar_t* tmp = new wchar_t[howMany + 1];
1232                                     wcsncpy( tmp, base, howMany + 1 );
1233                                     MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1234                                     expandedArgs.push_back( tmp );
1235                                     found = FindNextFileA( hf, &data );
1236                                 }
1237 #else
1238                                 int howMany = wcslen(data.cFileName) + baseLen;
1239                                 wchar_t* tmp = new wchar_t[howMany + 1];
1240                                 wcsncpy( tmp, base, howMany + 1 );
1241                                 wcsncat( tmp, data.cFileName, howMany + 1 );
1242                                 expandedArgs.push_back( tmp );
1243                                 found = FindNextFileW( hf, &data );
1244 #endif // REPLACEARGS_ANSI
1245                             } while ( found );
1247                             FindClose( hf );
1248                         }
1249                         else
1250                         {
1251                             expandedArgs.push_back( parsed[i1] );
1252                         }
1253 #ifdef REPLACEARGS_ANSI
1254                     }
1255 #endif // REPLACEARGS_ANSI
1257                     delete[] base;
1258                 }
1259                 else
1260                 {
1261                     expandedArgs.push_back( parsed[i1] );
1262                 }
1263             }
1265             {
1266                 wchar_t** block = new wchar_t*[expandedArgs.size()];
1267                 int iz = 0;
1268                 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1269                 {
1270                     block[iz++] = *it;
1271                 }
1272                 parsed = block;
1273                 numArgs = expandedArgs.size();
1274             }
1276             std::vector<gchar*> newArgs;
1277             for ( int i = 0; i < numArgs; i++ )
1278             {
1279                 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1280                 if ( replacement )
1281                 {
1282 #ifdef REPLACEARGS_DEBUG
1283                     gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1285                     if ( safe2 )
1286                     {
1287                         {
1288                             char tmp[1024];
1289                             snprintf( tmp, sizeof(tmp), "    [%2d] = '%s'", i, safe2 );
1290                             MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1291                         }
1292                         g_free( safe2 );
1293                     }
1294 #endif // REPLACEARGS_DEBUG
1296                     newArgs.push_back( replacement );
1297                 }
1298                 else
1299                 {
1300                     newArgs.push_back( blankParam );
1301                 }
1302             }
1304             // Now push our munged params to be the new argv and argc
1305             {
1306                 char** block = new char*[newArgs.size()];
1307                 int iz = 0;
1308                 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1309                 {
1310                     block[iz++] = *it;
1311                 }
1312                 argv = block;
1313                 argc = newArgs.size();
1314                 worked = true;
1315             }
1316         }
1317 #ifdef REPLACEARGS_DEBUG
1318         else
1319         {
1320             MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1321         }
1322 #endif // REPLACEARGS_DEBUG
1323     }
1324 #ifdef REPLACEARGS_DEBUG
1325     else
1326     {
1327         {
1328             MessageBoxA( NULL,  "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1329         }
1331         char* line2 = GetCommandLineA();
1332         if ( line2 )
1333         {
1334             gchar *safe = Inkscape::IO::sanitizeString(line2);
1335             {
1336                 {
1337                     char tmp[strlen(safe) + 32];
1338                     snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1339                     MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1340                 }
1341             }
1342         }
1343         else
1344         {
1345             MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1346         }
1347     }
1348 #endif // REPLACEARGS_DEBUG
1350     return worked;
1352 #endif // WIN32
1354 static GSList *
1355 sp_process_args(poptContext ctx)
1357     GSList *fl = NULL;
1359     gint a;
1360     while ((a = poptGetNextOpt(ctx)) >= 0) {
1361         switch (a) {
1362             case SP_ARG_FILE: {
1363                 gchar const *fn = poptGetOptArg(ctx);
1364                 if (fn != NULL) {
1365                     fl = g_slist_append(fl, g_strdup(fn));
1366                 }
1367                 break;
1368             }
1369             case SP_ARG_VERSION: {
1370                 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1371                 exit(0);
1372                 break;
1373             }
1374             case SP_ARG_EXTENSIONDIR: {
1375                 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1376                 exit(0);
1377                 break;
1378             }
1379             case SP_ARG_VERB_LIST: {
1380                 // This really shouldn't go here, we should init the app.
1381                 // But, since we're just exiting in this path, there is
1382                 // no harm, and this is really a better place to put
1383                 // everything else.
1384                 Inkscape::Extension::init();
1385                 Inkscape::Verb::list();
1386                 exit(0);
1387                 break;
1388             }
1389             case SP_ARG_VERB:
1390             case SP_ARG_SELECT: {
1391                 gchar const *arg = poptGetOptArg(ctx);
1392                 if (arg != NULL) {
1393                     // printf("Adding in: %s\n", arg);
1394                     new Inkscape::CmdLineAction((a == SP_ARG_VERB), arg);
1395                 }
1396                 break;
1397             }
1398             default: {
1399                 break;
1400             }
1401         }
1402     }
1404     gchar const ** const args = poptGetArgs(ctx);
1405     if (args != NULL) {
1406         for (unsigned i = 0; args[i] != NULL; i++) {
1407             fl = g_slist_append(fl, g_strdup(args[i]));
1408         }
1409     }
1411     return fl;
1415 /*
1416   Local Variables:
1417   mode:c++
1418   c-file-style:"stroustrup"
1419   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1420   indent-tabs-mode:nil
1421   fill-column:99
1422   End:
1423 */
1424 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :