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