Code

Fix RegisteredWidgets. Due to rev 16265, widgets were no longer initialized. This...
[inkscape.git] / src / main.cpp
1 #define __MAIN_C__
3 /** \file
4  * Inkscape - an ambitious vector drawing program
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *   Frank Felfe <innerspace@iname.com>
9  *   Davide Puricelli <evo@debian.org>
10  *   Mitsuru Oka <oka326@parkcity.ne.jp>
11  *   Masatake YAMATO  <jet@gyve.org>
12  *   F.J.Franklin <F.J.Franklin@sheffield.ac.uk>
13  *   Michael Meeks <michael@helixcode.com>
14  *   Chema Celorio <chema@celorio.com>
15  *   Pawel Palucha
16  *   Bryce Harrington <bryce@bryceharrington.com>
17  * ... and various people who have worked with various projects
18  *
19  * Copyright (C) 1999-2004 authors
20  * Copyright (C) 2001-2002 Ximian, Inc.
21  *
22  * Released under GNU GPL, read the file 'COPYING' for more information
23  */
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29 #include "path-prefix.h"
31 #include <gtk/gtkmessagedialog.h>
33 #ifdef HAVE_IEEEFP_H
34 #include <ieeefp.h>
35 #endif
36 #include <string.h>
37 #include <locale.h>
39 #include <popt.h>
40 #ifndef POPT_TABLEEND
41 #define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
42 #endif /* Not def: POPT_TABLEEND */
44 #include <libxml/tree.h>
45 #include <glib-object.h>
46 #include <gtk/gtkmain.h>
47 #include <gtk/gtksignal.h>
48 #include <gtk/gtkwindow.h>
49 #include <gtk/gtkbox.h>
51 #include "gc-core.h"
53 #include "macros.h"
54 #include "file.h"
55 #include "document.h"
56 #include "sp-object.h"
57 #include "interface.h"
58 #include "print.h"
59 #include "color.h"
60 #include "sp-item.h"
61 #include "sp-root.h"
62 #include "unit-constants.h"
64 #include "svg/svg.h"
65 #include "svg/svg-color.h"
66 #include "svg/stringstream.h"
68 #include "inkscape-private.h"
69 #include "inkscape-stock.h"
70 #include "inkscape_version.h"
72 #include "sp-namedview.h"
73 #include "sp-guide.h"
74 #include "sp-object-repr.h"
75 #include "xml/repr.h"
77 #include "io/sys.h"
79 #include "debug/logger.h"
80 #include "debug/log-display-config.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 #ifdef WIN32
137     SP_ARG_EXPORT_EMF,
138 #endif //WIN32
139     SP_ARG_EXPORT_TEXT_TO_PATH,
140     SP_ARG_EXPORT_FONT,
141     SP_ARG_EXPORT_BBOX_PAGE,
142     SP_ARG_EXTENSIONDIR,
143     SP_ARG_FIT_PAGE_TO_DRAWING,
144     SP_ARG_QUERY_X,
145     SP_ARG_QUERY_Y,
146     SP_ARG_QUERY_WIDTH,
147     SP_ARG_QUERY_HEIGHT,
148     SP_ARG_QUERY_ID,
149     SP_ARG_VERSION,
150     SP_ARG_VACUUM_DEFS,
151     SP_ARG_VERB_LIST,
152     SP_ARG_VERB,
153     SP_ARG_SELECT,
154     SP_ARG_LAST
155 };
157 int sp_main_gui(int argc, char const **argv);
158 int sp_main_console(int argc, char const **argv);
159 static void sp_do_export_png(SPDocument *doc);
160 static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
161 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const *mime);
162 #ifdef WIN32
163 static void do_export_emf(SPDocument* doc, gchar const* uri, char const *mime);
164 #endif //WIN32
165 static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
168 static gchar *sp_global_printer = NULL;
169 static gchar *sp_export_png = NULL;
170 static gchar *sp_export_dpi = NULL;
171 static gchar *sp_export_area = NULL;
172 static gboolean sp_export_area_drawing = FALSE;
173 static gboolean sp_export_area_canvas = FALSE;
174 static gchar *sp_export_width = NULL;
175 static gchar *sp_export_height = NULL;
176 static gchar *sp_export_id = NULL;
177 static gchar *sp_export_background = NULL;
178 static gchar *sp_export_background_opacity = NULL;
179 static gboolean sp_export_area_snap = FALSE;
180 static gboolean sp_export_use_hints = FALSE;
181 static gboolean sp_export_id_only = FALSE;
182 static gchar *sp_export_svg = NULL;
183 static gchar *sp_export_ps = NULL;
184 static gchar *sp_export_eps = NULL;
185 static gchar *sp_export_pdf = NULL;
186 #ifdef WIN32
187 static gchar *sp_export_emf = NULL;
188 #endif //WIN32
189 static gboolean sp_export_text_to_path = FALSE;
190 static gboolean sp_export_font = FALSE;
191 static gboolean sp_export_bbox_page = FALSE;
192 static gboolean sp_query_x = FALSE;
193 static gboolean sp_query_y = FALSE;
194 static gboolean sp_query_width = FALSE;
195 static gboolean sp_query_height = FALSE;
196 static gchar *sp_query_id = NULL;
197 static int sp_new_gui = FALSE;
198 static gboolean sp_vacuum_defs = FALSE;
200 static gchar *sp_export_png_utf8 = NULL;
201 static gchar *sp_export_svg_utf8 = NULL;
202 static gchar *sp_global_printer_utf8 = NULL;
204 #ifdef WIN32
205 static bool replaceArgs( int& argc, char**& argv );
206 #endif
207 static GSList *sp_process_args(poptContext ctx);
208 struct poptOption options[] = {
209     {"version", 'V',
210      POPT_ARG_NONE, NULL, SP_ARG_VERSION,
211      N_("Print the Inkscape version number"),
212      NULL},
214     {"without-gui", 'z',
215      POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
216      N_("Do not use X server (only process files from console)"),
217      NULL},
219     {"with-gui", 'g',
220      POPT_ARG_NONE, NULL, SP_ARG_GUI,
221      N_("Try to use X server (even if $DISPLAY is not set)"),
222      NULL},
224     {"file", 'f',
225      POPT_ARG_STRING, NULL, SP_ARG_FILE,
226      N_("Open specified document(s) (option string may be excluded)"),
227      N_("FILENAME")},
229     {"print", 'p',
230      POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
231      N_("Print document(s) to specified output file (use '| program' for pipe)"),
232      N_("FILENAME")},
234     {"export-png", 'e',
235      POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
236      N_("Export document to a PNG file"),
237      N_("FILENAME")},
239     {"export-dpi", 'd',
240      POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
241      N_("The resolution used for exporting SVG into bitmap (default 90)"),
242      N_("DPI")},
244     {"export-area", 'a',
245      POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
246      N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
247      N_("x0:y0:x1:y1")},
249     {"export-area-drawing", 'D',
250      POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
251      N_("Exported area is the entire drawing (not canvas)"),
252      NULL},
254     {"export-area-canvas", 'C',
255      POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
256      N_("Exported area is the entire canvas"),
257      NULL},
259     {"export-area-snap", 0,
260      POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
261      N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
262      NULL},
264     {"export-width", 'w',
265      POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
266      N_("The width of exported bitmap in pixels (overrides export-dpi)"),
267      N_("WIDTH")},
269     {"export-height", 'h',
270      POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
271      N_("The height of exported bitmap in pixels (overrides export-dpi)"),
272      N_("HEIGHT")},
274     {"export-id", 'i',
275      POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
276      N_("The ID of the object to export"),
277      N_("ID")},
279     {"export-id-only", 'j',
280      POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
281      // TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
282      //  See "man inkscape" for details.
283      N_("Export just the object with export-id, hide all others (only with export-id)"),
284      NULL},
286     {"export-use-hints", 't',
287      POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
288      N_("Use stored filename and DPI hints when exporting (only with export-id)"),
289      NULL},
291     {"export-background", 'b',
292      POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
293      N_("Background color of exported bitmap (any SVG-supported color string)"),
294      N_("COLOR")},
296     {"export-background-opacity", 'y',
297      POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
298      N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"),
299      N_("VALUE")},
301     {"export-plain-svg", 'l',
302      POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
303      N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"),
304      N_("FILENAME")},
306     {"export-ps", 'P',
307      POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
308      N_("Export document to a PS file"),
309      N_("FILENAME")},
311     {"export-eps", 'E',
312      POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
313      N_("Export document to an EPS file"),
314      N_("FILENAME")},
316     {"export-pdf", 'A',
317      POPT_ARG_STRING, &sp_export_pdf, SP_ARG_EXPORT_PDF,
318      N_("Export document to a PDF file"),
319      N_("FILENAME")},
321 #ifdef WIN32
322     {"export-emf", 'M',
323      POPT_ARG_STRING, &sp_export_emf, SP_ARG_EXPORT_EMF,
324      N_("Export document to an Enhanced Metafile (EMF) File"),
325      N_("FILENAME")},
326 #endif //WIN32
328     {"export-text-to-path", 'T',
329      POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
330      N_("Convert text object to paths on export (EPS)"),
331      NULL},
333     {"export-embed-fonts", 'F',
334      POPT_ARG_NONE, &sp_export_font, SP_ARG_EXPORT_FONT,
335      N_("Embed fonts on export (Type 1 only) (EPS)"),
336      NULL},
338     {"export-bbox-page", 'B',
339      POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
340      N_("Export files with the bounding box set to the page size (EPS)"),
341      NULL},
343     {"query-x", 'X',
344      POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
345      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
346      N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
347      NULL},
349     {"query-y", 'Y',
350      POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
351      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
352      N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
353      NULL},
355     {"query-width", 'W',
356      POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
357      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
358      N_("Query the width of the drawing or, if specified, of the object with --query-id"),
359      NULL},
361     {"query-height", 'H',
362      POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
363      // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
364      N_("Query the height of the drawing or, if specified, of the object with --query-id"),
365      NULL},
367     {"query-id", 'I',
368      POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
369      N_("The ID of the object whose dimensions are queried"),
370      N_("ID")},
372     {"extension-directory", 'x',
373      POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
374      // TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
375      N_("Print out the extension directory and exit"),
376      NULL},
378     {"vacuum-defs", 0,
379      POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
380      N_("Remove unused definitions from the defs section(s) of the document"),
381      NULL},
383     {"verb-list", 0,
384      POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
385      N_("List the IDs of all the verbs in Inkscape"),
386      NULL},
388     {"verb", 0,
389      POPT_ARG_STRING, NULL, SP_ARG_VERB,
390      N_("Verb to call when Inkscape opens."),
391      N_("VERB-ID")},
393     {"select", 0,
394      POPT_ARG_STRING, NULL, SP_ARG_SELECT,
395      N_("Object ID to select when Inkscape opens."),
396      N_("OBJECT-ID")},
398     POPT_AUTOHELP POPT_TABLEEND
399 };
401 static bool needToRecodeParams = true;
402 gchar* blankParam = "";
404 int
405 main(int argc, char **argv)
407 #ifdef HAVE_FPSETMASK
408     /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__.  It's probably
409        safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
410        the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
411     fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
412 #endif
414 #ifdef ENABLE_NLS
415 #ifdef WIN32
416     RegistryTool rt;
417     rt.setPathInfo();
418     gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
419     bindtextdomain(GETTEXT_PACKAGE, pathBuf);
420     g_free(pathBuf);
421 #else
422 #ifdef ENABLE_BINRELOC
423     bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
424 #else
425     bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
426 #endif
427 #endif
428     // Allow the user to override the locale directory by setting 
429     // the environment variable INKSCAPE_LOCALEDIR.
430     char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
431     if (inkscape_localedir != NULL) {
432         bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
433     }
434 #endif
436     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
438 #ifdef ENABLE_NLS
439     textdomain(GETTEXT_PACKAGE);
440 #endif
442     LIBXML_TEST_VERSION
444     Inkscape::GC::init();
446     Inkscape::Debug::Logger::init();
448     gboolean use_gui;
449 #ifndef WIN32
450     use_gui = (getenv("DISPLAY") != NULL);
451 #else
452     /*
453       Set the current directory to the directory of the
454       executable.  This seems redundant, but is needed for
455       when inkscape.exe is executed from another directory.
456       We use relative paths on win32.
457       HKCR\svgfile\shell\open\command is a good example
458     */
459     /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
460     char *homedir = g_path_get_dirname(argv[0]);
461     SetCurrentDirectory(homedir);
462     g_free(homedir);
464     use_gui = TRUE;
465 #endif
466     /* Test whether with/without GUI is forced */
467     for (int i = 1; i < argc; i++) {
468         if (!strcmp(argv[i], "-z")
469             || !strcmp(argv[i], "--without-gui")
470             || !strcmp(argv[i], "-p")
471             || !strncmp(argv[i], "--print", 7)
472             || !strcmp(argv[i], "-e")
473             || !strncmp(argv[i], "--export-png", 12)
474             || !strcmp(argv[i], "-l")
475             || !strncmp(argv[i], "--export-plain-svg", 12)
476             || !strcmp(argv[i], "-i")
477             || !strncmp(argv[i], "--export-area-drawing", 21)
478             || !strcmp(argv[i], "-D")
479             || !strncmp(argv[i], "--export-area-canvas", 20)
480             || !strcmp(argv[i], "-C")
481             || !strncmp(argv[i], "--export-id", 12)
482             || !strcmp(argv[i], "-P")
483             || !strncmp(argv[i], "--export-ps", 11)
484             || !strcmp(argv[i], "-E")
485             || !strncmp(argv[i], "--export-eps", 12)
486             || !strcmp(argv[i], "-A")
487             || !strncmp(argv[i], "--export-pdf", 12)
488 #ifdef WIN32
489             || !strcmp(argv[i], "-M")
490             || !strncmp(argv[i], "--export-emf", 12)
491 #endif //WIN32
492             || !strcmp(argv[i], "-W")
493             || !strncmp(argv[i], "--query-width", 13)
494             || !strcmp(argv[i], "-H")
495             || !strncmp(argv[i], "--query-height", 14)
496             || !strcmp(argv[i], "-X")
497             || !strncmp(argv[i], "--query-x", 13)
498             || !strcmp(argv[i], "-Y")
499             || !strncmp(argv[i], "--query-y", 14)
500             || !strcmp(argv[i], "--vacuum-defs")
501            )
502         {
503             /* main_console handles any exports -- not the gui */
504             use_gui = FALSE;
505             break;
506         } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
507             use_gui = TRUE;
508             break;
509         }
510     }
512 #ifdef WIN32
513 #ifndef REPLACEARGS_ANSI
514     if ( PrintWin32::is_os_wide() )
515 #endif // REPLACEARGS_ANSI
516     {
517         // If the call fails, we'll need to convert charsets
518         needToRecodeParams = !replaceArgs( argc, argv );
519     }
520 #endif // WIN32
522     /// \todo  Should this be a static object (see inkscape.cpp)?
523     Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
525     return app.run();
528 void fixupSingleFilename( gchar **orig, gchar **spare )
530     if ( orig && *orig && **orig ) {
531         GError *error = NULL;
532         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
533         if ( newFileName )
534         {
535             *orig = newFileName;
536             if ( spare ) {
537                 *spare = newFileName;
538             }
539 //             g_message("Set a replacement fixup");
540         }
541     }
544 GSList *fixupFilenameEncoding( GSList* fl )
546     GSList *newFl = NULL;
547     while ( fl ) {
548         gchar *fn = static_cast<gchar*>(fl->data);
549         fl = g_slist_remove( fl, fl->data );
550         gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
551         if ( newFileName ) {
553             if ( 0 )
554             {
555                 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
556                 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
557                 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
558                                                        "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
559                 gtk_dialog_run (GTK_DIALOG (w));
560                 gtk_widget_destroy (w);
561                 g_free(safeNewFn);
562                 g_free(safeFn);
563             }
565             g_free( fn );
566             fn = newFileName;
567             newFileName = 0;
568         }
569         else
570             if ( 0 )
571         {
572             gchar *safeFn = Inkscape::IO::sanitizeString(fn);
573             GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
574             gtk_dialog_run (GTK_DIALOG (w));
575             gtk_widget_destroy (w);
576             g_free(safeFn);
577         }
578         newFl = g_slist_append( newFl, fn );
579     }
580     return newFl;
583 int sp_common_main( int argc, char const **argv, GSList **flDest )
585     /// \todo fixme: Move these to some centralized location (Lauris)
586     sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
587     sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
590     // temporarily switch gettext encoding to locale, so that help messages can be output properly
591     gchar const *charset;
592     g_get_charset(&charset);
594     bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
596     poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
597     poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
598     g_return_val_if_fail(ctx != NULL, 1);
600     /* Collect own arguments */
601     GSList *fl = sp_process_args(ctx);
602     poptFreeContext(ctx);
604     // now switch gettext back to UTF-8 (for GUI)
605     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
607     // Now let's see if the file list still holds up
608     if ( needToRecodeParams )
609     {
610         fl = fixupFilenameEncoding( fl );
611     }
613     // Check the globals for filename-fixup
614     if ( needToRecodeParams )
615     {
616         fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
617         fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
618         fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
619     }
620     else
621     {
622         if ( sp_export_png )
623             sp_export_png_utf8 = g_strdup( sp_export_png );
624         if ( sp_export_svg )
625             sp_export_svg_utf8 = g_strdup( sp_export_svg );
626         if ( sp_global_printer )
627             sp_global_printer_utf8 = g_strdup( sp_global_printer );
628     }
630     // Return the list if wanted, else free it up.
631     if ( flDest ) {
632         *flDest = fl;
633         fl = 0;
634     } else {
635         while ( fl ) {
636             g_free( fl->data );
637             fl = g_slist_remove( fl, fl->data );
638         }
639     }
640     return 0;
643 static void
644 snooper(GdkEvent *event, gpointer data) { 
645     if(inkscape_mapalt())  /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
646     {
647         GdkModifierType mapping=(GdkModifierType)inkscape_mapalt();
648         switch (event->type) {
649             case GDK_MOTION_NOTIFY:
650                 if(event->motion.state & mapping) {
651                     event->motion.state|=GDK_MOD1_MASK;
652                 }
653                 break;       
654             case GDK_BUTTON_PRESS:
655                 if(event->button.state & mapping) {
656                     event->button.state|=GDK_MOD1_MASK;
657                 }
658                 break;       
659              case GDK_KEY_PRESS:
660                  if(event->key.state & mapping) {
661                      event->key.state|=GDK_MOD1_MASK;
662                  }
663                  break;                
664         default:
665             break;
666         }
667     }
668     gtk_main_do_event (event);
671 int
672 sp_main_gui(int argc, char const **argv)
674     Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
676     GSList *fl = NULL;
677     int retVal = sp_common_main( argc, argv, &fl );
678     g_return_val_if_fail(retVal == 0, 1);
680     inkscape_gtk_stock_init();
682     gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
684     Inkscape::Debug::log_display_config();
686     /* Set default icon */
687     gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
688     if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
689         gtk_window_set_default_icon_from_file(filename, NULL);
690     }
691     g_free (filename);
692     filename = 0;
694     gboolean create_new = TRUE;
696     /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
697     inkscape_application_init(argv[0], true);
699     while (fl) {
700         if (sp_file_open((gchar *)fl->data,NULL)) {
701             create_new=FALSE;
702         }
703         fl = g_slist_remove(fl, fl->data);
704     }
705     if (create_new) {
706         sp_file_new_default();
707     }
709     Glib::signal_idle().connect(sigc::ptr_fun(&Inkscape::CmdLineAction::idle));
710     main_instance.run();
712 #ifdef WIN32
713     //We might not need anything here
714     //sp_win32_finish(); <-- this is a NOP func
715 #endif
717     return 0;
720 int
721 sp_main_console(int argc, char const **argv)
723     /* We are started in text mode */
725     /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
726      * in a non-Gtk environment.  Used in libnrtype's
727      * FontInstance.cpp and FontFactory.cpp.
728      * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
729      */
730     g_type_init();
731     char **argv2 = const_cast<char **>(argv);
732     gtk_init_check( &argc, &argv2 );
733     //setlocale(LC_ALL, "");
735     GSList *fl = NULL;
736     int retVal = sp_common_main( argc, argv, &fl );
737     g_return_val_if_fail(retVal == 0, 1);
739     if (fl == NULL) {
740         g_print("Nothing to do!\n");
741         exit(0);
742     }
744     inkscape_application_init(argv[0], false);
746     while (fl) {
747         SPDocument *doc;
749         doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
750         if (doc == NULL) {
751             doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
752         }
753         if (doc == NULL) {
754             g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
755         } else {
756             if (sp_vacuum_defs) {
757                 vacuum_document(doc);
758             }
759             if (sp_vacuum_defs && !sp_export_svg) {
760                 // save under the name given in the command line
761                 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
762             }
763             if (sp_global_printer) {
764                 sp_print_document_to_file(doc, sp_global_printer);
765             }
766             if (sp_export_png || sp_export_id || sp_export_area_drawing) {
767                 sp_do_export_png(doc);
768             }
769             if (sp_export_svg) {
770                 Inkscape::XML::Document *rdoc;
771                 Inkscape::XML::Node *repr;
772                 rdoc = sp_repr_document_new("svg:svg");
773                 repr = rdoc->root();
774                 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
775                 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
776             }
777             if (sp_export_ps) {
778                 do_export_ps(doc, sp_export_ps, "image/x-postscript");
779             }
780             if (sp_export_eps) {
781                 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
782             }
783             if (sp_export_pdf) {
784                 do_export_pdf(doc, sp_export_pdf, "application/pdf");
785             }
786 #ifdef WIN32
787             if (sp_export_emf) {
788                 do_export_emf(doc, sp_export_emf, "image/x-emf");
789             }
790 #endif //WIN32
791             if (sp_query_width || sp_query_height) {
792                 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
793             } else if (sp_query_x || sp_query_y) {
794                 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
795             }
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);
830         // "true" SVG bbox for scripting
831         NR::Maybe<NR::Rect> area = item->getBounds(sp_item_i2doc_affine(item));
832         if (area) {
833             Inkscape::SVGOStringStream os;
834             if (extent) {
835                 os << area->extent(axis);
836             } else {
837                 os << area->min()[axis];
838             }
839             g_print ("%s", os.str().c_str());
840         } else {
841             g_print("0");
842         }
843     }
847 static void
848 sp_do_export_png(SPDocument *doc)
850     const gchar *filename = NULL;
851     gdouble dpi = 0.0;
853     if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
854         g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
855     }
857     GSList *items = NULL;
859     NRRect area;
860     if (sp_export_id || sp_export_area_drawing) {
862         SPObject *o = NULL;
863         SPObject *o_area = NULL;
864         if (sp_export_id && sp_export_area_drawing) {
865             o = doc->getObjectById(sp_export_id);
866             o_area = SP_DOCUMENT_ROOT (doc);
867         } else if (sp_export_id) {
868             o = doc->getObjectById(sp_export_id);
869             o_area = o;
870         } else if (sp_export_area_drawing) {
871             o = SP_DOCUMENT_ROOT (doc);
872             o_area = o;
873         } 
875         if (o) {
876             if (!SP_IS_ITEM (o)) {
877                 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
878                 return;
879             }
881             items = g_slist_prepend (items, SP_ITEM(o));
883             if (sp_export_id_only) {
884                 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
885             }
887             if (sp_export_use_hints) {
889                 // retrieve export filename hint
890                 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
891                 if (fn_hint) {
892                     if (sp_export_png) {
893                         g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
894                         filename = sp_export_png;
895                     } else {
896                         filename = fn_hint;
897                     }
898                 } else {
899                     g_warning ("Export filename hint not found for the object.");
900                     filename = sp_export_png;
901                 }
903                 // retrieve export dpi hints
904                 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
905                 if (dpi_hint) {
906                     if (sp_export_dpi || sp_export_width || sp_export_height) {
907                         g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
908                     } else {
909                         dpi = atof(dpi_hint);
910                     }
911                 } else {
912                     g_warning ("Export DPI hint not found for the object.");
913                 }
915             }
917             // write object bbox to area
918             sp_document_ensure_up_to_date (doc);
919             sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
920         } else {
921             g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
922             return;
923         }
924     }
925     
926     if (sp_export_area) {
927         /* Try to parse area (given in SVG pixels) */
928         if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
929             g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
930             return;
931         }
932         if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
933             g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
934             return;
935         }
936     } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
937         /* Export the whole canvas */
938         sp_document_ensure_up_to_date (doc);
939         area.x0 = SP_ROOT(doc->root)->x.computed;
940         area.y0 = SP_ROOT(doc->root)->y.computed;
941         area.x1 = area.x0 + sp_document_width (doc);
942         area.y1 = area.y0 + sp_document_height (doc);
943     }
945     // set filename and dpi from options, if not yet set from the hints
946     if (!filename) {
947         if (!sp_export_png) {
948             g_warning ("No export filename given and no filename hint. Nothing exported.");
949             return;
950         }
951         filename = sp_export_png;
952     }
954     if (sp_export_dpi && dpi == 0.0) {
955         dpi = atof(sp_export_dpi);
956         if ((dpi < 0.1) || (dpi > 10000.0)) {
957             g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
958             return;
959         }
960         g_print("DPI: %g\n", dpi);
961     }
963     if (sp_export_area_snap) {
964         area.x0 = std::floor (area.x0);
965         area.y0 = std::floor (area.y0);
966         area.x1 = std::ceil (area.x1);
967         area.y1 = std::ceil (area.y1);
968     }
970     // default dpi
971     if (dpi == 0.0)
972         dpi = PX_PER_IN;
974     gint width = 0;
975     gint height = 0;
977     if (sp_export_width) {
978         width = atoi(sp_export_width);
979         if ((width < 1) || (width > 65536)) {
980             g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
981             return;
982         }
983         dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
984     }
986     if (sp_export_height) {
987         height = atoi(sp_export_height);
988         if ((height < 1) || (height > 65536)) {
989             g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
990             return;
991         }
992         dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
993     }
995     if (!sp_export_width) {
996         width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
997     }
999     if (!sp_export_height) {
1000         height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
1001     }
1003     guint32 bgcolor = 0x00000000;
1004     if (sp_export_background) {
1005         // override the page color
1006         bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
1007         bgcolor |= 0xff; // default is no opacity
1008     } else {
1009         // read from namedview
1010         Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
1011         if (nv && nv->attribute("pagecolor"))
1012             bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
1013         if (nv && nv->attribute("inkscape:pageopacity"))
1014             bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
1015     }
1017     if (sp_export_background_opacity) {
1018         // override opacity
1019         gfloat value;
1020         if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
1021             if (value > 1.0) {
1022                 value = CLAMP (value, 1.0f, 255.0f);
1023                 bgcolor &= (guint32) 0xffffff00;
1024                 bgcolor |= (guint32) floor(value);
1025             } else {
1026                 value = CLAMP (value, 0.0f, 1.0f);
1027                 bgcolor &= (guint32) 0xffffff00;
1028                 bgcolor |= SP_COLOR_F_TO_U(value);
1029             }
1030         }
1031     }
1033     g_print("Background RRGGBBAA: %08x\n", bgcolor);
1035     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);
1037     g_print("Bitmap saved as: %s\n", filename);
1039     if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
1040         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);
1041     } else {
1042         g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
1043     }
1045     g_slist_free (items);
1049 /**
1050  *  Perform an export of either PS or EPS.
1051  *
1052  *  \param doc Document to export.
1053  *  \param uri URI to export to.
1054  *  \param mime MIME type to export as.
1055  */
1057 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
1059     Inkscape::Extension::DB::OutputList o;
1060     Inkscape::Extension::db.get_output_list(o);
1061     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1062     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1063         i++;
1064     }
1066     if (i == o.end())
1067     {
1068         g_warning ("Could not find an extension to export this file.");
1069         return;
1070     }
1072     bool old_text_to_path = false;
1073     bool old_font_embedded = false;
1074     bool old_bbox_page = false;
1076     try {
1077         old_text_to_path = (*i)->get_param_bool("textToPath");
1078         (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1079     }
1080     catch (...) {
1081         g_warning ("Could not set export-text-to-path option for this export.");
1082     }
1084     try {
1085         old_font_embedded = (*i)->get_param_bool("fontEmbedded");
1086         (*i)->set_param_bool("fontEmbedded", sp_export_font);
1087     }
1088     catch (...) {
1089         g_warning ("Could not set export-font option for this export.");
1090     }
1092     try {
1093         old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1094         (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1095     }
1096     catch (...) {
1097         g_warning ("Could not set export-bbox-page option for this export.");
1098     }
1100     (*i)->save(doc, uri);
1102     try {
1103         (*i)->set_param_bool("textToPath", old_text_to_path);
1104         (*i)->set_param_bool("fontEmbedded", old_font_embedded);
1105         (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1106     }
1107     catch (...) {
1109     }
1112 /**
1113  *  Perform a PDF export
1114  *
1115  *  \param doc Document to export.
1116  *  \param uri URI to export to.
1117  *  \param mime MIME type to export as.
1118  */
1120 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
1122     Inkscape::Extension::DB::OutputList o;
1123     Inkscape::Extension::db.get_output_list(o);
1124     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1125     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1126         i++;
1127     }
1129     if (i == o.end())
1130     {
1131         g_warning ("Could not find an extension to export this file.");
1132         return;
1133     }
1135     (*i)->save(doc, uri);
1138 #ifdef WIN32
1139 /**
1140  *  Export a document to EMF
1141  *
1142  *  \param doc Document to export.
1143  *  \param uri URI to export to.
1144  *  \param mime MIME type to export as (should be "image/x-emf")
1145  */
1147 static void do_export_emf(SPDocument* doc, gchar const* uri, char const* mime)
1149     Inkscape::Extension::DB::OutputList o;
1150     Inkscape::Extension::db.get_output_list(o);
1151     Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1152     while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1153         i++;
1154     }
1156     if (i == o.end())
1157     {
1158         g_warning ("Could not find an extension to export this file.");
1159         return;
1160     }
1162     (*i)->save(doc, uri);
1164 #endif //WIN32
1166 #ifdef WIN32
1167 bool replaceArgs( int& argc, char**& argv )
1169     bool worked = false;
1171 #ifdef REPLACEARGS_DEBUG
1172     MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1173 #endif // REPLACEARGS_DEBUG
1175     wchar_t* line = GetCommandLineW();
1176     if ( line )
1177     {
1178 #ifdef REPLACEARGS_DEBUG
1179         {
1180             gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1181             if ( utf8Line )
1182             {
1183                 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1184                 {
1185                     char tmp[strlen(safe) + 32];
1186                     snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1187                     MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1188                 }
1189             }
1190         }
1191 #endif // REPLACEARGS_DEBUG
1193         int numArgs = 0;
1194         wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1196 #ifdef REPLACEARGS_ANSI
1197 // test code for trying things on Win95/98/ME
1198         if ( !parsed )
1199         {
1200 #ifdef REPLACEARGS_DEBUG
1201             MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1202 #endif // REPLACEARGS_DEBUG
1203             int lineLen = wcslen(line) + 1;
1204             wchar_t* lineDup = new wchar_t[lineLen];
1205             wcsncpy( lineDup, line, lineLen );
1207             int pos = 0;
1208             bool inQuotes = false;
1209             bool inWhitespace = true;
1210             std::vector<int> places;
1211             while ( lineDup[pos] )
1212             {
1213                 if ( inQuotes )
1214                 {
1215                     if ( lineDup[pos] == L'"' )
1216                     {
1217                         inQuotes = false;
1218                     }
1219                 }
1220                 else if ( lineDup[pos] == L'"' )
1221                 {
1222                     inQuotes = true;
1223                     inWhitespace = false;
1224                     places.push_back(pos);
1225                 }
1226                 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1227                 {
1228                     if ( !inWhitespace )
1229                     {
1230                         inWhitespace = true;
1231                         lineDup[pos] = 0;
1232                     }
1233                 }
1234                 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1235                 {
1236                     inWhitespace = false;
1237                     places.push_back(pos);
1238                 }
1239                 else
1240                 {
1241                     // consume
1242                 }
1243                 pos++;
1244             }
1245 #ifdef REPLACEARGS_DEBUG
1246             {
1247                 char tmp[256];
1248                 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1249                 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1250             }
1251 #endif // REPLACEARGS_DEBUG
1253             wchar_t** block = new wchar_t*[places.size()];
1254             int i = 0;
1255             for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1256             {
1257                 block[i++] = &lineDup[*it];
1258             }
1259             parsed = block;
1260             numArgs = places.size();
1261         }
1262 #endif // REPLACEARGS_ANSI
1264         if ( parsed )
1265         {
1266             std::vector<wchar_t*>expandedArgs;
1267             if ( numArgs > 0 )
1268             {
1269                 expandedArgs.push_back( parsed[0] );
1270             }
1272             for ( int i1 = 1; i1 < numArgs; i1++ )
1273             {
1274                 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1275                 wildcarded &= parsed[i1][0] != L'"';
1276                 wildcarded &= parsed[i1][0] != L'-';
1277                 if ( wildcarded )
1278                 {
1279 #ifdef REPLACEARGS_ANSI
1280                     WIN32_FIND_DATAA data = {0};
1281 #else
1282                     WIN32_FIND_DATAW data = {0};
1283 #endif // REPLACEARGS_ANSI
1285                     int baseLen = wcslen(parsed[i1]) + 2;
1286                     wchar_t* base = new wchar_t[baseLen];
1287                     wcsncpy( base, parsed[i1], baseLen );
1288                     wchar_t* last = wcsrchr( base, L'\\' );
1289                     if ( last )
1290                     {
1291                         last[1] = 0;
1292                     }
1293                     else
1294                     {
1295                         base[0] = 0;
1296                     }
1297                     baseLen = wcslen( base );
1299 #ifdef REPLACEARGS_ANSI
1300                     char target[MAX_PATH];
1301                     if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1302                     {
1303                         HANDLE hf = FindFirstFileA( target, &data );
1304 #else
1305                         HANDLE hf = FindFirstFileW( parsed[i1], &data );
1306 #endif // REPLACEARGS_ANSI
1307                         if ( hf != INVALID_HANDLE_VALUE )
1308                         {
1309                             BOOL found = TRUE;
1310                             do
1311                             {
1312 #ifdef REPLACEARGS_ANSI
1313                                 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1314                                 if ( howMany > 0 )
1315                                 {
1316                                     howMany += baseLen;
1317                                     wchar_t* tmp = new wchar_t[howMany + 1];
1318                                     wcsncpy( tmp, base, howMany + 1 );
1319                                     MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1320                                     expandedArgs.push_back( tmp );
1321                                     found = FindNextFileA( hf, &data );
1322                                 }
1323 #else
1324                                 int howMany = wcslen(data.cFileName) + baseLen;
1325                                 wchar_t* tmp = new wchar_t[howMany + 1];
1326                                 wcsncpy( tmp, base, howMany + 1 );
1327                                 wcsncat( tmp, data.cFileName, howMany + 1 );
1328                                 expandedArgs.push_back( tmp );
1329                                 found = FindNextFileW( hf, &data );
1330 #endif // REPLACEARGS_ANSI
1331                             } while ( found );
1333                             FindClose( hf );
1334                         }
1335                         else
1336                         {
1337                             expandedArgs.push_back( parsed[i1] );
1338                         }
1339 #ifdef REPLACEARGS_ANSI
1340                     }
1341 #endif // REPLACEARGS_ANSI
1343                     delete[] base;
1344                 }
1345                 else
1346                 {
1347                     expandedArgs.push_back( parsed[i1] );
1348                 }
1349             }
1351             {
1352                 wchar_t** block = new wchar_t*[expandedArgs.size()];
1353                 int iz = 0;
1354                 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1355                 {
1356                     block[iz++] = *it;
1357                 }
1358                 parsed = block;
1359                 numArgs = expandedArgs.size();
1360             }
1362             std::vector<gchar*> newArgs;
1363             for ( int i = 0; i < numArgs; i++ )
1364             {
1365                 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1366                 if ( replacement )
1367                 {
1368 #ifdef REPLACEARGS_DEBUG
1369                     gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1371                     if ( safe2 )
1372                     {
1373                         {
1374                             char tmp[1024];
1375                             snprintf( tmp, sizeof(tmp), "    [%2d] = '%s'", i, safe2 );
1376                             MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1377                         }
1378                         g_free( safe2 );
1379                     }
1380 #endif // REPLACEARGS_DEBUG
1382                     newArgs.push_back( replacement );
1383                 }
1384                 else
1385                 {
1386                     newArgs.push_back( blankParam );
1387                 }
1388             }
1390             // Now push our munged params to be the new argv and argc
1391             {
1392                 char** block = new char*[newArgs.size()];
1393                 int iz = 0;
1394                 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1395                 {
1396                     block[iz++] = *it;
1397                 }
1398                 argv = block;
1399                 argc = newArgs.size();
1400                 worked = true;
1401             }
1402         }
1403 #ifdef REPLACEARGS_DEBUG
1404         else
1405         {
1406             MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1407         }
1408 #endif // REPLACEARGS_DEBUG
1409     }
1410 #ifdef REPLACEARGS_DEBUG
1411     else
1412     {
1413         {
1414             MessageBoxA( NULL,  "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1415         }
1417         char* line2 = GetCommandLineA();
1418         if ( line2 )
1419         {
1420             gchar *safe = Inkscape::IO::sanitizeString(line2);
1421             {
1422                 {
1423                     char tmp[strlen(safe) + 32];
1424                     snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1425                     MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1426                 }
1427             }
1428         }
1429         else
1430         {
1431             MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1432         }
1433     }
1434 #endif // REPLACEARGS_DEBUG
1436     return worked;
1438 #endif // WIN32
1440 static GSList *
1441 sp_process_args(poptContext ctx)
1443     GSList *fl = NULL;
1445     gint a;
1446     while ((a = poptGetNextOpt(ctx)) >= 0) {
1447         switch (a) {
1448             case SP_ARG_FILE: {
1449                 gchar const *fn = poptGetOptArg(ctx);
1450                 if (fn != NULL) {
1451                     fl = g_slist_append(fl, g_strdup(fn));
1452                 }
1453                 break;
1454             }
1455             case SP_ARG_VERSION: {
1456                 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1457                 exit(0);
1458                 break;
1459             }
1460             case SP_ARG_EXTENSIONDIR: {
1461                 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1462                 exit(0);
1463                 break;
1464             }
1465             case SP_ARG_VERB_LIST: {
1466                 // This really shouldn't go here, we should init the app.
1467                 // But, since we're just exiting in this path, there is
1468                 // no harm, and this is really a better place to put
1469                 // everything else.
1470                 Inkscape::Extension::init();
1471                 Inkscape::Verb::list();
1472                 exit(0);
1473                 break;
1474             }
1475             case SP_ARG_VERB:
1476             case SP_ARG_SELECT: {
1477                 gchar const *arg = poptGetOptArg(ctx);
1478                 if (arg != NULL) {
1479                     // printf("Adding in: %s\n", arg);
1480                     new Inkscape::CmdLineAction((a == SP_ARG_VERB), arg);
1481                 }
1482                 break;
1483             }
1484             default: {
1485                 break;
1486             }
1487         }
1488     }
1490     gchar const ** const args = poptGetArgs(ctx);
1491     if (args != NULL) {
1492         for (unsigned i = 0; args[i] != NULL; i++) {
1493             fl = g_slist_append(fl, g_strdup(args[i]));
1494         }
1495     }
1497     return fl;
1501 /*
1502   Local Variables:
1503   mode:c++
1504   c-file-style:"stroustrup"
1505   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1506   indent-tabs-mode:nil
1507   fill-column:99
1508   End:
1509 */
1510 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :