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