4
* Inkscape - an ambitious vector drawing program
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>
16
* Bryce Harrington <bryce@bryceharrington.com>
17
* ... and various people who have worked with various projects
19
* Copyright (C) 1999-2004 authors
20
* Copyright (C) 2001-2002 Ximian, Inc.
22
* Released under GNU GPL, read the file 'COPYING' for more information
29
#include "path-prefix.h"
31
// This has to be included prior to anything that includes setjmp.h, it croaks otherwise
34
#include <gtk/gtkmessagedialog.h>
46
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
47
#endif /* Not def: POPT_TABLEEND */
49
#include <libxml/tree.h>
50
#include <glib-object.h>
52
#include <gtk/gtkmain.h>
53
#include <gtk/gtksignal.h>
54
#include <gtk/gtkwindow.h>
55
#include <gtk/gtkbox.h>
62
#include "sp-object.h"
63
#include "interface.h"
68
#include "unit-constants.h"
71
#include "svg/svg-color.h"
72
#include "svg/stringstream.h"
74
#include "inkscape-private.h"
75
#include "inkscape-version.h"
77
#include "sp-namedview.h"
79
#include "sp-object-repr.h"
84
#include "debug/logger.h"
85
#include "debug/log-display-config.h"
87
#include "helper/png-write.h"
88
#include "helper/geom.h"
90
#include <extension/extension.h>
91
#include <extension/system.h>
92
#include <extension/db.h>
93
#include <extension/output.h>
96
//#define REPLACEARGS_ANSI
97
//#define REPLACEARGS_DEBUG
99
#include "registrytool.h"
101
#include "extension/internal/win32.h"
102
using Inkscape::Extension::Internal::PrintWin32;
106
#include "extension/init.h"
108
#include <glibmm/i18n.h>
109
#include <gtkmm/main.h>
111
#ifndef HAVE_BIND_TEXTDOMAIN_CODESET
112
#define bind_textdomain_codeset(p,c)
115
#include "application/application.h"
116
#include "main-cmdlineact.h"
117
#include "widgets/icon.h"
118
#include "ui/widget/panel.h"
131
SP_ARG_EXPORT_AREA_DRAWING,
132
SP_ARG_EXPORT_AREA_CANVAS,
133
SP_ARG_EXPORT_AREA_SNAP,
135
SP_ARG_EXPORT_HEIGHT,
137
SP_ARG_EXPORT_ID_ONLY,
138
SP_ARG_EXPORT_USE_HINTS,
139
SP_ARG_EXPORT_BACKGROUND,
140
SP_ARG_EXPORT_BACKGROUND_OPACITY,
148
SP_ARG_EXPORT_TEXT_TO_PATH,
149
SP_ARG_EXPORT_IGNORE_FILTERS,
166
int sp_main_gui(int argc, char const **argv);
167
int sp_main_console(int argc, char const **argv);
168
static void sp_do_export_png(SPDocument *doc);
169
static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const *mime);
171
static void do_export_emf(SPDocument* doc, gchar const* uri, char const *mime);
173
static void do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id);
174
static void do_query_all (SPDocument *doc);
175
static void do_query_all_recurse (SPObject *o);
177
static gchar *sp_global_printer = NULL;
178
static gchar *sp_export_png = NULL;
179
static gchar *sp_export_dpi = NULL;
180
static gchar *sp_export_area = NULL;
181
static gboolean sp_export_area_drawing = FALSE;
182
static gboolean sp_export_area_canvas = FALSE;
183
static gchar *sp_export_width = NULL;
184
static gchar *sp_export_height = NULL;
185
static gchar *sp_export_id = NULL;
186
static gchar *sp_export_background = NULL;
187
static gchar *sp_export_background_opacity = NULL;
188
static gboolean sp_export_area_snap = FALSE;
189
static gboolean sp_export_use_hints = FALSE;
190
static gboolean sp_export_id_only = FALSE;
191
static gchar *sp_export_svg = NULL;
192
static gchar *sp_export_ps = NULL;
193
static gchar *sp_export_eps = NULL;
194
static gchar *sp_export_pdf = NULL;
196
static gchar *sp_export_emf = NULL;
198
static gboolean sp_export_text_to_path = FALSE;
199
static gboolean sp_export_ignore_filters = FALSE;
200
static gboolean sp_export_font = FALSE;
201
static gboolean sp_query_x = FALSE;
202
static gboolean sp_query_y = FALSE;
203
static gboolean sp_query_width = FALSE;
204
static gboolean sp_query_height = FALSE;
205
static gboolean sp_query_all = FALSE;
206
static gchar *sp_query_id = NULL;
207
static int sp_new_gui = FALSE;
208
static gboolean sp_shell = FALSE;
209
static gboolean sp_vacuum_defs = FALSE;
211
static gchar *sp_export_png_utf8 = NULL;
212
static gchar *sp_export_svg_utf8 = NULL;
213
static gchar *sp_global_printer_utf8 = NULL;
217
* Reset variables to default values.
219
static void resetCommandlineGlobals() {
220
sp_global_printer = NULL;
221
sp_export_png = NULL;
222
sp_export_dpi = NULL;
223
sp_export_area = NULL;
224
sp_export_area_drawing = FALSE;
225
sp_export_area_canvas = FALSE;
226
sp_export_width = NULL;
227
sp_export_height = NULL;
229
sp_export_background = NULL;
230
sp_export_background_opacity = NULL;
231
sp_export_area_snap = FALSE;
232
sp_export_use_hints = FALSE;
233
sp_export_id_only = FALSE;
234
sp_export_svg = NULL;
236
sp_export_eps = NULL;
237
sp_export_pdf = NULL;
239
sp_export_emf = NULL;
241
sp_export_text_to_path = FALSE;
242
sp_export_ignore_filters = FALSE;
243
sp_export_font = FALSE;
246
sp_query_width = FALSE;
247
sp_query_height = FALSE;
248
sp_query_all = FALSE;
250
sp_vacuum_defs = FALSE;
252
sp_export_png_utf8 = NULL;
253
sp_export_svg_utf8 = NULL;
254
sp_global_printer_utf8 = NULL;
258
static bool replaceArgs( int& argc, char**& argv );
260
static GSList *sp_process_args(poptContext ctx);
261
struct poptOption options[] = {
263
POPT_ARG_NONE, NULL, SP_ARG_VERSION,
264
N_("Print the Inkscape version number"),
268
POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
269
N_("Do not use X server (only process files from console)"),
273
POPT_ARG_NONE, NULL, SP_ARG_GUI,
274
N_("Try to use X server (even if $DISPLAY is not set)"),
278
POPT_ARG_STRING, NULL, SP_ARG_FILE,
279
N_("Open specified document(s) (option string may be excluded)"),
283
POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
284
N_("Print document(s) to specified output file (use '| program' for pipe)"),
288
POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
289
N_("Export document to a PNG file"),
293
POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
294
N_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 90)"),
298
POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
299
N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
302
{"export-area-drawing", 'D',
303
POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
304
N_("Exported area is the entire drawing (not canvas)"),
307
{"export-area-canvas", 'C',
308
POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
309
N_("Exported area is the entire canvas"),
312
{"export-area-snap", 0,
313
POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
314
N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
317
{"export-width", 'w',
318
POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
319
N_("The width of exported bitmap in pixels (overrides export-dpi)"),
322
{"export-height", 'h',
323
POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
324
N_("The height of exported bitmap in pixels (overrides export-dpi)"),
328
POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
329
N_("The ID of the object to export"),
332
{"export-id-only", 'j',
333
POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
334
// TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
335
// See "man inkscape" for details.
336
N_("Export just the object with export-id, hide all others (only with export-id)"),
339
{"export-use-hints", 't',
340
POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
341
N_("Use stored filename and DPI hints when exporting (only with export-id)"),
344
{"export-background", 'b',
345
POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
346
N_("Background color of exported bitmap (any SVG-supported color string)"),
349
{"export-background-opacity", 'y',
350
POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
351
N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"),
354
{"export-plain-svg", 'l',
355
POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
356
N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"),
360
POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
361
N_("Export document to a PS file"),
365
POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
366
N_("Export document to an EPS file"),
370
POPT_ARG_STRING, &sp_export_pdf, SP_ARG_EXPORT_PDF,
371
N_("Export document to a PDF file"),
376
POPT_ARG_STRING, &sp_export_emf, SP_ARG_EXPORT_EMF,
377
N_("Export document to an Enhanced Metafile (EMF) File"),
381
{"export-text-to-path", 'T',
382
POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
383
N_("Convert text object to paths on export (PS, EPS, PDF)"),
386
{"export-ignore-filters", 0,
387
POPT_ARG_NONE, &sp_export_ignore_filters, SP_ARG_EXPORT_IGNORE_FILTERS,
388
N_("Render filtered objects without filters, instead of rasterizing (PS, EPS, PDF)"),
392
POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
393
// TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
394
N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
398
POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
399
// TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
400
N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
404
POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
405
// TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
406
N_("Query the width of the drawing or, if specified, of the object with --query-id"),
409
{"query-height", 'H',
410
POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
411
// TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
412
N_("Query the height of the drawing or, if specified, of the object with --query-id"),
416
POPT_ARG_NONE, &sp_query_all, SP_ARG_QUERY_ALL,
417
N_("List id,x,y,w,h for all objects"),
421
POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
422
N_("The ID of the object whose dimensions are queried"),
425
{"extension-directory", 'x',
426
POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
427
// TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
428
N_("Print out the extension directory and exit"),
432
POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
433
N_("Remove unused definitions from the defs section(s) of the document"),
437
POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
438
N_("List the IDs of all the verbs in Inkscape"),
442
POPT_ARG_STRING, NULL, SP_ARG_VERB,
443
N_("Verb to call when Inkscape opens."),
447
POPT_ARG_STRING, NULL, SP_ARG_SELECT,
448
N_("Object ID to select when Inkscape opens."),
452
POPT_ARG_NONE, &sp_shell, SP_ARG_SHELL,
453
N_("Start Inkscape in interactive shell mode."),
456
POPT_AUTOHELP POPT_TABLEEND
459
static bool needToRecodeParams = true;
460
gchar * blankParam = g_strdup("");
467
* Return the directory of the .exe that is currently running
469
static Glib::ustring _win32_getExePath()
471
char exeName[MAX_PATH+1];
472
// TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
473
GetModuleFileName(NULL, exeName, MAX_PATH);
474
char *slashPos = strrchr(exeName, '\\');
478
Glib::ustring s = exeName;
483
* Set up the PATH and PYTHONPATH environment variables on
486
static int _win32_set_inkscape_env(const Glib::ustring &exePath)
488
// TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
490
char *oldenv = getenv("PATH");
491
Glib::ustring tmp = "PATH=";
497
tmp += "\\python\\Scripts;"; // for uniconv.cmd
504
_putenv(tmp.c_str());
506
oldenv = getenv("PYTHONPATH");
511
tmp += "\\python\\Lib;";
513
tmp += "\\python\\DLLs";
518
_putenv(tmp.c_str());
525
* Add INKSCAPE_EXTENSIONDIR to PYTHONPATH so that extensions in users home
526
* can find inkex.py et al. (Bug #197475)
528
static int set_extensions_env()
530
char *oldenv = getenv("PYTHONPATH");
531
Glib::ustring tmp = INKSCAPE_EXTENSIONDIR;
532
if (oldenv != NULL) {
533
tmp += G_SEARCHPATH_SEPARATOR;
536
g_setenv("PYTHONPATH", tmp.c_str(), TRUE);
543
* This is the classic main() entry point of the program, though on some
544
* architectures it might be called by something else.
547
main(int argc, char **argv)
549
#ifdef HAVE_FPSETMASK
550
/* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__. It's probably
551
safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
552
the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
553
fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
558
Set the current directory to the directory of the
559
executable. This seems redundant, but is needed for
560
when inkscape.exe is executed from another directory.
561
We use relative paths on win32.
562
HKCR\svgfile\shell\open\command is a good example
564
Glib::ustring homedir = _win32_getExePath();
565
// TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
566
SetCurrentDirectory(homedir.c_str());
567
_win32_set_inkscape_env(homedir);
572
// Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
573
Gtk::Main::init_gtkmm_internals();
576
set_extensions_env();
579
* Call bindtextdomain() for various machines's paths
583
Glib::ustring localePath = homedir;
585
localePath += PACKAGE_LOCALE_DIR;
586
bindtextdomain(GETTEXT_PACKAGE, localePath.c_str());
588
#ifdef ENABLE_BINRELOC
589
bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
591
bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
594
// Allow the user to override the locale directory by setting
595
// the environment variable INKSCAPE_LOCALEDIR.
596
char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
597
if (inkscape_localedir != NULL) {
598
bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
602
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
605
textdomain(GETTEXT_PACKAGE);
610
Inkscape::GC::init();
612
Inkscape::Debug::Logger::init();
617
// TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
618
use_gui = (getenv("DISPLAY") != NULL);
622
/* Test whether with/without GUI is forced */
623
for (int i = 1; i < argc; i++) {
624
if (!strcmp(argv[i], "-z")
625
|| !strcmp(argv[i], "--without-gui")
626
|| !strcmp(argv[i], "-p")
627
|| !strncmp(argv[i], "--print", 7)
628
|| !strcmp(argv[i], "-e")
629
|| !strncmp(argv[i], "--export-png", 12)
630
|| !strcmp(argv[i], "-l")
631
|| !strncmp(argv[i], "--export-plain-svg", 12)
632
|| !strcmp(argv[i], "-i")
633
|| !strncmp(argv[i], "--export-area-drawing", 21)
634
|| !strcmp(argv[i], "-D")
635
|| !strncmp(argv[i], "--export-area-canvas", 20)
636
|| !strcmp(argv[i], "-C")
637
|| !strncmp(argv[i], "--export-id", 12)
638
|| !strcmp(argv[i], "-P")
639
|| !strncmp(argv[i], "--export-ps", 11)
640
|| !strcmp(argv[i], "-E")
641
|| !strncmp(argv[i], "--export-eps", 12)
642
|| !strcmp(argv[i], "-A")
643
|| !strncmp(argv[i], "--export-pdf", 12)
645
|| !strcmp(argv[i], "-M")
646
|| !strncmp(argv[i], "--export-emf", 12)
648
|| !strcmp(argv[i], "-W")
649
|| !strncmp(argv[i], "--query-width", 13)
650
|| !strcmp(argv[i], "-H")
651
|| !strncmp(argv[i], "--query-height", 14)
652
|| !strcmp(argv[i], "-S")
653
|| !strncmp(argv[i], "--query-all", 11)
654
|| !strcmp(argv[i], "-X")
655
|| !strncmp(argv[i], "--query-x", 13)
656
|| !strcmp(argv[i], "-Y")
657
|| !strncmp(argv[i], "--query-y", 14)
658
|| !strcmp(argv[i], "--vacuum-defs")
659
|| !strncmp(argv[i], "--shell", 7)
662
/* main_console handles any exports -- not the gui */
665
} else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
672
#ifndef REPLACEARGS_ANSI
673
if ( PrintWin32::is_os_wide() )
674
#endif // REPLACEARGS_ANSI
676
// If the call fails, we'll need to convert charsets
677
needToRecodeParams = !replaceArgs( argc, argv );
681
/// \todo Should this be a static object (see inkscape.cpp)?
682
Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
690
void fixupSingleFilename( gchar **orig, gchar **spare )
692
if ( orig && *orig && **orig ) {
693
GError *error = NULL;
694
gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
699
*spare = newFileName;
701
// g_message("Set a replacement fixup");
708
GSList *fixupFilenameEncoding( GSList* fl )
710
GSList *newFl = NULL;
712
gchar *fn = static_cast<gchar*>(fl->data);
713
fl = g_slist_remove( fl, fl->data );
714
gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
719
gchar *safeFn = Inkscape::IO::sanitizeString(fn);
720
gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
721
GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
722
"Note: Converted '%s' to '%s'", safeFn, safeNewFn );
723
gtk_dialog_run (GTK_DIALOG (w));
724
gtk_widget_destroy (w);
736
gchar *safeFn = Inkscape::IO::sanitizeString(fn);
737
GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
738
gtk_dialog_run (GTK_DIALOG (w));
739
gtk_widget_destroy (w);
742
newFl = g_slist_append( newFl, fn );
747
int sp_common_main( int argc, char const **argv, GSList **flDest )
749
/// \todo fixme: Move these to some centralized location (Lauris)
750
sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
751
sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);
754
// temporarily switch gettext encoding to locale, so that help messages can be output properly
755
gchar const *charset;
756
g_get_charset(&charset);
758
bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
760
poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
761
poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
762
g_return_val_if_fail(ctx != NULL, 1);
764
/* Collect own arguments */
765
GSList *fl = sp_process_args(ctx);
766
poptFreeContext(ctx);
768
// now switch gettext back to UTF-8 (for GUI)
769
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
771
// Now let's see if the file list still holds up
772
if ( needToRecodeParams )
774
fl = fixupFilenameEncoding( fl );
777
// Check the globals for filename-fixup
778
if ( needToRecodeParams )
780
fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
781
fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
782
fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
787
sp_export_png_utf8 = g_strdup( sp_export_png );
789
sp_export_svg_utf8 = g_strdup( sp_export_svg );
790
if ( sp_global_printer )
791
sp_global_printer_utf8 = g_strdup( sp_global_printer );
794
// Return the list if wanted, else free it up.
801
fl = g_slist_remove( fl, fl->data );
808
snooper(GdkEvent *event, gpointer /*data*/) {
809
if (inkscape_mapalt()) /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
811
GdkModifierType mapping=(GdkModifierType)inkscape_mapalt();
812
switch (event->type) {
813
case GDK_MOTION_NOTIFY:
814
if(event->motion.state & mapping) {
815
event->motion.state|=GDK_MOD1_MASK;
818
case GDK_BUTTON_PRESS:
819
if(event->button.state & mapping) {
820
event->button.state|=GDK_MOD1_MASK;
824
if(event->key.state & mapping) {
825
event->key.state|=GDK_MOD1_MASK;
833
if (inkscape_trackalt()) {
834
// MacOS X with X11 has some problem with the default
835
// xmodmapping. A ~/.xmodmap solution does not work reliably due
836
// to the way we package our executable in a .app that can launch
837
// X11 or use an already-running X11. The same problem has been
838
// reported on Linux but there is no .app/X11 to get in the way
839
// of ~/.xmodmap fixes. So we make this a preference.
841
// For some reason, Gdk senses changes in Alt (Mod1) state for
842
// many message types, but not for keystrokes! So this ugly hack
843
// tracks what the state of Alt-pressing is, and ensures
844
// GDK_MOD1_MASK is in the event->key.state as appropriate.
846
static gboolean altL_pressed = FALSE;
847
static gboolean altR_pressed = FALSE;
848
static gboolean alt_pressed = FALSE;
849
guint get_group0_keyval(GdkEventKey* event);
851
switch (event->type) {
852
case GDK_MOTION_NOTIFY:
853
alt_pressed = TRUE && (event->motion.state & GDK_MOD1_MASK);
855
case GDK_BUTTON_PRESS:
856
alt_pressed = TRUE && (event->button.state & GDK_MOD1_MASK);
859
keyval = get_group0_keyval(&event->key);
860
if (keyval == GDK_Alt_L) altL_pressed = TRUE;
861
if (keyval == GDK_Alt_R) altR_pressed = TRUE;
862
alt_pressed = alt_pressed || altL_pressed || altR_pressed;
863
alt_pressed = alt_pressed || (event->button.state & GDK_MOD1_MASK);
865
event->key.state |= GDK_MOD1_MASK;
867
event->key.state &= ~GDK_MOD1_MASK;
869
case GDK_KEY_RELEASE:
870
keyval = get_group0_keyval(&event->key);
871
if (keyval == GDK_Alt_L) altL_pressed = FALSE;
872
if (keyval == GDK_Alt_R) altR_pressed = FALSE;
873
if (!altL_pressed && !altR_pressed)
879
//printf("alt_pressed: %s\n", alt_pressed? "+" : "-");
882
gtk_main_do_event (event);
885
static std::vector<Glib::ustring> getDirectorySet(const gchar* userDir, const gchar* const * systemDirs) {
886
std::vector<Glib::ustring> listing;
887
listing.push_back(userDir);
888
for ( const char* const* cur = systemDirs; *cur; cur++ )
890
listing.push_back(*cur);
896
sp_main_gui(int argc, char const **argv)
898
Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
901
int retVal = sp_common_main( argc, argv, &fl );
902
g_return_val_if_fail(retVal == 0, 1);
904
// Add possible icon entry directories
905
std::vector<Glib::ustring> dataDirs = getDirectorySet( g_get_user_data_dir(),
906
g_get_system_data_dirs() );
907
for (std::vector<Glib::ustring>::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
909
std::vector<Glib::ustring> listing;
910
listing.push_back(*it);
911
listing.push_back("inkscape");
912
listing.push_back("icons");
913
Glib::ustring dir = Glib::build_filename(listing);
914
gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), dir.c_str());
917
// Add our icon directory to the search path for icon theme lookups.
918
gchar *usericondir = profile_path("icons");
919
gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), usericondir);
920
gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), INKSCAPE_PIXMAPDIR);
923
gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
924
Inkscape::Debug::log_display_config();
926
// Set default window icon. Obeys the theme.
927
gtk_window_set_default_icon_name("inkscape");
928
// Do things that were previously in inkscape_gtk_stock_init().
929
sp_icon_get_phys_size(GTK_ICON_SIZE_MENU);
930
Inkscape::UI::Widget::Panel::prep();
932
gboolean create_new = TRUE;
934
/// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
935
inkscape_application_init(argv[0], true);
938
if (sp_file_open((gchar *)fl->data,NULL)) {
941
fl = g_slist_remove(fl, fl->data);
944
sp_file_new_default();
947
Glib::signal_idle().connect(sigc::ptr_fun(&Inkscape::CmdLineAction::idle));
951
//We might not need anything here
952
//sp_win32_finish(); <-- this is a NOP func
961
void sp_process_file_list(GSList *fl)
964
const gchar *filename = (gchar *)fl->data;
965
SPDocument *doc = Inkscape::Extension::open(NULL, filename);
967
doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), filename);
970
g_warning("Specified document %s cannot be opened (is it a valid SVG file?)", filename);
972
if (sp_vacuum_defs) {
973
vacuum_document(doc);
975
if (sp_vacuum_defs && !sp_export_svg) {
976
// save under the name given in the command line
977
sp_repr_save_file(doc->rdoc, filename, SP_SVG_NS_URI);
979
if (sp_global_printer) {
980
sp_print_document_to_file(doc, sp_global_printer);
983
sp_do_export_png(doc);
986
Inkscape::XML::Document *rdoc;
987
Inkscape::XML::Node *repr;
988
rdoc = sp_repr_document_new("svg:svg");
990
repr = sp_document_root(doc)->updateRepr(rdoc, repr, SP_OBJECT_WRITE_BUILD);
991
sp_repr_save_rebased_file(repr->document(), sp_export_svg, SP_SVG_NS_URI,
992
doc->base, sp_export_svg);
995
do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript");
998
do_export_ps_pdf(doc, sp_export_eps, "image/x-e-postscript");
1000
if (sp_export_pdf) {
1001
do_export_ps_pdf(doc, sp_export_pdf, "application/pdf");
1004
if (sp_export_emf) {
1005
do_export_emf(doc, sp_export_emf, "image/x-emf");
1010
} else if (sp_query_width || sp_query_height) {
1011
do_query_dimension (doc, true, sp_query_width? Geom::X : Geom::Y, sp_query_id);
1012
} else if (sp_query_x || sp_query_y) {
1013
do_query_dimension (doc, false, sp_query_x? Geom::X : Geom::Y, sp_query_id);
1018
fl = g_slist_remove(fl, fl->data);
1023
* Run the application as an interactive shell, parsing command lines from stdin
1024
* Returns -1 on error.
1026
int sp_main_shell(char const* command_name)
1030
const unsigned int buffer_size = 4096;
1031
gchar *command_line = g_strnfill(buffer_size, 0);
1032
g_strlcpy(command_line, command_name, buffer_size);
1033
gsize offset = g_strlcat(command_line, " ", buffer_size);
1034
gsize sizeLeft = buffer_size - offset;
1035
gchar *useme = command_line + offset;
1037
fprintf(stdout, "Inkscape %s interactive shell mode. Type 'quit' to quit.\n", Inkscape::version_string);
1041
fprintf(stdout, ">");
1043
if ((linedata = fgets(useme, sizeLeft, stdin))) {
1044
size_t len = strlen(useme);
1045
if ( (len >= sizeLeft - 1) || (useme[len - 1] != '\n') ) {
1046
fprintf(stdout, "ERROR: Command line too long\n");
1047
// Consume rest of line
1048
retval = -1; // If the while loop completes, this remains -1
1049
while (fgets(useme, sizeLeft, stdin) && retval) {
1050
len = strlen(command_line);
1051
if ( (len < buffer_size) && (command_line[len-1] == '\n') ) {
1056
useme[--len] = '\0'; // Strip newline
1057
if (useme[len - 1] == '\r') {
1058
useme[--len] = '\0';
1060
if ( strcmp(useme, "quit") == 0 ) {
1063
linedata = 0; // mark for exit
1064
} else if ( len < 1 ) {
1065
// blank string. Do nothing.
1067
GError* parseError = 0;
1070
if ( g_shell_parse_argv(command_line, &argc, &argv, &parseError) ) {
1071
poptContext ctx = poptGetContext(NULL, argc, const_cast<const gchar**>(argv), options, 0);
1072
poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
1074
GSList *fl = sp_process_args(ctx);
1075
sp_process_file_list(fl);
1076
poptFreeContext(ctx);
1078
retval = 1; // not sure why. But this was the previous return value
1080
resetCommandlineGlobals();
1083
g_warning("Cannot parse commandline: %s", useme);
1087
} // if (linedata...
1088
} while (linedata && (retval == 0));
1090
g_free(command_line);
1094
int sp_main_console(int argc, char const **argv)
1096
/* We are started in text mode */
1098
/* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
1099
* in a non-Gtk environment. Used in libnrtype's
1100
* FontInstance.cpp and FontFactory.cpp.
1101
* http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
1104
char **argv2 = const_cast<char **>(argv);
1105
gtk_init_check( &argc, &argv2 );
1106
//setlocale(LC_ALL, "");
1109
int retVal = sp_common_main( argc, argv, &fl );
1110
g_return_val_if_fail(retVal == 0, 1);
1112
if (fl == NULL && !sp_shell) {
1113
g_print("Nothing to do!\n");
1117
inkscape_application_init(argv[0], false);
1120
sp_main_shell(argv[0]); // Run as interactive shell
1123
sp_process_file_list(fl); // Normal command line invokation
1130
do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id)
1135
o = doc->getObjectById(id);
1137
if (!SP_IS_ITEM (o)) {
1138
g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
1142
g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
1146
o = SP_DOCUMENT_ROOT(doc);
1150
sp_document_ensure_up_to_date (doc);
1151
SPItem *item = ((SPItem *) o);
1153
// "true" SVG bbox for scripting
1154
Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
1156
Inkscape::SVGOStringStream os;
1158
os << area->dimensions()[axis];
1160
os << area->min()[axis];
1162
g_print ("%s", os.str().c_str());
1170
do_query_all (SPDocument *doc)
1174
o = SP_DOCUMENT_ROOT(doc);
1177
sp_document_ensure_up_to_date (doc);
1178
do_query_all_recurse(o);
1183
do_query_all_recurse (SPObject *o)
1185
SPItem *item = ((SPItem *) o);
1186
if (o->id && SP_IS_ITEM(item)) {
1187
Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
1189
Inkscape::SVGOStringStream os;
1191
os << "," << area->min()[Geom::X];
1192
os << "," << area->min()[Geom::Y];
1193
os << "," << area->dimensions()[Geom::X];
1194
os << "," << area->dimensions()[Geom::Y];
1195
g_print ("%s\n", os.str().c_str());
1199
SPObject *child = o->children;
1201
do_query_all_recurse (child);
1202
child = child->next;
1208
sp_do_export_png(SPDocument *doc)
1210
const gchar *filename = NULL;
1213
if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
1214
g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
1217
GSList *items = NULL;
1220
if (sp_export_id || sp_export_area_drawing) {
1223
SPObject *o_area = NULL;
1224
if (sp_export_id && sp_export_area_drawing) {
1225
o = doc->getObjectById(sp_export_id);
1226
o_area = SP_DOCUMENT_ROOT (doc);
1227
} else if (sp_export_id) {
1228
o = doc->getObjectById(sp_export_id);
1230
} else if (sp_export_area_drawing) {
1231
o = SP_DOCUMENT_ROOT (doc);
1236
if (!SP_IS_ITEM (o)) {
1237
g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
1241
items = g_slist_prepend (items, SP_ITEM(o));
1243
if (sp_export_id_only) {
1244
g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
1247
if (sp_export_use_hints) {
1249
// retrieve export filename hint
1250
const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
1252
if (sp_export_png) {
1253
g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
1254
filename = sp_export_png;
1259
g_warning ("Export filename hint not found for the object.");
1260
filename = sp_export_png;
1263
// retrieve export dpi hints
1264
const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
1266
if (sp_export_dpi || sp_export_width || sp_export_height) {
1267
g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
1269
dpi = atof(dpi_hint);
1272
g_warning ("Export DPI hint not found for the object.");
1277
// write object bbox to area
1278
sp_document_ensure_up_to_date (doc);
1279
Geom::OptRect areaMaybe;
1280
sp_item_invoke_bbox((SPItem *) o_area, areaMaybe, sp_item_i2d_affine((SPItem *) o_area), TRUE);
1284
g_warning("Unable to determine a valid bounding box. Nothing exported.");
1288
g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
1293
if (sp_export_area) {
1294
/* Try to parse area (given in SVG pixels) */
1295
gdouble x0,y0,x1,y1;
1296
if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &x0, &y0, &x1, &y1) == 4) {
1297
g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
1300
area = Geom::Rect(Geom::Interval(x0,x1), Geom::Interval(y0,y1));
1301
} else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
1302
/* Export the whole canvas */
1303
sp_document_ensure_up_to_date (doc);
1304
Geom::Point origin (SP_ROOT(doc->root)->x.computed, SP_ROOT(doc->root)->y.computed);
1305
area = Geom::Rect(origin, origin + sp_document_dimensions(doc));
1308
// set filename and dpi from options, if not yet set from the hints
1310
if (!sp_export_png) {
1311
g_warning ("No export filename given and no filename hint. Nothing exported.");
1314
filename = sp_export_png;
1317
if (sp_export_dpi && dpi == 0.0) {
1318
dpi = atof(sp_export_dpi);
1319
if ((dpi < 0.1) || (dpi > 10000.0)) {
1320
g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
1323
g_print("DPI: %g\n", dpi);
1326
if (sp_export_area_snap) {
1327
round_rectangle_outwards(area);
1335
unsigned long int width = 0;
1336
unsigned long int height = 0;
1338
if (sp_export_width) {
1340
width = strtoul(sp_export_width, NULL, 0);
1341
if ((width < 1) || (width > PNG_UINT_31_MAX) || (errno == ERANGE) ) {
1342
g_warning("Export width %lu out of range (1 - %lu). Nothing exported.", width, (unsigned long int)PNG_UINT_31_MAX);
1345
dpi = (gdouble) width * PX_PER_IN / area.width();
1348
if (sp_export_height) {
1350
height = strtoul(sp_export_height, NULL, 0);
1351
if ((height < 1) || (height > PNG_UINT_31_MAX)) {
1352
g_warning("Export height %lu out of range (1 - %lu). Nothing exported.", height, (unsigned long int)PNG_UINT_31_MAX);
1355
dpi = (gdouble) height * PX_PER_IN / area.height();
1358
if (!sp_export_width) {
1359
width = (unsigned long int) (area.width() * dpi / PX_PER_IN + 0.5);
1362
if (!sp_export_height) {
1363
height = (unsigned long int) (area.height() * dpi / PX_PER_IN + 0.5);
1366
guint32 bgcolor = 0x00000000;
1367
if (sp_export_background) {
1368
// override the page color
1369
bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
1370
bgcolor |= 0xff; // default is no opacity
1372
// read from namedview
1373
Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
1374
if (nv && nv->attribute("pagecolor"))
1375
bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
1376
if (nv && nv->attribute("inkscape:pageopacity"))
1377
bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
1380
if (sp_export_background_opacity) {
1383
if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
1385
value = CLAMP (value, 1.0f, 255.0f);
1386
bgcolor &= (guint32) 0xffffff00;
1387
bgcolor |= (guint32) floor(value);
1389
value = CLAMP (value, 0.0f, 1.0f);
1390
bgcolor &= (guint32) 0xffffff00;
1391
bgcolor |= SP_COLOR_F_TO_U(value);
1396
g_print("Background RRGGBBAA: %08x\n", bgcolor);
1398
g_print("Area %g:%g:%g:%g exported to %lu x %lu pixels (%g dpi)\n", area[Geom::X][0], area[Geom::Y][0], area[Geom::X][1], area[Geom::Y][1], width, height, dpi);
1400
g_print("Bitmap saved as: %s\n", filename);
1402
if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) {
1403
sp_export_png_file(doc, filename, area, width, height, dpi, dpi, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
1405
g_warning("Calculated bitmap dimensions %lu %lu are out of range (1 - %lu). Nothing exported.", width, height, (unsigned long int)PNG_UINT_31_MAX);
1408
g_slist_free (items);
1413
* Perform a PDF/PS/EPS export
1415
* \param doc Document to export.
1416
* \param uri URI to export to.
1417
* \param mime MIME type to export as.
1420
static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
1422
Inkscape::Extension::DB::OutputList o;
1423
Inkscape::Extension::db.get_output_list(o);
1424
Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1425
while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1431
g_warning ("Could not find an extension to export to MIME type %s.", mime);
1436
SPObject *o = doc->getObjectById(sp_export_id);
1438
g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
1441
(*i)->set_param_string ("exportId", sp_export_id);
1443
(*i)->set_param_string ("exportId", "");
1446
if (sp_export_area_canvas && sp_export_area_drawing) {
1447
g_warning ("You cannot use --export-area-canvas and --export-area-drawing at the same time; only the former will take effect.");
1448
sp_export_area_drawing = false;
1451
if (sp_export_area_drawing) {
1452
(*i)->set_param_bool ("areaDrawing", TRUE);
1454
(*i)->set_param_bool ("areaDrawing", FALSE);
1457
if (sp_export_area_canvas) {
1458
if (sp_export_eps) {
1459
g_warning ("EPS cannot have its bounding box extend beyond its content, so if your drawing is smaller than the canvas, --export-area-canvas will clip it to drawing.");
1461
(*i)->set_param_bool ("areaCanvas", TRUE);
1463
(*i)->set_param_bool ("areaCanvas", FALSE);
1466
if (!sp_export_area_drawing && !sp_export_area_canvas && !sp_export_id) {
1467
// neither is set, set canvas as default for ps/pdf and drawing for eps
1468
if (sp_export_eps) {
1470
(*i)->set_param_bool("areaDrawing", TRUE);
1475
if (sp_export_text_to_path) {
1476
(*i)->set_param_bool("textToPath", TRUE);
1478
(*i)->set_param_bool("textToPath", FALSE);
1481
if (sp_export_ignore_filters) {
1482
(*i)->set_param_bool("blurToBitmap", FALSE);
1484
(*i)->set_param_bool("blurToBitmap", TRUE);
1487
if (sp_export_dpi) {
1488
dpi = atof(sp_export_dpi);
1489
if ((dpi < 1) || (dpi > 10000.0)) {
1490
g_warning("DPI value %s out of range [1 - 10000]. Using 90 dpi instead.", sp_export_dpi);
1495
(*i)->set_param_int("resolution", (int) dpi);
1498
(*i)->save(doc, uri);
1503
* Export a document to EMF
1505
* \param doc Document to export.
1506
* \param uri URI to export to.
1507
* \param mime MIME type to export as (should be "image/x-emf")
1510
static void do_export_emf(SPDocument* doc, gchar const* uri, char const* mime)
1512
Inkscape::Extension::DB::OutputList o;
1513
Inkscape::Extension::db.get_output_list(o);
1514
Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
1515
while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
1521
g_warning ("Could not find an extension to export to MIME type %s.", mime);
1525
(*i)->save(doc, uri);
1530
bool replaceArgs( int& argc, char**& argv )
1532
bool worked = false;
1534
#ifdef REPLACEARGS_DEBUG
1535
MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1536
#endif // REPLACEARGS_DEBUG
1538
wchar_t* line = GetCommandLineW();
1541
#ifdef REPLACEARGS_DEBUG
1543
gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
1546
gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
1548
char tmp[strlen(safe) + 32];
1549
snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
1550
MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1554
#endif // REPLACEARGS_DEBUG
1557
wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
1559
#ifdef REPLACEARGS_ANSI
1560
// test code for trying things on Win95/98/ME
1563
#ifdef REPLACEARGS_DEBUG
1564
MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1565
#endif // REPLACEARGS_DEBUG
1566
int lineLen = wcslen(line) + 1;
1567
wchar_t* lineDup = new wchar_t[lineLen];
1568
wcsncpy( lineDup, line, lineLen );
1571
bool inQuotes = false;
1572
bool inWhitespace = true;
1573
std::vector<int> places;
1574
while ( lineDup[pos] )
1578
if ( lineDup[pos] == L'"' )
1583
else if ( lineDup[pos] == L'"' )
1586
inWhitespace = false;
1587
places.push_back(pos);
1589
else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
1591
if ( !inWhitespace )
1593
inWhitespace = true;
1597
else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
1599
inWhitespace = false;
1600
places.push_back(pos);
1608
#ifdef REPLACEARGS_DEBUG
1611
snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
1612
MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1614
#endif // REPLACEARGS_DEBUG
1616
wchar_t** block = new wchar_t*[places.size()];
1618
for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
1620
block[i++] = &lineDup[*it];
1623
numArgs = places.size();
1625
#endif // REPLACEARGS_ANSI
1629
std::vector<wchar_t*>expandedArgs;
1632
expandedArgs.push_back( parsed[0] );
1635
for ( int i1 = 1; i1 < numArgs; i1++ )
1637
bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
1638
wildcarded &= parsed[i1][0] != L'"';
1639
wildcarded &= parsed[i1][0] != L'-';
1642
#ifdef REPLACEARGS_ANSI
1643
WIN32_FIND_DATAA data;
1645
WIN32_FIND_DATAW data;
1646
#endif // REPLACEARGS_ANSI
1648
memset((void *)&data, 0, sizeof(data));
1650
int baseLen = wcslen(parsed[i1]) + 2;
1651
wchar_t* base = new wchar_t[baseLen];
1652
wcsncpy( base, parsed[i1], baseLen );
1653
wchar_t* last = wcsrchr( base, L'\\' );
1662
baseLen = wcslen( base );
1664
#ifdef REPLACEARGS_ANSI
1665
char target[MAX_PATH];
1666
if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
1668
HANDLE hf = FindFirstFileA( target, &data );
1670
HANDLE hf = FindFirstFileW( parsed[i1], &data );
1671
#endif // REPLACEARGS_ANSI
1672
if ( hf != INVALID_HANDLE_VALUE )
1677
#ifdef REPLACEARGS_ANSI
1678
int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
1682
wchar_t* tmp = new wchar_t[howMany + 1];
1683
wcsncpy( tmp, base, howMany + 1 );
1684
MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
1685
expandedArgs.push_back( tmp );
1686
found = FindNextFileA( hf, &data );
1689
int howMany = wcslen(data.cFileName) + baseLen;
1690
wchar_t* tmp = new wchar_t[howMany + 1];
1691
wcsncpy( tmp, base, howMany + 1 );
1692
wcsncat( tmp, data.cFileName, howMany + 1 );
1693
expandedArgs.push_back( tmp );
1694
found = FindNextFileW( hf, &data );
1695
#endif // REPLACEARGS_ANSI
1702
expandedArgs.push_back( parsed[i1] );
1704
#ifdef REPLACEARGS_ANSI
1706
#endif // REPLACEARGS_ANSI
1712
expandedArgs.push_back( parsed[i1] );
1717
wchar_t** block = new wchar_t*[expandedArgs.size()];
1719
for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
1724
numArgs = expandedArgs.size();
1727
std::vector<gchar*> newArgs;
1728
for ( int i = 0; i < numArgs; i++ )
1730
gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
1733
#ifdef REPLACEARGS_DEBUG
1734
gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
1740
snprintf( tmp, sizeof(tmp), " [%2d] = '%s'", i, safe2 );
1741
MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1745
#endif // REPLACEARGS_DEBUG
1747
newArgs.push_back( replacement );
1751
newArgs.push_back( blankParam );
1755
// Now push our munged params to be the new argv and argc
1757
char** block = new char*[newArgs.size()];
1759
for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
1764
argc = newArgs.size();
1768
#ifdef REPLACEARGS_DEBUG
1771
MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
1773
#endif // REPLACEARGS_DEBUG
1775
#ifdef REPLACEARGS_DEBUG
1779
MessageBoxA( NULL, "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
1782
char* line2 = GetCommandLineA();
1785
gchar *safe = Inkscape::IO::sanitizeString(line2);
1788
char tmp[strlen(safe) + 32];
1789
snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
1790
MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1796
MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
1799
#endif // REPLACEARGS_DEBUG
1806
sp_process_args(poptContext ctx)
1811
while ((a = poptGetNextOpt(ctx)) != -1) {
1814
gchar const *fn = poptGetOptArg(ctx);
1816
fl = g_slist_append(fl, g_strdup(fn));
1820
case SP_ARG_VERSION: {
1821
printf("Inkscape %s (%s)\n", Inkscape::version_string, __DATE__);
1825
case SP_ARG_EXTENSIONDIR: {
1826
printf("%s\n", INKSCAPE_EXTENSIONDIR);
1830
case SP_ARG_VERB_LIST: {
1831
// This really shouldn't go here, we should init the app.
1832
// But, since we're just exiting in this path, there is
1833
// no harm, and this is really a better place to put
1835
Inkscape::Extension::init();
1836
Inkscape::Verb::list();
1841
case SP_ARG_SELECT: {
1842
gchar const *arg = poptGetOptArg(ctx);
1844
// printf("Adding in: %s\n", arg);
1845
new Inkscape::CmdLineAction((a == SP_ARG_VERB), arg);
1849
case POPT_ERROR_BADOPT: {
1850
g_warning ("Invalid option %s", poptBadOption(ctx, 0));
1860
gchar const ** const args = poptGetArgs(ctx);
1862
for (unsigned i = 0; args[i] != NULL; i++) {
1863
fl = g_slist_append(fl, g_strdup(args[i]));
1874
c-file-style:"stroustrup"
1875
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1876
indent-tabs-mode:nil
1880
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :