Code

r14649@tres: ted | 2007-02-28 23:21:44 -0800
[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(&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             }
760             //CmdLineAction::doList(doc);
761         }
763         fl = g_slist_remove(fl, fl->data);
764     }
766     inkscape_unref();
768     return 0;
771 static void
772 do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
774     SPObject *o = NULL;
776     if (id) {
777         o = doc->getObjectById(id);
778         if (o) {
779             if (!SP_IS_ITEM (o)) {
780                 g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
781                 return;
782             }
783         } else {
784             g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
785             return;
786         }
787     } else {
788         o = SP_DOCUMENT_ROOT(doc);
789     }
791     if (o) {
792         sp_document_ensure_up_to_date (doc);
793         SPItem *item = ((SPItem *) o);
794         NR::Rect area = item->invokeBbox(sp_item_i2doc_affine(item)); // "true" SVG bbox for scripting
796         Inkscape::SVGOStringStream os;
797         if (extent) {
798             os << area.extent(axis);
799         } else {
800             os << area.min()[axis];
801         }
802         g_print ("%s", os.str().c_str());
803     }
807 static void
808 sp_do_export_png(SPDocument *doc)
810     const gchar *filename = NULL;
811     gdouble dpi = 0.0;
813     if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
814         g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
815     }
817     GSList *items = NULL;
819     NRRect area;
820     if (sp_export_id || sp_export_area_drawing) {
822         SPObject *o = NULL;
823         SPObject *o_area = NULL;
824         if (sp_export_id && sp_export_area_drawing) {
825             o = doc->getObjectById(sp_export_id);
826             o_area = SP_DOCUMENT_ROOT (doc);
827         } else if (sp_export_id) {
828             o = doc->getObjectById(sp_export_id);
829             o_area = o;
830         } else if (sp_export_area_drawing) {
831             o = SP_DOCUMENT_ROOT (doc);
832             o_area = o;
833         } 
835         if (o) {
836             if (!SP_IS_ITEM (o)) {
837                 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
838                 return;
839             }
841             items = g_slist_prepend (items, SP_ITEM(o));
843             if (sp_export_id_only) {
844                 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
845             }
847             if (sp_export_use_hints) {
849                 // retrieve export filename hint
850                 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
851                 if (fn_hint) {
852                     if (sp_export_png) {
853                         g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
854                         filename = sp_export_png;
855                     } else {
856                         filename = fn_hint;
857                     }
858                 } else {
859                     g_warning ("Export filename hint not found for the object.");
860                     filename = sp_export_png;
861                 }
863                 // retrieve export dpi hints
864                 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
865                 if (dpi_hint) {
866                     if (sp_export_dpi || sp_export_width || sp_export_height) {
867                         g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
868                     } else {
869                         dpi = atof(dpi_hint);
870                     }
871                 } else {
872                     g_warning ("Export DPI hint not found for the object.");
873                 }
875             }
877             // write object bbox to area
878             sp_document_ensure_up_to_date (doc);
879             sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
880         } else {
881             g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
882             return;
883         }
884     }
885     
886     if (sp_export_area) {
887         /* Try to parse area (given in SVG pixels) */
888         if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
889             g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
890             return;
891         }
892         if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
893             g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
894             return;
895         }
896     } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
897         /* Export the whole canvas */
898         sp_document_ensure_up_to_date (doc);
899         area.x0 = SP_ROOT(doc->root)->x.computed;
900         area.y0 = SP_ROOT(doc->root)->y.computed;
901         area.x1 = area.x0 + sp_document_width (doc);
902         area.y1 = area.y0 + sp_document_height (doc);
903     }
905     // set filename and dpi from options, if not yet set from the hints
906     if (!filename) {
907         if (!sp_export_png) {
908             g_warning ("No export filename given and no filename hint. Nothing exported.");
909             return;
910         }
911         filename = sp_export_png;
912     }
914     if (sp_export_dpi && dpi == 0.0) {
915         dpi = atof(sp_export_dpi);
916         if ((dpi < 0.1) || (dpi > 10000.0)) {
917             g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
918             return;
919         }
920         g_print("DPI: %g\n", dpi);
921     }
923     if (sp_export_area_snap) {
924         area.x0 = std::floor (area.x0);
925         area.y0 = std::floor (area.y0);
926         area.x1 = std::ceil (area.x1);
927         area.y1 = std::ceil (area.y1);
928     }
930     // default dpi
931     if (dpi == 0.0)
932         dpi = PX_PER_IN;
934     gint width = 0;
935     gint height = 0;
937     if (sp_export_width) {
938         width = atoi(sp_export_width);
939         if ((width < 1) || (width > 65536)) {
940             g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
941             return;
942         }
943         dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
944     }
946     if (sp_export_height) {
947         height = atoi(sp_export_height);
948         if ((height < 1) || (height > 65536)) {
949             g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
950             return;
951         }
952         dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
953     }
955     if (!sp_export_width) {
956         width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
957     }
959     if (!sp_export_height) {
960         height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
961     }
963     guint32 bgcolor = 0x00000000;
964     if (sp_export_background) {
965         // override the page color
966         bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
967         bgcolor |= 0xff; // default is no opacity
968     } else {
969         // read from namedview
970         Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
971         if (nv && nv->attribute("pagecolor"))
972             bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
973         if (nv && nv->attribute("inkscape:pageopacity"))
974             bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
975     }
977     if (sp_export_background_opacity) {
978         // override opacity
979         gfloat value;
980         if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
981             if (value > 1.0) {
982                 value = CLAMP (value, 1.0f, 255.0f);
983                 bgcolor &= (guint32) 0xffffff00;
984                 bgcolor |= (guint32) floor(value);
985             } else {
986                 value = CLAMP (value, 0.0f, 1.0f);
987                 bgcolor &= (guint32) 0xffffff00;
988                 bgcolor |= SP_COLOR_F_TO_U(value);
989             }
990         }
991     }
993     g_print("Background RRGGBBAA: %08x\n", bgcolor);
995     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);
997     g_print("Bitmap saved as: %s\n", filename);
999     if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
1000         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);
1001     } else {
1002         g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
1003     }
1005     g_slist_free (items);
1009 /**
1010  *  Perform an export of either PS or EPS.
1011  *
1012  *  \param doc Document to export.
1013  *  \param uri URI to export to.
1014  *  \param mime MIME type to export as.
1015  */
1017 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
1019     Inkscape::Extension::DB::OutputList o;
1020     Inkscape::Extension::db.get_output_list(o);
1021     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1022     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1023         i++;
1024     }
1026     if (i == o.end())
1027     {
1028         g_warning ("Could not find an extension to export this file.");
1029         return;
1030     }
1032     bool old_text_to_path = false;
1033     bool old_font_embedded = false;
1034     bool old_bbox_page = false;
1036     try {
1037         old_text_to_path = (*i)->get_param_bool("textToPath");
1038         (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1039     }
1040     catch (...) {
1041         g_warning ("Could not set export-text-to-path option for this export.");
1042     }
1044     try {
1045         old_font_embedded = (*i)->get_param_bool("fontEmbedded");
1046         (*i)->set_param_bool("fontEmbedded", sp_export_font);
1047     }
1048     catch (...) {
1049         g_warning ("Could not set export-font option for this export.");
1050     }
1052     try {
1053         old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1054         (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1055     }
1056     catch (...) {
1057         g_warning ("Could not set export-bbox-page option for this export.");
1058     }
1060     (*i)->save(doc, uri);
1062     try {
1063         (*i)->set_param_bool("textToPath", old_text_to_path);
1064         (*i)->set_param_bool("fontEmbedded", old_font_embedded);
1065         (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1066     }
1067     catch (...) {
1069     }
1072 /**
1073  *  Perform a PDF export
1074  *
1075  *  \param doc Document to export.
1076  *  \param uri URI to export to.
1077  *  \param mime MIME type to export as.
1078  */
1080 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
1082     Inkscape::Extension::DB::OutputList o;
1083     Inkscape::Extension::db.get_output_list(o);
1084     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1085     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1086         i++;
1087     }
1089     if (i == o.end())
1090     {
1091         g_warning ("Could not find an extension to export this file.");
1092         return;
1093     }
1095     (*i)->save(doc, uri);
1098 #ifdef WIN32
1099 bool replaceArgs( int& argc, char**& argv )
1101     bool worked = false;
1103 #ifdef REPLACEARGS_DEBUG
1104     MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1105 #endif // REPLACEARGS_DEBUG
1107     wchar_t* line = GetCommandLineW();
1108     if ( line )
1109     {
1110 #ifdef REPLACEARGS_DEBUG
1111         {
1112             gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1113             if ( utf8Line )
1114             {
1115                 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1116                 {
1117                     char tmp[strlen(safe) + 32];
1118                     snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1119                     MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1120                 }
1121             }
1122         }
1123 #endif // REPLACEARGS_DEBUG
1125         int numArgs = 0;
1126         wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1128 #ifdef REPLACEARGS_ANSI
1129 // test code for trying things on Win95/98/ME
1130         if ( !parsed )
1131         {
1132 #ifdef REPLACEARGS_DEBUG
1133             MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1134 #endif // REPLACEARGS_DEBUG
1135             int lineLen = wcslen(line) + 1;
1136             wchar_t* lineDup = new wchar_t[lineLen];
1137             wcsncpy( lineDup, line, lineLen );
1139             int pos = 0;
1140             bool inQuotes = false;
1141             bool inWhitespace = true;
1142             std::vector<int> places;
1143             while ( lineDup[pos] )
1144             {
1145                 if ( inQuotes )
1146                 {
1147                     if ( lineDup[pos] == L'"' )
1148                     {
1149                         inQuotes = false;
1150                     }
1151                 }
1152                 else if ( lineDup[pos] == L'"' )
1153                 {
1154                     inQuotes = true;
1155                     inWhitespace = false;
1156                     places.push_back(pos);
1157                 }
1158                 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1159                 {
1160                     if ( !inWhitespace )
1161                     {
1162                         inWhitespace = true;
1163                         lineDup[pos] = 0;
1164                     }
1165                 }
1166                 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1167                 {
1168                     inWhitespace = false;
1169                     places.push_back(pos);
1170                 }
1171                 else
1172                 {
1173                     // consume
1174                 }
1175                 pos++;
1176             }
1177 #ifdef REPLACEARGS_DEBUG
1178             {
1179                 char tmp[256];
1180                 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1181                 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1182             }
1183 #endif // REPLACEARGS_DEBUG
1185             wchar_t** block = new wchar_t*[places.size()];
1186             int i = 0;
1187             for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1188             {
1189                 block[i++] = &lineDup[*it];
1190             }
1191             parsed = block;
1192             numArgs = places.size();
1193         }
1194 #endif // REPLACEARGS_ANSI
1196         if ( parsed )
1197         {
1198             std::vector<wchar_t*>expandedArgs;
1199             if ( numArgs > 0 )
1200             {
1201                 expandedArgs.push_back( parsed[0] );
1202             }
1204             for ( int i1 = 1; i1 < numArgs; i1++ )
1205             {
1206                 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1207                 wildcarded &= parsed[i1][0] != L'"';
1208                 wildcarded &= parsed[i1][0] != L'-';
1209                 if ( wildcarded )
1210                 {
1211 #ifdef REPLACEARGS_ANSI
1212                     WIN32_FIND_DATAA data = {0};
1213 #else
1214                     WIN32_FIND_DATAW data = {0};
1215 #endif // REPLACEARGS_ANSI
1217                     int baseLen = wcslen(parsed[i1]) + 2;
1218                     wchar_t* base = new wchar_t[baseLen];
1219                     wcsncpy( base, parsed[i1], baseLen );
1220                     wchar_t* last = wcsrchr( base, L'\\' );
1221                     if ( last )
1222                     {
1223                         last[1] = 0;
1224                     }
1225                     else
1226                     {
1227                         base[0] = 0;
1228                     }
1229                     baseLen = wcslen( base );
1231 #ifdef REPLACEARGS_ANSI
1232                     char target[MAX_PATH];
1233                     if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1234                     {
1235                         HANDLE hf = FindFirstFileA( target, &data );
1236 #else
1237                         HANDLE hf = FindFirstFileW( parsed[i1], &data );
1238 #endif // REPLACEARGS_ANSI
1239                         if ( hf != INVALID_HANDLE_VALUE )
1240                         {
1241                             BOOL found = TRUE;
1242                             do
1243                             {
1244 #ifdef REPLACEARGS_ANSI
1245                                 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1246                                 if ( howMany > 0 )
1247                                 {
1248                                     howMany += baseLen;
1249                                     wchar_t* tmp = new wchar_t[howMany + 1];
1250                                     wcsncpy( tmp, base, howMany + 1 );
1251                                     MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1252                                     expandedArgs.push_back( tmp );
1253                                     found = FindNextFileA( hf, &data );
1254                                 }
1255 #else
1256                                 int howMany = wcslen(data.cFileName) + baseLen;
1257                                 wchar_t* tmp = new wchar_t[howMany + 1];
1258                                 wcsncpy( tmp, base, howMany + 1 );
1259                                 wcsncat( tmp, data.cFileName, howMany + 1 );
1260                                 expandedArgs.push_back( tmp );
1261                                 found = FindNextFileW( hf, &data );
1262 #endif // REPLACEARGS_ANSI
1263                             } while ( found );
1265                             FindClose( hf );
1266                         }
1267                         else
1268                         {
1269                             expandedArgs.push_back( parsed[i1] );
1270                         }
1271 #ifdef REPLACEARGS_ANSI
1272                     }
1273 #endif // REPLACEARGS_ANSI
1275                     delete[] base;
1276                 }
1277                 else
1278                 {
1279                     expandedArgs.push_back( parsed[i1] );
1280                 }
1281             }
1283             {
1284                 wchar_t** block = new wchar_t*[expandedArgs.size()];
1285                 int iz = 0;
1286                 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1287                 {
1288                     block[iz++] = *it;
1289                 }
1290                 parsed = block;
1291                 numArgs = expandedArgs.size();
1292             }
1294             std::vector<gchar*> newArgs;
1295             for ( int i = 0; i < numArgs; i++ )
1296             {
1297                 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1298                 if ( replacement )
1299                 {
1300 #ifdef REPLACEARGS_DEBUG
1301                     gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1303                     if ( safe2 )
1304                     {
1305                         {
1306                             char tmp[1024];
1307                             snprintf( tmp, sizeof(tmp), "    [%2d] = '%s'", i, safe2 );
1308                             MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1309                         }
1310                         g_free( safe2 );
1311                     }
1312 #endif // REPLACEARGS_DEBUG
1314                     newArgs.push_back( replacement );
1315                 }
1316                 else
1317                 {
1318                     newArgs.push_back( blankParam );
1319                 }
1320             }
1322             // Now push our munged params to be the new argv and argc
1323             {
1324                 char** block = new char*[newArgs.size()];
1325                 int iz = 0;
1326                 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1327                 {
1328                     block[iz++] = *it;
1329                 }
1330                 argv = block;
1331                 argc = newArgs.size();
1332                 worked = true;
1333             }
1334         }
1335 #ifdef REPLACEARGS_DEBUG
1336         else
1337         {
1338             MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1339         }
1340 #endif // REPLACEARGS_DEBUG
1341     }
1342 #ifdef REPLACEARGS_DEBUG
1343     else
1344     {
1345         {
1346             MessageBoxA( NULL,  "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1347         }
1349         char* line2 = GetCommandLineA();
1350         if ( line2 )
1351         {
1352             gchar *safe = Inkscape::IO::sanitizeString(line2);
1353             {
1354                 {
1355                     char tmp[strlen(safe) + 32];
1356                     snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1357                     MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1358                 }
1359             }
1360         }
1361         else
1362         {
1363             MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1364         }
1365     }
1366 #endif // REPLACEARGS_DEBUG
1368     return worked;
1370 #endif // WIN32
1372 static GSList *
1373 sp_process_args(poptContext ctx)
1375     GSList *fl = NULL;
1377     gint a;
1378     while ((a = poptGetNextOpt(ctx)) >= 0) {
1379         switch (a) {
1380             case SP_ARG_FILE: {
1381                 gchar const *fn = poptGetOptArg(ctx);
1382                 if (fn != NULL) {
1383                     fl = g_slist_append(fl, g_strdup(fn));
1384                 }
1385                 break;
1386             }
1387             case SP_ARG_VERSION: {
1388                 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1389                 exit(0);
1390                 break;
1391             }
1392             case SP_ARG_EXTENSIONDIR: {
1393                 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1394                 exit(0);
1395                 break;
1396             }
1397             case SP_ARG_VERB_LIST: {
1398                 // This really shouldn't go here, we should init the app.
1399                 // But, since we're just exiting in this path, there is
1400                 // no harm, and this is really a better place to put
1401                 // everything else.
1402                 Inkscape::Extension::init();
1403                 Inkscape::Verb::list();
1404                 exit(0);
1405                 break;
1406             }
1407             case SP_ARG_VERB:
1408             case SP_ARG_SELECT: {
1409                 gchar const *arg = poptGetOptArg(ctx);
1410                 if (arg != NULL) {
1411                     // printf("Adding in: %s\n", arg);
1412                     new CmdLineAction(a, arg);
1413                 }
1414                 break;
1415             }
1416             default: {
1417                 break;
1418             }
1419         }
1420     }
1422     gchar const ** const args = poptGetArgs(ctx);
1423     if (args != NULL) {
1424         for (unsigned i = 0; args[i] != NULL; i++) {
1425             fl = g_slist_append(fl, g_strdup(args[i]));
1426         }
1427     }
1429     return fl;
1433 /*
1434   Local Variables:
1435   mode:c++
1436   c-file-style:"stroustrup"
1437   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1438   indent-tabs-mode:nil
1439   fill-column:99
1440   End:
1441 */
1442 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :