Logo Search packages:      
Sourcecode: inkscape version File versions  Download package

main.cpp

Go to the documentation of this file.
#define __MAIN_C__

/** \file
 * Inkscape - an ambitious vector drawing program
 *
 * Authors:
 *   Lauris Kaplinski <lauris@kaplinski.com>
 *   Frank Felfe <innerspace@iname.com>
 *   Davide Puricelli <evo@debian.org>
 *   Mitsuru Oka <oka326@parkcity.ne.jp>
 *   Masatake YAMATO  <jet@gyve.org>
 *   F.J.Franklin <F.J.Franklin@sheffield.ac.uk>
 *   Michael Meeks <michael@helixcode.com>
 *   Chema Celorio <chema@celorio.com>
 *   Pawel Palucha
 *   Bryce Harrington <bryce@bryceharrington.com>
 * ... and various people who have worked with various projects
 *
 * Copyright (C) 1999-2004 authors
 * Copyright (C) 2001-2002 Ximian, Inc.
 *
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

// Putting the following in main.cpp appears a natural choice.

/** \mainpage The Inkscape Source Code Documentation
 * While the standard doxygen documentation can be accessed through the links
 * in the header, the following documents are additionally available to the 
 * interested reader.
 * 
 * \section groups Main directory documentation
 * Inkscape's classes and files in the main directory can be grouped into 
 * the following categories:
 * 
 * - \subpage ObjectTree - inkscape's SVG canvas
 * - \subpage Tools - the tools UI
 * - \subpage UI - inkscape's user interface
 * - \subpage XmlTree - XML backbone of the document
 * - \subpage Rendering - rendering and buffering
 * - \subpage OtherServices - what doesn't fit in the above
 *
 * See also the <a href="dirs.html">other directories</a> until doxygen
 * allows setting links to those doc files.
 * 
 * \section extlinks Links to external documentation
 *
 * \subsection liblinks External documentation on libraries used in inkscape
 *
 * <a href="http://www.gtkmm.org/gtkmm2/docs/">Gtkmm</a>
 * <a href="http://www.gtkmm.org/gtkmm2/docs/reference/html/dir_000003.html">atkmm</a>
 * <a href="http://www.gtkmm.org/gtkmm2/docs/reference/html/dir_000009.html">gdkmm</a>
 * <a href="http://www.gtkmm.org/gtkmm2/docs/reference/html/dir_000007.html">pangomm</a>
 * <a href="http://libsigc.sourceforge.net/libsigc1_2/reference/html/modules.html">libsigc++</a>
 * <a href="http://www.gtk.org/api/">GTK+</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/gdk-pixbuf/index.html">gdk-pixbuf</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/gobject/index.html">GObject</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/atk/index.html">atk</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/pango/index.html">pango</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/gnome-vfs-2.0/">GnomeVFS</a>
 * <a href="http://libsigc.sourceforge.net/libsigc2/docs/index.html">libsigc</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/ORBit/index.html">ORBit</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/libbonobo/index.html">bonobo</a>
 * <a href="http://developer.gnome.org/doc/API/2.0/bonobo-activation/index.html">bonobo-activation</a>
 * <a href="http://xmlsoft.org/XSLT/html/libxslt-lib.html#LIBXSLT-LIB">libxslt</a>
 * <a href="http://xmlsoft.org/html/index.html">libxml2</a>
 *
 * \subsection stdlinks External standards documentation 
 *
 * <a href="http://www.w3.org/TR/SVG/">SVG1.1</a>
 * <a href="http://www.w3.org/TR/SVG12/">SVG1.2</a>
 * <a href="http://www.w3.org/TR/SVGMobile/">SVGMobile</a>
 * <a href="http://www.w3.org/Graphics/SVG/Test/">SVGTest</a>
 * <a href="http://www.libpng.org/pub/png/">PNG</a>
 * <a href="http://www.w3.org/TR/xslt">XSLT</a>
 * <a href="http://partners.adobe.com/public/developer/ps/index_specs.html">PS</a>
 * <a href="http://developer.gnome.org/projects/gup/hig/">Gnome-HIG</a>
 */

/** \page ObjectTree Object Tree Classes and Files
 * Inkscape::ObjectHierarchy [\ref object-hierarchy.cpp, \ref object-hierarchy.h]
 * - SPObject [\ref sp-object.cpp, \ref sp-object.h, \ref object-edit.cpp, \ref sp-object-repr.cpp]
 *   - SPDefs [\ref sp-defs.cpp, \ref sp-defs.h]
 *   - SPFlowline [\ref sp-flowdiv.cpp, \ref sp-flowdiv.h]
 *   - SPFlowregionbreak [\ref sp-flowdiv.cpp, \ref sp-flowdiv.h]
 *   - SPGuide [\ref sp-guide.cpp, \ref sp-guide.h]
 *   - SPItem [\ref sp-item.cpp, \ref sp-item.h, \ref sp-item-notify-moveto.cpp, \ref sp-item-rm-unsatisfied-cns.cpp, \ref sp-item-transform.cpp, \ref sp-item-update-cns.cpp, ]
 *     - SPFlowdiv [\ref sp-flowdiv.cpp, \ref sp-flowdiv.h]
 *     - SPFlowpara [\ref sp-flowdiv.cpp, \ref sp-flowdiv.h]
 *     - SPFlowregion [\ref sp-flowregion.cpp, \ref sp-flowregion.h]
 *     - SPFlowregionExclude [\ref sp-flowregion.cpp, \ref sp-flowregion.h]
 *     - SPFlowtext [\ref sp-flowtext.cpp, \ref sp-flowtext.h]
 *     - SPFlowtspan [\ref sp-flowdiv.cpp, \ref sp-flowdiv.h]
 *     - SPGroup [\ref sp-item-group.cpp, \ref sp-item-group.h]
 *       - SPAnchor [\ref sp-anchor.cpp, \ref sp-anchor.h]
 *       - SPMarker [\ref sp-marker.cpp, \ref sp-marker.h]
 *       - SPRoot [\ref sp-root.cpp, \ref sp-root.h]
 *       - SPSymbol [\ref sp-symbol.cpp, \ref sp-symbol.h]
 *     - SPImage [\ref sp-image.cpp, \ref sp-image.h]
 *     - SPShape [\ref sp-shape.cpp, \ref sp-shape.h, \ref marker-status.cpp]
 *       - SPGenericEllipse [\ref sp-ellipse.cpp, \ref sp-ellipse.h]
 *         - SPArc
 *         - SPCircle
 *         - SPEllipse
 *       - SPLine [\ref sp-line.cpp, \ref sp-line.h]
 *       - SPOffset [\ref sp-offset.cpp, \ref sp-offset.h]
 *       - SPPath [\ref sp-path.cpp, \ref sp-path.h, \ref path-chemistry.cpp, \ref nodepath.cpp, \ref nodepath.h, \ref splivarot.cpp]
 *       - SPPolygon [\ref sp-polygon.cpp, \ref sp-polygon.h]
 *         - SPStar [\ref sp-star.cpp, \ref sp-star.h]
 *       - SPPolyLine [\ref sp-polyline.cpp, \ref sp-polyline.h]
 *       - SPRect [\ref sp-rect.cpp, \ref sp-rect.h]
 *       - SPSpiral [\ref sp-spiral.cpp, \ref sp-spiral.h]
 *     - SPText [\ref sp-text.cpp, \ref sp-text.h, \ref text-chemistry.cpp, \ref text-editing.cpp]
 *     - SPTextPath [\ref sp-tspan.cpp, \ref sp-tspan.h]
 *     - SPTSpan [\ref sp-tspan.cpp, \ref sp-tspan.h]
 *     - SPUse [\ref sp-use.cpp, \ref sp-use.h]
 *   - SPMetadata [\ref sp-metadata.cpp, \ref sp-metadata.h]
 *   - SPObjectGroup [\ref sp-object-group.cpp, \ref sp-object-group.h]
 *     - SPClipPath [\ref sp-clippath.cpp, \ref sp-clippath.h]
 *     - SPMask [\ref sp-mask.cpp, \ref sp-mask.h]
 *     - SPNamedView [\ref sp-namedview.cpp, \ref sp-namedview.h]
 *   - SPPaintServer [\ref sp-paint-server.cpp, \ref sp-paint-server.h]
 *     - SPGradient [\ref sp-gradient.cpp, \ref sp-gradient.h, \ref gradient-chemistry.cpp, \ref sp-gradient-reference.h, \ref sp-gradient-spread.h, \ref sp-gradient-units.h, \ref sp-gradient-vector.h]
 *       - SPLinearGradient
 *       - SPRadialGradient
 *     - SPPattern [\ref sp-pattern.cpp, \ref sp-pattern.h]
 *   - SPSkeleton [\ref sp-skeleton.cpp, \ref sp-skeleton.h]
 *   - SPStop [\ref sp-stop.h]
 *   - SPString [\ref sp-string.cpp, \ref sp-string.h]
 *   - SPStyleElem [\ref sp-style-elem.cpp, \ref sp-style-elem.h]
 *
 */
/** \page Tools Tools Related Classes and Files
 * 
 * SPSelCue [\ref selcue.cpp, \ref selcue.h, \ref rubberband.cpp]
 * Inkscape::Selection [\ref selection.cpp, \ref selection.h, \ref selection-chemistry.cpp]
 * SPSelTrans [\ref seltrans.cpp, \ref seltrans.h]
 * 
 * \section Event Context Class Hierarchy
 * 
 *- SPEventContext[\ref event-context.cpp, \ref event-context.h]
 * - SPArcContext [\ref arc-context.cpp, \ref arc-context.h]
 * - SPDrawContext [\ref draw-context.cpp, \ref draw-context.h]
 *   - SPPenContext [\ref pen-context.cpp, \ref pen-context.h]
 *   - SPPencilContext [\ref pencil-context.cpp, \ref pencil-context.h]
 *   - SPConnectorContext [\ref connector-context.cpp, \ref connector-context.h, \ref sp-conn-end.cpp, \ref sp-conn-end-pair.cpp]
 * - SPGradientContext [\ref gradient-context.cpp, \ref gradient-context.h, \ref gradient-drag.cpp, \ref gradient-toolbar.cpp]
 * - SPRectContext [\ref rect-context.cpp, \ref rect-context.h]
 * - SPSelectContext [\ref select-context.cpp, \ref select-context.h]
 * - SPSpiralContext [\ref spiral-context.cpp, \ref spiral-context.h]
 * - SPStarContext [\ref star-context.cpp, \ref star-context.h]
 *   
 * SPNodeContext [\ref node-context.cpp, \ref node-context.h]
 * 
 * SPZoomContext [\ref zoom-context.cpp, \ref zoom-context.h]
 * 
 * SPDynaDrawContext [\ref dyna-draw-context.cpp, \ref dyna-draw-context.h] 
 * 
 * SPDropperContext [\ref dropper-context.cpp, \ref dropper-context.h] 
 */
/** \page UI User Interface Classes and Files
 *
 * - Inkscape::UI::View::View [\ref ui/view/view.cpp, \ref ui/view/view.h]
 *   - Inkscape::UI::View::Edit [\ref ui/view/edit.cpp, \ref ui/view/edit.h]
 *   - SPDesktop [\ref desktop.cpp, \ref desktop-affine.cpp, \ref desktop-events.cpp, \ref desktop-handles.cpp, \ref desktop-style.cpp, \ref desktop.h, \ref desktop-affine.h, \ref desktop-events.h, \ref desktop-handles.h, \ref desktop-style.h]
 *   - SPSVGView [\ref svg-view.cpp, \ref svg-view.h]
 *
 * SPDesktopWidget [\ref desktop-widget.h] SPSVGSPViewWidget [\ref svg-view.cpp]
 * SPDocument [\ref document.cpp, \ref document.h] 
 * 
 * SPDrawAnchor [\ref draw-anchor.cpp, \ref draw-anchor.h] 
 * SPKnot [\ref knot.cpp, \ref knot.h, \ref knot-enums.h]
 * SPKnotHolder [\ref knotholder.cpp, \ref knotholder.h, \ref knot-holder-entity.h]
 *
 * [\ref layer-fns.cpp, \ref selection-describer.h]
 * Inkscape::MessageContext [\ref message-context.h] 
 * Inkscape::MessageStack [\ref message-stack.h, \ref message.h] 
 *
 * Snapper, GridSnapper, GuideSnapper [\ref snap.cpp, \ref snap.h]
 *
 * SPGuide [\ref sp-guide.cpp, \ref sp-guide.h, \ref satisfied-guide-cns.cpp, \ref sp-guide-attachment.h, \ref sp-guide-constraint.h]
 * 
 * [\ref help.cpp] [\ref inkscape.cpp] [\ref inkscape-stock.cpp]
 * [\ref interface.cpp, \ref memeq.h] [\ref main.cpp, \ref winmain.cpp] 
 * [\ref menus-skeleton.h, \ref preferences-skeleton.h]
 * [\ref object-ui.cpp] [\ref select-toolbar.cpp] [\ref shortcuts.cpp]
 * [\ref sp-cursor.cpp] [\ref text-edit.cpp] [\ref toolbox.cpp, \ref ui/widget/toolbox.cpp] 
 * Inkscape::Verb [\ref verbs.h]
 *
 */
/** \page XmlTree CSS/XML Tree Classes and Files
 *
 * SPStyle [\ref style.cpp, \ref style.h]
 * Media [\ref media.cpp, \ref media.h]
 * [\ref attributes.cpp, \ref attributes.h] 
 *
 * - Inkscape::URIReference [\ref uri-references.cpp, \ref uri-references.h]
 *   - SPClipPathReference [\ref sp-clippath.h]
 *   - SPGradientReference [\ref sp-gradient-reference.h]
 *   - SPMarkerReference [\ref sp-marker.h]
 *   - SPMaskReference [\ref sp-mask.h]
 *   - SPUseReference [\ref sp-use-reference.h]
 *     - SPUsePath
 */
/** \page Rendering Rendering Related Classes and Files
 *
 * SPColor [\ref color.cpp, \ref color.h, \ref color-rgba.h] 
 * [\ref geom.cpp] [\ref isnan.h] [\ref mod360.cpp]
 */
