Code

now that selection description includes style (filtered, clipped), we need to update...
[inkscape.git] / src / main.cpp
index 165316cd2a614c9438f389511161b147e3cc997a..7bbe691d70f9abc871efc78a27d6141453db6be3 100644 (file)
  * 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
- *
- * SelCue [\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"
 #ifdef HAVE_IEEEFP_H
 #include <ieeefp.h>
 #endif
-#include <string.h>
+#include <cstring>
+#include <string>
 #include <locale.h>
+#include <stdlib.h>
 
 #include <popt.h>
 #ifndef POPT_TABLEEND
 #include <gtk/gtkwindow.h>
 #include <gtk/gtkbox.h>
 
-#include <gtk/gtkmain.h>
-
 #include "gc-core.h"
 
 #include "macros.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/svg-color.h"
 #include "svg/stringstream.h"
 
 #include "inkscape-private.h"
 #include "inkscape-stock.h"
-#include "inkscape_version.h"
+#include "inkscape-version.h"
 
 #include "sp-namedview.h"
 #include "sp-guide.h"
 #include "io/sys.h"
 
 #include "debug/logger.h"
+#include "debug/log-display-config.h"
+
+#include "helper/png-write.h"
+#include "helper/geom.h"
 
 #include <extension/extension.h>
 #include <extension/system.h>
@@ -315,6 +111,11 @@ using Inkscape::Extension::Internal::PrintWin32;
 
 #include "application/application.h"
 
+#include "main-cmdlineact.h"
+
+#include <png.h>
+#include <errno.h>
+
 enum {
     SP_ARG_NONE,
     SP_ARG_NOGUI,
@@ -325,6 +126,7 @@ enum {
     SP_ARG_EXPORT_DPI,
     SP_ARG_EXPORT_AREA,
     SP_ARG_EXPORT_AREA_DRAWING,
+    SP_ARG_EXPORT_AREA_CANVAS,
     SP_ARG_EXPORT_AREA_SNAP,
     SP_ARG_EXPORT_WIDTH,
     SP_ARG_EXPORT_HEIGHT,
@@ -336,34 +138,45 @@ enum {
     SP_ARG_EXPORT_SVG,
     SP_ARG_EXPORT_PS,
     SP_ARG_EXPORT_EPS,
+    SP_ARG_EXPORT_PDF,
+#ifdef WIN32
+    SP_ARG_EXPORT_EMF,
+#endif //WIN32
     SP_ARG_EXPORT_TEXT_TO_PATH,
-    SP_ARG_EXPORT_BBOX_PAGE,
+    SP_ARG_EXPORT_IGNORE_FILTERS,
     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_ALL,
     SP_ARG_QUERY_ID,
+    SP_ARG_SHELL,
     SP_ARG_VERSION,
-    SP_ARG_NEW_GUI,
     SP_ARG_VACUUM_DEFS,
+    SP_ARG_VERB_LIST,
+    SP_ARG_VERB,
+    SP_ARG_SELECT,
     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 void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const *mime);
+#ifdef WIN32
+static void do_export_emf(SPDocument* doc, gchar const* uri, char const *mime);
+#endif //WIN32
+static void do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id);
+static void do_query_all (SPDocument *doc);
+static void do_query_all_recurse (SPObject *o);
 
 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 gboolean sp_export_area_canvas = FALSE;
 static gchar *sp_export_width = NULL;
 static gchar *sp_export_height = NULL;
 static gchar *sp_export_id = NULL;
@@ -375,20 +188,69 @@ 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 gchar *sp_export_pdf = NULL;
+#ifdef WIN32
+static gchar *sp_export_emf = NULL;
+#endif //WIN32
 static gboolean sp_export_text_to_path = FALSE;
-static gboolean sp_export_bbox_page = FALSE;
+static gboolean sp_export_ignore_filters = FALSE;
+static gboolean sp_export_font = 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 gboolean sp_query_all = FALSE;
 static gchar *sp_query_id = NULL;
 static int sp_new_gui = FALSE;
+static gboolean sp_shell = 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;
 
+
+/**
+ *  Reset variables to default values.
+ */
+static void resetCommandlineGlobals() {
+        sp_global_printer = NULL;
+        sp_export_png = NULL;
+        sp_export_dpi = NULL;
+        sp_export_area = NULL;
+        sp_export_area_drawing = FALSE;
+        sp_export_area_canvas = FALSE;
+        sp_export_width = NULL;
+        sp_export_height = NULL;
+        sp_export_id = NULL;
+        sp_export_background = NULL;
+        sp_export_background_opacity = NULL;
+        sp_export_area_snap = FALSE;
+        sp_export_use_hints = FALSE;
+        sp_export_id_only = FALSE;
+        sp_export_svg = NULL;
+        sp_export_ps = NULL;
+        sp_export_eps = NULL;
+        sp_export_pdf = NULL;
+#ifdef WIN32
+        sp_export_emf = NULL;
+#endif //WIN32
+        sp_export_text_to_path = FALSE;
+        sp_export_ignore_filters = FALSE;
+        sp_export_font = FALSE;
+        sp_query_x = FALSE;
+        sp_query_y = FALSE;
+        sp_query_width = FALSE;
+        sp_query_height = FALSE;
+        sp_query_all = FALSE;
+        sp_query_id = NULL;
+        sp_vacuum_defs = FALSE;
+
+        sp_export_png_utf8 = NULL;
+        sp_export_svg_utf8 = NULL;
+        sp_global_printer_utf8 = NULL;
+}
+
 #ifdef WIN32
 static bool replaceArgs( int& argc, char**& argv );
 #endif
@@ -439,6 +301,11 @@ struct poptOption options[] = {
      N_("Exported area is the entire drawing (not canvas)"),
      NULL},
 
+    {"export-area-canvas", 'C',
+     POPT_ARG_NONE, &sp_export_area_canvas, SP_ARG_EXPORT_AREA_CANVAS,
+     N_("Exported area is the entire 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)"),
@@ -456,7 +323,7 @@ struct poptOption options[] = {
 
     {"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_("The ID of the object to export"),
      N_("ID")},
 
     {"export-id-only", 'j',
@@ -496,14 +363,26 @@ struct poptOption options[] = {
      N_("Export document to an EPS file"),
      N_("FILENAME")},
 
+    {"export-pdf", 'A',
+     POPT_ARG_STRING, &sp_export_pdf, SP_ARG_EXPORT_PDF,
+     N_("Export document to a PDF file"),
+     N_("FILENAME")},
+
+#ifdef WIN32
+    {"export-emf", 'M',
+     POPT_ARG_STRING, &sp_export_emf, SP_ARG_EXPORT_EMF,
+     N_("Export document to an Enhanced Metafile (EMF) File"),
+     N_("FILENAME")},
+#endif //WIN32
+
     {"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)"),
+     N_("Convert text object to paths on export (PS, EPS, PDF)"),
      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)"),
+    {"export-ignore-filters", 0,
+     POPT_ARG_NONE, &sp_export_ignore_filters, SP_ARG_EXPORT_IGNORE_FILTERS,
+     N_("Render filtered objects without filters, instead of rasterizing (PS, EPS, PDF)"),
      NULL},
 
     {"query-x", 'X',
@@ -530,6 +409,11 @@ struct poptOption options[] = {
      N_("Query the height of the drawing or, if specified, of the object with --query-id"),
      NULL},
 
+    {"query-all", 'S',
+     POPT_ARG_NONE, &sp_query_all, SP_ARG_QUERY_ALL,
+     N_("List id,x,y,w,h for all objects"),
+     NULL},
+
     {"query-id", 'I',
      POPT_ARG_STRING, &sp_query_id, SP_ARG_QUERY_ID,
      N_("The ID of the object whose dimensions are queried"),
@@ -541,27 +425,118 @@ struct poptOption options[] = {
      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"),
+    {"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},
 
-    {"new-gui", 'G',
-     POPT_ARG_NONE, &sp_new_gui, SP_ARG_NEW_GUI,
-     N_("Use the new Gtkmm GUI interface"),
+    {"verb-list", 0,
+     POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
+     N_("List the IDs of all the verbs in Inkscape"),
      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"),
+    {"verb", 0,
+     POPT_ARG_STRING, NULL, SP_ARG_VERB,
+     N_("Verb to call when Inkscape opens."),
+     N_("VERB-ID")},
+
+    {"select", 0,
+     POPT_ARG_STRING, NULL, SP_ARG_SELECT,
+     N_("Object ID to select when Inkscape opens."),
+     N_("OBJECT-ID")},
+
+    {"shell", 0,
+     POPT_ARG_NONE, &sp_shell, SP_ARG_SHELL,
+     N_("Start Inkscape in interative shell mode."),
      NULL},
 
     POPT_AUTOHELP POPT_TABLEEND
 };
 
 static bool needToRecodeParams = true;
-gchar* blankParam = "";
+gchar * blankParam = g_strdup("");
+
+
+
+#ifdef WIN32
 
+/**
+ * Return the directory of the .exe that is currently running
+ */
+static Glib::ustring _win32_getExePath()
+{
+    char exeName[MAX_PATH+1];
+    GetModuleFileName(NULL, exeName, MAX_PATH);
+    char *slashPos = strrchr(exeName, '\\');
+    if (slashPos)
+        *slashPos = '\0';
+    Glib::ustring s = exeName;
+    return s;
+}
+
+/**
+ * Set up the PATH and PYTHONPATH environment variables on
+ * win32
+ */
+static int _win32_set_inkscape_env(const Glib::ustring &exePath)
+{
+
+    char *oldenv = getenv("PATH");
+    Glib::ustring tmp = "PATH=";
+    tmp += exePath;
+    tmp += ";";
+    tmp += exePath;
+    tmp += "\\python;";
+    tmp += exePath;
+    tmp += "\\python\\Scripts;";  // for uniconv.cmd
+    tmp += exePath;
+    tmp += "\\perl";
+    if(oldenv != NULL) {
+        tmp += ";";
+        tmp += oldenv;
+    }
+    _putenv(tmp.c_str());
+
+    oldenv = getenv("PYTHONPATH");
+    tmp = "PYTHONPATH=";
+    tmp += exePath;
+    tmp += "\\python;";
+    tmp += exePath;
+    tmp += "\\python\\Lib;";
+    tmp += exePath;
+    tmp += "\\python\\DLLs";
+    if(oldenv != NULL) {
+        tmp += ";";
+        tmp += oldenv;
+    }
+    _putenv(tmp.c_str());
+
+    return 0;
+}
+#endif
+
+/**
+ * Add INKSCAPE_EXTENSIONDIR to PYTHONPATH so that extensions in users home
+ * can find inkex.py et al. (Bug #197475)
+ */
+static int set_extensions_env()
+{
+    char *oldenv = getenv("PYTHONPATH");
+    Glib::ustring tmp = INKSCAPE_EXTENSIONDIR;
+    if (oldenv != NULL) {
+        tmp += G_SEARCHPATH_SEPARATOR;
+        tmp += oldenv;
+    }
+    g_setenv("PYTHONPATH", tmp.c_str(), TRUE);
+    
+    return 0;
+}
+
+
+/**
+ * This is the classic main() entry point of the program, though on some
+ * architectures it might be called by something else.
+ */
 int
 main(int argc, char **argv)
 {
@@ -572,13 +547,36 @@ main(int argc, char **argv)
     fpsetmask(fpgetmask() & ~(FP_X_DZ | FP_X_INV));
 #endif
 
-#ifdef ENABLE_NLS
 #ifdef WIN32
+    /*
+      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
+    */
+    Glib::ustring homedir = _win32_getExePath();
+    SetCurrentDirectory(homedir.c_str());
+    _win32_set_inkscape_env(homedir);
     RegistryTool rt;
     rt.setPathInfo();
-    gchar *pathBuf = g_strconcat(g_path_get_dirname(argv[0]), "\\", PACKAGE_LOCALE_DIR, NULL);
-    bindtextdomain(GETTEXT_PACKAGE, pathBuf);
-    g_free(pathBuf);
+#endif
+
+    // Prevents errors like "Unable to wrap GdkPixbuf..." (in nr-filter-image.cpp for example)
+    Gtk::Main::init_gtkmm_internals();
+
+    // Bug #197475
+    set_extensions_env();
+
+   /**
+    * Call bindtextdomain() for various machines's paths
+    */
+#ifdef ENABLE_NLS
+#ifdef WIN32
+    Glib::ustring localePath = homedir;
+    localePath += "\\";
+    localePath += PACKAGE_LOCALE_DIR;
+    bindtextdomain(GETTEXT_PACKAGE, localePath.c_str());
 #else
 #ifdef ENABLE_BINRELOC
     bindtextdomain(GETTEXT_PACKAGE, BR_LOCALEDIR(""));
@@ -586,6 +584,12 @@ main(int argc, char **argv)
     bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
 #endif
 #endif
+    // Allow the user to override the locale directory by setting
+    // the environment variable INKSCAPE_LOCALEDIR.
+    char *inkscape_localedir = getenv("INKSCAPE_LOCALEDIR");
+    if (inkscape_localedir != NULL) {
+        bindtextdomain(GETTEXT_PACKAGE, inkscape_localedir);
+    }
 #endif
 
     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
@@ -601,21 +605,10 @@ main(int argc, char **argv)
     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 */
@@ -631,20 +624,31 @@ main(int argc, char **argv)
             || !strcmp(argv[i], "-i")
             || !strncmp(argv[i], "--export-area-drawing", 21)
             || !strcmp(argv[i], "-D")
+            || !strncmp(argv[i], "--export-area-canvas", 20)
+            || !strcmp(argv[i], "-C")
             || !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], "-A")
+            || !strncmp(argv[i], "--export-pdf", 12)
+#ifdef WIN32
+            || !strcmp(argv[i], "-M")
+            || !strncmp(argv[i], "--export-emf", 12)
+#endif //WIN32
             || !strcmp(argv[i], "-W")
             || !strncmp(argv[i], "--query-width", 13)
             || !strcmp(argv[i], "-H")
             || !strncmp(argv[i], "--query-height", 14)
+            || !strcmp(argv[i], "-S")
+            || !strncmp(argv[i], "--query-all", 11)
             || !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")
+            || !strncmp(argv[i], "--shell", 7)
            )
         {
             /* main_console handles any exports -- not the gui */
@@ -653,9 +657,6 @@ main(int argc, char **argv)
         } 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;
         }
     }
 
@@ -675,6 +676,9 @@ main(int argc, char **argv)
     return app.run();
 }
 
+
+
+
 void fixupSingleFilename( gchar **orig, gchar **spare )
 {
     if ( orig && *orig && **orig ) {
@@ -691,6 +695,8 @@ void fixupSingleFilename( gchar **orig, gchar **spare )
     }
 }
 
+
+
 GSList *fixupFilenameEncoding( GSList* fl )
 {
     GSList *newFl = NULL;
@@ -790,6 +796,34 @@ int sp_common_main( int argc, char const **argv, GSList **flDest )
     return 0;
 }
 
+static void
+snooper(GdkEvent *event, gpointer /*data*/) {
+    if(inkscape_mapalt())  /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
+    {
+        GdkModifierType mapping=(GdkModifierType)inkscape_mapalt();
+        switch (event->type) {
+            case GDK_MOTION_NOTIFY:
+                if(event->motion.state & mapping) {
+                    event->motion.state|=GDK_MOD1_MASK;
+                }
+                break;
+            case GDK_BUTTON_PRESS:
+                if(event->button.state & mapping) {
+                    event->button.state|=GDK_MOD1_MASK;
+                }
+                break;
+             case GDK_KEY_PRESS:
+                 if(event->key.state & mapping) {
+                     event->key.state|=GDK_MOD1_MASK;
+                 }
+                 break;
+        default:
+            break;
+        }
+    }
+    gtk_main_do_event (event);
+}
+
 int
 sp_main_gui(int argc, char const **argv)
 {
@@ -801,6 +835,10 @@ sp_main_gui(int argc, char const **argv)
 
     inkscape_gtk_stock_init();
 
+    gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
+
+    Inkscape::Debug::log_display_config();
+
     /* 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))) {
@@ -809,34 +847,22 @@ sp_main_gui(int argc, char const **argv)
     g_free (filename);
     filename = 0;
 
-    if (!sp_global_slideshow) {
-        gboolean create_new = TRUE;
+    gboolean create_new = TRUE;
 
-        /// \todo FIXME BROKEN - non-UTF-8 sneaks in here.
-        inkscape_application_init(argv[0], 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);
+    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();
     }
 
+    Glib::signal_idle().connect(sigc::ptr_fun(&Inkscape::CmdLineAction::idle));
     main_instance.run();
 
 #ifdef WIN32
@@ -847,53 +873,31 @@ sp_main_gui(int argc, char const **argv)
     return 0;
 }
 
-int
-sp_main_console(int argc, char const **argv)
+/**
+ * Process file list
+ */
+void sp_process_file_list(GSList *fl)
 {
-    /* 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);
+        const gchar *filename = (gchar *)fl->data;
+        SPDocument *doc = Inkscape::Extension::open(NULL, filename);
         if (doc == NULL) {
-            doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), (gchar *)fl->data);
+            doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), filename);
         }
         if (doc == NULL) {
-            g_warning("Specified document %s cannot be opened (is it valid SVG file?)", (gchar *) fl->data);
+            g_warning("Specified document %s cannot be opened (is it a valid SVG file?)", filename);
         } 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);
+                sp_repr_save_file(doc->rdoc, filename, 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) {
+            if (sp_export_png) {
                 sp_do_export_png(doc);
             }
             if (sp_export_svg) {
@@ -901,31 +905,146 @@ sp_main_console(int argc, char const **argv)
                 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);
+                repr = sp_document_root(doc)->updateRepr(rdoc, 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");
+                do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript");
             }
             if (sp_export_eps) {
-                do_export_ps(doc, sp_export_eps, "image/x-e-postscript");
+                do_export_ps_pdf(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);
+            if (sp_export_pdf) {
+                do_export_ps_pdf(doc, sp_export_pdf, "application/pdf");
+            }
+#ifdef WIN32
+            if (sp_export_emf) {
+                do_export_emf(doc, sp_export_emf, "image/x-emf");
+            }
+#endif //WIN32
+            if (sp_query_all) {
+                do_query_all (doc);
+            } else if (sp_query_width || sp_query_height) {
+                do_query_dimension (doc, true, sp_query_width? Geom::X : Geom::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);
+                do_query_dimension (doc, false, sp_query_x? Geom::X : Geom::Y, sp_query_id);
             }
+
+            delete doc;
         }
         fl = g_slist_remove(fl, fl->data);
     }
+}
 
-    inkscape_unref();
+/**
+ * Run the application as an interactive shell, parsing command lines from stdin
+ * Returns -1 on error.
+ */
+int sp_main_shell(char const* command_name)
+{
+    int retval = 0;
+
+    const unsigned int buffer_size = 4096;
+    gchar *command_line = g_strnfill(buffer_size, 0);
+    g_strlcpy(command_line, command_name, buffer_size);
+    gsize offset = g_strlcat(command_line, " ", buffer_size);
+    gsize sizeLeft = buffer_size - offset;
+    gchar *useme = command_line + offset;
+
+    fprintf(stdout, "Inkscape %s interactive shell mode. Type 'quit' to quit.\n", Inkscape::version_string);
+    fflush(stdout);
+    char* linedata = 0;
+    do {
+        fprintf(stdout, ">");
+        fflush(stdout);
+        if ((linedata = fgets(useme, sizeLeft, stdin))) {
+            size_t len = strlen(useme);
+            if ( (len >= sizeLeft - 1) || (useme[len - 1] != '\n') ) {
+                fprintf(stdout, "ERROR: Command line too long\n");
+                // Consume rest of line
+                retval = -1; // If the while loop completes, this remains -1
+                while (fgets(useme, sizeLeft, stdin) && retval) {
+                    len = strlen(command_line);
+                    if ( (len < buffer_size) && (command_line[len-1] == '\n') ) {
+                        retval = 0;
+                    }
+                }
+            } else {
+                useme[--len] = '\0';  // Strip newline
+                if (useme[len - 1] == '\r') {
+                    useme[--len] = '\0';
+                }
+                if ( strcmp(useme, "quit") == 0 ) {
+                    // Time to quit
+                    fflush(stdout);
+                    linedata = 0; // mark for exit
+                } else if ( len < 1 ) {
+                    // blank string. Do nothing.
+                } else {
+                    GError* parseError = 0;
+                    gchar** argv = 0;
+                    gint argc = 0;
+                    if ( g_shell_parse_argv(command_line, &argc, &argv, &parseError) ) {
+                        poptContext ctx = poptGetContext(NULL, argc, const_cast<const gchar**>(argv), options, 0);
+                        poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:"));
+                        if ( ctx ) {
+                            GSList *fl = sp_process_args(ctx);
+                            sp_process_file_list(fl);
+                            poptFreeContext(ctx);
+                        } else {
+                            retval = 1; // not sure why. But this was the previous return value
+                        }
+                        resetCommandlineGlobals();
+                        g_strfreev(argv);
+                    } else {
+                        g_warning("Cannot parse commandline: %s", useme);
+                    }
+                }
+            }
+        } // if (linedata...
+    } while (linedata && (retval == 0));
+
+    g_free(command_line);
+    return retval;
+}
+
+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 && !sp_shell) {
+        g_print("Nothing to do!\n");
+        exit(0);
+    }
+
+    inkscape_application_init(argv[0], false);
+
+    if (sp_shell) {
+        sp_main_shell(argv[0]); // Run as interactive shell
+        exit(0);
+    } else {
+        sp_process_file_list(fl); // Normal command line invokation
+    }
 
     return 0;
 }
 
 static void
-do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gchar *id)
+do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id)
 {
     SPObject *o = NULL;
 
@@ -946,15 +1065,58 @@ do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gch
 
     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);
+        SPItem *item = ((SPItem *) o);
+
+        // "true" SVG bbox for scripting
+        Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
+        if (area) {
+            Inkscape::SVGOStringStream os;
+            if (extent) {
+                os << area->dimensions()[axis];
+            } else {
+                os << area->min()[axis];
+            }
+            g_print ("%s", os.str().c_str());
         } else {
-            os << area.min()[axis];
+            g_print("0");
         }
-        g_print ("%s\n", os.str().c_str());
+    }
+}
+
+static void
+do_query_all (SPDocument *doc)
+{
+    SPObject *o = NULL;
+
+    o = SP_DOCUMENT_ROOT(doc);
+
+    if (o) {
+        sp_document_ensure_up_to_date (doc);
+        do_query_all_recurse(o);
+    }
+}
+
+static void
+do_query_all_recurse (SPObject *o)
+{
+    SPItem *item = ((SPItem *) o);
+    if (o->id && SP_IS_ITEM(item)) {
+        Geom::OptRect area = item->getBounds(sp_item_i2doc_affine(item));
+        if (area) {
+            Inkscape::SVGOStringStream os;
+            os << o->id;
+            os << "," << area->min()[Geom::X];
+            os << "," << area->min()[Geom::Y];
+            os << "," << area->dimensions()[Geom::X];
+            os << "," << area->dimensions()[Geom::Y];
+            g_print ("%s\n", os.str().c_str());
+        }
+    }
+
+    SPObject *child = o->children;
+    while (child) {
+        do_query_all_recurse (child);
+        child = child->next;
     }
 }
 
@@ -971,14 +1133,20 @@ sp_do_export_png(SPDocument *doc)
 
     GSList *items = NULL;
 
-    NRRect area;
+    Geom::Rect area;
     if (sp_export_id || sp_export_area_drawing) {
 
         SPObject *o = NULL;
-        if (sp_export_id) {
+        SPObject *o_area = NULL;
+        if (sp_export_id && sp_export_area_drawing) {
+            o = doc->getObjectById(sp_export_id);
+            o_area = SP_DOCUMENT_ROOT (doc);
+        } else if (sp_export_id) {
             o = doc->getObjectById(sp_export_id);
+            o_area = o;
         } else if (sp_export_area_drawing) {
             o = SP_DOCUMENT_ROOT (doc);
+            o_area = o;
         }
 
         if (o) {
@@ -986,9 +1154,6 @@ sp_do_export_png(SPDocument *doc)
                 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));
 
@@ -1028,28 +1193,33 @@ sp_do_export_png(SPDocument *doc)
 
             // 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);
+            Geom::OptRect areaMaybe;
+            sp_item_invoke_bbox((SPItem *) o_area, areaMaybe, sp_item_i2d_affine((SPItem *) o_area), TRUE);
+            if (areaMaybe) {
+                area = *areaMaybe;
+            } else {
+                g_warning("Unable to determine a valid bounding box. Nothing exported.");
+                return;
+            }
         } else {
             g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
             return;
         }
-    } else if (sp_export_area) {
+    }
+
+    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) {
+        gdouble x0,y0,x1,y1;
+        if (!sscanf(sp_export_area, "%lg:%lg:%lg:%lg", &x0, &y0, &x1, &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 {
+        area = Geom::Rect(Geom::Interval(x0,x1), Geom::Interval(y0,y1));
+    } else if (sp_export_area_canvas || !(sp_export_id || sp_export_area_drawing)) {
         /* 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);
+        Geom::Point origin (SP_ROOT(doc->root)->x.computed, SP_ROOT(doc->root)->y.computed);
+        area = Geom::Rect(origin, origin + sp_document_dimensions(doc));
     }
 
     // set filename and dpi from options, if not yet set from the hints
@@ -1071,43 +1241,43 @@ sp_do_export_png(SPDocument *doc)
     }
 
     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);
+        round_rectangle_outwards(area);
     }
 
     // default dpi
-    if (dpi == 0.0)
+    if (dpi == 0.0) {
         dpi = PX_PER_IN;
+    }
 
-    gint width = 0;
-    gint height = 0;
+    unsigned long int width = 0;
+    unsigned long int 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);
+        errno=0;
+        width = strtoul(sp_export_width, NULL, 0);
+        if ((width < 1) || (width > PNG_UINT_31_MAX) || (errno == ERANGE) ) {
+            g_warning("Export width %lu out of range (1 - %lu). Nothing exported.", width, (unsigned long int)PNG_UINT_31_MAX);
             return;
         }
-        dpi = (gdouble) width * PX_PER_IN / (area.x1 - area.x0);
+        dpi = (gdouble) width * PX_PER_IN / area.width();
     }
 
     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);
+        errno=0;
+        height = strtoul(sp_export_height, NULL, 0);
+        if ((height < 1) || (height > PNG_UINT_31_MAX)) {
+            g_warning("Export height %lu out of range (1 - %lu). Nothing exported.", height, (unsigned long int)PNG_UINT_31_MAX);
             return;
         }
-        dpi = (gdouble) height * PX_PER_IN / (area.y1 - area.y0);
+        dpi = (gdouble) height * PX_PER_IN / area.height();
     }
 
     if (!sp_export_width) {
-        width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
+        width = (unsigned long int) (area.width() * dpi / PX_PER_IN + 0.5);
     }
 
     if (!sp_export_height) {
-        height = (gint) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
+        height = (unsigned long int) (area.height() * dpi / PX_PER_IN + 0.5);
     }
 
     guint32 bgcolor = 0x00000000;
@@ -1142,14 +1312,14 @@ sp_do_export_png(SPDocument *doc)
 
     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("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);
 
     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);
+    if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) {
+        sp_export_png_file(doc, filename, area, width, height, dpi, dpi, 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_warning("Calculated bitmap dimensions %lu %lu are out of range (1 - %lu). Nothing exported.", width, height, (unsigned long int)PNG_UINT_31_MAX);
     }
 
     g_slist_free (items);
@@ -1157,21 +1327,15 @@ sp_do_export_png(SPDocument *doc)
 
 
 /**
- *  Perform an export of either PS or EPS.
+ *  Perform a PDF/PS/EPS export
  *
  *  \param doc Document to export.
  *  \param uri URI to export to.
  *  \param mime MIME type to export as.
  */
 
-static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
+static void do_export_ps_pdf(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();
@@ -1181,39 +1345,92 @@ static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
 
     if (i == o.end())
     {
-        g_warning ("Could not find an extension to export this file.");
+        g_warning ("Could not find an extension to export to MIME type %s.", mime);
         return;
     }
 
-    bool old_text_to_path = false;
-    bool old_bbox_page = false;
+    if (sp_export_id) {
+        SPObject *o = doc->getObjectById(sp_export_id);
+        if (o == NULL) {
+            g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
+            return;
+        }
+        (*i)->set_param_string ("exportId", sp_export_id);
+    } else {
+        (*i)->set_param_string ("exportId", "");
+    }
 
-    try {
-        old_text_to_path = (*i)->get_param_bool("textToPath");
-        (*i)->set_param_bool("textToPath", sp_export_text_to_path);
+    if (sp_export_area_canvas && sp_export_area_drawing) {
+        g_warning ("You cannot use --export-area-canvas and --export-area-drawing at the same time; only the former will take effect.");
+        sp_export_area_drawing = false;
     }
-    catch (...) {
-        g_warning ("Could not set export-text-to-path option for this export.");
+
+    if (sp_export_area_drawing) {
+        (*i)->set_param_bool ("areaDrawing", TRUE);
+    } else {
+        (*i)->set_param_bool ("areaDrawing", FALSE);
+    }
+
+    if (sp_export_area_canvas) {
+        if (sp_export_eps) {
+            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.");
+        } 
+        (*i)->set_param_bool ("areaCanvas", TRUE);
+    } else {
+        (*i)->set_param_bool ("areaCanvas", FALSE);
     }
 
-    try {
-        old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
-        (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
+    if (!sp_export_area_drawing && !sp_export_area_canvas && !sp_export_id) { 
+        // neither is set, set canvas as default for ps/pdf and drawing for eps
+        if (sp_export_eps) {
+            try {
+               (*i)->set_param_bool("areaDrawing", TRUE);
+            } catch (...) {}
+        } 
     }
-    catch (...) {
-        g_warning ("Could not set export-bbox-page option for this export.");
+
+    if (sp_export_text_to_path) {
+        (*i)->set_param_bool("textToPath", TRUE);
+    } else {
+        (*i)->set_param_bool("textToPath", FALSE);
+    }
+
+    if (sp_export_ignore_filters) {
+        (*i)->set_param_bool("blurToBitmap", FALSE);
+    } else {
+        (*i)->set_param_bool("blurToBitmap", TRUE);
     }
 
     (*i)->save(doc, uri);
+}
 
-    try {
-        (*i)->set_param_bool("textToPath", old_text_to_path);
-        (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
+#ifdef WIN32
+/**
+ *  Export a document to EMF
+ *
+ *  \param doc Document to export.
+ *  \param uri URI to export to.
+ *  \param mime MIME type to export as (should be "image/x-emf")
+ */
+
+static void do_export_emf(SPDocument* doc, gchar const* uri, char const* mime)
+{
+    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++;
     }
-    catch (...) {
 
+    if (i == o.end())
+    {
+        g_warning ("Could not find an extension to export to MIME type %s.", mime);
+        return;
     }
+
+    (*i)->save(doc, uri);
 }
+#endif //WIN32
 
 #ifdef WIN32
 bool replaceArgs( int& argc, char**& argv )
@@ -1329,11 +1546,13 @@ bool replaceArgs( int& argc, char**& argv )
                 if ( wildcarded )
                 {
 #ifdef REPLACEARGS_ANSI
-                    WIN32_FIND_DATAA data = {0};
+                    WIN32_FIND_DATAA data;
 #else
-                    WIN32_FIND_DATAW data = {0};
+                    WIN32_FIND_DATAW data;
 #endif // REPLACEARGS_ANSI
 
+                    memset((void *)&data, 0, sizeof(data));
+
                     int baseLen = wcslen(parsed[i1]) + 2;
                     wchar_t* base = new wchar_t[baseLen];
                     wcsncpy( base, parsed[i1], baseLen );
@@ -1495,7 +1714,7 @@ sp_process_args(poptContext ctx)
     GSList *fl = NULL;
 
     gint a;
-    while ((a = poptGetNextOpt(ctx)) >= 0) {
+    while ((a = poptGetNextOpt(ctx)) != -1) {
         switch (a) {
             case SP_ARG_FILE: {
                 gchar const *fn = poptGetOptArg(ctx);
@@ -1505,7 +1724,7 @@ sp_process_args(poptContext ctx)
                 break;
             }
             case SP_ARG_VERSION: {
-                printf("Inkscape %s (%s)\n", INKSCAPE_VERSION, __DATE__);
+                printf("Inkscape %s (%s)\n", Inkscape::version_string, __DATE__);
                 exit(0);
                 break;
             }
@@ -1514,6 +1733,30 @@ sp_process_args(poptContext ctx)
                 exit(0);
                 break;
             }
+            case SP_ARG_VERB_LIST: {
+                // This really shouldn't go here, we should init the app.
+                // But, since we're just exiting in this path, there is
+                // no harm, and this is really a better place to put
+                // everything else.
+                Inkscape::Extension::init();
+                Inkscape::Verb::list();
+                exit(0);
+                break;
+            }
+            case SP_ARG_VERB:
+            case SP_ARG_SELECT: {
+                gchar const *arg = poptGetOptArg(ctx);
+                if (arg != NULL) {
+                    // printf("Adding in: %s\n", arg);
+                    new Inkscape::CmdLineAction((a == SP_ARG_VERB), arg);
+                }
+                break;
+            }
+            case POPT_ERROR_BADOPT: {
+                g_warning ("Invalid option %s", poptBadOption(ctx, 0));
+                exit(1);
+                break;
+            }
             default: {
                 break;
             }