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 SP_ARG_EXPORT_TEXT_TO_PATH,
137 SP_ARG_EXPORT_FONT,
138 SP_ARG_EXPORT_BBOX_PAGE,
139 SP_ARG_EXTENSIONDIR,
140 SP_ARG_FIT_PAGE_TO_DRAWING,
141 SP_ARG_QUERY_X,
142 SP_ARG_QUERY_Y,
143 SP_ARG_QUERY_WIDTH,
144 SP_ARG_QUERY_HEIGHT,
145 SP_ARG_QUERY_ID,
146 SP_ARG_VERSION,
147 SP_ARG_VACUUM_DEFS,
148 SP_ARG_VERB_LIST,
149 SP_ARG_VERB,
150 SP_ARG_SELECT,
151 SP_ARG_LAST
152 };
154 int sp_main_gui(int argc, char const **argv);
155 int sp_main_console(int argc, char const **argv);
156 static void sp_do_export_png(SPDocument *doc);
157 static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
158 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const *mime);
159 static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
162 static gchar *sp_global_printer = NULL;
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 {"vacuum-defs", 0,
363 POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
364 N_("Remove unused definitions from the defs section(s) of the document"),
365 NULL},
367 {"verb-list", 0,
368 POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
369 N_("List the IDs of all the verbs in Inkscape"),
370 NULL},
372 {"verb", 0,
373 POPT_ARG_STRING, NULL, SP_ARG_VERB,
374 N_("Verb to call when Inkscape opens."),
375 N_("VERB-ID")},
377 {"select", 0,
378 POPT_ARG_STRING, NULL, SP_ARG_SELECT,
379 N_("Object ID to select when Inkscape opens."),
380 N_("OBJECT-ID")},
382 POPT_AUTOHELP POPT_TABLEEND
383 };
385 static bool needToRecodeParams = true;
386 gchar* blankParam = "";
388 int
389 main(int argc, char **argv)
390 {
391 #ifdef HAVE_FPSETMASK
392 /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__. It's probably
393 safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
394 the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
395 fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
396 #endif
398 #ifdef ENABLE_NLS
399 #ifdef WIN32
400 RegistryTool rt;
401 rt.setPathInfo();
402 gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
403 bindtextdomain(GETTEXT_PACKAGE, pathBuf);
404 g_free(pathBuf);
405 #else
406 #ifdef ENABLE_BINRELOC
407 bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
408 #else
409 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
410 #endif
411 #endif
412 // Allow the user to override the locale directory by setting
413 // the environment variable INKSCAPE_LOCALEDIR.
414 char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
415 if (inkscape_localedir != NULL) {
416 bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
417 }
418 #endif
420 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
422 #ifdef ENABLE_NLS
423 textdomain(GETTEXT_PACKAGE);
424 #endif
426 LIBXML_TEST_VERSION
428 Inkscape::GC::init();
430 Inkscape::Debug::Logger::init();
432 gboolean use_gui;
433 #ifndef WIN32
434 use_gui = (getenv("DISPLAY") != NULL);
435 #else
436 /*
437 Set the current directory to the directory of the
438 executable. This seems redundant, but is needed for
439 when inkscape.exe is executed from another directory.
440 We use relative paths on win32.
441 HKCR\svgfile\shell\open\command is a good example
442 */
443 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
444 char *homedir = g_path_get_dirname(argv[0]);
445 SetCurrentDirectory(homedir);
446 g_free(homedir);
448 use_gui = TRUE;
449 #endif
450 /* Test whether with/without GUI is forced */
451 for (int i = 1; i < argc; i++) {
452 if (!strcmp(argv[i], "-z")
453 || !strcmp(argv[i], "--without-gui")
454 || !strcmp(argv[i], "-p")
455 || !strncmp(argv[i], "--print", 7)
456 || !strcmp(argv[i], "-e")
457 || !strncmp(argv[i], "--export-png", 12)
458 || !strcmp(argv[i], "-l")
459 || !strncmp(argv[i], "--export-plain-svg", 12)
460 || !strcmp(argv[i], "-i")
461 || !strncmp(argv[i], "--export-area-drawing", 21)
462 || !strcmp(argv[i], "-D")
463 || !strncmp(argv[i], "--export-area-canvas", 20)
464 || !strcmp(argv[i], "-C")
465 || !strncmp(argv[i], "--export-id", 12)
466 || !strcmp(argv[i], "-P")
467 || !strncmp(argv[i], "--export-ps", 11)
468 || !strcmp(argv[i], "-E")
469 || !strncmp(argv[i], "--export-eps", 12)
470 || !strcmp(argv[i], "-A")
471 || !strncmp(argv[i], "--export-pdf", 12)
472 || !strcmp(argv[i], "-W")
473 || !strncmp(argv[i], "--query-width", 13)
474 || !strcmp(argv[i], "-H")
475 || !strncmp(argv[i], "--query-height", 14)
476 || !strcmp(argv[i], "-X")
477 || !strncmp(argv[i], "--query-x", 13)
478 || !strcmp(argv[i], "-Y")
479 || !strncmp(argv[i], "--query-y", 14)
480 || !strcmp(argv[i], "--vacuum-defs")
481 )
482 {
483 /* main_console handles any exports -- not the gui */
484 use_gui = FALSE;
485 break;
486 } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
487 use_gui = TRUE;
488 break;
489 }
490 }
492 #ifdef WIN32
493 #ifndef REPLACEARGS_ANSI
494 if ( PrintWin32::is_os_wide() )
495 #endif // REPLACEARGS_ANSI
496 {
497 // If the call fails, we'll need to convert charsets
498 needToRecodeParams = !replaceArgs( argc, argv );
499 }
500 #endif // WIN32
502 /// \todo Should this be a static object (see inkscape.cpp)?
503 Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
505 return app.run();
506 }
508 void fixupSingleFilename( gchar **orig, gchar **spare )
509 {
510 if ( orig && *orig && **orig ) {
511 GError *error = NULL;
512 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
513 if ( newFileName )
514 {
515 *orig = newFileName;
516 if ( spare ) {
517 *spare = newFileName;
518 }
519 // g_message("Set a replacement fixup");
520 }
521 }
522 }
524 GSList *fixupFilenameEncoding( GSList* fl )
525 {
526 GSList *newFl = NULL;
527 while ( fl ) {
528 gchar *fn = static_cast<gchar*>(fl->data);
529 fl = g_slist_remove( fl, fl->data );
530 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
531 if ( newFileName ) {
533 if ( 0 )
534 {
535 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
536 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
537 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
538 "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
539 gtk_dialog_run (GTK_DIALOG (w));
540 gtk_widget_destroy (w);
541 g_free(safeNewFn);
542 g_free(safeFn);
543 }
545 g_free( fn );
546 fn = newFileName;
547 newFileName = 0;
548 }
549 else
550 if ( 0 )
551 {
552 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
553 GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
554 gtk_dialog_run (GTK_DIALOG (w));
555 gtk_widget_destroy (w);
556 g_free(safeFn);
557 }
558 newFl = g_slist_append( newFl, fn );
559 }
560 return newFl;
561 }
563 int sp_common_main( int argc, char const **argv, GSList **flDest )
564 {
565 /// \todo fixme: Move these to some centralized location (Lauris)
566 sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
567 sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
570 // temporarily switch gettext encoding to locale, so that help messages can be output properly
571 gchar const *charset;
572 g_get_charset(&charset);
574 bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
576 poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
577 poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
578 g_return_val_if_fail(ctx != NULL, 1);
580 /* Collect own arguments */
581 GSList *fl = sp_process_args(ctx);
582 poptFreeContext(ctx);
584 // now switch gettext back to UTF-8 (for GUI)
585 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
587 // Now let's see if the file list still holds up
588 if ( needToRecodeParams )
589 {
590 fl = fixupFilenameEncoding( fl );
591 }
593 // Check the globals for filename-fixup
594 if ( needToRecodeParams )
595 {
596 fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
597 fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
598 fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
599 }
600 else
601 {
602 if ( sp_export_png )
603 sp_export_png_utf8 = g_strdup( sp_export_png );
604 if ( sp_export_svg )
605 sp_export_svg_utf8 = g_strdup( sp_export_svg );
606 if ( sp_global_printer )
607 sp_global_printer_utf8 = g_strdup( sp_global_printer );
608 }
610 // Return the list if wanted, else free it up.
611 if ( flDest ) {
612 *flDest = fl;
613 fl = 0;
614 } else {
615 while ( fl ) {
616 g_free( fl->data );
617 fl = g_slist_remove( fl, fl->data );
618 }
619 }
620 return 0;
621 }
623 static void
624 snooper(GdkEvent *event, gpointer data) {
625 if(inkscape_mapalt()) /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
626 {
627 GdkModifierType mapping=(GdkModifierType)inkscape_mapalt();
628 switch (event->type) {
629 case GDK_MOTION_NOTIFY:
630 if(event->motion.state & mapping) {
631 event->motion.state|=GDK_MOD1_MASK;
632 }
633 break;
634 case GDK_BUTTON_PRESS:
635 if(event->button.state & mapping) {
636 event->button.state|=GDK_MOD1_MASK;
637 }
638 break;
639 case GDK_KEY_PRESS:
640 if(event->key.state & mapping) {
641 event->key.state|=GDK_MOD1_MASK;
642 }
643 break;
644 default:
645 break;
646 }
647 }
648 gtk_main_do_event (event);
649 }
651 int
652 sp_main_gui(int argc, char const **argv)
653 {
654 Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
656 GSList *fl = NULL;
657 int retVal = sp_common_main( argc, argv, &fl );
658 g_return_val_if_fail(retVal == 0, 1);
660 inkscape_gtk_stock_init();
662 gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
664 Inkscape::Debug::log_display_config();
666 /* Set default icon */
667 gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
668 if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
669 gtk_window_set_default_icon_from_file(filename, NULL);
670 }
671 g_free (filename);
672 filename = 0;
674 gboolean create_new = TRUE;
676 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
677 inkscape_application_init(argv[0], true);
679 while (fl) {
680 if (sp_file_open((gchar *)fl->data,NULL)) {
681 create_new=FALSE;
682 }
683 fl = g_slist_remove(fl, fl->data);
684 }
685 if (create_new) {
686 sp_file_new_default();
687 }
689 Glib::signal_idle().connect(sigc::ptr_fun(&Inkscape::CmdLineAction::idle));
690 main_instance.run();
692 #ifdef WIN32
693 //We might not need anything here
694 //sp_win32_finish(); <-- this is a NOP func
695 #endif
697 return 0;
698 }
700 int
701 sp_main_console(int argc, char const **argv)
702 {
703 /* We are started in text mode */
705 /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
706 * in a non-Gtk environment. Used in libnrtype's
707 * FontInstance.cpp and FontFactory.cpp.
708 * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
709 */
710 g_type_init();
711 char **argv2 = const_cast<char **>(argv);
712 gtk_init_check( &argc, &argv2 );
713 //setlocale(LC_ALL, "");
715 GSList *fl = NULL;
716 int retVal = sp_common_main( argc, argv, &fl );
717 g_return_val_if_fail(retVal == 0, 1);
719 if (fl == NULL) {
720 g_print("Nothing to do!\n");
721 exit(0);
722 }
724 inkscape_application_init(argv[0], false);
726 while (fl) {
727 SPDocument *doc;
729 doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
730 if (doc == NULL) {
731 doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
732 }
733 if (doc == NULL) {
734 g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
735 } else {
736 if (sp_vacuum_defs) {
737 vacuum_document(doc);
738 }
739 if (sp_vacuum_defs && !sp_export_svg) {
740 // save under the name given in the command line
741 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
742 }
743 if (sp_global_printer) {
744 sp_print_document_to_file(doc, sp_global_printer);
745 }
746 if (sp_export_png || sp_export_id || sp_export_area_drawing) {
747 sp_do_export_png(doc);
748 }
749 if (sp_export_svg) {
750 Inkscape::XML::Document *rdoc;
751 Inkscape::XML::Node *repr;
752 rdoc = sp_repr_document_new("svg:svg");
753 repr = rdoc->root();
754 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
755 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
756 }
757 if (sp_export_ps) {
758 do_export_ps(doc, sp_export_ps, "image/x-postscript");
759 }
760 if (sp_export_eps) {
761 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
762 }
763 if (sp_export_pdf) {
764 do_export_pdf(doc, sp_export_pdf, "application/pdf");
765 }
766 if (sp_query_width || sp_query_height) {
767 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
768 } else if (sp_query_x || sp_query_y) {
769 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
770 }
771 }
773 fl = g_slist_remove(fl, fl->data);
774 }
776 inkscape_unref();
778 return 0;
779 }
781 static void
782 do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
783 {
784 SPObject *o = NULL;
786 if (id) {
787 o = doc->getObjectById(id);
788 if (o) {
789 if (!SP_IS_ITEM (o)) {
790 g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
791 return;
792 }
793 } else {
794 g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
795 return;
796 }
797 } else {
798 o = SP_DOCUMENT_ROOT(doc);
799 }
801 if (o) {
802 sp_document_ensure_up_to_date (doc);
803 SPItem *item = ((SPItem *) o);
805 // "true" SVG bbox for scripting
806 NR::Maybe<NR::Rect> area = item->getBounds(sp_item_i2doc_affine(item));
807 if (area) {
808 Inkscape::SVGOStringStream os;
809 if (extent) {
810 os << area->extent(axis);
811 } else {
812 os << area->min()[axis];
813 }
814 g_print ("%s", os.str().c_str());
815 } else {
816 g_print("0");
817 }
818 }
819 }
822 static void
823 sp_do_export_png(SPDocument *doc)
824 {
825 const gchar *filename = NULL;
826 gdouble dpi = 0.0;
828 if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
829 g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
830 }
832 GSList *items = NULL;
834 NRRect area;
835 if (sp_export_id || sp_export_area_drawing) {
837 SPObject *o = NULL;
838 SPObject *o_area = NULL;
839 if (sp_export_id && sp_export_area_drawing) {
840 o = doc->getObjectById(sp_export_id);
841 o_area = SP_DOCUMENT_ROOT (doc);
842 } else if (sp_export_id) {
843 o = doc->getObjectById(sp_export_id);
844 o_area = o;
845 } else if (sp_export_area_drawing) {
846 o = SP_DOCUMENT_ROOT (doc);
847 o_area = o;
848 }
850 if (o) {
851 if (!SP_IS_ITEM (o)) {
852 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
853 return;
854 }
856 items = g_slist_prepend (items, SP_ITEM(o));
858 if (sp_export_id_only) {
859 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
860 }
862 if (sp_export_use_hints) {
864 // retrieve export filename hint
865 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
866 if (fn_hint) {
867 if (sp_export_png) {
868 g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
869 filename = sp_export_png;
870 } else {
871 filename = fn_hint;
872 }
873 } else {
874 g_warning ("Export filename hint not found for the object.");
875 filename = sp_export_png;
876 }
878 // retrieve export dpi hints
879 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
880 if (dpi_hint) {
881 if (sp_export_dpi || sp_export_width || sp_export_height) {
882 g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
883 } else {
884 dpi = atof(dpi_hint);
885 }
886 } else {
887 g_warning ("Export DPI hint not found for the object.");
888 }
890 }
892 // write object bbox to area
893 sp_document_ensure_up_to_date (doc);
894 sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
895 } else {
896 g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
897 return;
898 }
899 }
901 if (sp_export_area) {
902 /* Try to parse area (given in SVG pixels) */
903 if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
904 g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
905 return;
906 }
907 if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
908 g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
909 return;
910 }
911 } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
912 /* Export the whole canvas */
913 sp_document_ensure_up_to_date (doc);
914 area.x0 = SP_ROOT(doc->root)->x.computed;
915 area.y0 = SP_ROOT(doc->root)->y.computed;
916 area.x1 = area.x0 + sp_document_width (doc);
917 area.y1 = area.y0 + sp_document_height (doc);
918 }
920 // set filename and dpi from options, if not yet set from the hints
921 if (!filename) {
922 if (!sp_export_png) {
923 g_warning ("No export filename given and no filename hint. Nothing exported.");
924 return;
925 }
926 filename = sp_export_png;
927 }
929 if (sp_export_dpi && dpi == 0.0) {
930 dpi = atof(sp_export_dpi);
931 if ((dpi < 0.1) || (dpi > 10000.0)) {
932 g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
933 return;
934 }
935 g_print("DPI: %g\n", dpi);
936 }
938 if (sp_export_area_snap) {
939 area.x0 = std::floor (area.x0);
940 area.y0 = std::floor (area.y0);
941 area.x1 = std::ceil (area.x1);
942 area.y1 = std::ceil (area.y1);
943 }
945 // default dpi
946 if (dpi == 0.0)
947 dpi = PX_PER_IN;
949 gint width = 0;
950 gint height = 0;
952 if (sp_export_width) {
953 width = atoi(sp_export_width);
954 if ((width < 1) || (width > 65536)) {
955 g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
956 return;
957 }
958 dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
959 }
961 if (sp_export_height) {
962 height = atoi(sp_export_height);
963 if ((height < 1) || (height > 65536)) {
964 g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
965 return;
966 }
967 dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
968 }
970 if (!sp_export_width) {
971 width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
972 }
974 if (!sp_export_height) {
975 height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
976 }
978 guint32 bgcolor = 0x00000000;
979 if (sp_export_background) {
980 // override the page color
981 bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
982 bgcolor |= 0xff; // default is no opacity
983 } else {
984 // read from namedview
985 Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
986 if (nv && nv->attribute("pagecolor"))
987 bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
988 if (nv && nv->attribute("inkscape:pageopacity"))
989 bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
990 }
992 if (sp_export_background_opacity) {
993 // override opacity
994 gfloat value;
995 if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
996 if (value > 1.0) {
997 value = CLAMP (value, 1.0f, 255.0f);
998 bgcolor &= (guint32) 0xffffff00;
999 bgcolor |= (guint32) floor(value);
1000 } else {
1001 value = CLAMP (value, 0.0f, 1.0f);
1002 bgcolor &= (guint32) 0xffffff00;
1003 bgcolor |= SP_COLOR_F_TO_U(value);
1004 }
1005 }
1006 }
1008 g_print("Background RRGGBBAA: %08x\n", bgcolor);
1010 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);
1012 g_print("Bitmap saved as: %s\n", filename);
1014 if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
1015 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);
1016 } else {
1017 g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
1018 }
1020 g_slist_free (items);
1021 }
1024 /**
1025 * Perform an export of either PS or EPS.
1026 *
1027 * \param doc Document to export.
1028 * \param uri URI to export to.
1029 * \param mime MIME type to export as.
1030 */
1032 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
1033 {
1034 Inkscape::Extension::DB::OutputList o;
1035 Inkscape::Extension::db.get_output_list(o);
1036 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1037 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1038 i++;
1039 }
1041 if (i == o.end())
1042 {
1043 g_warning ("Could not find an extension to export this file.");
1044 return;
1045 }
1047 bool old_text_to_path = false;
1048 bool old_font_embedded = false;
1049 bool old_bbox_page = false;
1051 try {
1052 old_text_to_path = (*i)->get_param_bool("textToPath");
1053 (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1054 }
1055 catch (...) {
1056 g_warning ("Could not set export-text-to-path option for this export.");
1057 }
1059 try {
1060 old_font_embedded = (*i)->get_param_bool("fontEmbedded");
1061 (*i)->set_param_bool("fontEmbedded", sp_export_font);
1062 }
1063 catch (...) {
1064 g_warning ("Could not set export-font option for this export.");
1065 }
1067 try {
1068 old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1069 (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1070 }
1071 catch (...) {
1072 g_warning ("Could not set export-bbox-page option for this export.");
1073 }
1075 (*i)->save(doc, uri);
1077 try {
1078 (*i)->set_param_bool("textToPath", old_text_to_path);
1079 (*i)->set_param_bool("fontEmbedded", old_font_embedded);
1080 (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1081 }
1082 catch (...) {
1084 }
1085 }
1087 /**
1088 * Perform a PDF export
1089 *
1090 * \param doc Document to export.
1091 * \param uri URI to export to.
1092 * \param mime MIME type to export as.
1093 */
1095 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
1096 {
1097 Inkscape::Extension::DB::OutputList o;
1098 Inkscape::Extension::db.get_output_list(o);
1099 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1100 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1101 i++;
1102 }
1104 if (i == o.end())
1105 {
1106 g_warning ("Could not find an extension to export this file.");
1107 return;
1108 }
1110 (*i)->save(doc, uri);
1111 }
1113 #ifdef WIN32
1114 bool replaceArgs( int& argc, char**& argv )
1115 {
1116 bool worked = false;
1118 #ifdef REPLACEARGS_DEBUG
1119 MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1120 #endif // REPLACEARGS_DEBUG
1122 wchar_t* line = GetCommandLineW();
1123 if ( line )
1124 {
1125 #ifdef REPLACEARGS_DEBUG
1126 {
1127 gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1128 if ( utf8Line )
1129 {
1130 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1131 {
1132 char tmp[strlen(safe) + 32];
1133 snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1134 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1135 }
1136 }
1137 }
1138 #endif // REPLACEARGS_DEBUG
1140 int numArgs = 0;
1141 wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1143 #ifdef REPLACEARGS_ANSI
1144 // test code for trying things on Win95/98/ME
1145 if ( !parsed )
1146 {
1147 #ifdef REPLACEARGS_DEBUG
1148 MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1149 #endif // REPLACEARGS_DEBUG
1150 int lineLen = wcslen(line) + 1;
1151 wchar_t* lineDup = new wchar_t[lineLen];
1152 wcsncpy( lineDup, line, lineLen );
1154 int pos = 0;
1155 bool inQuotes = false;
1156 bool inWhitespace = true;
1157 std::vector<int> places;
1158 while ( lineDup[pos] )
1159 {
1160 if ( inQuotes )
1161 {
1162 if ( lineDup[pos] == L'"' )
1163 {
1164 inQuotes = false;
1165 }
1166 }
1167 else if ( lineDup[pos] == L'"' )
1168 {
1169 inQuotes = true;
1170 inWhitespace = false;
1171 places.push_back(pos);
1172 }
1173 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1174 {
1175 if ( !inWhitespace )
1176 {
1177 inWhitespace = true;
1178 lineDup[pos] = 0;
1179 }
1180 }
1181 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1182 {
1183 inWhitespace = false;
1184 places.push_back(pos);
1185 }
1186 else
1187 {
1188 // consume
1189 }
1190 pos++;
1191 }
1192 #ifdef REPLACEARGS_DEBUG
1193 {
1194 char tmp[256];
1195 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1196 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1197 }
1198 #endif // REPLACEARGS_DEBUG
1200 wchar_t** block = new wchar_t*[places.size()];
1201 int i = 0;
1202 for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1203 {
1204 block[i++] = &lineDup[*it];
1205 }
1206 parsed = block;
1207 numArgs = places.size();
1208 }
1209 #endif // REPLACEARGS_ANSI
1211 if ( parsed )
1212 {
1213 std::vector<wchar_t*>expandedArgs;
1214 if ( numArgs > 0 )
1215 {
1216 expandedArgs.push_back( parsed[0] );
1217 }
1219 for ( int i1 = 1; i1 < numArgs; i1++ )
1220 {
1221 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1222 wildcarded &= parsed[i1][0] != L'"';
1223 wildcarded &= parsed[i1][0] != L'-';
1224 if ( wildcarded )
1225 {
1226 #ifdef REPLACEARGS_ANSI
1227 WIN32_FIND_DATAA data = {0};
1228 #else
1229 WIN32_FIND_DATAW data = {0};
1230 #endif // REPLACEARGS_ANSI
1232 int baseLen = wcslen(parsed[i1]) + 2;
1233 wchar_t* base = new wchar_t[baseLen];
1234 wcsncpy( base, parsed[i1], baseLen );
1235 wchar_t* last = wcsrchr( base, L'\\' );
1236 if ( last )
1237 {
1238 last[1] = 0;
1239 }
1240 else
1241 {
1242 base[0] = 0;
1243 }
1244 baseLen = wcslen( base );
1246 #ifdef REPLACEARGS_ANSI
1247 char target[MAX_PATH];
1248 if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1249 {
1250 HANDLE hf = FindFirstFileA( target, &data );
1251 #else
1252 HANDLE hf = FindFirstFileW( parsed[i1], &data );
1253 #endif // REPLACEARGS_ANSI
1254 if ( hf != INVALID_HANDLE_VALUE )
1255 {
1256 BOOL found = TRUE;
1257 do
1258 {
1259 #ifdef REPLACEARGS_ANSI
1260 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1261 if ( howMany > 0 )
1262 {
1263 howMany += baseLen;
1264 wchar_t* tmp = new wchar_t[howMany + 1];
1265 wcsncpy( tmp, base, howMany + 1 );
1266 MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1267 expandedArgs.push_back( tmp );
1268 found = FindNextFileA( hf, &data );
1269 }
1270 #else
1271 int howMany = wcslen(data.cFileName) + baseLen;
1272 wchar_t* tmp = new wchar_t[howMany + 1];
1273 wcsncpy( tmp, base, howMany + 1 );
1274 wcsncat( tmp, data.cFileName, howMany + 1 );
1275 expandedArgs.push_back( tmp );
1276 found = FindNextFileW( hf, &data );
1277 #endif // REPLACEARGS_ANSI
1278 } while ( found );
1280 FindClose( hf );
1281 }
1282 else
1283 {
1284 expandedArgs.push_back( parsed[i1] );
1285 }
1286 #ifdef REPLACEARGS_ANSI
1287 }
1288 #endif // REPLACEARGS_ANSI
1290 delete[] base;
1291 }
1292 else
1293 {
1294 expandedArgs.push_back( parsed[i1] );
1295 }
1296 }
1298 {
1299 wchar_t** block = new wchar_t*[expandedArgs.size()];
1300 int iz = 0;
1301 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1302 {
1303 block[iz++] = *it;
1304 }
1305 parsed = block;
1306 numArgs = expandedArgs.size();
1307 }
1309 std::vector<gchar*> newArgs;
1310 for ( int i = 0; i < numArgs; i++ )
1311 {
1312 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1313 if ( replacement )
1314 {
1315 #ifdef REPLACEARGS_DEBUG
1316 gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1318 if ( safe2 )
1319 {
1320 {
1321 char tmp[1024];
1322 snprintf( tmp, sizeof(tmp), " [%2d] = '%s'", i, safe2 );
1323 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1324 }
1325 g_free( safe2 );
1326 }
1327 #endif // REPLACEARGS_DEBUG
1329 newArgs.push_back( replacement );
1330 }
1331 else
1332 {
1333 newArgs.push_back( blankParam );
1334 }
1335 }
1337 // Now push our munged params to be the new argv and argc
1338 {
1339 char** block = new char*[newArgs.size()];
1340 int iz = 0;
1341 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1342 {
1343 block[iz++] = *it;
1344 }
1345 argv = block;
1346 argc = newArgs.size();
1347 worked = true;
1348 }
1349 }
1350 #ifdef REPLACEARGS_DEBUG
1351 else
1352 {
1353 MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1354 }
1355 #endif // REPLACEARGS_DEBUG
1356 }
1357 #ifdef REPLACEARGS_DEBUG
1358 else
1359 {
1360 {
1361 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1362 }
1364 char* line2 = GetCommandLineA();
1365 if ( line2 )
1366 {
1367 gchar *safe = Inkscape::IO::sanitizeString(line2);
1368 {
1369 {
1370 char tmp[strlen(safe) + 32];
1371 snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1372 MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1373 }
1374 }
1375 }
1376 else
1377 {
1378 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1379 }
1380 }
1381 #endif // REPLACEARGS_DEBUG
1383 return worked;
1384 }
1385 #endif // WIN32
1387 static GSList *
1388 sp_process_args(poptContext ctx)
1389 {
1390 GSList *fl = NULL;
1392 gint a;
1393 while ((a = poptGetNextOpt(ctx)) >= 0) {
1394 switch (a) {
1395 case SP_ARG_FILE: {
1396 gchar const *fn = poptGetOptArg(ctx);
1397 if (fn != NULL) {
1398 fl = g_slist_append(fl, g_strdup(fn));
1399 }
1400 break;
1401 }
1402 case SP_ARG_VERSION: {
1403 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1404 exit(0);
1405 break;
1406 }
1407 case SP_ARG_EXTENSIONDIR: {
1408 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1409 exit(0);
1410 break;
1411 }
1412 case SP_ARG_VERB_LIST: {
1413 // This really shouldn't go here, we should init the app.
1414 // But, since we're just exiting in this path, there is
1415 // no harm, and this is really a better place to put
1416 // everything else.
1417 Inkscape::Extension::init();
1418 Inkscape::Verb::list();
1419 exit(0);
1420 break;
1421 }
1422 case SP_ARG_VERB:
1423 case SP_ARG_SELECT: {
1424 gchar const *arg = poptGetOptArg(ctx);
1425 if (arg != NULL) {
1426 // printf("Adding in: %s\n", arg);
1427 new Inkscape::CmdLineAction((a == SP_ARG_VERB), arg);
1428 }
1429 break;
1430 }
1431 default: {
1432 break;
1433 }
1434 }
1435 }
1437 gchar const ** const args = poptGetArgs(ctx);
1438 if (args != NULL) {
1439 for (unsigned i = 0; args[i] != NULL; i++) {
1440 fl = g_slist_append(fl, g_strdup(args[i]));
1441 }
1442 }
1444 return fl;
1445 }
1448 /*
1449 Local Variables:
1450 mode:c++
1451 c-file-style:"stroustrup"
1452 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1453 indent-tabs-mode:nil
1454 fill-column:99
1455 End:
1456 */
1457 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :