fdfa3aa7bb1f57eaa42c96d2138979a505eb3f32
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 if (sp_export_id) {
782 o = doc->getObjectById(sp_export_id);
783 } else if (sp_export_area_drawing) {
784 o = SP_DOCUMENT_ROOT (doc);
785 }
787 SPObject *o_area = NULL;
788 if (sp_export_area_drawing) {
789 o_area = SP_DOCUMENT_ROOT (doc);
790 } else if (sp_export_id) {
791 o_area = doc->getObjectById(sp_export_id);
792 }
794 if (o) {
795 if (!SP_IS_ITEM (o)) {
796 g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
797 return;
798 }
800 items = g_slist_prepend (items, SP_ITEM(o));
802 if (sp_export_id_only) {
803 g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
804 }
806 if (sp_export_use_hints) {
808 // retrieve export filename hint
809 const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
810 if (fn_hint) {
811 if (sp_export_png) {
812 g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
813 filename = sp_export_png;
814 } else {
815 filename = fn_hint;
816 }
817 } else {
818 g_warning ("Export filename hint not found for the object.");
819 filename = sp_export_png;
820 }
822 // retrieve export dpi hints
823 const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
824 if (dpi_hint) {
825 if (sp_export_dpi || sp_export_width || sp_export_height) {
826 g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
827 } else {
828 dpi = atof(dpi_hint);
829 }
830 } else {
831 g_warning ("Export DPI hint not found for the object.");
832 }
834 }
836 // write object bbox to area
837 sp_document_ensure_up_to_date (doc);
838 sp_item_invoke_bbox((SPItem *) o_area, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
839 } else {
840 g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
841 return;
842 }
843 }
845 if (sp_export_area) {
846 /* Try to parse area (given in SVG pixels) */
847 if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
848 g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
849 return;
850 }
851 if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
852 g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
853 return;
854 }
855 } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
856 /* Export the whole canvas */
857 sp_document_ensure_up_to_date (doc);
858 area.x0 = SP_ROOT(doc->root)->x.computed;
859 area.y0 = SP_ROOT(doc->root)->y.computed;
860 area.x1 = area.x0 + sp_document_width (doc);
861 area.y1 = area.y0 + sp_document_height (doc);
862 }
864 // set filename and dpi from options, if not yet set from the hints
865 if (!filename) {
866 if (!sp_export_png) {
867 g_warning ("No export filename given and no filename hint. Nothing exported.");
868 return;
869 }
870 filename = sp_export_png;
871 }
873 if (sp_export_dpi && dpi == 0.0) {
874 dpi = atof(sp_export_dpi);
875 if ((dpi < 0.1) || (dpi > 10000.0)) {
876 g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
877 return;
878 }
879 g_print("DPI: %g\n", dpi);
880 }
882 if (sp_export_area_snap) {
883 area.x0 = std::floor (area.x0);
884 area.y0 = std::floor (area.y0);
885 area.x1 = std::ceil (area.x1);
886 area.y1 = std::ceil (area.y1);
887 }
889 // default dpi
890 if (dpi == 0.0)
891 dpi = PX_PER_IN;
893 gint width = 0;
894 gint height = 0;
896 if (sp_export_width) {
897 width = atoi(sp_export_width);
898 if ((width < 1) || (width > 65536)) {
899 g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
900 return;
901 }
902 dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
903 }
905 if (sp_export_height) {
906 height = atoi(sp_export_height);
907 if ((height < 1) || (height > 65536)) {
908 g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
909 return;
910 }
911 dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
912 }
914 if (!sp_export_width) {
915 width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
916 }
918 if (!sp_export_height) {
919 height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
920 }
922 guint32 bgcolor = 0x00000000;
923 if (sp_export_background) {
924 // override the page color
925 bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
926 bgcolor |= 0xff; // default is no opacity
927 } else {
928 // read from namedview
929 Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
930 if (nv && nv->attribute("pagecolor"))
931 bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
932 if (nv && nv->attribute("inkscape:pageopacity"))
933 bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
934 }
936 if (sp_export_background_opacity) {
937 // override opacity
938 gfloat value;
939 if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
940 if (value > 1.0) {
941 value = CLAMP (value, 1.0f, 255.0f);
942 bgcolor &= (guint32) 0xffffff00;
943 bgcolor |= (guint32) floor(value);
944 } else {
945 value = CLAMP (value, 0.0f, 1.0f);
946 bgcolor &= (guint32) 0xffffff00;
947 bgcolor |= SP_COLOR_F_TO_U(value);
948 }
949 }
950 }
952 g_print("Background RRGGBBAA: %08x\n", bgcolor);
954 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);
956 g_print("Bitmap saved as: %s\n", filename);
958 if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
959 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);
960 } else {
961 g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
962 }
964 g_slist_free (items);
965 }
968 /**
969 * Perform an export of either PS or EPS.
970 *
971 * \param doc Document to export.
972 * \param uri URI to export to.
973 * \param mime MIME type to export as.
974 */
976 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
977 {
978 /** \todo
979 * FIXME: I've no idea if this is the `proper' way to do this.
980 * If anyone feels qualified to say that it is, perhaps they
981 * could remove this comment.
982 */
984 Inkscape::Extension::DB::OutputList o;
985 Inkscape::Extension::db.get_output_list(o);
986 Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
987 while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
988 i++;
989 }
991 if (i == o.end())
992 {
993 g_warning ("Could not find an extension to export this file.");
994 return;
995 }
997 bool old_text_to_path = false;
998 bool old_bbox_page = false;
1000 try {
1001 old_text_to_path = (*i)->get_param_bool("textToPath");
1002 (*i)->set_param_bool("textToPath", sp_export_text_to_path);
1003 }
1004 catch (...) {
1005 g_warning ("Could not set export-text-to-path option for this export.");
1006 }
1008 try {
1009 old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
1010 (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
1011 }
1012 catch (...) {
1013 g_warning ("Could not set export-bbox-page option for this export.");
1014 }
1016 (*i)->save(doc, uri);
1018 try {
1019 (*i)->set_param_bool("textToPath", old_text_to_path);
1020 (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
1021 }
1022 catch (...) {
1024 }
1025 }
1027 #ifdef WIN32
1028 bool replaceArgs( int& argc, char**& argv )
1029 {
1030 bool worked = false;
1032 #ifdef REPLACEARGS_DEBUG
1033 MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1034 #endif // REPLACEARGS_DEBUG
1036 wchar_t* line = GetCommandLineW();
1037 if ( line )
1038 {
1039 #ifdef REPLACEARGS_DEBUG
1040 {
1041 gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1042 if ( utf8Line )
1043 {
1044 gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1045 {
1046 char tmp[strlen(safe) + 32];
1047 snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1048 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1049 }
1050 }
1051 }
1052 #endif // REPLACEARGS_DEBUG
1054 int numArgs = 0;
1055 wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1057 #ifdef REPLACEARGS_ANSI
1058 // test code for trying things on Win95/98/ME
1059 if ( !parsed )
1060 {
1061 #ifdef REPLACEARGS_DEBUG
1062 MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1063 #endif // REPLACEARGS_DEBUG
1064 int lineLen = wcslen(line) + 1;
1065 wchar_t* lineDup = new wchar_t[lineLen];
1066 wcsncpy( lineDup, line, lineLen );
1068 int pos = 0;
1069 bool inQuotes = false;
1070 bool inWhitespace = true;
1071 std::vector<int> places;
1072 while ( lineDup[pos] )
1073 {
1074 if ( inQuotes )
1075 {
1076 if ( lineDup[pos] == L'"' )
1077 {
1078 inQuotes = false;
1079 }
1080 }
1081 else if ( lineDup[pos] == L'"' )
1082 {
1083 inQuotes = true;
1084 inWhitespace = false;
1085 places.push_back(pos);
1086 }
1087 else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1088 {
1089 if ( !inWhitespace )
1090 {
1091 inWhitespace = true;
1092 lineDup[pos] = 0;
1093 }
1094 }
1095 else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1096 {
1097 inWhitespace = false;
1098 places.push_back(pos);
1099 }
1100 else
1101 {
1102 // consume
1103 }
1104 pos++;
1105 }
1106 #ifdef REPLACEARGS_DEBUG
1107 {
1108 char tmp[256];
1109 snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1110 MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1111 }
1112 #endif // REPLACEARGS_DEBUG
1114 wchar_t** block = new wchar_t*[places.size()];
1115 int i = 0;
1116 for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1117 {
1118 block[i++] = &lineDup[*it];
1119 }
1120 parsed = block;
1121 numArgs = places.size();
1122 }
1123 #endif // REPLACEARGS_ANSI
1125 if ( parsed )
1126 {
1127 std::vector<wchar_t*>expandedArgs;
1128 if ( numArgs > 0 )
1129 {
1130 expandedArgs.push_back( parsed[0] );
1131 }
1133 for ( int i1 = 1; i1 < numArgs; i1++ )
1134 {
1135 bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1136 wildcarded &= parsed[i1][0] != L'"';
1137 wildcarded &= parsed[i1][0] != L'-';
1138 if ( wildcarded )
1139 {
1140 #ifdef REPLACEARGS_ANSI
1141 WIN32_FIND_DATAA data = {0};
1142 #else
1143 WIN32_FIND_DATAW data = {0};
1144 #endif // REPLACEARGS_ANSI
1146 int baseLen = wcslen(parsed[i1]) + 2;
1147 wchar_t* base = new wchar_t[baseLen];
1148 wcsncpy( base, parsed[i1], baseLen );
1149 wchar_t* last = wcsrchr( base, L'\\' );
1150 if ( last )
1151 {
1152 last[1] = 0;
1153 }
1154 else
1155 {
1156 base[0] = 0;
1157 }
1158 baseLen = wcslen( base );
1160 #ifdef REPLACEARGS_ANSI
1161 char target[MAX_PATH];
1162 if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1163 {
1164 HANDLE hf = FindFirstFileA( target, &data );
1165 #else
1166 HANDLE hf = FindFirstFileW( parsed[i1], &data );
1167 #endif // REPLACEARGS_ANSI
1168 if ( hf != INVALID_HANDLE_VALUE )
1169 {
1170 BOOL found = TRUE;
1171 do
1172 {
1173 #ifdef REPLACEARGS_ANSI
1174 int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1175 if ( howMany > 0 )
1176 {
1177 howMany += baseLen;
1178 wchar_t* tmp = new wchar_t[howMany + 1];
1179 wcsncpy( tmp, base, howMany + 1 );
1180 MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1181 expandedArgs.push_back( tmp );
1182 found = FindNextFileA( hf, &data );
1183 }
1184 #else
1185 int howMany = wcslen(data.cFileName) + baseLen;
1186 wchar_t* tmp = new wchar_t[howMany + 1];
1187 wcsncpy( tmp, base, howMany + 1 );
1188 wcsncat( tmp, data.cFileName, howMany + 1 );
1189 expandedArgs.push_back( tmp );
1190 found = FindNextFileW( hf, &data );
1191 #endif // REPLACEARGS_ANSI
1192 } while ( found );
1194 FindClose( hf );
1195 }
1196 else
1197 {
1198 expandedArgs.push_back( parsed[i1] );
1199 }
1200 #ifdef REPLACEARGS_ANSI
1201 }
1202 #endif // REPLACEARGS_ANSI
1204 delete[] base;
1205 }
1206 else
1207 {
1208 expandedArgs.push_back( parsed[i1] );
1209 }
1210 }
1212 {
1213 wchar_t** block = new wchar_t*[expandedArgs.size()];
1214 int iz = 0;
1215 for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1216 {
1217 block[iz++] = *it;
1218 }
1219 parsed = block;
1220 numArgs = expandedArgs.size();
1221 }
1223 std::vector<gchar*> newArgs;
1224 for ( int i = 0; i < numArgs; i++ )
1225 {
1226 gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1227 if ( replacement )
1228 {
1229 #ifdef REPLACEARGS_DEBUG
1230 gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1232 if ( safe2 )
1233 {
1234 {
1235 char tmp[1024];
1236 snprintf( tmp, sizeof(tmp), " [%2d] = '%s'", i, safe2 );
1237 MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1238 }
1239 g_free( safe2 );
1240 }
1241 #endif // REPLACEARGS_DEBUG
1243 newArgs.push_back( replacement );
1244 }
1245 else
1246 {
1247 newArgs.push_back( blankParam );
1248 }
1249 }
1251 // Now push our munged params to be the new argv and argc
1252 {
1253 char** block = new char*[newArgs.size()];
1254 int iz = 0;
1255 for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1256 {
1257 block[iz++] = *it;
1258 }
1259 argv = block;
1260 argc = newArgs.size();
1261 worked = true;
1262 }
1263 }
1264 #ifdef REPLACEARGS_DEBUG
1265 else
1266 {
1267 MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1268 }
1269 #endif // REPLACEARGS_DEBUG
1270 }
1271 #ifdef REPLACEARGS_DEBUG
1272 else
1273 {
1274 {
1275 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1276 }
1278 char* line2 = GetCommandLineA();
1279 if ( line2 )
1280 {
1281 gchar *safe = Inkscape::IO::sanitizeString(line2);
1282 {
1283 {
1284 char tmp[strlen(safe) + 32];
1285 snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1286 MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1287 }
1288 }
1289 }
1290 else
1291 {
1292 MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1293 }
1294 }
1295 #endif // REPLACEARGS_DEBUG
1297 return worked;
1298 }
1299 #endif // WIN32
1301 static GSList *
1302 sp_process_args(poptContext ctx)
1303 {
1304 GSList *fl = NULL;
1306 gint a;
1307 while ((a = poptGetNextOpt(ctx)) >= 0) {
1308 switch (a) {
1309 case SP_ARG_FILE: {
1310 gchar const *fn = poptGetOptArg(ctx);
1311 if (fn != NULL) {
1312 fl = g_slist_append(fl, g_strdup(fn));
1313 }
1314 break;
1315 }
1316 case SP_ARG_VERSION: {
1317 printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
1318 exit(0);
1319 break;
1320 }
1321 case SP_ARG_EXTENSIONDIR: {
1322 printf("%s\n", INKSCAPE_EXTENSIONDIR);
1323 exit(0);
1324 break;
1325 }
1326 default: {
1327 break;
1328 }
1329 }
1330 }
1332 gchar const ** const args = poptGetArgs(ctx);
1333 if (args != NULL) {
1334 for (unsigned i = 0; args[i] != NULL; i++) {
1335 fl = g_slist_append(fl, g_strdup(args[i]));
1336 }
1337 }
1339 return fl;
1340 }
1343 /*
1344 Local Variables:
1345 mode:c++
1346 c-file-style:"stroustrup"
1347 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1348 indent-tabs-mode:nil
1349 fill-column:99
1350 End:
1351 */
1352 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :