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