Code

NR::Maybe => boost::optional
[inkscape.git] / src / main.cpp
index 60050c461adc326e74bc287392315da0b6492b89..d6f0ae9e827a49c93d7257673ed8db6da96061dd 100644 (file)
@@ -33,7 +33,8 @@
 #ifdef HAVE_IEEEFP_H
 #include <ieeefp.h>
 #endif
-#include <string.h>
+#include <cstring>
+#include <string>
 #include <locale.h>
 
 #include <popt.h>
@@ -48,8 +49,6 @@
 #include <gtk/gtkwindow.h>
 #include <gtk/gtkbox.h>
 
-#include <gtk/gtkmain.h>
-
 #include "gc-core.h"
 
 #include "macros.h"
@@ -58,7 +57,6 @@
 #include "sp-object.h"
 #include "interface.h"
 #include "print.h"
-#include "slideshow.h"
 #include "color.h"
 #include "sp-item.h"
 #include "sp-root.h"
@@ -80,6 +78,7 @@
 #include "io/sys.h"
 
 #include "debug/logger.h"
+#include "debug/log-display-config.h"
 
 #include "helper/png-write.h"
 
@@ -110,6 +109,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,
@@ -133,17 +137,25 @@ enum {
     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_FONT,
     SP_ARG_EXPORT_BBOX_PAGE,
     SP_ARG_EXTENSIONDIR,
-    SP_ARG_SLIDESHOW,
+    SP_ARG_FIT_PAGE_TO_DRAWING,
     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_VERSION,
     SP_ARG_VACUUM_DEFS,
+    SP_ARG_VERB_LIST,
+    SP_ARG_VERB,
+    SP_ARG_SELECT,
     SP_ARG_LAST
 };
 
@@ -152,11 +164,14 @@ 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_export_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, NR::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;
@@ -174,12 +189,17 @@ 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_font = 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 gboolean sp_query_all = FALSE;
 static gchar *sp_query_id = NULL;
 static int sp_new_gui = FALSE;
 static gboolean sp_vacuum_defs = FALSE;
@@ -305,11 +325,23 @@ struct poptOption options[] = {
      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)"),
      NULL},
 
+    {"export-embed-fonts", 'F',
+     POPT_ARG_NONE, &sp_export_font, SP_ARG_EXPORT_FONT,
+     N_("Embed fonts on export (Type 1 only) (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)"),
@@ -339,6 +371,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"),
@@ -350,22 +387,97 @@ 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"),
-     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},
 
+    {"verb-list", 0,
+     POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
+     N_("List the IDs of all the verbs in Inkscape"),
+     NULL},
+
+    {"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")},
+
     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
+
+
+
+/**
+ * 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)
 {
@@ -376,13 +488,30 @@ 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
+
+   /**
+    * 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(""));
@@ -390,6 +519,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");
@@ -405,21 +540,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 */
@@ -444,10 +568,16 @@ main(int argc, char **argv)
             || !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")
@@ -480,6 +610,9 @@ main(int argc, char **argv)
     return app.run();
 }
 
+
+
+
 void fixupSingleFilename( gchar **orig, gchar **spare )
 {
     if ( orig && *orig && **orig ) {
@@ -496,6 +629,8 @@ void fixupSingleFilename( gchar **orig, gchar **spare )
     }
 }
 
+
+
 GSList *fixupFilenameEncoding( GSList* fl )
 {
     GSList *newFl = NULL;
@@ -595,6 +730,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)
 {
@@ -606,6 +769,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))) {
@@ -614,34 +781,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
@@ -698,7 +853,7 @@ sp_main_console(int argc, char const **argv)
             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) {
@@ -706,7 +861,7 @@ 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) {
@@ -718,12 +873,20 @@ sp_main_console(int argc, char const **argv)
             if (sp_export_pdf) {
                 do_export_pdf(doc, sp_export_pdf, "application/pdf");
             }
-            if (sp_query_width || sp_query_height) {
+#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? 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);
     }
 
@@ -755,15 +918,57 @@ do_query_dimension (SPDocument *doc, bool extent, NR::Dim2 const axis, const gch
     if (o) {
         sp_document_ensure_up_to_date (doc);
         SPItem *item = ((SPItem *) o);
-        NR::Rect area = item->invokeBbox(sp_item_i2doc_affine(item)); // "true" SVG bbox for scripting
 
-        Inkscape::SVGOStringStream os;
-        if (extent) {
-            os << area.extent(axis);
+        // "true" SVG bbox for scripting
+        boost::optional<NR::Rect> area = item->getBounds(from_2geom(sp_item_i2doc_affine(item)));
+        if (area) {
+            Inkscape::SVGOStringStream os;
+            if (extent) {
+                os << area->extent(axis);
+            } else {
+                os << area->min()[axis];
+            }
+            g_print ("%s", os.str().c_str());
         } else {
-            os << area.min()[axis];
+            g_print("0");
+        }
+    }
+}
+
+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)) {
+        boost::optional<NR::Rect> area = item->getBounds(from_2geom(sp_item_i2doc_affine(item)));
+        if (area) {
+            Inkscape::SVGOStringStream os;
+            os << o->id;
+            os << "," << area->min()[NR::X];
+            os << "," << area->min()[NR::Y];
+            os << "," << area->extent(NR::X);
+            os << "," << area->extent(NR::Y);
+            g_print ("%s\n", os.str().c_str());
         }
-        g_print ("%s", os.str().c_str());
+    }
+
+    SPObject *child = o->children;
+    while (child) {
+        do_query_all_recurse (child);
+        child = child->next;
     }
 }
 
