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