/** \page OtherServices Classes and Files From Other Services
 * [\ref inkview.cpp, \ref slideshow.cpp] [\ref sp-animation.cpp]
 * 
 * Inkscape::GC
 *
 * [\ref sp-metrics.cpp, \ref sp-metrics.h]
 * 
 * [\ref prefs-utils.cpp] [\ref print.cpp]
 *
 * - Inkscape::GZipBuffer [\ref streams-gzip.h]
 * - Inkscape::JarBuffer [\ref streams-jar.h]
 * - Inkscape::ZlibBuffer [\ref streams-zlib.h]
 * - Inkscape::URIHandle [\ref streams-handles.h]
 *   - Inkscape::FileHandle
 * [\ref dir-util.cpp] [\ref file.cpp] 
 * Inkscape::URI [\ref uri.h, \ref extract-uri.cpp, \ref uri-references.cpp]
 * Inkscape::BadURIException [\ref bad-uri-exception.h] 
 * 
 * Inkscape::Whiteboard::UndoStackObserver [\ref undo-stack-observer.cpp, \ref composite-undo-stack-observer.cpp]
 * [\ref document-undo.cpp]
 * 
 * {\ref dialogs/} [\ref approx-equal.h] [\ref decimal-round.h] [\ref enums.h] [\ref unit-constants.h]
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "path-prefix.h"

#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
#include <string.h>
#include <locale.h>

#include <popt.h>
#ifndef POPT_TABLEEND
#define POPT_TABLEEND { NULL, '\0', 0, 0, 0, NULL, NULL }
#endif /* Not def: POPT_TABLEEND */

#include <libxml/tree.h>
#include <glib-object.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkwindow.h>
#include <gtk/gtkbox.h>

#include <gtk/gtkmain.h>

#include "gc-core.h"

#include "macros.h"
#include "file.h"
#include "document.h"
#include "sp-object.h"
#include "interface.h"
#include "print.h"
#include "slideshow.h"
#include "color.h"
#include "sp-item.h"
#include "sp-root.h"
#include "unit-constants.h"

#include "svg/svg.h"
#include "svg/stringstream.h"

#include "inkscape-private.h"
#include "inkscape-stock.h"
#include "inkscape_version.h"

#include "sp-namedview.h"
#include "sp-guide.h"
#include "sp-object-repr.h"
#include "xml/repr.h"

#include "io/sys.h"

#include "debug/logger.h"

#include <extension/extension.h>
#include <extension/system.h>
#include <extension/db.h>
#include <extension/output.h>

#ifdef WIN32
//#define REPLACEARGS_ANSI
//#define REPLACEARGS_DEBUG

#include "extension/internal/win32.h"
using Inkscape::Extension::Internal::PrintWin32;

#endif // WIN32

#include "extension/init.h"

#include <glibmm/i18n.h>
#include <gtkmm/main.h>

#ifndef HAVE_BIND_TEXTDOMAIN_CODESET
#define bind_textdomain_codeset(p,c)
#endif

#include "application/application.h"

enum {
    SP_ARG_NONE,
    SP_ARG_NOGUI,
    SP_ARG_GUI,
    SP_ARG_FILE,
    SP_ARG_PRINT,
    SP_ARG_EXPORT_PNG,
    SP_ARG_EXPORT_DPI,
    SP_ARG_EXPORT_AREA,
    SP_ARG_EXPORT_AREA_DRAWING,
    SP_ARG_EXPORT_AREA_SNAP,
    SP_ARG_EXPORT_WIDTH,
    SP_ARG_EXPORT_HEIGHT,
    SP_ARG_EXPORT_ID,
    SP_ARG_EXPORT_ID_ONLY,
    SP_ARG_EXPORT_USE_HINTS,
    SP_ARG_EXPORT_BACKGROUND,
    SP_ARG_EXPORT_BACKGROUND_OPACITY,
    SP_ARG_EXPORT_SVG,
    SP_ARG_EXPORT_PS,
    SP_ARG_EXPORT_EPS,
    SP_ARG_EXPORT_TEXT_TO_PATH,
    SP_ARG_EXPORT_BBOX_PAGE,
    SP_ARG_EXTENSIONDIR,
    SP_ARG_SLIDESHOW,
    SP_ARG_QUERY_X,
    SP_ARG_QUERY_Y,
    SP_ARG_QUERY_WIDTH,
    SP_ARG_QUERY_HEIGHT,
    SP_ARG_QUERY_ID,
    SP_ARG_VERSION,
    SP_ARG_NEW_GUI,
    SP_ARG_VACUUM_DEFS,
    SP_ARG_LAST
};

int sp_main_gui(int argc, char const **argv);
int sp_main_console(int argc, char const **argv);
static void sp_do_export_png(SPDocument *doc);
static void do_export_ps(SPDocument* doc, gchar const* uri, char const *mime);
static void do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id);


static gchar *sp_global_printer = NULL;
static gboolean sp_global_slideshow = FALSE;
static gchar *sp_export_png = NULL;
static gchar *sp_export_dpi = NULL;
static gchar *sp_export_area = NULL;
static gboolean sp_export_area_drawing = FALSE;
static gchar *sp_export_width = NULL;
static gchar *sp_export_height = NULL;
static gchar *sp_export_id = NULL;
static gchar *sp_export_background = NULL;
static gchar *sp_export_background_opacity = NULL;
static gboolean sp_export_area_snap = FALSE;
static gboolean sp_export_use_hints = FALSE;
static gboolean sp_export_id_only = FALSE;
static gchar *sp_export_svg = NULL;
static gchar *sp_export_ps = NULL;
static gchar *sp_export_eps = NULL;
static gboolean sp_export_text_to_path = FALSE;
static gboolean sp_export_bbox_page = FALSE;
static gboolean sp_query_x = FALSE;
static gboolean sp_query_y = FALSE;
static gboolean sp_query_width = FALSE;
static gboolean sp_query_height = FALSE;
static gchar *sp_query_id = NULL;
static int sp_new_gui = FALSE;
static gboolean sp_vacuum_defs = FALSE;

static gchar *sp_export_png_utf8 = NULL;
static gchar *sp_export_svg_utf8 = NULL;
static gchar *sp_global_printer_utf8 = NULL;

#ifdef WIN32
static bool replaceArgs( int& argc, char**& argv );
#endif
static GSList *sp_process_args(poptContext ctx);
struct poptOption options[] = {
    {"version", 'V', 
     POPT_ARG_NONE, NULL, SP_ARG_VERSION,
     N_("Print the Inkscape version number"), 
     NULL},

    {"without-gui", 'z', 
     POPT_ARG_NONE, NULL, SP_ARG_NOGUI,
     N_("Do not use X server (only process files from console)"),
     NULL},

    {"with-gui", 'g', 
     POPT_ARG_NONE, NULL, SP_ARG_GUI,
     N_("Try to use X server (even if $DISPLAY is not set)"),
     NULL},

    {"file", 'f', 
     POPT_ARG_STRING, NULL, SP_ARG_FILE,
     N_("Open specified document(s) (option string may be excluded)"),
     N_("FILENAME")},

    {"print", 'p', 
     POPT_ARG_STRING, &sp_global_printer, SP_ARG_PRINT,
     N_("Print document(s) to specified output file (use '| program' for pipe)"),
     N_("FILENAME")},

    {"export-png", 'e', 
     POPT_ARG_STRING, &sp_export_png, SP_ARG_EXPORT_PNG,
     N_("Export document to a PNG file"),
     N_("FILENAME")},

    {"export-dpi", 'd', 
     POPT_ARG_STRING, &sp_export_dpi, SP_ARG_EXPORT_DPI,
     N_("The resolution used for exporting SVG into bitmap (default 90)"),
     N_("DPI")},

    {"export-area", 'a', 
     POPT_ARG_STRING, &sp_export_area, SP_ARG_EXPORT_AREA,
     N_("Exported area in SVG user units (default is the canvas; 0,0 is lower-left corner)"),
     N_("x0:y0:x1:y1")},

    {"export-area-drawing", 'D', 
     POPT_ARG_NONE, &sp_export_area_drawing, SP_ARG_EXPORT_AREA_DRAWING,
     N_("Exported area is the entire drawing (not canvas)"),
     NULL},

    {"export-area-snap", 0,
     POPT_ARG_NONE, &sp_export_area_snap, SP_ARG_EXPORT_AREA_SNAP,
     N_("Snap the bitmap export area outwards to the nearest integer values (in SVG user units)"),
     NULL},

    {"export-width", 'w', 
     POPT_ARG_STRING, &sp_export_width, SP_ARG_EXPORT_WIDTH,
     N_("The width of exported bitmap in pixels (overrides export-dpi)"), 
     N_("WIDTH")},

    {"export-height", 'h', 
     POPT_ARG_STRING, &sp_export_height, SP_ARG_EXPORT_HEIGHT,
     N_("The height of exported bitmap in pixels (overrides export-dpi)"), 
     N_("HEIGHT")},

    {"export-id", 'i', 
     POPT_ARG_STRING, &sp_export_id, SP_ARG_EXPORT_ID,
     N_("The ID of the object to export (overrides export-area)"), 
     N_("ID")},

    {"export-id-only", 'j', 
     POPT_ARG_NONE, &sp_export_id_only, SP_ARG_EXPORT_ID_ONLY,
     // TRANSLATORS: this means: "Only export the object whose id is given in --export-id".
     //  See "man inkscape" for details.
     N_("Export just the object with export-id, hide all others (only with export-id)"), 
     NULL},

    {"export-use-hints", 't', 
     POPT_ARG_NONE, &sp_export_use_hints, SP_ARG_EXPORT_USE_HINTS,
     N_("Use stored filename and DPI hints when exporting (only with export-id)"), 
     NULL},

    {"export-background", 'b', 
     POPT_ARG_STRING, &sp_export_background, SP_ARG_EXPORT_BACKGROUND,
     N_("Background color of exported bitmap (any SVG-supported color string)"), 
     N_("COLOR")},

    {"export-background-opacity", 'y', 
     POPT_ARG_STRING, &sp_export_background_opacity, SP_ARG_EXPORT_BACKGROUND_OPACITY,
     N_("Background opacity of exported bitmap (either 0.0 to 1.0, or 1 to 255)"), 
     N_("VALUE")},

    {"export-plain-svg", 'l', 
     POPT_ARG_STRING, &sp_export_svg, SP_ARG_EXPORT_SVG,
     N_("Export document to plain SVG file (no sodipodi or inkscape namespaces)"), 
     N_("FILENAME")},

    {"export-ps", 'P',
     POPT_ARG_STRING, &sp_export_ps, SP_ARG_EXPORT_PS,
     N_("Export document to a PS file"),
     N_("FILENAME")},

    {"export-eps", 'E',
     POPT_ARG_STRING, &sp_export_eps, SP_ARG_EXPORT_EPS,
     N_("Export document to an EPS file"),
     N_("FILENAME")},

    {"export-text-to-path", 'T',
     POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH,
     N_("Convert text object to paths on export (EPS)"),
     NULL},

    {"export-bbox-page", 'B',
     POPT_ARG_NONE, &sp_export_bbox_page, SP_ARG_EXPORT_BBOX_PAGE,
     N_("Export files with the bounding box set to the page size (EPS)"),
     NULL},

    {"query-x", 'X',
     POPT_ARG_NONE, &sp_query_x, SP_ARG_QUERY_X,
     // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
     N_("Query the X coordinate of the drawing or, if specified, of the object with --query-id"),
     NULL},

    {"query-y", 'Y',
     POPT_ARG_NONE, &sp_query_y, SP_ARG_QUERY_Y,
     // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
     N_("Query the Y coordinate of the drawing or, if specified, of the object with --query-id"),
     NULL},

    {"query-width", 'W',
     POPT_ARG_NONE, &sp_query_width, SP_ARG_QUERY_WIDTH,
     // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
     N_("Query the width of the drawing or, if specified, of the object with --query-id"),
     NULL},

    {"query-height", 'H',
     POPT_ARG_NONE, &sp_query_height, SP_ARG_QUERY_HEIGHT,
     // TRANSLATORS: "--query-id" is an Inkscape command line option; see "inkscape --help"
     N_("Query the height of the drawing or, if specified, of the object with --query-id"),
     NULL},

    {"query-id", 'I', 
     POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
     N_("The ID of the object whose dimensions are queried"), 
     N_("ID")},

    {"extension-directory", 'x',
     POPT_ARG_NONE, NULL, SP_ARG_EXTENSIONDIR,
     // TRANSLATORS: this option makes Inkscape print the name (path) of the extension directory
     N_("Print out the extension directory and exit"),
     NULL},

    {"slideshow", 's', 
     POPT_ARG_NONE, &sp_global_slideshow, SP_ARG_SLIDESHOW,
     N_("Show given files one-by-one, switch to next on any key/mouse event"), 
     NULL},

    {"new-gui", 'G', 
     POPT_ARG_NONE, &sp_new_gui, SP_ARG_NEW_GUI,
     N_("Use the new Gtkmm GUI interface"),
     NULL},

    {"vacuum-defs", 0,
     POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
     N_("Remove unused definitions from the defs section(s) of the document"),
     NULL},

    POPT_AUTOHELP POPT_TABLEEND
};

static bool needToRecodeParams = true;
gchar* blankParam = "";

int
00562 main(int argc, char **argv)
{
#ifdef HAVE_FPSETMASK
    /* This is inherited from Sodipodi code, where it was in #ifdef __FreeBSD__.  It's probably
       safe to remove: the default mask is already 0 in C99, and in current FreeBSD according to
       the fenv man page on www.freebsd.org, and in glibc according to (libc)FP Exceptions. */
    fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
#endif

#ifdef ENABLE_NLS
#ifdef WIN32
    gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
    bindtextdomain(GETTEXT_PACKAGE, pathBuf);
    g_free(pathBuf);
#else
#ifdef ENABLE_BINRELOC
    bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
#else
    bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
#endif
#endif
#endif

    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");

#ifdef ENABLE_NLS
    textdomain(GETTEXT_PACKAGE);
#endif

    LIBXML_TEST_VERSION

    Inkscape::GC::init();

    Inkscape::Debug::Logger::init();

    gboolean use_gui;
#ifndef WIN32
    use_gui = (getenv("DISPLAY") != NULL);
#else
    /*
      Set the current directory to the directory of the
      executable.  This seems redundant, but is needed for
      when inkscape.exe is executed from another directory.
      We use relative paths on win32.
      HKCR\svgfile\shell\open\command is a good example
    */
    /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
    char *homedir = g_path_get_dirname(argv[0]);
    SetCurrentDirectory(homedir);
    g_free(homedir);

    use_gui = TRUE;
#endif
    /* Test whether with/without GUI is forced */
    for (int i = 1; i < argc; i++) {
        if (!strcmp(argv[i], "-z")
            || !strcmp(argv[i], "--without-gui")
            || !strcmp(argv[i], "-p")
            || !strncmp(argv[i], "--print", 7)
            || !strcmp(argv[i], "-e")
            || !strncmp(argv[i], "--export-png", 12)
            || !strcmp(argv[i], "-l")
            || !strncmp(argv[i], "--export-plain-svg", 12)
            || !strcmp(argv[i], "-i")
            || !strncmp(argv[i], "--export-area-drawing", 21)
            || !strcmp(argv[i], "-D")
            || !strncmp(argv[i], "--export-id", 12)
            || !strcmp(argv[i], "-P")
            || !strncmp(argv[i], "--export-ps", 11)
            || !strcmp(argv[i], "-E")
            || !strncmp(argv[i], "--export-eps", 12)
            || !strcmp(argv[i], "-W")
            || !strncmp(argv[i], "--query-width", 13)
            || !strcmp(argv[i], "-H")
            || !strncmp(argv[i], "--query-height", 14)
            || !strcmp(argv[i], "-X")
            || !strncmp(argv[i], "--query-x", 13)
            || !strcmp(argv[i], "-Y")
            || !strncmp(argv[i], "--query-y", 14)
            || !strcmp(argv[i], "--vacuum-defs")
           )
        {
            /* main_console handles any exports -- not the gui */
            use_gui = FALSE;
            break;
        } else if (!strcmp(argv[i], "-g") || !strcmp(argv[i], "--with-gui")) {
            use_gui = TRUE;
            break;
        } else if (!strcmp(argv[i], "-G") || !strcmp(argv[i], "--new-gui")) {
            sp_new_gui = TRUE;
            break;
        }
    }

#ifdef WIN32
#ifndef REPLACEARGS_ANSI
    if ( PrintWin32::is_os_wide() )
#endif // REPLACEARGS_ANSI
    {
        // If the call fails, we'll need to convert charsets
        needToRecodeParams = !replaceArgs( argc, argv );
    }
#endif // WIN32

    /// \todo  Should this be a static object (see inkscape.cpp)?
    Inkscape::NSApplication::Application app(argc, argv, use_gui, sp_new_gui);

    return app.run();
}

void fixupSingleFilename( gchar **orig, gchar **spare )
{
    if ( orig && *orig && **orig ) {
        GError *error = NULL;
        gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(*orig, -1, NULL, NULL, &error);
        if ( newFileName )
        {
            *orig = newFileName;
            if ( spare ) {
                *spare = newFileName;
            }
//             g_message("Set a replacement fixup");
        }
    }
}

GSList *fixupFilenameEncoding( GSList* fl )
{
    GSList *newFl = NULL;
    while ( fl ) {
        gchar *fn = static_cast<gchar*>(fl->data);
        fl = g_slist_remove( fl, fl->data );
        gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL);
        if ( newFileName ) {

            if ( 0 )
            {
                gchar *safeFn = Inkscape::IO::sanitizeString(fn);
                gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName);
                GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
                                                       "Note: Converted '%s' to '%s'", safeFn, safeNewFn );
                gtk_dialog_run (GTK_DIALOG (w));
                gtk_widget_destroy (w);
                g_free(safeNewFn);
                g_free(safeFn);
            }

            g_free( fn );
            fn = newFileName;
            newFileName = 0;
        }
        else
            if ( 0 )
        {
            gchar *safeFn = Inkscape::IO::sanitizeString(fn);
            GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn );
            gtk_dialog_run (GTK_DIALOG (w));
            gtk_widget_destroy (w);
            g_free(safeFn);
        }
        newFl = g_slist_append( newFl, fn );
    }
    return newFl;
}

00727 int sp_common_main( int argc, char const **argv, GSList **flDest )
{
    /// \todo fixme: Move these to some centralized location (Lauris)
    sp_object_type_register("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
    sp_object_type_register("sodipodi:guide", SP_TYPE_GUIDE);


    // temporarily switch gettext encoding to locale, so that help messages can be output properly
    gchar const *charset;
    g_get_charset(&charset);

    bind_textdomain_codeset(GETTEXT_PACKAGE, charset);

    poptContext ctx = poptGetContext(NULL, argc, argv, options, 0);
    poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
    g_return_val_if_fail(ctx != NULL, 1);

    /* Collect own arguments */
    GSList *fl = sp_process_args(ctx);
    poptFreeContext(ctx);

    // now switch gettext back to UTF-8 (for GUI)
    bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");

    // Now let's see if the file list still holds up
    if ( needToRecodeParams )
    {
        fl = fixupFilenameEncoding( fl );
    }

    // Check the globals for filename-fixup
    if ( needToRecodeParams )
    {
        fixupSingleFilename( &sp_export_png, &sp_export_png_utf8 );
        fixupSingleFilename( &sp_export_svg, &sp_export_svg_utf8 );
        fixupSingleFilename( &sp_global_printer, &sp_global_printer_utf8 );
    }
    else
    {
        if ( sp_export_png )
            sp_export_png_utf8 = g_strdup( sp_export_png );
        if ( sp_export_svg )
            sp_export_svg_utf8 = g_strdup( sp_export_svg );
        if ( sp_global_printer )
            sp_global_printer_utf8 = g_strdup( sp_global_printer );
    }

    // Return the list if wanted, else free it up.
    if ( flDest ) {
        *flDest = fl;
        fl = 0;
    } else {
        while ( fl ) {
            g_free( fl->data );
            fl = g_slist_remove( fl, fl->data );
        }
    }
    return 0;
}

int
sp_main_gui(int argc, char const **argv)
{
    Gtk::Main main_instance (&argc, const_cast<char ***>(&argv));

    GSList *fl = NULL;
    int retVal = sp_common_main( argc, argv, &fl );
    g_return_val_if_fail(retVal == 0, 1);

    inkscape_gtk_stock_init();

    /* Set default icon */
    gchar *filename = (gchar *) g_build_filename (INKSCAPE_APPICONDIR, "inkscape.png", NULL);
    if (Inkscape::IO::file_test(filename, (GFileTest)(G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))) {
        gtk_window_set_default_icon_from_file(filename, NULL);
    }
    g_free (filename);
    filename = 0;

    if (!sp_global_slideshow) {
        gboolean create_new = TRUE;

        /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
        inkscape_application_init(argv[0], true);

        while (fl) {
            if (sp_file_open((gchar *)fl->data,NULL)) {
                create_new=FALSE;
            }
            fl = g_slist_remove(fl, fl->data);
        }
        if (create_new) {
            sp_file_new_default();
        }
    } else {
        if (fl) {
            GtkWidget *ss;
            /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
            inkscape_application_init(argv[0], true);
            ss = sp_slideshow_new(fl);
            if (ss) gtk_widget_show(ss);
        } else {
            g_warning ("No slides to display");
            exit(0);
        }
    }

    main_instance.run();

#ifdef WIN32
    //We might not need anything here
    //sp_win32_finish(); <-- this is a NOP func
#endif

    return 0;
}

int
sp_main_console(int argc, char const **argv)
{
    /* We are started in text mode */

    /* Do this g_type_init(), so that we can use Xft/Freetype2 (Pango)
     * in a non-Gtk environment.  Used in libnrtype's
     * FontInstance.cpp and FontFactory.cpp.
     * http://mail.gnome.org/archives/gtk-list/2003-December/msg00063.html
     */
    g_type_init();
    char **argv2 = const_cast<char **>(argv);
    gtk_init_check( &argc, &argv2 );
    //setlocale(LC_ALL, "");

    GSList *fl = NULL;
    int retVal = sp_common_main( argc, argv, &fl );
    g_return_val_if_fail(retVal == 0, 1);

    if (fl == NULL) {
        g_print("Nothing to do!\n");
        exit(0);
    }

    inkscape_application_init(argv[0], false);

    while (fl) {
        SPDocument *doc;

        doc = Inkscape::Extension::open(NULL, (gchar *)fl->data);
        if (doc == NULL) {
            doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
        }
        if (doc == NULL) {
            g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
        } else {
            if (sp_vacuum_defs) {
                vacuum_document(doc);
            }
            if (sp_vacuum_defs && !sp_export_svg) {
                // save under the name given in the command line
                sp_repr_save_file(doc->rdoc, (gchar *)fl->data, SP_SVG_NS_URI);
            }
            if (sp_global_printer) {
                sp_print_document_to_file(doc, sp_global_printer);
            }
            if (sp_export_png || sp_export_id || sp_export_area_drawing) {
                sp_do_export_png(doc);
            }
            if (sp_export_svg) {
                Inkscape::XML::Document *rdoc;
                Inkscape::XML::Node *repr;
                rdoc = sp_repr_document_new("svg:svg");
                repr = rdoc->root();
                repr = sp_document_root(doc)->updateRepr(repr, SP_OBJECT_WRITE_BUILD);
                sp_repr_save_file(repr->document(), sp_export_svg, SP_SVG_NS_URI);
            }
            if (sp_export_ps) {
                do_export_ps(doc, sp_export_ps, "image/x-postscript");
            }
            if (sp_export_eps) {
                do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
            }
            if (sp_query_width || sp_query_height) {
                do_query_dimension (doc, true, sp_query_width? NR::X : NR::Y, sp_query_id);
            } else if (sp_query_x || sp_query_y) {
                do_query_dimension (doc, false, sp_query_x? NR::X : NR::Y, sp_query_id);
            }
        }
        fl = g_slist_remove(fl, fl->data);
    }

    inkscape_unref();

    return 0;
}

static void
do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
{
    SPObject *o = NULL;

    if (id) {
        o = doc->getObjectById(id);
        if (o) {
            if (!SP_IS_ITEM (o)) {
                g_warning("Object with id=\"%s\" is not a visible item. Cannot query dimensions.", id);
                return;
            }
        } else {
            g_warning("Object with id=\"%s\" is not found. Cannot query dimensions.", id);
            return;
        }
    } else {
        o = SP_DOCUMENT_ROOT(doc);
    }

    if (o) {
        sp_document_ensure_up_to_date (doc);
        NR::Rect area = sp_item_bbox_desktop((SPItem *) o);

        Inkscape::SVGOStringStream os;
        if (extent) {
            os << area.extent(axis);
        } else {
            os << area.min()[axis];
        }
        g_print ("%s\n", os.str().c_str());
    }
}


static void
sp_do_export_png(SPDocument *doc)
{
    const gchar *filename = NULL;
    gdouble dpi = 0.0;

    if (sp_export_use_hints && (!sp_export_id && !sp_export_area_drawing)) {
        g_warning ("--export-use-hints can only be used with --export-id or --export-area-drawing; ignored.");
    }

    GSList *items = NULL;

    NRRect area;
    if (sp_export_id || sp_export_area_drawing) {

        SPObject *o = NULL;
        if (sp_export_id) {
            o = doc->getObjectById(sp_export_id);
        } else if (sp_export_area_drawing) {
            o = SP_DOCUMENT_ROOT (doc);
        }

        if (o) {
            if (!SP_IS_ITEM (o)) {
                g_warning("Object with id=\"%s\" is not a visible item. Nothing exported.", sp_export_id);
                return;
            }
            if (sp_export_area) {
                g_warning ("Object with id=\"%s\" is being exported; --export-area is ignored.", sp_export_id);
            }

            items = g_slist_prepend (items, SP_ITEM(o));

            if (sp_export_id_only) {
                g_print("Exporting only object with id=\"%s\"; all other objects hidden\n", sp_export_id);
            }

            if (sp_export_use_hints) {

                // retrieve export filename hint
                const gchar *fn_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-filename");
                if (fn_hint) {
                    if (sp_export_png) {
                        g_warning ("Using export filename from the command line (--export-png). Filename hint %s is ignored.", fn_hint);
                        filename = sp_export_png;
                    } else {
                        filename = fn_hint;
                    }
                } else {
                    g_warning ("Export filename hint not found for the object.");
                    filename = sp_export_png;
                }

                // retrieve export dpi hints
                const gchar *dpi_hint = SP_OBJECT_REPR(o)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
                if (dpi_hint) {
                    if (sp_export_dpi || sp_export_width || sp_export_height) {
                        g_warning ("Using bitmap dimensions from the command line (--export-dpi, --export-width, or --export-height). DPI hint %s is ignored.", dpi_hint);
                    } else {
                        dpi = atof(dpi_hint);
                    }
                } else {
                    g_warning ("Export DPI hint not found for the object.");
                }

            }

            // write object bbox to area
            sp_document_ensure_up_to_date (doc);
            sp_item_invoke_bbox((SPItem *) o, &area, sp_item_i2r_affine((SPItem *) o), TRUE);
        } else {
            g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
            return;
        }
    } else if (sp_export_area) {
        /* Try to parse area (given in SVG pixels) */
        if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &area.x0, &area.y0, &area.x1, &area.y1) == 4) {
            g_warning("Cannot parse export area '%s'; use 'x0:y0:x1:y1'. Nothing exported.", sp_export_area);
            return;
        }
        if ((area.x0 >= area.x1) || (area.y0 >= area.y1)) {
            g_warning("Export area '%s' has negative width or height. Nothing exported.", sp_export_area);
            return;
        }
    } else {
        /* Export the whole canvas */
        sp_document_ensure_up_to_date (doc);
        area.x0 = SP_ROOT(doc->root)->x.computed;
        area.y0 = SP_ROOT(doc->root)->y.computed;
        area.x1 = area.x0 + sp_document_width (doc);
        area.y1 = area.y0 + sp_document_height (doc);
    }

    // set filename and dpi from options, if not yet set from the hints
    if (!filename) {
        if (!sp_export_png) {
            g_warning ("No export filename given and no filename hint. Nothing exported.");
            return;
        }
        filename = sp_export_png;
    }

    if (sp_export_dpi && dpi == 0.0) {
        dpi = atof(sp_export_dpi);
        if ((dpi < 0.1) || (dpi > 10000.0)) {
            g_warning("DPI value %s out of range [0.1 - 10000.0]. Nothing exported.", sp_export_dpi);
            return;
        }
        g_print("DPI: %g\n", dpi);
    } 

    if (sp_export_area_snap) {
        area.x0 = std::floor (area.x0);
        area.y0 = std::floor (area.y0);
        area.x1 = std::ceil (area.x1);
        area.y1 = std::ceil (area.y1);
    }

    // default dpi
    if (dpi == 0.0)
        dpi = PX_PER_IN;

    gint width = 0;
    gint height = 0;

    if (sp_export_width) {
        width = atoi(sp_export_width);
        if ((width < 1) || (width > 65536)) {
            g_warning("Export width %d out of range (1 - 65536). Nothing exported.", width);
            return;
        }
        dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
    }

    if (sp_export_height) {
        height = atoi(sp_export_height);
        if ((height < 1) || (height > 65536)) {
            g_warning("Export height %d out of range (1 - 65536). Nothing exported.", width);
            return;
        }
        dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
    }

    if (!sp_export_width) {
        width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
    }

    if (!sp_export_height) {
        height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
    }

    guint32 bgcolor = 0x00000000;
    if (sp_export_background) {
        // override the page color
        bgcolor = sp_svg_read_color(sp_export_background, 0xffffff00);
        bgcolor |= 0xff; // default is no opacity
    } else {
        // read from namedview
        Inkscape::XML::Node *nv = sp_repr_lookup_name (doc->rroot, "sodipodi:namedview");
        if (nv && nv->attribute("pagecolor"))
            bgcolor = sp_svg_read_color(nv->attribute("pagecolor"), 0xffffff00);
        if (nv && nv->attribute("inkscape:pageopacity"))
            bgcolor |= SP_COLOR_F_TO_U(sp_repr_get_double_attribute (nv, "inkscape:pageopacity", 1.0));
    }

    if (sp_export_background_opacity) {
        // override opacity
        gfloat value;
        if (sp_svg_number_read_f (sp_export_background_opacity, &value)) {
            if (value > 1.0) {
                value = CLAMP (value, 1.0f, 255.0f);
                bgcolor &= (guint32) 0xffffff00;
                bgcolor |= (guint32) floor(value);
            } else {
                value = CLAMP (value, 0.0f, 1.0f);
                bgcolor &= (guint32) 0xffffff00;
                bgcolor |= SP_COLOR_F_TO_U(value);
            }
        }
    }

    g_print("Background RRGGBBAA: %08x\n", bgcolor);

    g_print("Area %g:%g:%g:%g exported to %d x %d pixels (%g dpi)\n", area.x0, area.y0, area.x1, area.y1, width, height, dpi);

    g_print("Bitmap saved as: %s\n", filename);
  
    if ((width >= 1) && (height >= 1) && (width < 65536) && (height < 65536)) {
        sp_export_png_file(doc, filename, area.x0, area.y0, area.x1, area.y1, width, height, bgcolor, NULL, NULL, true, sp_export_id_only ? items : NULL);
    } else {
        g_warning("Calculated bitmap dimensions %d %d are out of range (1 - 65535). Nothing exported.", width, height);
    }

    g_slist_free (items);
}


