Code

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