~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/main.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#define __MAIN_C__
 
2
 
 
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
 */
 
24
 
 
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
# include "config.h"
 
28
#endif
 
29
#include "path-prefix.h"
 
30
 
 
31
// This has to be included prior to anything that includes setjmp.h, it croaks otherwise
 
32
#include <png.h>
 
33
 
 
34
#include <gtk/gtkmessagedialog.h>
 
35
 
 
36
#ifdef HAVE_IEEEFP_H
 
37
#include <ieeefp.h>
 
38
#endif
 
39
#include <cstring>
 
40
#include <string>
 
41
#include <locale.h>
 
42
#include <stdlib.h>
 
43
 
 
44
#include <popt.h>
 
45
#ifndef POPT_TABLEEND
 
46
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
 
47
#endif /* Not def: POPT_TABLEEND */
 
48
 
 
49
#include <libxml/tree.h>
 
50
#include <glib-object.h>
 
51
#include <gtk/gtk.h>
 
52
#include <gtk/gtkmain.h>
 
53
#include <gtk/gtksignal.h>
 
54
#include <gtk/gtkwindow.h>
 
55
#include <gtk/gtkbox.h>
 
56
 
 
57
#include "gc-core.h"
 
58
 
 
59
#include "macros.h"
 
60
#include "file.h"
 
61
#include "document.h"
 
62
#include "sp-object.h"
 
63
#include "interface.h"
 
64
#include "print.h"
 
65
#include "color.h"
 
66
#include "sp-item.h"
 
67
#include "sp-root.h"
 
68
#include "unit-constants.h"
 
69
 
 
70
#include "svg/svg.h"
 
71
#include "svg/svg-color.h"
 
72
#include "svg/stringstream.h"
 
73
 
 
74
#include "inkscape-private.h"
 
75
#include "inkscape-version.h"
 
76
 
 
77
#include "sp-namedview.h"
 
78
#include "sp-guide.h"
 
79
#include "sp-object-repr.h"
 
80
#include "xml/repr.h"
 
81
 
 
82
#include "io/sys.h"
 
83
 
 
84
#include "debug/logger.h"
 
85
#include "debug/log-display-config.h"
 
86
 
 
87
#include "helper/png-write.h"
 
88
#include "helper/geom.h"
 
89
 
 
90
#include <extension/extension.h>
 
91
#include <extension/system.h>
 
92
#include <extension/db.h>
 
93
#include <extension/output.h>
 
94
 
 
95
#ifdef WIN32
 
96
//#define REPLACEARGS_ANSI
 
97
//#define REPLACEARGS_DEBUG
 
98
 
 
99
#include "registrytool.h"
 
100
 
 
101
#include "extension/internal/win32.h"
 
102
using Inkscape::Extension::Internal::PrintWin32;
 
103
 
 
104
#endif // WIN32
 
105
 
 
106
#include "extension/init.h"
 
107
 
 
108
#include <glibmm/i18n.h>
 
109
#include <gtkmm/main.h>
 
110
 
 
111
#ifndef HAVE_BIND_TEXTDOMAIN_CODESET
 
112
#define bind_textdomain_codeset(p,c)
 
113
#endif
 
114
 
 
115
#include "application/application.h"
 
116
#include "main-cmdlineact.h"
 
117
#include "widgets/icon.h"
 
118
#include "ui/widget/panel.h"
 
119
 
 
120
#include <errno.h>
 
121
 
 
122
enum {
 
123
    SP_ARG_NONE,
 
124
    SP_ARG_NOGUI,
 
125
    SP_ARG_GUI,
 
126
    SP_ARG_FILE,
 
127
    SP_ARG_PRINT,
 
128
    SP_ARG_EXPORT_PNG,
 
129
    SP_ARG_EXPORT_DPI,
 
130
    SP_ARG_EXPORT_AREA,
 
131
    SP_ARG_EXPORT_AREA_DRAWING,
 
132
    SP_ARG_EXPORT_AREA_CANVAS,
 
133
    SP_ARG_EXPORT_AREA_SNAP,
 
134
    SP_ARG_EXPORT_WIDTH,
 
135
    SP_ARG_EXPORT_HEIGHT,
 
136
    SP_ARG_EXPORT_ID,
 
137
    SP_ARG_EXPORT_ID_ONLY,
 
138
    SP_ARG_EXPORT_USE_HINTS,
 
139
    SP_ARG_EXPORT_BACKGROUND,
 
140
    SP_ARG_EXPORT_BACKGROUND_OPACITY,
 
141
    SP_ARG_EXPORT_SVG,
 
142
    SP_ARG_EXPORT_PS,
 
143
    SP_ARG_EXPORT_EPS,
 
144
    SP_ARG_EXPORT_PDF,
 
145
#ifdef WIN32
 
146
    SP_ARG_EXPORT_EMF,
 
147
#endif //WIN32
 
148
    SP_ARG_EXPORT_TEXT_TO_PATH,
 
149
    SP_ARG_EXPORT_IGNORE_FILTERS,
 
150
    SP_ARG_EXTENSIONDIR,
 
151
    SP_ARG_QUERY_X,
 
152
    SP_ARG_QUERY_Y,
 
153
    SP_ARG_QUERY_WIDTH,
 
154
    SP_ARG_QUERY_HEIGHT,
 
155
    SP_ARG_QUERY_ALL,
 
156
    SP_ARG_QUERY_ID,
 
157
    SP_ARG_SHELL,
 
158
    SP_ARG_VERSION,
 
159
    SP_ARG_VACUUM_DEFS,
 
160
    SP_ARG_VERB_LIST,
 
161
    SP_ARG_VERB,
 
162
    SP_ARG_SELECT,
 
163
    SP_ARG_LAST
 
164
};
 
165
 
 
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);
 
170
#ifdef WIN32
 
171
static void do_export_emf(SPDocument* doc, gchar const* uri, char const *mime);
 
172
#endif //WIN32
 
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);
 
176
 
 
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;
 
195
#ifdef WIN32
 
196
static gchar *sp_export_emf = NULL;
 
197
#endif //WIN32
 
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;
 
210
 
 
211
static gchar *sp_export_png_utf8 = NULL;
 
212
static gchar *sp_export_svg_utf8 = NULL;
 
213
static gchar *sp_global_printer_utf8 = NULL;
 
214
 
 
215
 
 
216
/**
 
217
 *  Reset variables to default values.
 
218
 */
 
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;
 
228
        sp_export_id = 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;
 
235
        sp_export_ps = NULL;
 
236
        sp_export_eps = NULL;
 
237
        sp_export_pdf = NULL;
 
238
#ifdef WIN32
 
239
        sp_export_emf = NULL;
 
240
#endif //WIN32
 
241
        sp_export_text_to_path = FALSE;
 
242
        sp_export_ignore_filters = FALSE;
 
243
        sp_export_font = FALSE;
 
244
        sp_query_x = FALSE;
 
245
        sp_query_y = FALSE;
 
246
        sp_query_width = FALSE;
 
247
        sp_query_height = FALSE;
 
248
        sp_query_all = FALSE;
 
249
        sp_query_id = NULL;
 
250
        sp_vacuum_defs = FALSE;
 
251
 
 
252
        sp_export_png_utf8 = NULL;
 
253
        sp_export_svg_utf8 = NULL;
 
254
        sp_global_printer_utf8 = NULL;
 
255
}
 
256
 
 
257
#ifdef WIN32
 
258
static bool replaceArgs( int& argc, char**& argv );
 
259
#endif
 
260
static GSList *sp_process_args(poptContext ctx);
 
261
struct poptOption options[] = {
 
262
    {"version", 'V',
 
263
     POPT_ARG_NONE, NULL, SP_ARG_VERSION,
 
264
     N_("Print the Inkscape version number"),
 
265
     NULL},
 
266
 
 
267
    {"without-gui", 'z',
 
268
     POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
 
269
     N_("Do not use X server (only process files from console)"),
 
270
     NULL},
 
271
 
 
272
    {"with-gui", 'g',
 
273
     POPT_ARG_NONE, NULL, SP_ARG_GUI,
 
274
     N_("Try to use X server (even if $DISPLAY is not set)"),
 
275
     NULL},
 
276
 
 
277
    {"file", 'f',
 
278
     POPT_ARG_STRING, NULL, SP_ARG_FILE,
 
279
     N_("Open specified document(s) (option string may be excluded)"),
 
280
     N_("FILENAME")},
 
281
 
 
282
    {"print", 'p',
 
283
     POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
 
284
     N_("Print document(s) to specified output file (use '| program' for pipe)"),
 
285
     N_("FILENAME")},
 
286
 
 
287
    {"export-png", 'e',
 
288
     POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
 
289
     N_("Export document to a PNG file"),
 
290
     N_("FILENAME")},
 
291
 
 
292
    {"export-dpi", 'd',
 
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)"),
 
295
     N_("DPI")},
 
296
 
 
297
    {"export-area", 'a',
 
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)"),
 
300
     N_("x0:y0:x1:y1")},
 
301
 
 
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)"),
 
305
     NULL},
 
306
 
 
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"),
 
310
     NULL},
 
311
 
 
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)"),
 
315
     NULL},
 
316
 
 
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)"),
 
320
     N_("WIDTH")},
 
321
 
 
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)"),
 
325
     N_("HEIGHT")},
 
326
 
 
327
    {"export-id", 'i',
 
328
     POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
 
329
     N_("The ID of the object to export"),
 
330
     N_("ID")},
 
331
 
 
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)"),
 
337
     NULL},
 
338
 
 
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)"),
 
342
     NULL},
 
343
 
 
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)"),
 
347
     N_("COLOR")},
 
348
 
 
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)"),
 
352
     N_("VALUE")},
 
353
 
 
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)"),
 
357
     N_("FILENAME")},
 
358
 
 
359
    {"export-ps", 'P',
 
360
     POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
 
361
     N_("Export document to a PS file"),
 
362
     N_("FILENAME")},
 
363
 
 
364
    {"export-eps", 'E',
 
365
     POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
 
366
     N_("Export document to an EPS file"),
 
367
     N_("FILENAME")},
 
368
 
 
369
    {"export-pdf", 'A',
 
370
     POPT_ARG_STRING, &sp_export_pdf, SP_ARG_EXPORT_PDF,
 
371
     N_("Export document to a PDF file"),
 
372
     N_("FILENAME")},
 
373
 
 
374
#ifdef WIN32
 
375
    {"export-emf", 'M',
 
376
     POPT_ARG_STRING, &sp_export_emf, SP_ARG_EXPORT_EMF,
 
377
     N_("Export document to an Enhanced Metafile (EMF) File"),
 
378
     N_("FILENAME")},
 
379
#endif //WIN32
 
380
 
 
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)"),
 
384
     NULL},
 
385
 
 
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)"),
 
389
     NULL},
 
390
 
 
391
    {"query-x", 'X',
 
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"),
 
395
     NULL},
 
396
 
 
397
    {"query-y", 'Y',
 
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"),
 
401
     NULL},
 
402
 
 
403
    {"query-width", 'W',
 
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"),
 
407
     NULL},
 
408
 
 
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"),
 
413
     NULL},
 
414
 
 
415
    {"query-all", 'S',
 
416
     POPT_ARG_NONE, &sp_query_all, SP_ARG_QUERY_ALL,
 
417
     N_("List id,x,y,w,h for all objects"),
 
418
     NULL},
 
419
 
 
420
    {"query-id", 'I',
 
421
     POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
 
422
     N_("The ID of the object whose dimensions are queried"),
 
423
     N_("ID")},
 
424
 
 
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"),
 
429
     NULL},
 
430
 
 
431
    {"vacuum-defs", 0,
 
432
     POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
 
433
     N_("Remove unused definitions from the defs section(s) of the document"),
 
434
     NULL},
 
435
 
 
436
    {"verb-list", 0,
 
437
     POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
 
438
     N_("List the IDs of all the verbs in Inkscape"),
 
439
     NULL},
 
440
 
 
441
    {"verb", 0,
 
442
     POPT_ARG_STRING, NULL, SP_ARG_VERB,
 
443
     N_("Verb to call when Inkscape opens."),
 
444
     N_("VERB-ID")},
 
445
 
 
446
    {"select", 0,
 
447
     POPT_ARG_STRING, NULL, SP_ARG_SELECT,
 
448
     N_("Object ID to select when Inkscape opens."),
 
449
     N_("OBJECT-ID")},
 
450
 
 
451
    {"shell", 0,
 
452
     POPT_ARG_NONE, &sp_shell, SP_ARG_SHELL,
 
453
     N_("Start Inkscape in interactive shell mode."),
 
454
     NULL},
 
455
 
 
456
    POPT_AUTOHELP POPT_TABLEEND
 
457
};
 
458
 
 
459
static bool needToRecodeParams = true;
 
460
gchar * blankParam = g_strdup("");
 
461
 
 
462
 
 
463
 
 
464
#ifdef WIN32
 
465
 
 
466
/**
 
467
 * Return the directory of the .exe that is currently running
 
468
 */
 
469
static Glib::ustring _win32_getExePath()
 