/**
 *  Perform an export of either PS or EPS.
 *
 *  \param doc Document to export.
 *  \param uri URI to export to.
 *  \param mime MIME type to export as.
 */

01161 static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
{
    /** \todo
     * FIXME: I've no idea if this is the `proper' way to do this.
     * If anyone feels qualified to say that it is, perhaps they
     * could remove this comment.
     */

    Inkscape::Extension::DB::OutputList o;
    Inkscape::Extension::db.get_output_list(o);
    Inkscape::Extension::DB::OutputList::const_iterator i = o.begin();
    while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
        i++;
    }

    if (i == o.end())
    {
        g_warning ("Could not find an extension to export this file.");
        return;
    }

    bool old_text_to_path = false;
    bool old_bbox_page = false;
    
    try {
        old_text_to_path = (*i)->get_param_bool("textToPath");
        (*i)->set_param_bool("textToPath", sp_export_text_to_path);
    }
    catch (...) {
        g_warning ("Could not set export-text-to-path option for this export.");
    }

    try {
        old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
        (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
    }
    catch (...) {
        g_warning ("Could not set export-bbox-page option for this export.");
    }
    
    (*i)->save(doc, uri);

    try {
        (*i)->set_param_bool("textToPath", old_text_to_path);
        (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
    }
    catch (...) {
        
    }
}

#ifdef WIN32
bool replaceArgs( int& argc, char**& argv )
{
    bool worked = false;

#ifdef REPLACEARGS_DEBUG
    MessageBoxA( NULL, "GetCommandLineW() getting called", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
#endif // REPLACEARGS_DEBUG

    wchar_t* line = GetCommandLineW();
    if ( line )
    {
#ifdef REPLACEARGS_DEBUG
        {
            gchar* utf8Line = g_utf16_to_utf8( (gunichar2*)line, -1, NULL, NULL, NULL );
            if ( utf8Line )
            {
                gchar *safe = Inkscape::IO::sanitizeString(utf8Line);
                {
                    char tmp[strlen(safe) + 32];
                    snprintf( tmp, sizeof(tmp), "GetCommandLineW() = '%s'", safe );
                    MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
                }
            }
        }
#endif // REPLACEARGS_DEBUG

        int numArgs = 0;
        wchar_t** parsed = CommandLineToArgvW( line, &numArgs );

#ifdef REPLACEARGS_ANSI
// test code for trying things on Win95/98/ME
        if ( !parsed )
        {
#ifdef REPLACEARGS_DEBUG
            MessageBoxA( NULL, "Unable to process command-line. Faking it", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
#endif // REPLACEARGS_DEBUG
            int lineLen = wcslen(line) + 1;
            wchar_t* lineDup = new wchar_t[lineLen];
            wcsncpy( lineDup, line, lineLen );

            int pos = 0;
            bool inQuotes = false;
            bool inWhitespace = true;
            std::vector<int> places;
            while ( lineDup[pos] )
            {
                if ( inQuotes )
                {
                    if ( lineDup[pos] == L'"' )
                    {
                        inQuotes = false;
                    }
                }
                else if ( lineDup[pos] == L'"' )
                {
                    inQuotes = true;
                    inWhitespace = false;
                    places.push_back(pos);
                }
                else if ( lineDup[pos] == L' ' || lineDup[pos] == L'\t' )
                {
                    if ( !inWhitespace )
                    {
                        inWhitespace = true;
                        lineDup[pos] = 0;
                    }
                }
                else if ( inWhitespace && (lineDup[pos] != L' ' && lineDup[pos] != L'\t') )
                {
                    inWhitespace = false;
                    places.push_back(pos);
                }
                else
                {
                    // consume
                }
                pos++;
            }
#ifdef REPLACEARGS_DEBUG
            {
                char tmp[256];
                snprintf( tmp, sizeof(tmp), "Counted %d args", places.size() );
                MessageBoxA( NULL, tmp, "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
            }
#endif // REPLACEARGS_DEBUG

            wchar_t** block = new wchar_t*[places.size()];
            int i = 0;
            for ( std::vector<int>::iterator it = places.begin(); it != places.end(); it++ )
            {
                block[i++] = &lineDup[*it];
            }
            parsed = block;
            numArgs = places.size();
        }
#endif // REPLACEARGS_ANSI

        if ( parsed )
        {
            std::vector<wchar_t*>expandedArgs;
            if ( numArgs > 0 )
            {
                expandedArgs.push_back( parsed[0] );
            }

            for ( int i1 = 1; i1 < numArgs; i1++ )
            {
                bool wildcarded = (wcschr(parsed[i1], L'?') != NULL) || (wcschr(parsed[i1], L'*') != NULL);
                wildcarded &= parsed[i1][0] != L'"';
                wildcarded &= parsed[i1][0] != L'-';
                if ( wildcarded )
                {
#ifdef REPLACEARGS_ANSI
                    WIN32_FIND_DATAA data = {0};
#else
                    WIN32_FIND_DATAW data = {0};
#endif // REPLACEARGS_ANSI

                    int baseLen = wcslen(parsed[i1]) + 2;
                    wchar_t* base = new wchar_t[baseLen];
                    wcsncpy( base, parsed[i1], baseLen );
                    wchar_t* last = wcsrchr( base, L'\\' );
                    if ( last )
                    {
                        last[1] = 0;
                    }
                    else
                    {
                        base[0] = 0;
                    }
                    baseLen = wcslen( base );

#ifdef REPLACEARGS_ANSI
                    char target[MAX_PATH];
                    if ( WideCharToMultiByte( CP_ACP, 0, parsed[i1], -1, target, sizeof(target), NULL, NULL) )
                    {
                        HANDLE hf = FindFirstFileA( target, &data );
#else
                        HANDLE hf = FindFirstFileW( parsed[i1], &data );
#endif // REPLACEARGS_ANSI
                        if ( hf != INVALID_HANDLE_VALUE )
                        {
                            BOOL found = TRUE;
                            do
                            {
#ifdef REPLACEARGS_ANSI
                                int howMany = MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, NULL, 0 );
                                if ( howMany > 0 )
                                {
                                    howMany += baseLen;
                                    wchar_t* tmp = new wchar_t[howMany + 1];
                                    wcsncpy( tmp, base, howMany + 1 );
                                    MultiByteToWideChar( CP_ACP, 0, data.cFileName, -1, tmp + baseLen, howMany + 1 - baseLen );
                                    expandedArgs.push_back( tmp );
                                    found = FindNextFileA( hf, &data );
                                }
#else
                                int howMany = wcslen(data.cFileName) + baseLen;
                                wchar_t* tmp = new wchar_t[howMany + 1];
                                wcsncpy( tmp, base, howMany + 1 );
                                wcsncat( tmp, data.cFileName, howMany + 1 );
                                expandedArgs.push_back( tmp );
                                found = FindNextFileW( hf, &data );
#endif // REPLACEARGS_ANSI
                            } while ( found );

                            FindClose( hf );
                        }
                        else
                        {
                            expandedArgs.push_back( parsed[i1] );
                        }
#ifdef REPLACEARGS_ANSI
                    }
#endif // REPLACEARGS_ANSI

                    delete[] base;
                }
                else
                {
                    expandedArgs.push_back( parsed[i1] );
                }
            }

            {
                wchar_t** block = new wchar_t*[expandedArgs.size()];
                int iz = 0;
                for ( std::vector<wchar_t*>::iterator it = expandedArgs.begin(); it != expandedArgs.end(); it++ )
                {
                    block[iz++] = *it;
                }
                parsed = block;
                numArgs = expandedArgs.size();
            }

            std::vector<gchar*> newArgs;
            for ( int i = 0; i < numArgs; i++ )
            {
                gchar* replacement = g_utf16_to_utf8( (gunichar2*)parsed[i], -1, NULL, NULL, NULL );
                if ( replacement )
                {
#ifdef REPLACEARGS_DEBUG
                    gchar *safe2 = Inkscape::IO::sanitizeString(replacement);

                    if ( safe2 )
                    {
                        {
                            char tmp[1024];
                            snprintf( tmp, sizeof(tmp), "    [%2d] = '%s'", i, safe2 );
                            MessageBoxA( NULL, tmp, "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
                        }
                        g_free( safe2 );
                    }
#endif // REPLACEARGS_DEBUG

                    newArgs.push_back( replacement );
                }
                else
                {
                    newArgs.push_back( blankParam );
                }
            }

            // Now push our munged params to be the new argv and argc
            {
                char** block = new char*[newArgs.size()];
                int iz = 0;
                for ( std::vector<char*>::iterator it = newArgs.begin(); it != newArgs.end(); it++ )
                {
                    block[iz++] = *it;
                }
                argv = block;
                argc = newArgs.size();
                worked = true;
            }
        }
#ifdef REPLACEARGS_DEBUG
        else
        {
            MessageBoxA( NULL, "Unable to process command-line", "CommandLineToArgvW", MB_OK | MB_ICONINFORMATION );
        }
#endif // REPLACEARGS_DEBUG
    }
#ifdef REPLACEARGS_DEBUG
    else
    {
        {
            MessageBoxA( NULL,  "Unable to fetch result from GetCommandLineW()", "GetCommandLineW", MB_OK | MB_ICONINFORMATION );
        }

        char* line2 = GetCommandLineA();
        if ( line2 )
        {
            gchar *safe = Inkscape::IO::sanitizeString(line2);
            {
                {
                    char tmp[strlen(safe) + 32];
                    snprintf( tmp, sizeof(tmp), "GetCommandLineA() = '%s'", safe );
                    MessageBoxA( NULL, tmp, "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
                }
            }
        }
        else
        {
            MessageBoxA( NULL, "Unable to fetch result from GetCommandLineA()", "GetCommandLineA", MB_OK | MB_ICONINFORMATION );
        }
    }
#endif // REPLACEARGS_DEBUG

    return worked;
}
#endif // WIN32

static GSList *
sp_process_args(poptContext ctx)
{
    GSList *fl = NULL;

    gint a;
    while ((a = poptGetNextOpt(ctx)) >= 0) {
        switch (a) {
            case SP_ARG_FILE: {
                gchar const *fn = poptGetOptArg(ctx);
                if (fn != NULL) {
                    fl = g_slist_append(fl, g_strdup(fn));
                }
                break;
            }
            case SP_ARG_VERSION: {
                printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
                exit(0);
                break;
            }
            case SP_ARG_EXTENSIONDIR: {
                printf("%s\n", INKSCAPE_EXTENSIONDIR);
                exit(0);
                break;
            }
            default: {
                break;
            }
        }
    }

    gchar const ** const args = poptGetArgs(ctx);
    if (args != NULL) {
        for (unsigned i = 0; args[i] != NULL; i++) {
            fl = g_slist_append(fl, g_strdup(args[i]));
        }
    }

    return fl;
}


/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :

Generated by  Doxygen 1.6.0   Back to index