@@ -794,7 +999,7 @@ sp_do_export_png(SPDocument *doc)
         } else if (sp_export_area_drawing) {
             o = SP_DOCUMENT_ROOT (doc);
             o_area = o;
-        } 
+        }
 
         if (o) {
             if (!SP_IS_ITEM (o)) {
@@ -840,13 +1045,13 @@ 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, &area, sp_item_i2r_affine((SPItem *) o_area), TRUE);
+            sp_item_invoke_bbox((SPItem *) o_area, &area, from_2geom(sp_item_i2r_affine((SPItem *) o_area)), TRUE);
         } else {
             g_warning("Object with id=\"%s\" was not found in the document. Nothing exported.", sp_export_id);
             return;
         }
     }
-    
+
     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) {
@@ -895,33 +1100,33 @@ sp_do_export_png(SPDocument *doc)
     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);
+        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);
     }
 
     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);
+        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);
     }
 
     if (!sp_export_width) {
-        width = (gint) ((area.x1 - area.x0) * dpi / PX_PER_IN + 0.5);
+        width = (unsigned long int) ((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);
+        height = (unsigned long int) ((area.y1 - area.y0) * dpi / PX_PER_IN + 0.5);
     }
 
     guint32 bgcolor = 0x00000000;
@@ -956,14 +1161,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.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)) {
+    if ((width >= 1) && (height >= 1) && (width <= PNG_UINT_31_MAX) && (height <= PNG_UINT_31_MAX)) {
         sp_export_png_file(doc, filename, area.x0, area.y0, area.x1, area.y1, 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);
@@ -989,11 +1194,12 @@ 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_font_embedded = false;
     bool old_bbox_page = false;
 
     try {
@@ -1004,6 +1210,14 @@ static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
         g_warning ("Could not set export-text-to-path option for this export.");
     }
 
+    try {
+        old_font_embedded = (*i)->get_param_bool("fontEmbedded");
+        (*i)->set_param_bool("fontEmbedded", sp_export_font);
+    }
+    catch (...) {
+        g_warning ("Could not set export-font option for this export.");
+    }
+
     try {
         old_bbox_page = (*i)->get_param_bool("pageBoundingBox");
         (*i)->set_param_bool("pageBoundingBox", sp_export_bbox_page);
@@ -1016,6 +1230,7 @@ static void do_export_ps(SPDocument* doc, gchar const* uri, char const* mime)
 
     try {
         (*i)->set_param_bool("textToPath", old_text_to_path);
+        (*i)->set_param_bool("fontEmbedded", old_font_embedded);
         (*i)->set_param_bool("pageBoundingBox", old_bbox_page);
     }
     catch (...) {
@@ -1042,12 +1257,69 @@ static void do_export_pdf(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;
+    }
+
+    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", "");
+    }
+
+    if (sp_export_area_drawing) {
+        (*i)->set_param_bool ("exportDrawing", TRUE);
+    } else {
+        (*i)->set_param_bool ("exportDrawing", FALSE);
+    }
+
+    if (sp_export_area_canvas) {
+        (*i)->set_param_bool ("exportCanvas", TRUE);
+    } else {
+        (*i)->set_param_bool ("exportCanvas", FALSE);
+    }
+
+    if (sp_export_text_to_path) {
+        (*i)->set_param_bool("textToPath", TRUE);
+    } else {
+        (*i)->set_param_bool("textToPath", FALSE);
+    }
+
+    (*i)->save(doc, uri);
+}
+
+#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++;
+    }
+
+    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 )
@@ -1163,11 +1435,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 );
@@ -1348,6 +1622,25 @@ 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;
+            }
             default: {
                 break;
             }