470
{
 
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, '\\');
 
475
    if (slashPos) {
 
476
        *slashPos = '\0';
 
477
    }
 
478
    Glib::ustring s = exeName;
 
479
    return s;
 
480
}
 
481
 
 
482
/**
 
483
 * Set up the PATH and PYTHONPATH environment variables on
 
484
 * win32
 
485
 */
 
486
static int _win32_set_inkscape_env(const Glib::ustring &exePath)
 
487
{
 
488
    // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
 
489
 
 
490
    char *oldenv = getenv("PATH");
 
491
    Glib::ustring tmp = "PATH=";
 
492
    tmp += exePath;
 
493
    tmp += ";";
 
494
    tmp += exePath;
 
495
    tmp += "\\python;";
 
496
    tmp += exePath;
 
497
    tmp += "\\python\\Scripts;";  // for uniconv.cmd
 
498
    tmp += exePath;
 
499
    tmp += "\\perl";
 
500
    if(oldenv != NULL) {
 
501
        tmp += ";";
 
502
        tmp += oldenv;
 
503
    }
 
504
    _putenv(tmp.c_str());
 
505
 
 
506
    oldenv = getenv("PYTHONPATH");
 
507
    tmp = "PYTHONPATH=";
 
508
    tmp += exePath;
 
509
    tmp += "\\python;";
 
510
    tmp += exePath;
 
511
    tmp += "\\python\\Lib;";
 
512
    tmp += exePath;
 
513
    tmp += "\\python\\DLLs";
 
514
    if(oldenv != NULL) {
 
515
        tmp += ";";
 
516
        tmp += oldenv;
 
517
    }
 
518
    _putenv(tmp.c_str());
 
519
 
 
520
    return 0;
 
521
}
 
522
#endif
 
523
 
 
524
/**
 
525
 * Add INKSCAPE_EXTENSIONDIR to PYTHONPATH so that extensions in users home
 
526
 * can find inkex.py et al. (Bug #197475)
 
527
 */
 
528
static int set_extensions_env()
 
529
{
 
530
    char *oldenv = getenv("PYTHONPATH");
 
531
    Glib::ustring tmp = INKSCAPE_EXTENSIONDIR;
 
532
    if (oldenv != NULL) {
 
533
        tmp += G_SEARCHPATH_SEPARATOR;
 
534
        tmp += oldenv;
 
535
    }
 
536
    g_setenv("PYTHONPATH", tmp.c_str(), TRUE);
 
537
 
 
538
    return 0;
 
539
}
 
540
 
 
541
 
 
542
/**
 
543
 * This is the classic main() entry point of the program, though on some
 
544
 * architectures it might be called by something else.
 
545
 */
 
546
int
 
547
main(int argc, char **argv)
 
548
{
 
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));
 
554
#endif
 
555
 
 
556
#ifdef WIN32
 
557
    /*
 
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
 
563
    */
 
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);
 
568
    RegistryTool rt;
 
569
    rt.setPathInfo();
 
570
#endif
 
571
 
 
572
    // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
 
573
    Gtk::Main::init_gtkmm_internals();
 
574
 
 
575
    // Bug #197475
 
576
    set_extensions_env();
 
577
 
 
578
   /**
 
579
    * Call bindtextdomain() for various machines's paths
 
580
    */
 
581
#ifdef ENABLE_NLS
 
582
#ifdef WIN32
 
583
    Glib::ustring localePath = homedir;
 
584
    localePath += "\\";
 
585
    localePath += PACKAGE_LOCALE_DIR;
 
586
    bindtextdomain(GETTEXT_PACKAGE, localePath.c_str());
 
587
#else
 
588
#ifdef ENABLE_BINRELOC
 
589
    bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
 
590
#else
 
591
    bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
 
592
#endif
 
593
#endif
 
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);
 
599
    }
 
600
#endif
 
601
 
 
602
    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
 
603
 
 
604
#ifdef ENABLE_NLS
 
605
    textdomain(GETTEXT_PACKAGE);
 
606
#endif
 
607
 
 
608
    LIBXML_TEST_VERSION
 
609
 
 
610
    Inkscape::GC::init();
 
611
 
 
612
    Inkscape::Debug::Logger::init();
 
613
 
 
614
    gboolean use_gui;
 
615
 
 
616
#ifndef WIN32
 
617
    // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
 
618
    use_gui = (getenv("DISPLAY") != NULL);
 
619
#else
 
620
    use_gui = TRUE;
 
621
#endif
 
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)
 
644
#ifdef WIN32
 
645
            || !strcmp(argv[i], "-M")
 
646
            || !strncmp(argv[i], "--export-emf", 12)
 
647
#endif //WIN32
 
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)
 
660
           )
 
661
        {
 
662
            /* main_console handles any exports -- not the gui */
 
663
            use_gui = FALSE;
 
664
            break;
 
665
        } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
 
666
            use_gui = TRUE;
 
667
            break;
 
668
        }
 
669
    }
 
670
 
 
671
#ifdef WIN32
 
672
#ifndef REPLACEARGS_ANSI
 
673
    if ( PrintWin32::is_os_wide() )
 
674
#endif // REPLACEARGS_ANSI
 
675
    {
 
676
        // If the call fails, we'll need to convert charsets
 
677
        needToRecodeParams = !replaceArgs( argc, argv );
 
678
    }
 
679
#endif // WIN32
 
680
 
 
681
    /// \todo  Should this be a static object (see inkscape.cpp)?
 
682
    Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);
 
683
 
 
684
    return app.run();
 
685
}
 
686
 
 
687
 
 
688
 
 
689
 
 
690
void fixupSingleFilename( gchar **orig, gchar **spare )
 
691
{
 
692
    if ( orig && *orig && **orig ) {
 
693
        GError *error = NULL;
 
694
        gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
 
695
        if ( newFileName )
 
696
        {
 
697
            *orig = newFileName;
 
698
            if ( spare ) {
 
699
                *spare = newFileName;
 
700
            }
 
701
//             g_message("Set a replacement fixup");
 
702
        }
 
703
    }
 
704
}
 
705
 
 
706
 
 
707
 
 
708
GSList *fixupFilenameEncoding( GSList* fl )
 
709
{
 
710
    GSList *newFl = NULL;
 
711
    while ( fl ) {
 
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);
 
715
        if ( newFileName ) {
 
716
 
 
717
            if ( 0 )
 
718
            {
 
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);
 
725
                g_free(safeNewFn);
 
726
                g_free(safeFn);
 
727
            }
 
728
 
 
729
            g_free( fn );
 
730
            fn = newFileName;
 
731
            newFileName = 0;
 
732
        }
 
733
        else
 
734
            if ( 0 )
 
735
        {
 
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);
 
740
            g_free(safeFn);
 
741
        }
 
742
        newFl = g_slist_append( newFl, fn );
 
743
    }
 
744
    return newFl;
 
745
}
 
746
 
 
747
int sp_common_main( int argc, char const **argv, GSList **flDest )
 
748
{
 
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);
 
752
 
 
753
 
 
754
    // temporarily switch gettext encoding to locale, so that help messages can be output properly
 
755
    gchar const *charset;
 
756
    g_get_charset(&charset);
 
757
 
 
758
    bind_textdomain_codeset(GETTEXT_PACKAGE, charset);
 
759
 
 
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);
 
763
 
 
764
    /* Collect own arguments */
 
765
    GSList *fl = sp_process_args(ctx);
 
766
    poptFreeContext(ctx);
 
767
 
 
768
    // now switch gettext back to UTF-8 (for GUI)
 
769
    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
 
770
 
 
771
    // Now let's see if the file list still holds up
 
772
    if ( needToRecodeParams )
 
773
    {
 
774
        fl = fixupFilenameEncoding( fl );
 
775
    }
 
776
 
 
777
    // Check the globals for filename-fixup
 
778
    if ( needToRecodeParams )
 
779
    {
 
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 );
 
783
    }
 
784
    else
 
785
    {
 
786
        if ( sp_export_png )
 
787
            sp_export_png_utf8 = g_strdup( sp_export_png );
 
788
        if ( sp_export_svg )
 
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 );
 
792
    }
 
793
 
 
794
    // Return the list if wanted, else free it up.
 
795
    if ( flDest ) {
 
796
        *flDest = fl;
 
797
        fl = 0;
 
798
    } else {
 
799
        while ( fl ) {
 
800
            g_free( fl->data );
 
801
            fl = g_slist_remove( fl, fl->data );
 
802
        }
 
803
    }
 
804
    return 0;
 
805
}
 
806
 
 
807
static void
 
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 */
 
810
    {
 
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;
 
816
                }
 
817
                break;
 
818
            case GDK_BUTTON_PRESS:
 
819
                if(event->button.state & mapping) {
 
820
                    event->button.state|=GDK_MOD1_MASK;
 
821
                }
 
822
                break;
 
823
             case GDK_KEY_PRESS:
 
824
                 if(event->key.state & mapping) {
 
825
                     event->key.state|=GDK_MOD1_MASK;
 
826
                 }
 
827
                 break;
 
828
        default:
 
829
            break;
 
830
        }
 
831
    }
 
832
 
 
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.
 
840
        //
 
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.
 
845
        //
 
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);
 
850
        guint keyval = 0;
 
851
        switch (event->type) {
 
852
        case GDK_MOTION_NOTIFY:
 
853
            alt_pressed = TRUE && (event->motion.state & GDK_MOD1_MASK);
 
854
            break;
 
855
        case GDK_BUTTON_PRESS:
 
856
            alt_pressed = TRUE && (event->button.state & GDK_MOD1_MASK);
 
857
            break;
 
858
        case GDK_KEY_PRESS:
 
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);
 
864
            if (alt_pressed)
 
865
                event->key.state |= GDK_MOD1_MASK;
 
866
            else
 
867
                event->key.state &= ~GDK_MOD1_MASK;
 
868
            break;
 
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)
 
874
                alt_pressed = FALSE;
 
875
            break;
 
876
        default:
 
877
            break;
 
878
        }
 
879
        //printf("alt_pressed: %s\n", alt_pressed? "+" : "-");
 
880
    }
 
881
 
 
882
    gtk_main_do_event (event);
 
883
}
 
884
 
 
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++ )
 
889
    {
 
890
        listing.push_back(*cur);
 
891
    }
 
892
    return listing;
 
893
}
 
894
 
 
895
int
 
896
sp_main_gui(int argc, char const **argv)
 
897
{
 
898
    Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));
 
899
 
 
900
    GSList *fl = NULL;
 
901
    int retVal = sp_common_main( argc, argv, &fl );
 
902
    g_return_val_if_fail(retVal == 0, 1);
 
903
 
 
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)
 
908
    {
 
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());
 
915
    }
 
916
 
 
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);
 
921
    g_free(usericondir);
 
922
 
 
923
    gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
 
924
    Inkscape::Debug::log_display_config();
 
925
 
 
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();
 
931
 
 
932
    gboolean create_new = TRUE;
 
933
 
 
934
    /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
 
935
    inkscape_application_init(argv[0], true);
 
936
 
 
937
    while (fl) {
 
938
        if (sp_file_open((gchar *)fl->data,NULL)) {
 
939
            create_new=FALSE;
 
940
        }
 
941
        fl = g_slist_remove(fl, fl->data);
 
942
    }
 
943
    if (create_new) {
 
944
        sp_file_new_default();
 
945
    }
 
946
 
 
947
    Glib::signal_idle().connect(sigc::ptr_fun(&Inkscape::CmdLineAction::idle));
 
948
    main_instance.run();
 
949
 
 
950
#ifdef WIN32
 
951
    //We might not need anything here
 
952
    //sp_win32_finish(); <-- this is a NOP func
 
953
#endif
 
954
 
 
955
    return 0;
 
956
}
 
957
 
 
958
/**
 
959
 * Process file list
 
960
 */
 
961
void sp_process_file_list(GSList *fl)
 
962
{
 
963
    while (fl) {
 
964
        const gchar *filename = (gchar *)fl->data;
 
965
        SPDocument *doc = Inkscape::Extension::open(NULL, filename);
 
966
        if (doc == NULL) {
 
967
            doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), filename);
 
968
        }
 
969
        if (doc == NULL) {
 
970
            g_warning("Specified document %s cannot be opened (is it a valid SVG file?)", filename);
 
971
        } else {
 
972
            if (sp_vacuum_defs) {
 
973
                vacuum_document(doc);
 
974
            }
 
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);
 
978
            }
 
979
            if (sp_global_printer) {
 
980
                sp_print_document_to_file(doc, sp_global_printer);
 
981
            }
 
982
            if (sp_export_png) {
 
983
                sp_do_export_png(doc);
 
984
            }
 
985
            if (sp_export_svg) {
 
986
                Inkscape::XML::Document *rdoc;
 
987
                Inkscape::XML::Node *repr;
 
988
                rdoc = sp_repr_document_new("svg:svg");
 
989
                repr = rdoc->root();
 
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);
 
993
            }
 
994
            if (sp_export_ps) {
 
995
                do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript");
 
996
            }
 
997
            if (sp_export_eps) {
 
998
                do_export_ps_pdf(doc, sp_export_eps, "image/x-e-postscript");
 
999
            }
 
1000
            if (sp_export_pdf) {
 
1001
                do_export_ps_pdf(doc, sp_export_pdf, "application/pdf");
 
1002
            }
 
1003
#ifdef WIN32
 
1004
            if (sp_export_emf) {
 
1005
                do_export_emf(doc, sp_export_emf, "image/x-emf");
 
1006
            }
 
1007
#endif //WIN32
 
1008
            if (sp_query_all) {
 
1009
                do_query_all (doc);
 
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);
 
1014
            }
 
1015
 
 
1016
            delete doc;
 
1017
        }
 
1018
        fl = g_slist_remove(fl, fl->data);
 
1019
    }
 
1020
}
 
1021
 
 
1022
/**
 
1023
 * Run the application as an interactive shell, parsing command lines from stdin
 
1024
 * Returns -1 on error.
 
1025
 */
 
1026
int sp_main_shell(char const* command_name)
 
1027
{
 
1028
    int retval = 0;
 
1029
 
 
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;
 
1036
 
 
1037
    fprintf(stdout, "Inkscape %s interactive shell mode. Type 'quit' to quit.\n", Inkscape::version_string);
 
1038
    fflush(stdout);
 
1039
    char* linedata = 0;
 
1040
    do {
 
1041
        fprintf(stdout, ">");
 
1042
        fflush(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') ) {
 
1052
                        retval = 0;
 
1053
                    }
 
1054
                }
 
1055
            } else {
 
1056
                useme[--len] = '\0';  // Strip newline
 
1057
                if (useme[len - 1] == '\r') {
 
1058
                    useme[--len] = '\0';
 
1059
                }
 
1060
                if ( strcmp(useme, "quit") == 0 ) {
 
1061
                    // Time to quit
 
1062
                    fflush(stdout);
 
1063
                    linedata = 0; // mark for exit
 
1064
                } else if ( len < 1 ) {
 
1065
                    // blank string. Do nothing.
 
1066
                } else {
 
1067
                    GError* parseError = 0;
 
1068
                    gchar** argv = 0;
 
1069
                    gint argc = 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:"));
 
1073
                        if ( ctx ) {
 
1074
                            GSList *fl = sp_process_args(ctx);
 
1075
                            sp_process_file_list(fl);
 
1076
                            poptFreeContext(ctx);
 
1077
                        } else {
 
1078
                            retval = 1; // not sure why. But this was the previous return value
 
1079
                        }
 
1080
                        resetCommandlineGlobals();
 
1081
                        g_strfreev(argv);
 
1082
                    } else {
 
1083
                        g_warning("Cannot parse commandline: %s", useme);
 
1084
                    }
 
1085
                }
 
1086
            }
 
1087
        } // if (linedata...
 
1088
    } while (linedata && (retval == 0));
 
1089
 
 
1090
    g_free(command_line);
 
1091
    return retval;
 
1092
}
 
1093
 
 
1094
int sp_main_console(int argc, char const **argv)
 
1095
{
 
1096
    /* We are started in text mode */
 
1097
 
 
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
 
1102
     */
 
1103
    g_type_init();
 
1104
    char **argv2 = const_cast<char **>(argv);
 
1105
    gtk_init_check( &argc, &argv2 );
 
1106
    //setlocale(LC_ALL, "");
 
1107
 
 
1108
    GSList *fl = NULL;
 
1109
    int retVal = sp_common_main( argc, argv, &fl );
 
1110
    g_return_val_if_fail(retVal == 0, 1);
 
1111
 
 
1112
    if (fl == NULL && !sp_shell) {
 
1113
        g_print("Nothing to do!\n");
 
1114
        exit(0);
 
1115
    }
 
1116
 
 
1117
    inkscape_application_init(argv[0], false);
 
1118
 
 
1119
    if (sp_shell) {
 
1120
        sp_main_shell(argv[0]); // Run as interactive shell
 
1121
        exit(0);
 
1122
    } else {
 
1123
        sp_process_file_list(fl); // Normal command line invokation
 
1124
    }
 
1125
 
 
1126
    return 0;
 
1127
}
 
1128
 
 
1129
static void
 
1130
do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id)
 
1131
{
 
1132
    SPObject *o = NULL;
 
1133
 
 
1134
    if (id) {
 
1135
        o = doc->getObjectById(id);
 
1136
        if (o) {
 
1137
            if (!SP_IS_ITEM (o)) {
 
1138
                g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
 
1139
                return;
 
1140
            }
 
1141
        } else {
 
1142
            g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
 
1143
            return;
 
1144
        }
 
1145
    } else {
 
1146
        o = SP_DOCUMENT_ROOT(doc);
 
1147
    }
 
1148
 
 
1149
    if (o) {
 
1150
        sp_document_ensure_up_to_date (doc);
 
1151
        SPItem *item = ((SPItem *) o);
 
1152
 
 
1153
        // "true" SVG bbox for scripting
 
1154
        Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
 
1155
        if (area) {
 
1156
            Inkscape::SVGOStringStream os;
 
1157
            if (extent) {
 
1158
                os << area->dimensions()[axis];
 
1159
            } else {
 
1160
                os << area->min()[axis];
 
1161
            }
 
1162
            g_print ("%s", os.str().c_str());
 
1163
        } else {
 
1164
            g_print("0");
 
1165
        }
 
1166
    }
 
1167
}
 
1168
 
 
1169
static void
 
1170
do_query_all (SPDocument *doc)
 
1171
{
 
1172
    SPObject *o = NULL;
 
1173
 
 
1174
    o = SP_DOCUMENT_ROOT(doc);
 
1175
 
 
1176
    if (o) {
 
1177
        sp_document_ensure_up_to_date (doc);
 
1178
        do_query_all_recurse(o);
 
1179
    }
 
1180
}
 
1181
 
 
1182
static void
 
1183
do_query_all_recurse (SPObject *o)
 
1184
{
 
1185
    SPItem *item = ((SPItem *) o);
 
1186
    if (o->id && SP_IS_ITEM(item)) {
 
1187
        Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
 
1188
        if (area) {
 
1189
            Inkscape::SVGOStringStream os;
 
1190
            os << o->id;
 
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());
 
1196
        }
 
1197
    }
 
1198
 
 
1199
    SPObject *child = o->children;
 
1200
    while (child) {
 
1201
        do_query_all_recurse (child);
 
1202
        child = child->next;
 
1203
    }
 
1204
}
 
1205
 
 
1206
 
 
1207
static void
 
1208
sp_do_export_png(SPDocument *doc)
 
