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