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