778928f4c0ff309bb468f1ed744eba420af4bf76
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 enum {
112 SP_ARG_NONE,
113 SP_ARG_NOGUI,
114 SP_ARG_GUI,
115 SP_ARG_FILE,
116 SP_ARG_PRINT,
117 SP_ARG_EXPORT_PNG,
118 SP_ARG_EXPORT_DPI,
119 SP_ARG_EXPORT_AREA,
120 SP_ARG_EXPORT_AREA_DRAWING,
121 SP_ARG_EXPORT_AREA_CANVAS,
122 SP_ARG_EXPORT_AREA_SNAP,
123 SP_ARG_EXPORT_WIDTH,
124 SP_ARG_EXPORT_HEIGHT,
125 SP_ARG_EXPORT_ID,
126 SP_ARG_EXPORT_ID_ONLY,
127 SP_ARG_EXPORT_USE_HINTS,
128 SP_ARG_EXPORT_BACKGROUND,
129 SP_ARG_EXPORT_BACKGROUND_OPACITY,
130 SP_ARG_EXPORT_SVG,
131 SP_ARG_EXPORT_PS,
132 SP_ARG_EXPORT_EPS,
133 SP_ARG_EXPORT_PDF,
134 SP_ARG_EXPORT_TEXT_TO_PATH,
135 SP_ARG_EXPORT_FONT,
136 SP_ARG_EXPORT_BBOX_PAGE,
137 SP_ARG_EXTENSIONDIR,
138 SP_ARG_FIT_PAGE_TO_DRAWING,
139 SP_ARG_SLIDESHOW,
140 SP_ARG_QUERY_X,
141 SP_ARG_QUERY_Y,
142 SP_ARG_QUERY_WIDTH,
143 SP_ARG_QUERY_HEIGHT,
144 SP_ARG_QUERY_ID,
145 SP_ARG_VERSION,
146 SP_ARG_VACUUM_DEFS,
147 SP_ARG_VERB_LIST,
148 SP_ARG_VERB,
149 SP_ARG_SELECT,
150 SP_ARG_LAST
151 };
153 int sp_main_gui(int argc, char const **argv);
154 int sp_main_console(int argc, char const **argv);
155 static void sp_do_export_png(SPDocument *doc);
156 static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
157 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const *mime);
158 static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
161 static gchar *sp_global_printer = NULL;
162 static gboolean sp_global_slideshow = FALSE;
163 static gchar *sp_export_png = NULL;
164 static gchar *sp_export_dpi = NULL;
165 static gchar *sp_export_area = NULL;
166 static gboolean sp_export_area_drawing = FALSE;
167 static gboolean sp_export_area_canvas = FALSE;
168 static gchar *sp_export_width = NULL;
169 static gchar *sp_export_height = NULL;
170 static gchar *sp_export_id = NULL;
171 static gchar *sp_export_background = NULL;
172 static gchar *sp_export_background_opacity = NULL;
173 static gboolean sp_export_area_snap = FALSE;
174 static gboolean sp_export_use_hints = FALSE;
175 static gboolean sp_export_id_only = FALSE;
176 static gchar *sp_export_svg = NULL;
177 static gchar *sp_export_ps = NULL;
178 static gchar *sp_export_eps = NULL;
179 static gchar *sp_export_pdf = NULL;
180 static gboolean sp_export_text_to_path = FALSE;
181 static gboolean sp_export_font = FALSE;
182 static gboolean sp_export_bbox_page = FALSE;
183 static gboolean sp_query_x = FALSE;
184 static gboolean sp_query_y = FALSE;
185 static gboolean sp_query_width = FALSE;
186 static gboolean sp_query_height = FALSE;
187 static gchar *sp_query_id = NULL;
188 static int sp_new_gui = FALSE;
189 static gboolean sp_vacuum_defs = FALSE;
191 static gchar *sp_export_png_utf8 = NULL;
192 static gchar *sp_export_svg_utf8 = NULL;
193 static gchar *sp_global_printer_utf8 = NULL;
195 #ifdef WIN32
196 static bool replaceArgs( int& argc, char**& argv );
197 #endif
198 static GSList *sp_process_args(poptContext ctx);
199 struct poptOption options[] = {
200 {"version", 'V',
201 POPT_ARG_NONE, NULL, SP_ARG_VERSION,
202 N_("Print the Inkscape version number"),
203 NULL},
205 {"without-gui", 'z',
206 POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
207 N_("Do not use X server (only process files from console)"),
208 NULL},
210 {"with-gui", 'g',
211 POPT_ARG_NONE, NULL, SP_ARG_GUI,
212 N_("Try to use X server (even if $DISPLAY is not set)"),
213 NULL},
215 {"file", 'f',
216 POPT_ARG_STRING, NULL, SP_ARG_FILE,
217 N_("Open specified document(s) (option string may be excluded)"),
218 N_("FILENAME")},
220 {"print", 'p',
221 POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
222 N_("Print document(s) to specified output file (use '| program' for pipe)"),
223 N_("FILENAME")},
225 {"export-png", 'e',
226 POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
227 N_("Export document to a PNG file"),
228 N_("FILENAME")},
230 {"export-dpi", 'd',
231 POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
232 N_("The resolution used for exporting SVG into bitmap (default 90)"),
233 N_("DPI")},
235 {"export-area", 'a',
236 POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
237 N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
238 N_("x0:y0:x1:y1")},
240 {"export-area-drawing", 'D',
241 POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
242 N_("Exported area is the entire drawing (not canvas)"),
243 NULL},
245 {"export-area-canvas", 'C',
246 POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
247 N_("Exported area is the entire canvas"),
248 NULL},
250 {"export-area-snap", 0,
251 POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
252 N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
253 NULL},
255 {"export-width", 'w',
256 POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
257 N_("The width of exported bitmap in pixels (overrides export-dpi)"),
258 N_("WIDTH")},
260 {"export-height", 'h',
261 POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
262 N_("The height of exported bitmap in pixels (overrides export-dpi)"),
263 N_("HEIGHT")},
265 {"export-id", 'i',
266 POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
267 N_("The ID of the object to export"),
268 N_("ID")},
270 {"export-id-only", 'j',
271 POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
272 // TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
273 // See "man inkscape" for details.
274 N_("Export just the object with export-id, hide all others (only with export-id)"),
275 NULL},
277 {"export-use-hints", 't',
278 POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
279 N_("Use stored filename and DPI hints when exporting (only with export-id)"),
280 NULL},
282 {"export-background", 'b',
283 POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
284 N_("Background color of exported bitmap (any SVG-supported color string)"),
285 N_("COLOR")},
287 {"export-background-opacity", 'y',
288 POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
289 N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"),
290 N_("VALUE")},
292 {"export-plain-svg", 'l',
293 POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
294 N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"),
295 N_("FILENAME")},
297 {"export-ps", 'P',
298 POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
299 N_("Export document to a PS file"),
300 N_("FILENAME")},
302 {"export-eps", 'E',
303 POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
304 N_("Export document to an EPS file"),
305 N_("FILENAME")},
307 {"export-pdf", 'A',
308 POPT_ARG_STRING, &sp_export_pdf, SP_ARG_EXPORT_PDF,
309 N_("Export document to a PDF file"),
310 N_("FILENAME")},
312 {"export-text-to-path", 'T',
313 POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
314 N_("Convert text object to paths on export (EPS)"),
315 NULL},
317 {"export-embed-fonts", 'F',
318 POPT_ARG_NONE, &sp_export_font, SP_ARG_EXPORT_FONT,
319 N_("Embed fonts on export (Type 1 only) (EPS)"),
320 NULL},
322 {"export-bbox-page", 'B',
323 POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
324 N_("Export files with the bounding box set to the page size (EPS)"),
325 NULL},
327 {"query-x", 'X',
328 POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
329 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
330 N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
331 NULL},
333 {"query-y", 'Y',
334 POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
335 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
336 N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
337 NULL},
339 {"query-width", 'W',
340 POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
341 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
342 N_("Query the width of the drawing or, if specified, of the object with --query-id"),
343 NULL},
345 {"query-height", 'H',
346 POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
347 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
348 N_("Query the height of the drawing or, if specified, of the object with --query-id"),
349 NULL},
351 {"query-id", 'I',
352 POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
353 N_("The ID of the object whose dimensions are queried"),
354 N_("ID")},
356 {"extension-directory", 'x',
357 POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
358 // TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
359 N_("Print out the extension directory and exit"),
360 NULL},
362 {"slideshow", 's',
363 POPT_ARG_NONE, &sp_global_slideshow, SP_ARG_SLIDESHOW,
364 N_("Show given files one-by-one, switch to next on any key/mouse event"),
365 NULL},
367 {"vacuum-defs", 0,
368 POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
369 N_("Remove unused definitions from the defs section(s) of the document"),
370 NULL},
372 {"verb-list", 0,
373 POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
374 N_("List the IDs of all the verbs in Inkscape"),
375 NULL},
377 {"verb", 0,
378 POPT_ARG_STRING, NULL, SP_ARG_VERB,
379 N_("Verb to call when Inkscape opens."),
380 N_("VERB-ID")},
382 {"select", 0,
383 POPT_ARG_STRING, NULL, SP_ARG_SELECT,
384 N_("Object ID to select when Inkscape opens."),
385 N_("OBJECT-ID")},
387 POPT_AUTOHELP POPT_TABLEEND
388 };
390 class CmdLineAction {
391 gint _type;
392 gchar * _arg;
394 static std::list <CmdLineAction *> _list;
396 public:
397 CmdLineAction (gint type, gchar const * arg) : _type(type), _arg(NULL) {
398 if (arg != NULL) {
399 _arg = g_strdup(arg);
400 }
402 _list.insert(_list.end(), this);
404 return;
405 }
407 ~CmdLineAction () {
408 if (_arg != NULL) {
409 g_free(_arg);
410 }
411 }
413 void doIt (SPDocument * doc) {
414 printf("Doing: %s\n", _arg);
415 }
417 static void doList (SPDocument * doc) {
418 for (std::list<CmdLineAction *>::iterator i = _list.begin();
419 i != _list.end(); i++) {
420 CmdLineAction * entry = *i;
421 entry->doIt(doc);
422 }
423 }
424 };
425 std::list <CmdLineAction *> CmdLineAction::_list;
428 static bool needToRecodeParams = true;
429 gchar* blankParam = "";
431 int
432 main(int argc, char **argv)
433 {
434 #ifdef HAVE_FPSETMASK
435 /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__. It's probably
436 safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
437 the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
438 fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
439 #endif
441 #ifdef ENABLE_NLS
442 #ifdef WIN32
443 RegistryTool rt;
444 rt.setPathInfo();
445 gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
446 bindtextdomain(GETTEXT_PACKAGE, pathBuf);
447 g_free(pathBuf);
448 #else
449 #ifdef ENABLE_BINRELOC
450 bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
451 #else
452 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
453 #endif
454 #endif
455 // Allow the user to override the locale directory by setting
456 // the environment variable INKSCAPE_LOCALEDIR.
457 char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
458 if (inkscape_localedir != NULL) {
459 bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
460 }
461 #endif
463 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
465 #ifdef ENABLE_NLS
466 textdomain(GETTEXT_PACKAGE);
467 #endif
469 LIBXML_TEST_VERSION
471 Inkscape::GC::init();
473 Inkscape::Debug::Logger::init();
475 gboolean use_gui;
476 #ifndef WIN32
477 use_gui = (getenv("DISPLAY") != NULL);
478 #else
479 /*
480 Set the current directory to the directory of the
481 executable. This seems redundant, but is needed for
482 when inkscape.exe is executed from another directory.
483 We use relative paths on win32.
484 HKCR\svgfile\shell\open\command is a good example
485 */
486 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
487 char *homedir = g_path_get_dirname(argv[0]);
488 SetCurrentDirectory(homedir);
489 g_free(homedir);
491 use_gui = TRUE;
492 #endif
493 /* Test whether with/without GUI is forced */
494 for (int i = 1; i < argc; i++) {
495 if (!strcmp(argv[i], "-z")
496 || !strcmp(argv[i], "--without-gui")
497 || !strcmp(argv[i], "-p")
498 || !strncmp(argv[i], "--print", 7)
499 || !strcmp(argv[i], "-e")
500 || !strncmp(argv[i], "--export-png", 12)
501 || !strcmp(argv[i], "-l")
502 || !strncmp(argv[i], "--export-plain-svg", 12)
503 || !strcmp(argv[i], "-i")
504 || !strncmp(argv[i], "--export-area-drawing", 21)
505 || !strcmp(argv[i], "-D")
506 || !strncmp(argv[i], "--export-area-canvas", 20)
507 || !strcmp(argv[i], "-C")
508 || !strncmp(argv[i], "--export-id", 12)
509 || !strcmp(argv[i], "-P")
510 || !strncmp(argv[i], "--export-ps", 11)
511 || !strcmp(argv[i], "-E")
512 || !strncmp(argv[i], "--export-eps", 12)
513 || !strcmp(argv[i], "-A")
514 || !strncmp(argv[i], "--export-pdf", 12)
515 || !strcmp(argv[i], "-W")
516 || !strncmp(argv[i], "--query-width", 13)
517 || !strcmp(argv[i], "-H")
518 || !strncmp(argv[i], "--query-height", 14)
519 || !strcmp(argv[i], "-X")
520 || !strncmp(argv[i], "--query-x", 13)
521 || !strcmp(argv[i], "-Y")
522 || !strncmp(argv[i], "--query-y", 14)
523 || !strcmp(argv[i], "--vacuum-defs")
524 )
525 {
526 /* main_console handles any exports -- not the gui */
527 use_gui = FALSE;
528 break;
529 } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
530 use_gui = TRUE;
531 break;
532 }
533 }
535 #ifdef WIN32
536 #ifndef REPLACEARGS_ANSI
537 if ( PrintWin32::is_os_wide() )
538 #endif // REPLACEARGS_ANSI
539 {
540 // If the call fails, we'll need to convert charsets
541 needToRecodeParams = !replaceArgs( argc, argv );
542 }
543 #endif // WIN32
545 /// \todo Should this be a static object (see inkscape.cpp)?
546 Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
548 return app.run();
549 }
551 void fixupSingleFilename( gchar **orig, gchar **spare )
552 {
553 if ( orig && *orig && **orig ) {
554 GError *error = NULL;
555 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
556 if ( newFileName )
557 {
558 *orig = newFileName;
559 if ( spare ) {
560 *spare = newFileName;
561 }
562 // g_message("Set a replacement fixup");
563 }
564 }
565 }
567 GSList *fixupFilenameEncoding( GSList* fl )
568 {
569 GSList *newFl = NULL;
570 while ( fl ) {
571 gchar *fn = static_cast<gchar*>(fl->data);
572 fl = g_slist_remove( fl, fl->data );
573 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
574 if ( newFileName ) {
576 if ( 0 )
577 {
578 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
579 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
580 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
581 "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
582 gtk_dialog_run (GTK_DIALOG (w));
583 gtk_widget_destroy (w);
584 g_free(safeNewFn);
585 g_free(safeFn);
586 }
588 g_free( fn );
589 fn = newFileName;
590 newFileName = 0;
591 }
592 else
593 if ( 0 )
594 {
595 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
596 GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
597 gtk_dialog_run (GTK_DIALOG (w));
598 gtk_widget_destroy (w);
599 g_free(safeFn);
600 }
601 newFl = g_slist_append( newFl, fn );
602 }
603 return newFl;
604 }
606 int sp_common_main( int argc, char const **argv, GSList **flDest )
607 {
608 /// \todo fixme: Move these to some centralized location (Lauris)
609 sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
610 sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
613 // temporarily switch gettext encoding to locale, so that help messages can be output properly
614 gchar const *charset;
615 g_get_charset(&charset);
617 bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
619 poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
620 poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
621 g_return_val_if_fail(ctx != NULL, 1);
623 /* Collect own arguments */
624 GSList *fl = sp_process_args(ctx);
625 poptFreeContext(ctx);
627 // now switch gettext back to UTF-8 (for GUI)
628 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
630 // Now let's see if the file list still holds up
631 if ( needToRecodeParams )
632 {
633 fl = fixupFilenameEncoding( fl );
634 }
636 // Check the globals for filename-fixup
637 if ( needToRecodeParams )
638 {
639 fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
640 fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
641 fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
642 }
643 else
644 {
645 if ( sp_export_png )
646 sp_export_png_utf8 = g_strdup( sp_export_png );
647 if ( sp_export_svg )
648 sp_export_svg_utf8 = g_strdup( sp_export_svg );
649 if ( sp_global_printer )
650 sp_global_printer_utf8 = g_strdup( sp_global_printer );
651 }
653 // Return the list if wanted, else free it up.
654 if ( flDest ) {
655 *flDest = fl;
656 fl = 0;
657 } else {
658 while ( fl ) {
659 g_free( fl->data );
660 fl = g_slist_remove( fl, fl->data );
661 }
662 }
663 return 0;
664 }
666 int
667 sp_main_gui(int argc, char const **argv)
668 {
669 Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
671 GSList *fl = NULL;
672 int retVal = sp_common_main( argc, argv, &fl );
673 g_return_val_if_fail(retVal == 0, 1);
675 inkscape_gtk_stock_init();
677 /* Set default icon */
678 gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
679 if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
680 gtk_window_set_default_icon_from_file(filename, NULL);
681 }
682 g_free (filename);
683 filename = 0;
685 if (!sp_global_slideshow) {
686 gboolean create_new = TRUE;
688 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
689 inkscape_application_init(argv[0], true);
691 while (fl) {
692 if (sp_file_open((gchar *)fl->data,NULL)) {
693 create_new=FALSE;
694 }
695 fl = g_slist_remove(fl, fl->data);
696 }
697 if (create_new) {
698 sp_file_new_default();
699 }
700 } else {
701 if (fl) {
702 GtkWidget *ss;
703 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
704 inkscape_application_init(argv[0], true);
705 ss = sp_slideshow_new(fl);
706 if (ss) gtk_widget_show(ss);
707 } else {
708 g_warning ("No slides to display");
709 exit(0);
710 }
711 }
713 main_instance.run();
715 #ifdef WIN32
716 //We might not need anything here
717 //sp_win32_finish(); <-- this is a NOP func
718 #endif
720 return 0;
721 }
723 int
724 sp_main_console(int argc, char const **argv)
725 {
726 /* We are started in text mode */
728 /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
729 * in a non-Gtk environment. Used in libnrtype's
730 * FontInstance.cpp and FontFactory.cpp.
731 * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
732 */
733 g_type_init();
734 char **argv2 = const_cast<char **>(argv);
735 gtk_init_check( &argc, &argv2 );
736 //setlocale(LC_ALL, "");
738 GSList *fl = NULL;
739 int retVal = sp_common_main( argc, argv, &fl );
740 g_return_val_if_fail(retVal == 0, 1);
742 if (fl == NULL) {
743 g_print("Nothing to do!\n");
744 exit(0);
745 }
747 inkscape_application_init(argv[0], false);
749 while (fl) {
750 SPDocument *doc;
752 doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
753 if (doc == NULL) {
754 doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
755 }
756 if (doc == NULL) {
757 g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
758 } else {
759 if (sp_vacuum_defs) {
760 vacuum_document(doc);
761 }
762 if (sp_vacuum_defs && !sp_export_svg) {
763 // save under the name given in the command line
764 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
765 }
766 if (sp_global_printer) {
767 sp_print_document_to_file(doc, sp_global_printer);
768 }
769 if (sp_export_png || sp_export_id || sp_export_area_drawing) {
770 sp_do_export_png(doc);
771 }
772 if (sp_export_svg) {
773 Inkscape::XML::Document *rdoc;
774 Inkscape::XML::Node *repr;
775 rdoc = sp_repr_document_new("svg:svg");
776 repr = rdoc->root();
777 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
778 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
779 }
780 if (sp_export_ps) {
781 do_export_ps(doc, sp_export_ps, "image/x-postscript");
782 }
783 if (sp_export_eps) {
784 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
785 }
786 if (sp_export_pdf) {
787 do_export_pdf(doc, sp_export_pdf, "application/pdf");
788 }
789 if (sp_query_width || sp_query_height) {
790 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
791 } else if (sp_query_x || sp_query_y) {
792 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
793 }
795 CmdLineAction::doList(doc);
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);
829 NR::Rect area = item->invokeBbox(sp_item_i2doc_affine(item)); // "true" SVG bbox for scripting
831 Inkscape::SVGOStringStream os;
832 if (extent) {
833 os << area.extent(axis);
834 } else {
835 os << area.min()[axis];
836 }
837 g_print ("%s", os.str().c_str());
838 }
839 }
842 static void
843 sp_do_export_png(SPDocument *doc)
844 {
845 const gchar *filename = NULL;
846 gdouble dpi = 0.0;
848 if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
849 g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
850 }
852 GSList *items = NULL;
854 NRRect area;
855 if (sp_export_id || sp_export_area_drawing) {
857 SPObject *o = NULL;
858 SPObject *o_area = NULL;
859 if (sp_export_id && sp_export_area_drawing) {
860 o = doc->getObjectById(sp_export_id);
861 o_area = SP_DOCUMENT_ROOT (doc);
862 } else if (sp_export_id) {
863 o = doc->getObjectById(sp_export_id);
864 o_area = o;
865 } else if (sp_export_area_drawing) {
866 o = SP_DOCUMENT_ROOT (doc);
867 o_area = o;
868 }
870 if (o) {
871 if (!SP_IS_ITEM (o)) {
872 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
873 return;
874 }
876 items = g_slist_prepend (items, SP_ITEM(o));
878 if (sp_export_id_only) {
879 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
880 }
882 if (sp_export_use_hints) {
884 // retrieve export filename hint
885 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
886 if (fn_hint) {
887 if (sp_export_png) {
888 g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
889 filename = sp_export_png;
890 } else {
891 filename = fn_hint;
892 }
893 } else {
894 g_warning ("Export filename hint not found for the object.");
895 filename = sp_export_png;
896 }
898 // retrieve export dpi hints
899 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
900 if (dpi_hint) {
901 if (sp_export_dpi || sp_export_width || sp_export_height) {
902 g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
903 } else {
904 dpi = atof(dpi_hint);
905 }
906 } else {
907 g_warning ("Export DPI hint not found for the object.");
908 }
910 }
912 // write object bbox to area
913 sp_document_ensure_up_to_date (doc);
914 sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
915 } else {
916 g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
917 return;
918 }
919 }
921 if (sp_export_area) {
922 /* Try to parse area (given in SVG pixels) */
923 if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
924 g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
925 return;
926 }
927 if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
928 g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
929 return;
930 }
931 } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
932 /* Export the whole canvas */
933 sp_document_ensure_up_to_date (doc);
934 area.x0 = SP_ROOT(doc->root)->x.computed;
935 area.y0 = SP_ROOT(doc->root)->y.computed;
936 area.x1 = area.x0 + sp_document_width (doc);
937 area.y1 = area.y0 + sp_document_height (doc);
938 }
940 // set filename and dpi from options, if not yet set from the hints
941 if (!filename) {
942 if (!sp_export_png) {
943 g_warning ("No export filename given and no filename hint. Nothing exported.");
944 return;
945 }
946 filename = sp_export_png;
947 }
949 if (sp_export_dpi && dpi == 0.0) {
950 dpi = atof(sp_export_dpi);
951 if ((dpi < 0.1) || (dpi > 10000.0)) {
952 g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
953 return;
954 }
955 g_print("DPI: %g\n", dpi);
956 }
958 if (sp_export_area_snap) {
959 area.x0 = std::floor (area.x0);
960 area.y0 = std::floor (area.y0);
961 area.x1 = std::ceil (area.x1);
962 area.y1 = std::ceil (area.y1);
963 }
965 // default dpi
966 if (dpi == 0.0)
967 dpi = PX_PER_IN;
969 gint width = 0;
970 gint height = 0;
972 if (sp_export_width) {
973 width = atoi(sp_export_width);
974 if ((width < 1) || (width > 65536)) {
975 g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
976 return;
977 }
978 dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
979 }
981 if (sp_export_height) {
982 height = atoi(sp_export_height);
983 if ((height < 1) || (height > 65536)) {
984 g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
985 return;
986 }
987 dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
988 }
990 if (!sp_export_width) {
991 width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
992 }
994 if (!sp_export_height) {
995 height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
996 }
998 guint32 bgcolor = 0x00000000;
999 if (sp_export_background) {
1000 // override the page color
1001 bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
1002 bgcolor |= 0xff; // default is no opacity
1003 } else {
1004 // read from namedview
1005 Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
1006 if (nv && nv->attribute("pagecolor"))
1007 bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
1008 if (nv && nv->attribute("inkscape:pageopacity"))
1009 bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
1010 }
1012 if (sp_export_background_opacity) {
1013 // override opacity
1014 gfloat value;
1015 if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
1016 if (value > 1.0) {
1017 value = CLAMP (value, 1.0f, 255.0f);
1018 bgcolor &= (guint32) 0xffffff00;
1019 bgcolor |= (guint32) floor(value);
1020 } else {
1021 value = CLAMP (value, 0.0f, 1.0f);
1022 bgcolor &= (guint32) 0xffffff00;
1023 bgcolor |= SP_COLOR_F_TO_U(value);
1024 }
1025 }
1026 }
1028 g_print("Background RRGGBBAA: %08x\n", bgcolor);
1030 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);
1032 g_print("Bitmap saved as: %s\n", filename);
1034 if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
1035 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);
1036 } else {
1037 g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
1038 }
1040 g_slist_free (items);
1041 }
1044 /**
1045 * Perform an export of either PS or EPS.
1046 *
1047 * \param doc Document to export.
1048 * \param uri URI to export to.
1049 * \param mime MIME type to export as.
1050 */
1052 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
1053 {
1054 Inkscape::Extension::DB::OutputList o;
1055 Inkscape::Extension::db.get_output_list(o);
1056 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1057 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1058 i++;
1059 }
1061 if (i == o.end())
1062 {
1063 g_warning ("Could not find an extension to export this file.");
1064 return;
1065 }
1067 bool old_text_to_path = false;
1068 bool old_font_embedded = false;
1069 bool old_bbox_page = false;
1071 try {
1072 old_text_to_path = (*i)->get_param_bool("textToPath");
1073 (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1074 }
1075 catch (...) {
1076 g_warning ("Could not set export-text-to-path option for this export.");
1077 }
1079 try {
1080 old_font_embedded = (*i)->get_param_bool("fontEmbedded");
1081 (*i)->set_param_bool("fontEmbedded", sp_export_font);
1082 }
1083 catch (...) {
1084 g_warning ("Could not set export-font option for this export.");
1085 }
1087 try {
1088 old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1089 (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1090 }
1091 catch (...) {
1092 g_warning ("Could not set export-bbox-page option for this export.");
1093 }
1095 (*i)->save(doc, uri);
1097 try {
1098 (*i)->set_param_bool("textToPath", old_text_to_path);
1099 (*i)->set_param_bool("fontEmbedded", old_font_embedded);
1100 (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1101 }
1102 catch (...) {
1104 }
1105 }
1107 /**
1108 * Perform a PDF export
1109 *
1110 * \param doc Document to export.
1111 * \param uri URI to export to.
1112 * \param mime MIME type to export as.
1113 */
1115 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
1116 {
1117 Inkscape::Extension::DB::OutputList o;
1118 Inkscape::Extension::db.get_output_list(o);
1119 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1120 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1121 i++;
1122 }
1124 if (i == o.end())
1125 {
1126 g_warning ("Could not find an extension to export this file.");
1127 return;
1128 }
1130 (*i)->save(doc, uri);
1131 }
1133 #ifdef WIN32
1134 bool replaceArgs( int& argc, char**& argv )
1135 {
1136 bool worked = false;
1138 #ifdef REPLACEARGS_DEBUG
1139 MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1140 #endif // REPLACEARGS_DEBUG
1142 wchar_t* line = GetCommandLineW();
1143 if ( line )
1144 {
1145 #ifdef REPLACEARGS_DEBUG
1146 {
1147 gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1148 if ( utf8Line )
1149 {
1150 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1151 {
1152 char tmp[strlen(safe) + 32];
1153 snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1154 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1155 }
1156 }
1157 }
1158 #endif // REPLACEARGS_DEBUG
1160 int numArgs = 0;
1161 wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1163 #ifdef REPLACEARGS_ANSI
1164 // test code for trying things on Win95/98/ME
1165 if ( !parsed )
1166 {
1167 #ifdef REPLACEARGS_DEBUG
1168 MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1169 #endif // REPLACEARGS_DEBUG
1170 int lineLen = wcslen(line) + 1;
1171 wchar_t* lineDup = new wchar_t[lineLen];
1172 wcsncpy( lineDup, line, lineLen );
1174 int pos = 0;
1175 bool inQuotes = false;
1176 bool inWhitespace = true;
1177 std::vector<int> places;
1178 while ( lineDup[pos] )
1179 {
1180 if ( inQuotes )
1181 {
1182 if ( lineDup[pos] == L'"' )
1183 {
1184 inQuotes = false;
1185 }
1186 }
1187 else if ( lineDup[pos] == L'"' )
1188 {
1189 inQuotes = true;
1190 inWhitespace = false;
1191 places.push_back(pos);
1192 }
1193 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1194 {
1195 if ( !inWhitespace )
1196 {
1197 inWhitespace = true;
1198 lineDup[pos] = 0;
1199 }
1200 }
1201 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1202 {
1203 inWhitespace = false;
1204 places.push_back(pos);
1205 }
1206 else
1207 {
1208 // consume
1209 }
1210 pos++;
1211 }
1212 #ifdef REPLACEARGS_DEBUG
1213 {
1214 char tmp[256];
1215 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1216 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1217 }
1218 #endif // REPLACEARGS_DEBUG
1220 wchar_t** block = new wchar_t*[places.size()];
1221 int i = 0;
1222 for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1223 {
1224 block[i++] = &lineDup[*it];
1225 }
1226 parsed = block;
1227 numArgs = places.size();
1228 }
1229 #endif // REPLACEARGS_ANSI
1231 if ( parsed )
1232 {
1233 std::vector<wchar_t*>expandedArgs;
1234 if ( numArgs > 0 )
1235 {
1236 expandedArgs.push_back( parsed[0] );
1237 }
1239 for ( int i1 = 1; i1 < numArgs; i1++ )
1240 {
1241 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1242 wildcarded &= parsed[i1][0] != L'"';
1243 wildcarded &= parsed[i1][0] != L'-';
1244 if ( wildcarded )
1245 {
1246 #ifdef REPLACEARGS_ANSI
1247 WIN32_FIND_DATAA data = {0};
1248 #else
1249 WIN32_FIND_DATAW data = {0};
1250 #endif // REPLACEARGS_ANSI
1252 int baseLen = wcslen(parsed[i1]) + 2;
1253 wchar_t* base = new wchar_t[baseLen];
1254 wcsncpy( base, parsed[i1], baseLen );
1255 wchar_t* last = wcsrchr( base, L'\\' );
1256 if ( last )
1257 {
1258 last[1] = 0;
1259 }
1260 else
1261 {
1262 base[0] = 0;
1263 }
1264 baseLen = wcslen( base );
1266 #ifdef REPLACEARGS_ANSI
1267 char target[MAX_PATH];
1268 if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1269 {
1270 HANDLE hf = FindFirstFileA( target, &data );
1271 #else
1272 HANDLE hf = FindFirstFileW( parsed[i1], &data );
1273 #endif // REPLACEARGS_ANSI
1274 if ( hf != INVALID_HANDLE_VALUE )
1275 {
1276 BOOL found = TRUE;
1277 do
1278 {
1279 #ifdef REPLACEARGS_ANSI
1280 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1281 if ( howMany > 0 )
1282 {
1283 howMany += baseLen;
1284 wchar_t* tmp = new wchar_t[howMany + 1];
1285 wcsncpy( tmp, base, howMany + 1 );
1286 MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1287 expandedArgs.push_back( tmp );
1288 found = FindNextFileA( hf, &data );
1289 }
1290 #else
1291 int howMany = wcslen(data.cFileName) + baseLen;
1292 wchar_t* tmp = new wchar_t[howMany + 1];
1293 wcsncpy( tmp, base, howMany + 1 );
1294 wcsncat( tmp, data.cFileName, howMany + 1 );
1295 expandedArgs.push_back( tmp );
1296 found = FindNextFileW( hf, &data );
1297 #endif // REPLACEARGS_ANSI
1298 } while ( found );
1300 FindClose( hf );
1301 }
1302 else
1303 {
1304 expandedArgs.push_back( parsed[i1] );
1305 }
1306 #ifdef REPLACEARGS_ANSI
1307 }
1308 #endif // REPLACEARGS_ANSI
1310 delete[] base;
1311 }
1312 else
1313 {
1314 expandedArgs.push_back( parsed[i1] );
1315 }
1316 }
1318 {
1319 wchar_t** block = new wchar_t*[expandedArgs.size()];
1320 int iz = 0;
1321 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1322 {
1323 block[iz++] = *it;
1324 }
1325 parsed = block;
1326 numArgs = expandedArgs.size();
1327 }
1329 std::vector<gchar*> newArgs;
1330 for ( int i = 0; i < numArgs; i++ )
1331 {
1332 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1333 if ( replacement )
1334 {
1335 #ifdef REPLACEARGS_DEBUG
1336 gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1338 if ( safe2 )
1339 {
1340 {
1341 char tmp[1024];
1342 snprintf( tmp, sizeof(tmp), " [%2d] = '%s'", i, safe2 );
1343 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1344 }
1345 g_free( safe2 );
1346 }
1347 #endif // REPLACEARGS_DEBUG
1349 newArgs.push_back( replacement );
1350 }
1351 else
1352 {
1353 newArgs.push_back( blankParam );
1354 }
1355 }
1357 // Now push our munged params to be the new argv and argc
1358 {
1359 char** block = new char*[newArgs.size()];
1360 int iz = 0;
1361 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1362 {
1363 block[iz++] = *it;
1364 }
1365 argv = block;
1366 argc = newArgs.size();
1367 worked = true;
1368 }
1369 }
1370 #ifdef REPLACEARGS_DEBUG
1371 else
1372 {
1373 MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1374 }
1375 #endif // REPLACEARGS_DEBUG
1376 }
1377 #ifdef REPLACEARGS_DEBUG
1378 else
1379 {
1380 {
1381 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1382 }
1384 char* line2 = GetCommandLineA();
1385 if ( line2 )
1386 {
1387 gchar *safe = Inkscape::IO::sanitizeString(line2);
1388 {
1389 {
1390 char tmp[strlen(safe) + 32];
1391 snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1392 MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1393 }
1394 }
1395 }
1396 else
1397 {
1398 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1399 }
1400 }
1401 #endif // REPLACEARGS_DEBUG
1403 return worked;
1404 }
1405 #endif // WIN32
1407 static GSList *
1408 sp_process_args(poptContext ctx)
1409 {
1410 GSList *fl = NULL;
1412 gint a;
1413 while ((a = poptGetNextOpt(ctx)) >= 0) {
1414 switch (a) {
1415 case SP_ARG_FILE: {
1416 gchar const *fn = poptGetOptArg(ctx);
1417 if (fn != NULL) {
1418 fl = g_slist_append(fl, g_strdup(fn));
1419 }
1420 break;
1421 }
1422 case SP_ARG_VERSION: {
1423 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1424 exit(0);
1425 break;
1426 }
1427 case SP_ARG_EXTENSIONDIR: {
1428 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1429 exit(0);
1430 break;
1431 }
1432 case SP_ARG_VERB_LIST: {
1433 // This really shouldn't go here, we should init the app.
1434 // But, since we're just exiting in this path, there is
1435 // no harm, and this is really a better place to put
1436 // everything else.
1437 Inkscape::Extension::init();
1438 Inkscape::Verb::list();
1439 exit(0);
1440 break;
1441 }
1442 case SP_ARG_VERB:
1443 case SP_ARG_SELECT: {
1444 gchar const *arg = poptGetOptArg(ctx);
1445 if (arg != NULL) {
1446 // printf("Adding in: %s\n", arg);
1447 new CmdLineAction(a, arg);
1448 }
1449 break;
1450 }
1451 default: {
1452 break;
1453 }
1454 }
1455 }
1457 gchar const ** const args = poptGetArgs(ctx);
1458 if (args != NULL) {
1459 for (unsigned i = 0; args[i] != NULL; i++) {
1460 fl = g_slist_append(fl, g_strdup(args[i]));
1461 }
1462 }
1464 return fl;
1465 }
1468 /*
1469 Local Variables:
1470 mode:c++
1471 c-file-style:"stroustrup"
1472 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1473 indent-tabs-mode:nil
1474 fill-column:99
1475 End:
1476 */
1477 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :