Code

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