1209
{
 
1210
    const gchar *filename = NULL;
 
1211
    gdouble dpi = 0.0;
 
1212
 
 
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.");
 
1215
    }
 
1216
 
 
1217
    GSList *items = NULL;
 
1218
 
 
1219
    Geom::Rect area;
 
1220
    if (sp_export_id || sp_export_area_drawing) {
 
1221
 
 
1222
        SPObject *o = NULL;
 
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);
 
1229
            o_area = o;
 
1230
        } else if (sp_export_area_drawing) {
 
1231
            o = SP_DOCUMENT_ROOT (doc);
 
1232
            o_area = o;
 
1233
        }
 
1234
 
 
1235
        if (o) {
 
1236
            if (!SP_IS_ITEM (o)) {
 
1237
                g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
 
1238
                return;
 
1239
            }
 
1240
 
 
1241
            items = g_slist_prepend (items, SP_ITEM(o));
 
1242
 
 
1243
            if (sp_export_id_only) {
 
1244
                g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
 
1245
            }
 
1246
 
 
1247
            if (sp_export_use_hints) {
 
1248
 
 
1249
                // retrieve export filename hint
 
1250
                const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
 
1251
                if (fn_hint) {
 
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;
 
1255
                    } else {
 
1256
                        filename = fn_hint;
 
1257
                    }
 
1258
                } else {
 
1259
                    g_warning ("Export filename hint not found for the object.");
 
1260
                    filename = sp_export_png;
 
1261
                }
 
1262
 
 
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
 
1265
                if (dpi_hint) {
 
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);
 
1268
                    } else {
 
1269
                        dpi = atof(dpi_hint);
 
1270
                    }
 
1271
                } else {
 
1272
                    g_warning ("Export DPI hint not found for the object.");
 
1273
                }
 
1274
 
 
1275
            }
 
1276
 
 
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);
 
1281
            if (areaMaybe) {
 
1282
                area = *areaMaybe;
 
1283
            } else {
 
1284
                g_warning("Unable to determine a valid bounding box. Nothing exported.");
 
1285
                return;
 
1286
            }
 
1287
        } else {
 
1288
            g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
 
1289
            return;
 
1290
        }
 
1291
    }
 
1292
 
 
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);
 
1298
            return;
 
1299
        }
 
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));
 
1306
    }
 
1307
 
 
1308
    // set filename and dpi from options, if not yet set from the hints
 
1309
    if (!filename) {
 
1310
        if (!sp_export_png) {
 
1311
            g_warning ("No export filename given and no filename hint. Nothing exported.");
 
1312
            return;
 
1313
        }
 
1314
        filename = sp_export_png;
 
1315
    }
 
1316
 
 
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);
 
1321
            return;
 
1322
        }
 
1323
        g_print("DPI: %g\n", dpi);
 
1324
    }
 
1325
 
 
1326
    if (sp_export_area_snap) {
 
1327
        round_rectangle_outwards(area);
 
1328
    }
 
1329
 
 
1330
    // default dpi
 
1331
    if (dpi == 0.0) {
 
1332
        dpi = PX_PER_IN;
 
1333
    }
 
1334
 
 
1335
    unsigned long int width = 0;
 
1336
    unsigned long int height = 0;
 
1337
 
 
1338
    if (sp_export_width) {
 
1339
        errno=0;
 
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);
 
1343
            return;
 
1344
        }
 
1345
        dpi = (gdouble) width * PX_PER_IN / area.width();
 
1346
    }
 
1347
 
 
1348
    if (sp_export_height) {
 
1349
        errno=0;
 
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);
 
1353
            return;
 
1354
        }
 
1355
        dpi = (gdouble) height * PX_PER_IN / area.height();
 
1356
    }
 
1357
 
 
1358
    if (!sp_export_width) {
 
1359
        width = (unsigned long int) (area.width() * dpi / PX_PER_IN + 0.5);
 
1360
    }
 
1361
 
 
1362
    if (!sp_export_height) {
 
1363
        height = (unsigned long int) (area.height() * dpi / PX_PER_IN + 0.5);
 
1364
    }
 
1365
 
 
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
 
1371
    } else {
 
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));
 
1378
    }
 
1379
 
 
1380
    if (sp_export_background_opacity) {
 
1381
        // override opacity
 
1382
        gfloat value;
 
1383
        if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
 
1384
            if (value > 1.0) {
 
1385
                value = CLAMP (value, 1.0f, 255.0f);
 
1386
                bgcolor &= (guint32) 0xffffff00;
 
1387
                bgcolor |= (guint32) floor(value);
 
1388
            } else {
 
1389
                value = CLAMP (value, 0.0f, 1.0f);
 
1390
                bgcolor &= (guint32) 0xffffff00;
 
1391
                bgcolor |= SP_COLOR_F_TO_U(value);
 
1392
            }
 
1393
        }
 
1394
    }
 
1395
 
 
1396
    g_print("Background RRGGBBAA: %08x\n", bgcolor);
 
1397
 
 
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);
 
1399
 
 
1400
    g_print("Bitmap saved as: %s\n", filename);
 
1401
 
 
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);
 
1404
    } else {
 
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);
 
1406
    }
 
1407
 
 
1408
    g_slist_free (items);
 
1409
}
 
1410
 
 
1411
 
 
1412
/**
 
1413
 *  Perform a PDF/PS/EPS export
 
1414
 *
 
1415
 *  \param doc Document to export.
 
1416
 *  \param uri URI to export to.
 
1417
 *  \param mime MIME type to export as.
 
1418
 */
 
1419
 
 
1420
static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
 
1421
{
 
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) {
 
1426
        i++;
 
1427
    }
 
1428
 
 
1429
    if (i == o.end())
 
1430
    {
 
1431
        g_warning ("Could not find an extension to export to MIME type %s.", mime);
 
1432
        return;
 
1433
    }
 
1434
 
 
1435
    if (sp_export_id) {
 
1436
        SPObject *o = doc->getObjectById(sp_export_id);
 
1437
        if (o == NULL) {
 
1438
            g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
 
1439
            return;
 
1440
        }
 
1441
        (*i)->set_param_string ("exportId", sp_export_id);
 
1442
    } else {
 
1443
        (*i)->set_param_string ("exportId", "");
 
1444
    }
 
1445
 
 
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;
 
1449
    }
 
1450
 
 
1451
    if (sp_export_area_drawing) {
 
1452
        (*i)->set_param_bool ("areaDrawing", TRUE);
 
1453
    } else {
 
1454
        (*i)->set_param_bool ("areaDrawing", FALSE);
 
1455
    }
 
1456
 
 
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.");
 
1460
        }
 
1461
        (*i)->set_param_bool ("areaCanvas", TRUE);
 
1462
    } else {
 
1463
        (*i)->set_param_bool ("areaCanvas", FALSE);
 
1464
    }
 
1465
 
 
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) {
 
1469
            try {
 
1470
               (*i)->set_param_bool("areaDrawing", TRUE);
 
1471
            } catch (...) {}
 
1472
        }
 
1473
    }
 
1474
 
 
1475
    if (sp_export_text_to_path) {
 
1476
        (*i)->set_param_bool("textToPath", TRUE);
 
1477
    } else {
 
1478
        (*i)->set_param_bool("textToPath", FALSE);
 
1479
    }
 
1480
 
 
1481
    if (sp_export_ignore_filters) {
 
1482
        (*i)->set_param_bool("blurToBitmap", FALSE);
 
1483
    } else {
 
1484
        (*i)->set_param_bool("blurToBitmap", TRUE);
 
1485
 
 
1486
        gdouble dpi = 90.0;
 
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);
 
1491
                dpi = 90;
 
1492
            }
 
1493
        }
 
1494
 
 
1495
        (*i)->set_param_int("resolution", (int) dpi);
 
1496
    }
 
1497
 
 
1498
    (*i)->save(doc, uri);
 
1499
}
 
1500
 
 
1501
#ifdef WIN32
 
1502
/**
 
1503
 *  Export a document to EMF
 
1504
 *
 
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")
 
1508
 */
 
1509
 
 
1510
static void do_export_emf(SPDocument* doc, gchar const* uri, char const* mime)
 
1511
{
 
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) {
 
1516
        i++;
 
1517
    }
 
1518
 
 
1519
    if (i == o.end())
 
1520
    {
 
1521
        g_warning ("Could not find an extension to export to MIME type %s.", mime);
 
1522
        return;
 
1523
    }
 
1524
 
 
1525
    (*i)->save(doc, uri);
 
1526
}
 
1527
#endif //WIN32
 
1528
 
 
1529
#ifdef WIN32
 
1530
bool replaceArgs( int& argc, char**& argv )
 
1531
{
 
1532
    bool worked = false;
 
1533
 
 
1534
#ifdef REPLACEARGS_DEBUG
 
1535
    MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
 
1536
#endif // REPLACEARGS_DEBUG
 
1537
 
 
1538
    wchar_t* line = GetCommandLineW();
 
1539
    if ( line )
 
1540
    {
 
1541
#ifdef REPLACEARGS_DEBUG
 
1542
        {
 
1543
            gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
 
1544
            if ( utf8Line )
 
1545
            {
 
1546
                gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
 
1547
                {
 
1548
                    char tmp[strlen(safe) + 32];
 
1549
                    snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
 
1550
                    MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
 
1551
                }
 
1552
            }
 
1553
        }
 
1554
#endif // REPLACEARGS_DEBUG
 
1555
 
 
1556
        int numArgs = 0;
 
1557
        wchar_t** parsed = CommandLineToArgvW( line, &numArgs );
 
1558
 
 
1559
#ifdef REPLACEARGS_ANSI
 
1560
// test code for trying things on Win95/98/ME
 
1561
        if ( !parsed )
 
1562
        {
 
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 );
 
1569
 
 
1570
            int pos = 0;
 
1571
            bool inQuotes = false;
 
1572
            bool inWhitespace = true;
 
1573
            std::vector<int> places;
 
1574
            while ( lineDup[pos] )
 
1575
            {
 
1576
                if ( inQuotes )
 
1577
                {
 
1578
                    if ( lineDup[pos] == L'"' )
 
1579
                    {
 
1580
                        inQuotes = false;
 
1581
                    }
 
1582
                }
 
1583
                else if ( lineDup[pos] == L'"' )
 
1584
                {
 
1585
                    inQuotes = true;
 
1586
                    inWhitespace = false;
 
1587
                    places.push_back(pos);
 
1588
                }
 
1589
                else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
 
1590
                {
 
1591
                    if ( !inWhitespace )
 
1592
                    {
 
1593
                        inWhitespace = true;
 
1594
                        lineDup[pos] = 0;
 
1595
                    }
 
1596
                }
 
1597
                else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
 
1598
                {
 
1599
                    inWhitespace = false;
 
1600
                    places.push_back(pos);
 
1601
                }
 
1602
                else
 
1603
                {
 
1604
                    // consume
 
1605
                }
 
1606
                pos++;
 
1607
            }
 
1608
#ifdef REPLACEARGS_DEBUG
 
1609
            {
 
1610
                char tmp[256];
 
1611
                snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
 
1612
                MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
 
1613
            }
 
1614
#endif // REPLACEARGS_DEBUG
 
1615
 
 
1616
            wchar_t** block = new wchar_t*[places.size()];
 
1617
            int i = 0;
 
1618
            for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
 
1619
            {
 
1620
                block[i++] = &lineDup[*it];
 
1621
            }
 
1622
            parsed = block;
 
1623
            numArgs = places.size();
 
1624
        }
 
1625
#endif // REPLACEARGS_ANSI
 
1626
 
 
1627
        if ( parsed )
 
1628
        {
 
1629
            std::vector<wchar_t*>expandedArgs;
 
1630
            if ( numArgs > 0 )
 
1631
            {
 
1632
                expandedArgs.push_back( parsed[0] );
 
1633
            }
 
1634
 
 
1635
            for ( int i1 = 1; i1 < numArgs; i1++ )
 
1636
            {
 
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'-';
 
1640
                if ( wildcarded )
 
1641
                {
 
1642
#ifdef REPLACEARGS_ANSI
 
1643
                    WIN32_FIND_DATAA data;
 
1644
#else
 
1645
                    WIN32_FIND_DATAW data;
 
1646
#endif // REPLACEARGS_ANSI
 
1647
 
 
1648
                    memset((void *)&data, 0, sizeof(data));
 
1649
 
 
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'\\' );
 
1654
                    if ( last )
 
1655
                    {
 
1656
                        last[1] = 0;
 
1657
                    }
 
1658
                    else
 
1659
                    {
 
1660
                        base[0] = 0;
 
1661
                    }
 
1662
                    baseLen = wcslen( base );
 
1663
 
 
1664
#ifdef REPLACEARGS_ANSI
 
1665
                    char target[MAX_PATH];
 
1666
                    if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
 
1667
                    {
 
1668
                        HANDLE hf = FindFirstFileA( target, &data );
 
1669
#else
 
1670
                        HANDLE hf = FindFirstFileW( parsed[i1], &data );
 
1671
#endif // REPLACEARGS_ANSI
 
1672
                        if ( hf != INVALID_HANDLE_VALUE )
 
1673
                        {
 
1674
                            BOOL found = TRUE;
 
1675
                            do
 
1676
                            {
 
1677
#ifdef REPLACEARGS_ANSI
 
1678
                                int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
 
1679
                                if ( howMany > 0 )
 
1680
                                {
 
1681
                                    howMany += baseLen;
 
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 );
 
1687
                                }
 
1688
#else
 
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
 
1696
                            } while ( found );
 
1697
 
 
1698
                            FindClose( hf );
 
1699
                        }
 
1700
                        else
 
1701
                        {
 
1702
                            expandedArgs.push_back( parsed[i1] );
 
1703
                        }
 
1704
#ifdef REPLACEARGS_ANSI
 
1705
                    }
 
1706
#endif // REPLACEARGS_ANSI
 
1707
 
 
1708
                    delete[] base;
 
1709
                }
 
1710
                else
 
1711
                {
 
1712
                    expandedArgs.push_back( parsed[i1] );
 
1713
                }
 
1714
            }
 
1715
 
 
1716
            {
 
1717
                wchar_t** block = new wchar_t*[expandedArgs.size()];
 
1718
                int iz = 0;
 
1719
                for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
 
1720
                {
 
1721
                    block[iz++] = *it;
 
1722
                }
 
1723
                parsed = block;
 
1724
                numArgs = expandedArgs.size();
 
1725
            }
 
1726
 
 
1727
            std::vector<gchar*> newArgs;
 
1728
            for ( int i = 0; i < numArgs; i++ )
 
1729
            {
 
1730
                gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
 
1731
                if ( replacement )
 
1732
                {
 
1733
#ifdef REPLACEARGS_DEBUG
 
1734
                    gchar *safe2 = Inkscape::IO::sanitizeString(replacement);
 
1735
 
 
1736
                    if ( safe2 )
 
1737
                    {
 
1738
                        {
 
1739
                            char tmp[1024];
 
1740
                            snprintf( tmp, sizeof(tmp), "    [%2d] = '%s'", i, safe2 );
 
1741
                            MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
 
1742
                        }
 
1743
                        g_free( safe2 );
 
1744
                    }
 
1745
#endif // REPLACEARGS_DEBUG
 
1746
 
 
1747
                    newArgs.push_back( replacement );
 
1748
                }
 
1749
                else
 
1750
                {
 
1751
                    newArgs.push_back( blankParam );
 
1752
                }
 
1753
            }
 
1754
 
 
1755
            // Now push our munged params to be the new argv and argc
 
1756
            {
 
1757
                char** block = new char*[newArgs.size()];
 
1758
                int iz = 0;
 
1759
                for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
 
1760
                {
 
1761
                    block[iz++] = *it;
 
1762
                }
 
1763
                argv = block;
 
1764
                argc = newArgs.size();
 
1765
                worked = true;
 
1766
            }
 
1767
        }
 
1768
#ifdef REPLACEARGS_DEBUG
 
1769
        else
 
1770
        {
 
1771
            MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
 
1772
        }
 
1773
#endif // REPLACEARGS_DEBUG
 
1774
    }
 
1775
#ifdef REPLACEARGS_DEBUG
 
1776
    else
 
1777
    {
 
1778
        {
 
1779
            MessageBoxA( NULL,  "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
 
1780
        }
 
1781
 
 
1782
        char* line2 = GetCommandLineA();
 
1783
        if ( line2 )
 
1784
        {
 
1785
            gchar *safe = Inkscape::IO::sanitizeString(line2);
 
1786
            {
 
1787
                {
 
1788
                    char tmp[strlen(safe) + 32];
 
1789
                    snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
 
1790
                    MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
 
1791
                }
 
1792
            }
 
1793
        }
 
1794
        else
 
1795
        {
 
1796
            MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
 
1797
        }
 
1798
    }
 
1799
#endif // REPLACEARGS_DEBUG
 
1800
 
 
1801
    return worked;
 
1802
}
 
1803
#endif // WIN32
 
1804
 
 
1805
static GSList *
 
1806
sp_process_args(poptContext ctx)
 
1807
{
 
1808
    GSList *fl = NULL;
 
1809
 
 
1810
    gint a;
 
1811
    while ((a = poptGetNextOpt(ctx)) != -1) {
 
1812
        switch (a) {
 
1813
            case SP_ARG_FILE: {
 
1814
                gchar const *fn = poptGetOptArg(ctx);
 
1815
                if (fn != NULL) {
 
1816
                    fl = g_slist_append(fl, g_strdup(fn));
 
1817
                }
 
1818
                break;
 
1819
            }
 
1820
            case SP_ARG_VERSION: {
 
1821
                printf("Inkscape %s (%s)\n", Inkscape::version_string, __DATE__);
 
1822
                exit(0);
 
1823
                break;
 
1824
            }
 
1825
            case SP_ARG_EXTENSIONDIR: {
 
1826
                printf("%s\n", INKSCAPE_EXTENSIONDIR);
 
1827
                exit(0);
 
1828
                break;
 
1829
            }
 
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
 
1834
                // everything else.
 
1835
                Inkscape::Extension::init();
 
1836
                Inkscape::Verb::list();
 
1837
                exit(0);
 
1838
                break;
 
1839
            }
 
1840
            case SP_ARG_VERB:
 
1841
            case SP_ARG_SELECT: {
 
1842
                gchar const *arg = poptGetOptArg(ctx);
 
1843
                if (arg != NULL) {
 
1844
                    // printf("Adding in: %s\n", arg);
 
1845
                    new Inkscape::CmdLineAction((a == SP_ARG_VERB), arg);
 
1846
                }
 
1847
                break;
 
1848
            }
 
1849
            case POPT_ERROR_BADOPT: {
 
1850
                g_warning ("Invalid option %s", poptBadOption(ctx, 0));
 
1851
                exit(1);
 
1852
                break;
 
1853
            }
 
1854
            default: {
 
1855
                break;
 
1856
            }
 
1857
        }
 
1858
    }
 
1859
 
 
1860
    gchar const ** const args = poptGetArgs(ctx);
 
1861
    if (args != NULL) {
 
1862
        for (unsigned i = 0; args[i] != NULL; i++) {
 
1863
            fl = g_slist_append(fl, g_strdup(args[i]));
 
1864
        }
 
1865
    }
 
1866
 
 
1867
    return fl;
 
1868
}
 
1869
 
 
1870
 
 
1871
/*
 
1872
  Local Variables:
 
1873
  mode:c++
 
1874
  c-file-style:"stroustrup"
 
1875
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
1876
  indent-tabs-mode:nil
 
1877
  fill-column:99
 
1878
  End:
 
1879
*/
 
1880
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :