9a6dc0b769394094d51199566c4528657f8eccd9
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 #include <ui/view/view.h>
391 #include <desktop.h>
392 #include <helper/action.h>
394 class CmdLineAction {
395 gint _type;
396 gchar * _arg;
398 static std::list <CmdLineAction *> _list;
400 public:
401 CmdLineAction (gint type, gchar const * arg) : _type(type), _arg(NULL) {
402 if (arg != NULL) {
403 _arg = g_strdup(arg);
404 }
406 _list.insert(_list.end(), this);
408 return;
409 }
411 ~CmdLineAction () {
412 if (_arg != NULL) {
413 g_free(_arg);
414 }
415 }
417 void doIt (Inkscape::UI::View::View * view) {
418 printf("Doing: %s\n", _arg);
419 switch (_type) {
420 case SP_ARG_VERB: {
421 Inkscape::Verb * verb = Inkscape::Verb::getbyid(_arg);
422 if (verb == NULL) {
423 printf(_("Unable to find verb ID '%s' specified on the command line.\n"), _arg);
424 }
425 SPAction * action = verb->get_action(view);
426 sp_action_perform(action, NULL);
427 break;
428 }
429 case SP_ARG_SELECT: {
431 break;
432 }
433 }
434 }
436 static void doList (Inkscape::UI::View::View * view) {
437 for (std::list<CmdLineAction *>::iterator i = _list.begin();
438 i != _list.end(); i++) {
439 CmdLineAction * entry = *i;
440 entry->doIt(view);
441 }
442 }
444 static bool idle (void) {
445 std::list<SPDesktop *> desktops;
446 inkscape_get_all_desktops(desktops);
448 // We're going to assume one desktop per document, because no one
449 // should have had time to make more at this point.
450 for (std::list<SPDesktop *>::iterator i = desktops.begin();
451 i != desktops.end(); i++) {
452 SPDesktop * desktop = *i;
453 //Inkscape::UI::View::View * view = dynamic_cast<Inkscape::UI::View::View *>(desktop);
454 doList(desktop);
455 }
456 return false;
457 }
458 };
459 std::list <CmdLineAction *> CmdLineAction::_list;
462 static bool needToRecodeParams = true;
463 gchar* blankParam = "";
465 int
466 main(int argc, char **argv)
467 {
468 #ifdef HAVE_FPSETMASK
469 /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__. It's probably
470 safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
471 the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
472 fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
473 #endif
475 #ifdef ENABLE_NLS
476 #ifdef WIN32
477 RegistryTool rt;
478 rt.setPathInfo();
479 gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
480 bindtextdomain(GETTEXT_PACKAGE, pathBuf);
481 g_free(pathBuf);
482 #else
483 #ifdef ENABLE_BINRELOC
484 bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
485 #else
486 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
487 #endif
488 #endif
489 // Allow the user to override the locale directory by setting
490 // the environment variable INKSCAPE_LOCALEDIR.
491 char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
492 if (inkscape_localedir != NULL) {
493 bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
494 }
495 #endif
497 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
499 #ifdef ENABLE_NLS
500 textdomain(GETTEXT_PACKAGE);
501 #endif
503 LIBXML_TEST_VERSION
505 Inkscape::GC::init();
507 Inkscape::Debug::Logger::init();
509 gboolean use_gui;
510 #ifndef WIN32
511 use_gui = (getenv("DISPLAY") != NULL);
512 #else
513 /*
514 Set the current directory to the directory of the
515 executable. This seems redundant, but is needed for
516 when inkscape.exe is executed from another directory.
517 We use relative paths on win32.
518 HKCR\svgfile\shell\open\command is a good example
519 */
520 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
521 char *homedir = g_path_get_dirname(argv[0]);
522 SetCurrentDirectory(homedir);
523 g_free(homedir);
525 use_gui = TRUE;
526 #endif
527 /* Test whether with/without GUI is forced */
528 for (int i = 1; i < argc; i++) {
529 if (!strcmp(argv[i], "-z")
530 || !strcmp(argv[i], "--without-gui")
531 || !strcmp(argv[i], "-p")
532 || !strncmp(argv[i], "--print", 7)
533 || !strcmp(argv[i], "-e")
534 || !strncmp(argv[i], "--export-png", 12)
535 || !strcmp(argv[i], "-l")
536 || !strncmp(argv[i], "--export-plain-svg", 12)
537 || !strcmp(argv[i], "-i")
538 || !strncmp(argv[i], "--export-area-drawing", 21)
539 || !strcmp(argv[i], "-D")
540 || !strncmp(argv[i], "--export-area-canvas", 20)
541 || !strcmp(argv[i], "-C")
542 || !strncmp(argv[i], "--export-id", 12)
543 || !strcmp(argv[i], "-P")
544 || !strncmp(argv[i], "--export-ps", 11)
545 || !strcmp(argv[i], "-E")
546 || !strncmp(argv[i], "--export-eps", 12)
547 || !strcmp(argv[i], "-A")
548 || !strncmp(argv[i], "--export-pdf", 12)
549 || !strcmp(argv[i], "-W")
550 || !strncmp(argv[i], "--query-width", 13)
551 || !strcmp(argv[i], "-H")
552 || !strncmp(argv[i], "--query-height", 14)
553 || !strcmp(argv[i], "-X")
554 || !strncmp(argv[i], "--query-x", 13)
555 || !strcmp(argv[i], "-Y")
556 || !strncmp(argv[i], "--query-y", 14)
557 || !strcmp(argv[i], "--vacuum-defs")
558 )
559 {
560 /* main_console handles any exports -- not the gui */
561 use_gui = FALSE;
562 break;
563 } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
564 use_gui = TRUE;
565 break;
566 }
567 }
569 #ifdef WIN32
570 #ifndef REPLACEARGS_ANSI
571 if ( PrintWin32::is_os_wide() )
572 #endif // REPLACEARGS_ANSI
573 {
574 // If the call fails, we'll need to convert charsets
575 needToRecodeParams = !replaceArgs( argc, argv );
576 }
577 #endif // WIN32
579 /// \todo Should this be a static object (see inkscape.cpp)?
580 Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
582 return app.run();
583 }
585 void fixupSingleFilename( gchar **orig, gchar **spare )
586 {
587 if ( orig && *orig && **orig ) {
588 GError *error = NULL;
589 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
590 if ( newFileName )
591 {
592 *orig = newFileName;
593 if ( spare ) {
594 *spare = newFileName;
595 }
596 // g_message("Set a replacement fixup");
597 }
598 }
599 }
601 GSList *fixupFilenameEncoding( GSList* fl )
602 {
603 GSList *newFl = NULL;
604 while ( fl ) {
605 gchar *fn = static_cast<gchar*>(fl->data);
606 fl = g_slist_remove( fl, fl->data );
607 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
608 if ( newFileName ) {
610 if ( 0 )
611 {
612 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
613 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
614 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
615 "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
616 gtk_dialog_run (GTK_DIALOG (w));
617 gtk_widget_destroy (w);
618 g_free(safeNewFn);
619 g_free(safeFn);
620 }
622 g_free( fn );
623 fn = newFileName;
624 newFileName = 0;
625 }
626 else
627 if ( 0 )
628 {
629 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
630 GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
631 gtk_dialog_run (GTK_DIALOG (w));
632 gtk_widget_destroy (w);
633 g_free(safeFn);
634 }
635 newFl = g_slist_append( newFl, fn );
636 }
637 return newFl;
638 }
640 int sp_common_main( int argc, char const **argv, GSList **flDest )
641 {
642 /// \todo fixme: Move these to some centralized location (Lauris)
643 sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
644 sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
647 // temporarily switch gettext encoding to locale, so that help messages can be output properly
648 gchar const *charset;
649 g_get_charset(&charset);
651 bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
653 poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
654 poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
655 g_return_val_if_fail(ctx != NULL, 1);
657 /* Collect own arguments */
658 GSList *fl = sp_process_args(ctx);
659 poptFreeContext(ctx);
661 // now switch gettext back to UTF-8 (for GUI)
662 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
664 // Now let's see if the file list still holds up
665 if ( needToRecodeParams )
666 {
667 fl = fixupFilenameEncoding( fl );
668 }
670 // Check the globals for filename-fixup
671 if ( needToRecodeParams )
672 {
673 fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
674 fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
675 fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
676 }
677 else
678 {
679 if ( sp_export_png )
680 sp_export_png_utf8 = g_strdup( sp_export_png );
681 if ( sp_export_svg )
682 sp_export_svg_utf8 = g_strdup( sp_export_svg );
683 if ( sp_global_printer )
684 sp_global_printer_utf8 = g_strdup( sp_global_printer );
685 }
687 // Return the list if wanted, else free it up.
688 if ( flDest ) {
689 *flDest = fl;
690 fl = 0;
691 } else {
692 while ( fl ) {
693 g_free( fl->data );
694 fl = g_slist_remove( fl, fl->data );
695 }
696 }
697 return 0;
698 }
700 int
701 sp_main_gui(int argc, char const **argv)
702 {
703 Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
705 GSList *fl = NULL;
706 int retVal = sp_common_main( argc, argv, &fl );
707 g_return_val_if_fail(retVal == 0, 1);
709 inkscape_gtk_stock_init();
711 /* Set default icon */
712 gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
713 if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
714 gtk_window_set_default_icon_from_file(filename, NULL);
715 }
716 g_free (filename);
717 filename = 0;
719 if (!sp_global_slideshow) {
720 gboolean create_new = TRUE;
722 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
723 inkscape_application_init(argv[0], true);
725 while (fl) {
726 if (sp_file_open((gchar *)fl->data,NULL)) {
727 create_new=FALSE;
728 }
729 fl = g_slist_remove(fl, fl->data);
730 }
731 if (create_new) {
732 sp_file_new_default();
733 }
734 } else {
735 if (fl) {
736 GtkWidget *ss;
737 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
738 inkscape_application_init(argv[0], true);
739 ss = sp_slideshow_new(fl);
740 if (ss) gtk_widget_show(ss);
741 } else {
742 g_warning ("No slides to display");
743 exit(0);
744 }
745 }
747 Glib::signal_idle().connect(sigc::ptr_fun(&CmdLineAction::idle));
748 main_instance.run();
750 #ifdef WIN32
751 //We might not need anything here
752 //sp_win32_finish(); <-- this is a NOP func
753 #endif
755 return 0;
756 }
758 int
759 sp_main_console(int argc, char const **argv)
760 {
761 /* We are started in text mode */
763 /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
764 * in a non-Gtk environment. Used in libnrtype's
765 * FontInstance.cpp and FontFactory.cpp.
766 * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
767 */
768 g_type_init();
769 char **argv2 = const_cast<char **>(argv);
770 gtk_init_check( &argc, &argv2 );
771 //setlocale(LC_ALL, "");
773 GSList *fl = NULL;
774 int retVal = sp_common_main( argc, argv, &fl );
775 g_return_val_if_fail(retVal == 0, 1);
777 if (fl == NULL) {
778 g_print("Nothing to do!\n");
779 exit(0);
780 }
782 inkscape_application_init(argv[0], false);
784 while (fl) {
785 SPDocument *doc;
787 doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
788 if (doc == NULL) {
789 doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
790 }
791 if (doc == NULL) {
792 g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
793 } else {
794 if (sp_vacuum_defs) {
795 vacuum_document(doc);
796 }
797 if (sp_vacuum_defs && !sp_export_svg) {
798 // save under the name given in the command line
799 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
800 }
801 if (sp_global_printer) {
802 sp_print_document_to_file(doc, sp_global_printer);
803 }
804 if (sp_export_png || sp_export_id || sp_export_area_drawing) {
805 sp_do_export_png(doc);
806 }
807 if (sp_export_svg) {
808 Inkscape::XML::Document *rdoc;
809 Inkscape::XML::Node *repr;
810 rdoc = sp_repr_document_new("svg:svg");
811 repr = rdoc->root();
812 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
813 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
814 }
815 if (sp_export_ps) {
816 do_export_ps(doc, sp_export_ps, "image/x-postscript");
817 }
818 if (sp_export_eps) {
819 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
820 }
821 if (sp_export_pdf) {
822 do_export_pdf(doc, sp_export_pdf, "application/pdf");
823 }
824 if (sp_query_width || sp_query_height) {
825 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
826 } else if (sp_query_x || sp_query_y) {
827 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
828 }
830 //CmdLineAction::doList(doc);
831 }
833 fl = g_slist_remove(fl, fl->data);
834 }
836 inkscape_unref();
838 return 0;
839 }
841 static void
842 do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
843 {
844 SPObject *o = NULL;
846 if (id) {
847 o = doc->getObjectById(id);
848 if (o) {
849 if (!SP_IS_ITEM (o)) {
850 g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
851 return;
852 }
853 } else {
854 g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
855 return;
856 }
857 } else {
858 o = SP_DOCUMENT_ROOT(doc);
859 }
861 if (o) {
862 sp_document_ensure_up_to_date (doc);
863 SPItem *item = ((SPItem *) o);
864 NR::Rect area = item->invokeBbox(sp_item_i2doc_affine(item)); // "true" SVG bbox for scripting
866 Inkscape::SVGOStringStream os;
867 if (extent) {
868 os << area.extent(axis);
869 } else {
870 os << area.min()[axis];
871 }
872 g_print ("%s", os.str().c_str());
873 }
874 }
877 static void
878 sp_do_export_png(SPDocument *doc)
879 {
880 const gchar *filename = NULL;
881 gdouble dpi = 0.0;
883 if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
884 g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
885 }
887 GSList *items = NULL;
889 NRRect area;
890 if (sp_export_id || sp_export_area_drawing) {
892 SPObject *o = NULL;
893 SPObject *o_area = NULL;
894 if (sp_export_id && sp_export_area_drawing) {
895 o = doc->getObjectById(sp_export_id);
896 o_area = SP_DOCUMENT_ROOT (doc);
897 } else if (sp_export_id) {
898 o = doc->getObjectById(sp_export_id);
899 o_area = o;
900 } else if (sp_export_area_drawing) {
901 o = SP_DOCUMENT_ROOT (doc);
902 o_area = o;
903 }
905 if (o) {
906 if (!SP_IS_ITEM (o)) {
907 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
908 return;
909 }
911 items = g_slist_prepend (items, SP_ITEM(o));
913 if (sp_export_id_only) {
914 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
915 }
917 if (sp_export_use_hints) {
919 // retrieve export filename hint
920 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
921 if (fn_hint) {
922 if (sp_export_png) {
923 g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
924 filename = sp_export_png;
925 } else {
926 filename = fn_hint;
927 }
928 } else {
929 g_warning ("Export filename hint not found for the object.");
930 filename = sp_export_png;
931 }
933 // retrieve export dpi hints
934 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
935 if (dpi_hint) {
936 if (sp_export_dpi || sp_export_width || sp_export_height) {
937 g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
938 } else {
939 dpi = atof(dpi_hint);
940 }
941 } else {
942 g_warning ("Export DPI hint not found for the object.");
943 }
945 }
947 // write object bbox to area
948 sp_document_ensure_up_to_date (doc);
949 sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
950 } else {
951 g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
952 return;
953 }
954 }
956 if (sp_export_area) {
957 /* Try to parse area (given in SVG pixels) */
958 if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
959 g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
960 return;
961 }
962 if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
963 g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
964 return;
965 }
966 } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
967 /* Export the whole canvas */
968 sp_document_ensure_up_to_date (doc);
969 area.x0 = SP_ROOT(doc->root)->x.computed;
970 area.y0 = SP_ROOT(doc->root)->y.computed;
971 area.x1 = area.x0 + sp_document_width (doc);
972 area.y1 = area.y0 + sp_document_height (doc);
973 }
975 // set filename and dpi from options, if not yet set from the hints
976 if (!filename) {
977 if (!sp_export_png) {
978 g_warning ("No export filename given and no filename hint. Nothing exported.");
979 return;
980 }
981 filename = sp_export_png;
982 }
984 if (sp_export_dpi && dpi == 0.0) {
985 dpi = atof(sp_export_dpi);
986 if ((dpi < 0.1) || (dpi > 10000.0)) {
987 g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
988 return;
989 }
990 g_print("DPI: %g\n", dpi);
991 }
993 if (sp_export_area_snap) {
994 area.x0 = std::floor (area.x0);
995 area.y0 = std::floor (area.y0);
996 area.x1 = std::ceil (area.x1);
997 area.y1 = std::ceil (area.y1);
998 }
1000 // default dpi
1001 if (dpi == 0.0)
1002 dpi = PX_PER_IN;
1004 gint width = 0;
1005 gint height = 0;
1007 if (sp_export_width) {
1008 width = atoi(sp_export_width);
1009 if ((width < 1) || (width > 65536)) {
1010 g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
1011 return;
1012 }
1013 dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
1014 }
1016 if (sp_export_height) {
1017 height = atoi(sp_export_height);
1018 if ((height < 1) || (height > 65536)) {
1019 g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
1020 return;
1021 }
1022 dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
1023 }
1025 if (!sp_export_width) {
1026 width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
1027 }
1029 if (!sp_export_height) {
1030 height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
1031 }
1033 guint32 bgcolor = 0x00000000;
1034 if (sp_export_background) {
1035 // override the page color
1036 bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
1037 bgcolor |= 0xff; // default is no opacity
1038 } else {
1039 // read from namedview
1040 Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
1041 if (nv && nv->attribute("pagecolor"))
1042 bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
1043 if (nv && nv->attribute("inkscape:pageopacity"))
1044 bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
1045 }
1047 if (sp_export_background_opacity) {
1048 // override opacity
1049 gfloat value;
1050 if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
1051 if (value > 1.0) {
1052 value = CLAMP (value, 1.0f, 255.0f);
1053 bgcolor &= (guint32) 0xffffff00;
1054 bgcolor |= (guint32) floor(value);
1055 } else {
1056 value = CLAMP (value, 0.0f, 1.0f);
1057 bgcolor &= (guint32) 0xffffff00;
1058 bgcolor |= SP_COLOR_F_TO_U(value);
1059 }
1060 }
1061 }
1063 g_print("Background RRGGBBAA: %08x\n", bgcolor);
1065 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);
1067 g_print("Bitmap saved as: %s\n", filename);
1069 if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
1070 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);
1071 } else {
1072 g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
1073 }
1075 g_slist_free (items);
1076 }
1079 /**
1080 * Perform an export of either PS or EPS.
1081 *
1082 * \param doc Document to export.
1083 * \param uri URI to export to.
1084 * \param mime MIME type to export as.
1085 */
1087 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
1088 {
1089 Inkscape::Extension::DB::OutputList o;
1090 Inkscape::Extension::db.get_output_list(o);
1091 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1092 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1093 i++;
1094 }
1096 if (i == o.end())
1097 {
1098 g_warning ("Could not find an extension to export this file.");
1099 return;
1100 }
1102 bool old_text_to_path = false;
1103 bool old_font_embedded = false;
1104 bool old_bbox_page = false;
1106 try {
1107 old_text_to_path = (*i)->get_param_bool("textToPath");
1108 (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1109 }
1110 catch (...) {
1111 g_warning ("Could not set export-text-to-path option for this export.");
1112 }
1114 try {
1115 old_font_embedded = (*i)->get_param_bool("fontEmbedded");
1116 (*i)->set_param_bool("fontEmbedded", sp_export_font);
1117 }
1118 catch (...) {
1119 g_warning ("Could not set export-font option for this export.");
1120 }
1122 try {
1123 old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1124 (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1125 }
1126 catch (...) {
1127 g_warning ("Could not set export-bbox-page option for this export.");
1128 }
1130 (*i)->save(doc, uri);
1132 try {
1133 (*i)->set_param_bool("textToPath", old_text_to_path);
1134 (*i)->set_param_bool("fontEmbedded", old_font_embedded);
1135 (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1136 }
1137 catch (...) {
1139 }
1140 }
1142 /**
1143 * Perform a PDF export
1144 *
1145 * \param doc Document to export.
1146 * \param uri URI to export to.
1147 * \param mime MIME type to export as.
1148 */
1150 static void do_export_pdf(SPDocument* doc, gchar const* uri, char const* mime)
1151 {
1152 Inkscape::Extension::DB::OutputList o;
1153 Inkscape::Extension::db.get_output_list(o);
1154 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1155 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1156 i++;
1157 }
1159 if (i == o.end())
1160 {
1161 g_warning ("Could not find an extension to export this file.");
1162 return;
1163 }
1165 (*i)->save(doc, uri);
1166 }
1168 #ifdef WIN32
1169 bool replaceArgs( int& argc, char**& argv )
1170 {
1171 bool worked = false;
1173 #ifdef REPLACEARGS_DEBUG
1174 MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1175 #endif // REPLACEARGS_DEBUG
1177 wchar_t* line = GetCommandLineW();
1178 if ( line )
1179 {
1180 #ifdef REPLACEARGS_DEBUG
1181 {
1182 gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1183 if ( utf8Line )
1184 {
1185 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1186 {
1187 char tmp[strlen(safe) + 32];
1188 snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1189 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1190 }
1191 }
1192 }
1193 #endif // REPLACEARGS_DEBUG
1195 int numArgs = 0;
1196 wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1198 #ifdef REPLACEARGS_ANSI
1199 // test code for trying things on Win95/98/ME
1200 if ( !parsed )
1201 {
1202 #ifdef REPLACEARGS_DEBUG
1203 MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1204 #endif // REPLACEARGS_DEBUG
1205 int lineLen = wcslen(line) + 1;
1206 wchar_t* lineDup = new wchar_t[lineLen];
1207 wcsncpy( lineDup, line, lineLen );
1209 int pos = 0;
1210 bool inQuotes = false;
1211 bool inWhitespace = true;
1212 std::vector<int> places;
1213 while ( lineDup[pos] )
1214 {
1215 if ( inQuotes )
1216 {
1217 if ( lineDup[pos] == L'"' )
1218 {
1219 inQuotes = false;
1220 }
1221 }
1222 else if ( lineDup[pos] == L'"' )
1223 {
1224 inQuotes = true;
1225 inWhitespace = false;
1226 places.push_back(pos);
1227 }
1228 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1229 {
1230 if ( !inWhitespace )
1231 {
1232 inWhitespace = true;
1233 lineDup[pos] = 0;
1234 }
1235 }
1236 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1237 {
1238 inWhitespace = false;
1239 places.push_back(pos);
1240 }
1241 else
1242 {
1243 // consume
1244 }
1245 pos++;
1246 }
1247 #ifdef REPLACEARGS_DEBUG
1248 {
1249 char tmp[256];
1250 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1251 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1252 }
1253 #endif // REPLACEARGS_DEBUG
1255 wchar_t** block = new wchar_t*[places.size()];
1256 int i = 0;
1257 for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1258 {
1259 block[i++] = &lineDup[*it];
1260 }
1261 parsed = block;
1262 numArgs = places.size();
1263 }
1264 #endif // REPLACEARGS_ANSI
1266 if ( parsed )
1267 {
1268 std::vector<wchar_t*>expandedArgs;
1269 if ( numArgs > 0 )
1270 {
1271 expandedArgs.push_back( parsed[0] );
1272 }
1274 for ( int i1 = 1; i1 < numArgs; i1++ )
1275 {
1276 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1277 wildcarded &= parsed[i1][0] != L'"';
1278 wildcarded &= parsed[i1][0] != L'-';
1279 if ( wildcarded )
1280 {
1281 #ifdef REPLACEARGS_ANSI
1282 WIN32_FIND_DATAA data = {0};
1283 #else
1284 WIN32_FIND_DATAW data = {0};
1285 #endif // REPLACEARGS_ANSI
1287 int baseLen = wcslen(parsed[i1]) + 2;
1288 wchar_t* base = new wchar_t[baseLen];
1289 wcsncpy( base, parsed[i1], baseLen );
1290 wchar_t* last = wcsrchr( base, L'\\' );
1291 if ( last )
1292 {
1293 last[1] = 0;
1294 }
1295 else
1296 {
1297 base[0] = 0;
1298 }
1299 baseLen = wcslen( base );
1301 #ifdef REPLACEARGS_ANSI
1302 char target[MAX_PATH];
1303 if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1304 {
1305 HANDLE hf = FindFirstFileA( target, &data );
1306 #else
1307 HANDLE hf = FindFirstFileW( parsed[i1], &data );
1308 #endif // REPLACEARGS_ANSI
1309 if ( hf != INVALID_HANDLE_VALUE )
1310 {
1311 BOOL found = TRUE;
1312 do
1313 {
1314 #ifdef REPLACEARGS_ANSI
1315 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1316 if ( howMany > 0 )
1317 {
1318 howMany += baseLen;
1319 wchar_t* tmp = new wchar_t[howMany + 1];
1320 wcsncpy( tmp, base, howMany + 1 );
1321 MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1322 expandedArgs.push_back( tmp );
1323 found = FindNextFileA( hf, &data );
1324 }
1325 #else
1326 int howMany = wcslen(data.cFileName) + baseLen;
1327 wchar_t* tmp = new wchar_t[howMany + 1];
1328 wcsncpy( tmp, base, howMany + 1 );
1329 wcsncat( tmp, data.cFileName, howMany + 1 );
1330 expandedArgs.push_back( tmp );
1331 found = FindNextFileW( hf, &data );
1332 #endif // REPLACEARGS_ANSI
1333 } while ( found );
1335 FindClose( hf );
1336 }
1337 else
1338 {
1339 expandedArgs.push_back( parsed[i1] );
1340 }
1341 #ifdef REPLACEARGS_ANSI
1342 }
1343 #endif // REPLACEARGS_ANSI
1345 delete[] base;
1346 }
1347 else
1348 {
1349 expandedArgs.push_back( parsed[i1] );
1350 }
1351 }
1353 {
1354 wchar_t** block = new wchar_t*[expandedArgs.size()];
1355 int iz = 0;
1356 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1357 {
1358 block[iz++] = *it;
1359 }
1360 parsed = block;
1361 numArgs = expandedArgs.size();
1362 }
1364 std::vector<gchar*> newArgs;
1365 for ( int i = 0; i < numArgs; i++ )
1366 {
1367 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1368 if ( replacement )
1369 {
1370 #ifdef REPLACEARGS_DEBUG
1371 gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1373 if ( safe2 )
1374 {
1375 {
1376 char tmp[1024];
1377 snprintf( tmp, sizeof(tmp), " [%2d] = '%s'", i, safe2 );
1378 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1379 }
1380 g_free( safe2 );
1381 }
1382 #endif // REPLACEARGS_DEBUG
1384 newArgs.push_back( replacement );
1385 }
1386 else
1387 {
1388 newArgs.push_back( blankParam );
1389 }
1390 }
1392 // Now push our munged params to be the new argv and argc
1393 {
1394 char** block = new char*[newArgs.size()];
1395 int iz = 0;
1396 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1397 {
1398 block[iz++] = *it;
1399 }
1400 argv = block;
1401 argc = newArgs.size();
1402 worked = true;
1403 }
1404 }
1405 #ifdef REPLACEARGS_DEBUG
1406 else
1407 {
1408 MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1409 }
1410 #endif // REPLACEARGS_DEBUG
1411 }
1412 #ifdef REPLACEARGS_DEBUG
1413 else
1414 {
1415 {
1416 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1417 }
1419 char* line2 = GetCommandLineA();
1420 if ( line2 )
1421 {
1422 gchar *safe = Inkscape::IO::sanitizeString(line2);
1423 {
1424 {
1425 char tmp[strlen(safe) + 32];
1426 snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1427 MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1428 }
1429 }
1430 }
1431 else
1432 {
1433 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1434 }
1435 }
1436 #endif // REPLACEARGS_DEBUG
1438 return worked;
1439 }
1440 #endif // WIN32
1442 static GSList *
1443 sp_process_args(poptContext ctx)
1444 {
1445 GSList *fl = NULL;
1447 gint a;
1448 while ((a = poptGetNextOpt(ctx)) >= 0) {
1449 switch (a) {
1450 case SP_ARG_FILE: {
1451 gchar const *fn = poptGetOptArg(ctx);
1452 if (fn != NULL) {
1453 fl = g_slist_append(fl, g_strdup(fn));
1454 }
1455 break;
1456 }
1457 case SP_ARG_VERSION: {
1458 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1459 exit(0);
1460 break;
1461 }
1462 case SP_ARG_EXTENSIONDIR: {
1463 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1464 exit(0);
1465 break;
1466 }
1467 case SP_ARG_VERB_LIST: {
1468 // This really shouldn't go here, we should init the app.
1469 // But, since we're just exiting in this path, there is
1470 // no harm, and this is really a better place to put
1471 // everything else.
1472 Inkscape::Extension::init();
1473 Inkscape::Verb::list();
1474 exit(0);
1475 break;
1476 }
1477 case SP_ARG_VERB:
1478 case SP_ARG_SELECT: {
1479 gchar const *arg = poptGetOptArg(ctx);
1480 if (arg != NULL) {
1481 // printf("Adding in: %s\n", arg);
1482 new CmdLineAction(a, arg);
1483 }
1484 break;
1485 }
1486 default: {
1487 break;
1488 }
1489 }
1490 }
1492 gchar const ** const args = poptGetArgs(ctx);
1493 if (args != NULL) {
1494 for (unsigned i = 0; args[i] != NULL; i++) {
1495 fl = g_slist_append(fl, g_strdup(args[i]));
1496 }
1497 }
1499 return fl;
1500 }
1503 /*
1504 Local Variables:
1505 mode:c++
1506 c-file-style:"stroustrup"
1507 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1508 indent-tabs-mode:nil
1509 fill-column:99
1510 End:
1511 */
1512 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :