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