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 <gtk/gtkmain.h>
53 #include "gc-core.h"
55 #include "macros.h"
56 #include "file.h"
57 #include "document.h"
58 #include "sp-object.h"
59 #include "interface.h"
60 #include "print.h"
61 #include "slideshow.h"
62 #include "color.h"
63 #include "sp-item.h"
64 #include "sp-root.h"
65 #include "unit-constants.h"
67 #include "svg/svg.h"
68 #include "svg/svg-color.h"
69 #include "svg/stringstream.h"
71 #include "inkscape-private.h"
72 #include "inkscape-stock.h"
73 #include "inkscape_version.h"
75 #include "sp-namedview.h"
76 #include "sp-guide.h"
77 #include "sp-object-repr.h"
78 #include "xml/repr.h"
80 #include "io/sys.h"
82 #include "debug/logger.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_TEXT_TO_PATH,
134 SP_ARG_EXPORT_BBOX_PAGE,
135 SP_ARG_EXTENSIONDIR,
136 SP_ARG_SLIDESHOW,
137 SP_ARG_QUERY_X,
138 SP_ARG_QUERY_Y,
139 SP_ARG_QUERY_WIDTH,
140 SP_ARG_QUERY_HEIGHT,
141 SP_ARG_QUERY_ID,
142 SP_ARG_VERSION,
143 SP_ARG_NEW_GUI,
144 SP_ARG_VACUUM_DEFS,
145 SP_ARG_LAST
146 };
148 int sp_main_gui(int argc, char const **argv);
149 int sp_main_console(int argc, char const **argv);
150 static void sp_do_export_png(SPDocument *doc);
151 static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
152 static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);
155 static gchar *sp_global_printer = NULL;
156 static gboolean sp_global_slideshow = FALSE;
157 static gchar *sp_export_png = NULL;
158 static gchar *sp_export_dpi = NULL;
159 static gchar *sp_export_area = NULL;
160 static gboolean sp_export_area_drawing = FALSE;
161 static gboolean sp_export_area_canvas = FALSE;
162 static gchar *sp_export_width = NULL;
163 static gchar *sp_export_height = NULL;
164 static gchar *sp_export_id = NULL;
165 static gchar *sp_export_background = NULL;
166 static gchar *sp_export_background_opacity = NULL;
167 static gboolean sp_export_area_snap = FALSE;
168 static gboolean sp_export_use_hints = FALSE;
169 static gboolean sp_export_id_only = FALSE;
170 static gchar *sp_export_svg = NULL;
171 static gchar *sp_export_ps = NULL;
172 static gchar *sp_export_eps = NULL;
173 static gboolean sp_export_text_to_path = FALSE;
174 static gboolean sp_export_bbox_page = FALSE;
175 static gboolean sp_query_x = FALSE;
176 static gboolean sp_query_y = FALSE;
177 static gboolean sp_query_width = FALSE;
178 static gboolean sp_query_height = FALSE;
179 static gchar *sp_query_id = NULL;
180 static int sp_new_gui = FALSE;
181 static gboolean sp_vacuum_defs = FALSE;
183 static gchar *sp_export_png_utf8 = NULL;
184 static gchar *sp_export_svg_utf8 = NULL;
185 static gchar *sp_global_printer_utf8 = NULL;
187 #ifdef WIN32
188 static bool replaceArgs( int& argc, char**& argv );
189 #endif
190 static GSList *sp_process_args(poptContext ctx);
191 struct poptOption options[] = {
192 {"version", 'V',
193 POPT_ARG_NONE, NULL, SP_ARG_VERSION,
194 N_("Print the Inkscape version number"),
195 NULL},
197 {"without-gui", 'z',
198 POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
199 N_("Do not use X server (only process files from console)"),
200 NULL},
202 {"with-gui", 'g',
203 POPT_ARG_NONE, NULL, SP_ARG_GUI,
204 N_("Try to use X server (even if $DISPLAY is not set)"),
205 NULL},
207 {"file", 'f',
208 POPT_ARG_STRING, NULL, SP_ARG_FILE,
209 N_("Open specified document(s) (option string may be excluded)"),
210 N_("FILENAME")},
212 {"print", 'p',
213 POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
214 N_("Print document(s) to specified output file (use '| program' for pipe)"),
215 N_("FILENAME")},
217 {"export-png", 'e',
218 POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
219 N_("Export document to a PNG file"),
220 N_("FILENAME")},
222 {"export-dpi", 'd',
223 POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
224 N_("The resolution used for exporting SVG into bitmap (default 90)"),
225 N_("DPI")},
227 {"export-area", 'a',
228 POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
229 N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
230 N_("x0:y0:x1:y1")},
232 {"export-area-drawing", 'D',
233 POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
234 N_("Exported area is the entire drawing (not canvas)"),
235 NULL},
237 {"export-area-canvas", 'C',
238 POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
239 N_("Exported area is the entire canvas"),
240 NULL},
242 {"export-area-snap", 0,
243 POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
244 N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
245 NULL},
247 {"export-width", 'w',
248 POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
249 N_("The width of exported bitmap in pixels (overrides export-dpi)"),
250 N_("WIDTH")},
252 {"export-height", 'h',
253 POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
254 N_("The height of exported bitmap in pixels (overrides export-dpi)"),
255 N_("HEIGHT")},
257 {"export-id", 'i',
258 POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
259 N_("The ID of the object to export"),
260 N_("ID")},
262 {"export-id-only", 'j',
263 POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
264 // TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
265 // See "man inkscape" for details.
266 N_("Export just the object with export-id, hide all others (only with export-id)"),
267 NULL},
269 {"export-use-hints", 't',
270 POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
271 N_("Use stored filename and DPI hints when exporting (only with export-id)"),
272 NULL},
274 {"export-background", 'b',
275 POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
276 N_("Background color of exported bitmap (any SVG-supported color string)"),
277 N_("COLOR")},
279 {"export-background-opacity", 'y',
280 POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
281 N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"),
282 N_("VALUE")},
284 {"export-plain-svg", 'l',
285 POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
286 N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"),
287 N_("FILENAME")},
289 {"export-ps", 'P',
290 POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
291 N_("Export document to a PS file"),
292 N_("FILENAME")},
294 {"export-eps", 'E',
295 POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
296 N_("Export document to an EPS file"),
297 N_("FILENAME")},
299 {"export-text-to-path", 'T',
300 POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
301 N_("Convert text object to paths on export (EPS)"),
302 NULL},
304 {"export-bbox-page", 'B',
305 POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
306 N_("Export files with the bounding box set to the page size (EPS)"),
307 NULL},
309 {"query-x", 'X',
310 POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
311 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
312 N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
313 NULL},
315 {"query-y", 'Y',
316 POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
317 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
318 N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
319 NULL},
321 {"query-width", 'W',
322 POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
323 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
324 N_("Query the width of the drawing or, if specified, of the object with --query-id"),
325 NULL},
327 {"query-height", 'H',
328 POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
329 // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
330 N_("Query the height of the drawing or, if specified, of the object with --query-id"),
331 NULL},
333 {"query-id", 'I',
334 POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
335 N_("The ID of the object whose dimensions are queried"),
336 N_("ID")},
338 {"extension-directory", 'x',
339 POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
340 // TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
341 N_("Print out the extension directory and exit"),
342 NULL},
344 {"slideshow", 's',
345 POPT_ARG_NONE, &sp_global_slideshow, SP_ARG_SLIDESHOW,
346 N_("Show given files one-by-one, switch to next on any key/mouse event"),
347 NULL},
349 {"new-gui", 'G',
350 POPT_ARG_NONE, &sp_new_gui, SP_ARG_NEW_GUI,
351 N_("Use the new Gtkmm GUI interface"),
352 NULL},
354 {"vacuum-defs", 0,
355 POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
356 N_("Remove unused definitions from the defs section(s) of the document"),
357 NULL},
359 POPT_AUTOHELP POPT_TABLEEND
360 };
362 static bool needToRecodeParams = true;
363 gchar* blankParam = "";
365 int
366 main(int argc, char **argv)
367 {
368 #ifdef HAVE_FPSETMASK
369 /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__. It's probably
370 safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
371 the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
372 fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
373 #endif
375 #ifdef ENABLE_NLS
376 #ifdef WIN32
377 RegistryTool rt;
378 rt.setPathInfo();
379 gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
380 bindtextdomain(GETTEXT_PACKAGE, pathBuf);
381 g_free(pathBuf);
382 #else
383 #ifdef ENABLE_BINRELOC
384 bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
385 #else
386 bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
387 #endif
388 #endif
389 #endif
391 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
393 #ifdef ENABLE_NLS
394 textdomain(GETTEXT_PACKAGE);
395 #endif
397 LIBXML_TEST_VERSION
399 Inkscape::GC::init();
401 Inkscape::Debug::Logger::init();
403 gboolean use_gui;
404 #ifndef WIN32
405 use_gui = (getenv("DISPLAY") != NULL);
406 #else
407 /*
408 Set the current directory to the directory of the
409 executable. This seems redundant, but is needed for
410 when inkscape.exe is executed from another directory.
411 We use relative paths on win32.
412 HKCR\svgfile\shell\open\command is a good example
413 */
414 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
415 char *homedir = g_path_get_dirname(argv[0]);
416 SetCurrentDirectory(homedir);
417 g_free(homedir);
419 use_gui = TRUE;
420 #endif
421 /* Test whether with/without GUI is forced */
422 for (int i = 1; i < argc; i++) {
423 if (!strcmp(argv[i], "-z")
424 || !strcmp(argv[i], "--without-gui")
425 || !strcmp(argv[i], "-p")
426 || !strncmp(argv[i], "--print", 7)
427 || !strcmp(argv[i], "-e")
428 || !strncmp(argv[i], "--export-png", 12)
429 || !strcmp(argv[i], "-l")
430 || !strncmp(argv[i], "--export-plain-svg", 12)
431 || !strcmp(argv[i], "-i")
432 || !strncmp(argv[i], "--export-area-drawing", 21)
433 || !strcmp(argv[i], "-D")
434 || !strncmp(argv[i], "--export-area-canvas", 20)
435 || !strcmp(argv[i], "-C")
436 || !strncmp(argv[i], "--export-id", 12)
437 || !strcmp(argv[i], "-P")
438 || !strncmp(argv[i], "--export-ps", 11)
439 || !strcmp(argv[i], "-E")
440 || !strncmp(argv[i], "--export-eps", 12)
441 || !strcmp(argv[i], "-W")
442 || !strncmp(argv[i], "--query-width", 13)
443 || !strcmp(argv[i], "-H")
444 || !strncmp(argv[i], "--query-height", 14)
445 || !strcmp(argv[i], "-X")
446 || !strncmp(argv[i], "--query-x", 13)
447 || !strcmp(argv[i], "-Y")
448 || !strncmp(argv[i], "--query-y", 14)
449 || !strcmp(argv[i], "--vacuum-defs")
450 )
451 {
452 /* main_console handles any exports -- not the gui */
453 use_gui = FALSE;
454 break;
455 } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
456 use_gui = TRUE;
457 break;
458 } else if (!strcmp(argv[i], "-G") || !strcmp(argv[i], "--new-gui")) {
459 sp_new_gui = TRUE;
460 break;
461 }
462 }
464 #ifdef WIN32
465 #ifndef REPLACEARGS_ANSI
466 if ( PrintWin32::is_os_wide() )
467 #endif // REPLACEARGS_ANSI
468 {
469 // If the call fails, we'll need to convert charsets
470 needToRecodeParams = !replaceArgs( argc, argv );
471 }
472 #endif // WIN32
474 /// \todo Should this be a static object (see inkscape.cpp)?
475 Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
477 return app.run();
478 }
480 void fixupSingleFilename( gchar **orig, gchar **spare )
481 {
482 if ( orig && *orig && **orig ) {
483 GError *error = NULL;
484 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
485 if ( newFileName )
486 {
487 *orig = newFileName;
488 if ( spare ) {
489 *spare = newFileName;
490 }
491 // g_message("Set a replacement fixup");
492 }
493 }
494 }
496 GSList *fixupFilenameEncoding( GSList* fl )
497 {
498 GSList *newFl = NULL;
499 while ( fl ) {
500 gchar *fn = static_cast<gchar*>(fl->data);
501 fl = g_slist_remove( fl, fl->data );
502 gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
503 if ( newFileName ) {
505 if ( 0 )
506 {
507 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
508 gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
509 GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
510 "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
511 gtk_dialog_run (GTK_DIALOG (w));
512 gtk_widget_destroy (w);
513 g_free(safeNewFn);
514 g_free(safeFn);
515 }
517 g_free( fn );
518 fn = newFileName;
519 newFileName = 0;
520 }
521 else
522 if ( 0 )
523 {
524 gchar *safeFn = Inkscape::IO::sanitizeString(fn);
525 GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
526 gtk_dialog_run (GTK_DIALOG (w));
527 gtk_widget_destroy (w);
528 g_free(safeFn);
529 }
530 newFl = g_slist_append( newFl, fn );
531 }
532 return newFl;
533 }
535 int sp_common_main( int argc, char const **argv, GSList **flDest )
536 {
537 /// \todo fixme: Move these to some centralized location (Lauris)
538 sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
539 sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
542 // temporarily switch gettext encoding to locale, so that help messages can be output properly
543 gchar const *charset;
544 g_get_charset(&charset);
546 bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
548 poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
549 poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
550 g_return_val_if_fail(ctx != NULL, 1);
552 /* Collect own arguments */
553 GSList *fl = sp_process_args(ctx);
554 poptFreeContext(ctx);
556 // now switch gettext back to UTF-8 (for GUI)
557 bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
559 // Now let's see if the file list still holds up
560 if ( needToRecodeParams )
561 {
562 fl = fixupFilenameEncoding( fl );
563 }
565 // Check the globals for filename-fixup
566 if ( needToRecodeParams )
567 {
568 fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
569 fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
570 fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
571 }
572 else
573 {
574 if ( sp_export_png )
575 sp_export_png_utf8 = g_strdup( sp_export_png );
576 if ( sp_export_svg )
577 sp_export_svg_utf8 = g_strdup( sp_export_svg );
578 if ( sp_global_printer )
579 sp_global_printer_utf8 = g_strdup( sp_global_printer );
580 }
582 // Return the list if wanted, else free it up.
583 if ( flDest ) {
584 *flDest = fl;
585 fl = 0;
586 } else {
587 while ( fl ) {
588 g_free( fl->data );
589 fl = g_slist_remove( fl, fl->data );
590 }
591 }
592 return 0;
593 }
595 int
596 sp_main_gui(int argc, char const **argv)
597 {
598 Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
600 GSList *fl = NULL;
601 int retVal = sp_common_main( argc, argv, &fl );
602 g_return_val_if_fail(retVal == 0, 1);
604 inkscape_gtk_stock_init();
606 /* Set default icon */
607 gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
608 if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
609 gtk_window_set_default_icon_from_file(filename, NULL);
610 }
611 g_free (filename);
612 filename = 0;
614 if (!sp_global_slideshow) {
615 gboolean create_new = TRUE;
617 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
618 inkscape_application_init(argv[0], true);
620 while (fl) {
621 if (sp_file_open((gchar *)fl->data,NULL)) {
622 create_new=FALSE;
623 }
624 fl = g_slist_remove(fl, fl->data);
625 }
626 if (create_new) {
627 sp_file_new_default();
628 }
629 } else {
630 if (fl) {
631 GtkWidget *ss;
632 /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
633 inkscape_application_init(argv[0], true);
634 ss = sp_slideshow_new(fl);
635 if (ss) gtk_widget_show(ss);
636 } else {
637 g_warning ("No slides to display");
638 exit(0);
639 }
640 }
642 main_instance.run();
644 #ifdef WIN32
645 //We might not need anything here
646 //sp_win32_finish(); <-- this is a NOP func
647 #endif
649 return 0;
650 }
652 int
653 sp_main_console(int argc, char const **argv)
654 {
655 /* We are started in text mode */
657 /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
658 * in a non-Gtk environment. Used in libnrtype's
659 * FontInstance.cpp and FontFactory.cpp.
660 * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
661 */
662 g_type_init();
663 char **argv2 = const_cast<char **>(argv);
664 gtk_init_check( &argc, &argv2 );
665 //setlocale(LC_ALL, "");
667 GSList *fl = NULL;
668 int retVal = sp_common_main( argc, argv, &fl );
669 g_return_val_if_fail(retVal == 0, 1);
671 if (fl == NULL) {
672 g_print("Nothing to do!\n");
673 exit(0);
674 }
676 inkscape_application_init(argv[0], false);
678 while (fl) {
679 SPDocument *doc;
681 doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
682 if (doc == NULL) {
683 doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
684 }
685 if (doc == NULL) {
686 g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
687 } else {
688 if (sp_vacuum_defs) {
689 vacuum_document(doc);
690 }
691 if (sp_vacuum_defs && !sp_export_svg) {
692 // save under the name given in the command line
693 sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
694 }
695 if (sp_global_printer) {
696 sp_print_document_to_file(doc, sp_global_printer);
697 }
698 if (sp_export_png || sp_export_id || sp_export_area_drawing) {
699 sp_do_export_png(doc);
700 }
701 if (sp_export_svg) {
702 Inkscape::XML::Document *rdoc;
703 Inkscape::XML::Node *repr;
704 rdoc = sp_repr_document_new("svg:svg");
705 repr = rdoc->root();
706 repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
707 sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
708 }
709 if (sp_export_ps) {
710 do_export_ps(doc, sp_export_ps, "image/x-postscript");
711 }
712 if (sp_export_eps) {
713 do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
714 }
715 if (sp_query_width || sp_query_height) {
716 do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
717 } else if (sp_query_x || sp_query_y) {
718 do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
719 }
720 }
721 fl = g_slist_remove(fl, fl->data);
722 }
724 inkscape_unref();
726 return 0;
727 }
729 static void
730 do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
731 {
732 SPObject *o = NULL;
734 if (id) {
735 o = doc->getObjectById(id);
736 if (o) {
737 if (!SP_IS_ITEM (o)) {
738 g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
739 return;
740 }
741 } else {
742 g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
743 return;
744 }
745 } else {
746 o = SP_DOCUMENT_ROOT(doc);
747 }
749 if (o) {
750 sp_document_ensure_up_to_date (doc);
751 SPItem *item = ((SPItem *) o);
752 NR::Rect area = item->invokeBbox(sp_item_i2doc_affine(item)); // "true" SVG bbox for scripting
754 Inkscape::SVGOStringStream os;
755 if (extent) {
756 os << area.extent(axis);
757 } else {
758 os << area.min()[axis];
759 }
760 g_print ("%s", os.str().c_str());
761 }
762 }
765 static void
766 sp_do_export_png(SPDocument *doc)
767 {
768 const gchar *filename = NULL;
769 gdouble dpi = 0.0;
771 if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
772 g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
773 }
775 GSList *items = NULL;
777 NRRect area;
778 if (sp_export_id || sp_export_area_drawing) {
780 SPObject *o = NULL;
781 SPObject *o_area = NULL;
782 if (sp_export_id && sp_export_area_drawing) {
783 o = doc->getObjectById(sp_export_id);
784 o_area = SP_DOCUMENT_ROOT (doc);
785 } else if (sp_export_id) {
786 o = doc->getObjectById(sp_export_id);
787 o_area = o;
788 } else if (sp_export_area_drawing) {
789 o = SP_DOCUMENT_ROOT (doc);
790 o_area = o;
791 }
793 if (o) {
794 if (!SP_IS_ITEM (o)) {
795 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
796 return;
797 }
799 items = g_slist_prepend (items, SP_ITEM(o));
801 if (sp_export_id_only) {
802 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
803 }
805 if (sp_export_use_hints) {
807 // retrieve export filename hint
808 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
809 if (fn_hint) {
810 if (sp_export_png) {
811 g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
812 filename = sp_export_png;
813 } else {
814 filename = fn_hint;
815 }
816 } else {
817 g_warning ("Export filename hint not found for the object.");
818 filename = sp_export_png;
819 }
821 // retrieve export dpi hints
822 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
823 if (dpi_hint) {
824 if (sp_export_dpi || sp_export_width || sp_export_height) {
825 g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
826 } else {
827 dpi = atof(dpi_hint);
828 }
829 } else {
830 g_warning ("Export DPI hint not found for the object.");
831 }
833 }
835 // write object bbox to area
836 sp_document_ensure_up_to_date (doc);
837 sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
838 } else {
839 g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
840 return;
841 }
842 }
844 if (sp_export_area) {
845 /* Try to parse area (given in SVG pixels) */
846 if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
847 g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
848 return;
849 }
850 if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
851 g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
852 return;
853 }
854 } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
855 /* Export the whole canvas */
856 sp_document_ensure_up_to_date (doc);
857 area.x0 = SP_ROOT(doc->root)->x.computed;
858 area.y0 = SP_ROOT(doc->root)->y.computed;
859 area.x1 = area.x0 + sp_document_width (doc);
860 area.y1 = area.y0 + sp_document_height (doc);
861 }
863 // set filename and dpi from options, if not yet set from the hints
864 if (!filename) {
865 if (!sp_export_png) {
866 g_warning ("No export filename given and no filename hint. Nothing exported.");
867 return;
868 }
869 filename = sp_export_png;
870 }
872 if (sp_export_dpi && dpi == 0.0) {
873 dpi = atof(sp_export_dpi);
874 if ((dpi < 0.1) || (dpi > 10000.0)) {
875 g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
876 return;
877 }
878 g_print("DPI: %g\n", dpi);
879 }
881 if (sp_export_area_snap) {
882 area.x0 = std::floor (area.x0);
883 area.y0 = std::floor (area.y0);
884 area.x1 = std::ceil (area.x1);
885 area.y1 = std::ceil (area.y1);
886 }
888 // default dpi
889 if (dpi == 0.0)
890 dpi = PX_PER_IN;
892 gint width = 0;
893 gint height = 0;
895 if (sp_export_width) {
896 width = atoi(sp_export_width);
897 if ((width < 1) || (width > 65536)) {
898 g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
899 return;
900 }
901 dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
902 }
904 if (sp_export_height) {
905 height = atoi(sp_export_height);
906 if ((height < 1) || (height > 65536)) {
907 g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
908 return;
909 }
910 dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
911 }
913 if (!sp_export_width) {
914 width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
915 }
917 if (!sp_export_height) {
918 height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
919 }
921 guint32 bgcolor = 0x00000000;
922 if (sp_export_background) {
923 // override the page color
924 bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
925 bgcolor |= 0xff; // default is no opacity
926 } else {
927 // read from namedview
928 Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
929 if (nv && nv->attribute("pagecolor"))
930 bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
931 if (nv && nv->attribute("inkscape:pageopacity"))
932 bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
933 }
935 if (sp_export_background_opacity) {
936 // override opacity
937 gfloat value;
938 if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
939 if (value > 1.0) {
940 value = CLAMP (value, 1.0f, 255.0f);
941 bgcolor &= (guint32) 0xffffff00;
942 bgcolor |= (guint32) floor(value);
943 } else {
944 value = CLAMP (value, 0.0f, 1.0f);
945 bgcolor &= (guint32) 0xffffff00;
946 bgcolor |= SP_COLOR_F_TO_U(value);
947 }
948 }
949 }
951 g_print("Background RRGGBBAA: %08x\n", bgcolor);
953 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);
955 g_print("Bitmap saved as: %s\n", filename);
957 if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
958 sp_export_png_file(doc, filename, area.x0, area.y0, area.x1, area.y1, width, height, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
959 } else {
960 g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
961 }
963 g_slist_free (items);
964 }
967 /**
968 * Perform an export of either PS or EPS.
969 *
970 * \param doc Document to export.
971 * \param uri URI to export to.
972 * \param mime MIME type to export as.
973 */
975 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
976 {
977 /** \todo
978 * FIXME: I've no idea if this is the `proper' way to do this.
979 * If anyone feels qualified to say that it is, perhaps they
980 * could remove this comment.
981 */
983 Inkscape::Extension::DB::OutputList o;
984 Inkscape::Extension::db.get_output_list(o);
985 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
986 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
987 i++;
988 }
990 if (i == o.end())
991 {
992 g_warning ("Could not find an extension to export this file.");
993 return;
994 }
996 bool old_text_to_path = false;
997 bool old_bbox_page = false;
999 try {
1000 old_text_to_path = (*i)->get_param_bool("textToPath");
1001 (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1002 }
1003 catch (...) {
1004 g_warning ("Could not set export-text-to-path option for this export.");
1005 }
1007 try {
1008 old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1009 (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1010 }
1011 catch (...) {
1012 g_warning ("Could not set export-bbox-page option for this export.");
1013 }
1015 (*i)->save(doc, uri);
1017 try {
1018 (*i)->set_param_bool("textToPath", old_text_to_path);
1019 (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1020 }
1021 catch (...) {
1023 }
1024 }
1026 #ifdef WIN32
1027 bool replaceArgs( int& argc, char**& argv )
1028 {
1029 bool worked = false;
1031 #ifdef REPLACEARGS_DEBUG
1032 MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1033 #endif // REPLACEARGS_DEBUG
1035 wchar_t* line = GetCommandLineW();
1036 if ( line )
1037 {
1038 #ifdef REPLACEARGS_DEBUG
1039 {
1040 gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1041 if ( utf8Line )
1042 {
1043 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1044 {
1045 char tmp[strlen(safe) + 32];
1046 snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1047 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1048 }
1049 }
1050 }
1051 #endif // REPLACEARGS_DEBUG
1053 int numArgs = 0;
1054 wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1056 #ifdef REPLACEARGS_ANSI
1057 // test code for trying things on Win95/98/ME
1058 if ( !parsed )
1059 {
1060 #ifdef REPLACEARGS_DEBUG
1061 MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1062 #endif // REPLACEARGS_DEBUG
1063 int lineLen = wcslen(line) + 1;
1064 wchar_t* lineDup = new wchar_t[lineLen];
1065 wcsncpy( lineDup, line, lineLen );
1067 int pos = 0;
1068 bool inQuotes = false;
1069 bool inWhitespace = true;
1070 std::vector<int> places;
1071 while ( lineDup[pos] )
1072 {
1073 if ( inQuotes )
1074 {
1075 if ( lineDup[pos] == L'"' )
1076 {
1077 inQuotes = false;
1078 }
1079 }
1080 else if ( lineDup[pos] == L'"' )
1081 {
1082 inQuotes = true;
1083 inWhitespace = false;
1084 places.push_back(pos);
1085 }
1086 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1087 {
1088 if ( !inWhitespace )
1089 {
1090 inWhitespace = true;
1091 lineDup[pos] = 0;
1092 }
1093 }
1094 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1095 {
1096 inWhitespace = false;
1097 places.push_back(pos);
1098 }
1099 else
1100 {
1101 // consume
1102 }
1103 pos++;
1104 }
1105 #ifdef REPLACEARGS_DEBUG
1106 {
1107 char tmp[256];
1108 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1109 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1110 }
1111 #endif // REPLACEARGS_DEBUG
1113 wchar_t** block = new wchar_t*[places.size()];
1114 int i = 0;
1115 for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1116 {
1117 block[i++] = &lineDup[*it];
1118 }
1119 parsed = block;
1120 numArgs = places.size();
1121 }
1122 #endif // REPLACEARGS_ANSI
1124 if ( parsed )
1125 {
1126 std::vector<wchar_t*>expandedArgs;
1127 if ( numArgs > 0 )
1128 {
1129 expandedArgs.push_back( parsed[0] );
1130 }
1132 for ( int i1 = 1; i1 < numArgs; i1++ )
1133 {
1134 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1135 wildcarded &= parsed[i1][0] != L'"';
1136 wildcarded &= parsed[i1][0] != L'-';
1137 if ( wildcarded )
1138 {
1139 #ifdef REPLACEARGS_ANSI
1140 WIN32_FIND_DATAA data = {0};
1141 #else
1142 WIN32_FIND_DATAW data = {0};
1143 #endif // REPLACEARGS_ANSI
1145 int baseLen = wcslen(parsed[i1]) + 2;
1146 wchar_t* base = new wchar_t[baseLen];
1147 wcsncpy( base, parsed[i1], baseLen );
1148 wchar_t* last = wcsrchr( base, L'\\' );
1149 if ( last )
1150 {
1151 last[1] = 0;
1152 }
1153 else
1154 {
1155 base[0] = 0;
1156 }
1157 baseLen = wcslen( base );
1159 #ifdef REPLACEARGS_ANSI
1160 char target[MAX_PATH];
1161 if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1162 {
1163 HANDLE hf = FindFirstFileA( target, &data );
1164 #else
1165 HANDLE hf = FindFirstFileW( parsed[i1], &data );
1166 #endif // REPLACEARGS_ANSI
1167 if ( hf != INVALID_HANDLE_VALUE )
1168 {
1169 BOOL found = TRUE;
1170 do
1171 {
1172 #ifdef REPLACEARGS_ANSI
1173 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1174 if ( howMany > 0 )
1175 {
1176 howMany += baseLen;
1177 wchar_t* tmp = new wchar_t[howMany + 1];
1178 wcsncpy( tmp, base, howMany + 1 );
1179 MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1180 expandedArgs.push_back( tmp );
1181 found = FindNextFileA( hf, &data );
1182 }
1183 #else
1184 int howMany = wcslen(data.cFileName) + baseLen;
1185 wchar_t* tmp = new wchar_t[howMany + 1];
1186 wcsncpy( tmp, base, howMany + 1 );
1187 wcsncat( tmp, data.cFileName, howMany + 1 );
1188 expandedArgs.push_back( tmp );
1189 found = FindNextFileW( hf, &data );
1190 #endif // REPLACEARGS_ANSI
1191 } while ( found );
1193 FindClose( hf );
1194 }
1195 else
1196 {
1197 expandedArgs.push_back( parsed[i1] );
1198 }
1199 #ifdef REPLACEARGS_ANSI
1200 }
1201 #endif // REPLACEARGS_ANSI
1203 delete[] base;
1204 }
1205 else
1206 {
1207 expandedArgs.push_back( parsed[i1] );
1208 }
1209 }
1211 {
1212 wchar_t** block = new wchar_t*[expandedArgs.size()];
1213 int iz = 0;
1214 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1215 {
1216 block[iz++] = *it;
1217 }
1218 parsed = block;
1219 numArgs = expandedArgs.size();
1220 }
1222 std::vector<gchar*> newArgs;
1223 for ( int i = 0; i < numArgs; i++ )
1224 {
1225 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1226 if ( replacement )
1227 {
1228 #ifdef REPLACEARGS_DEBUG
1229 gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1231 if ( safe2 )
1232 {
1233 {
1234 char tmp[1024];
1235 snprintf( tmp, sizeof(tmp), " [%2d] = '%s'", i, safe2 );
1236 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1237 }
1238 g_free( safe2 );
1239 }
1240 #endif // REPLACEARGS_DEBUG
1242 newArgs.push_back( replacement );
1243 }
1244 else
1245 {
1246 newArgs.push_back( blankParam );
1247 }
1248 }
1250 // Now push our munged params to be the new argv and argc
1251 {
1252 char** block = new char*[newArgs.size()];
1253 int iz = 0;
1254 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1255 {
1256 block[iz++] = *it;
1257 }
1258 argv = block;
1259 argc = newArgs.size();
1260 worked = true;
1261 }
1262 }
1263 #ifdef REPLACEARGS_DEBUG
1264 else
1265 {
1266 MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1267 }
1268 #endif // REPLACEARGS_DEBUG
1269 }
1270 #ifdef REPLACEARGS_DEBUG
1271 else
1272 {
1273 {
1274 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1275 }
1277 char* line2 = GetCommandLineA();
1278 if ( line2 )
1279 {
1280 gchar *safe = Inkscape::IO::sanitizeString(line2);
1281 {
1282 {
1283 char tmp[strlen(safe) + 32];
1284 snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1285 MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1286 }
1287 }
1288 }
1289 else
1290 {
1291 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1292 }
1293 }
1294 #endif // REPLACEARGS_DEBUG
1296 return worked;
1297 }
1298 #endif // WIN32
1300 static GSList *
1301 sp_process_args(poptContext ctx)
1302 {
1303 GSList *fl = NULL;
1305 gint a;
1306 while ((a = poptGetNextOpt(ctx)) >= 0) {
1307 switch (a) {
1308 case SP_ARG_FILE: {
1309 gchar const *fn = poptGetOptArg(ctx);
1310 if (fn != NULL) {
1311 fl = g_slist_append(fl, g_strdup(fn));
1312 }
1313 break;
1314 }
1315 case SP_ARG_VERSION: {
1316 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1317 exit(0);
1318 break;
1319 }
1320 case SP_ARG_EXTENSIONDIR: {
1321 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1322 exit(0);
1323 break;
1324 }
1325 default: {
1326 break;
1327 }
1328 }
1329 }
1331 gchar const ** const args = poptGetArgs(ctx);
1332 if (args != NULL) {
1333 for (unsigned i = 0; args[i] != NULL; i++) {
1334 fl = g_slist_append(fl, g_strdup(args[i]));
1335 }
1336 }
1338 return fl;
1339 }
1342 /*
1343 Local Variables:
1344 mode:c++
1345 c-file-style:"stroustrup"
1346 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1347 indent-tabs-mode:nil
1348 fill-column:99
1349 End:
1350 */
1351 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :