Code

SPDocument->Document
[inkscape.git] / src / main.cpp
index b9e5a98e2f4f39ae1afaec9c5b4f5dfd77fee4a9..64fcb664dd431985aa5c35cbab3da214454d1dda 100644 (file)
@@ -28,6 +28,9 @@
 #endif
 #include "path-prefix.h"
 
+// This has to be included prior to anything that includes setjmp.h, it croaks otherwise
+#include <png.h>
+
 #include <gtk/gtkmessagedialog.h>
 
 #ifdef HAVE_IEEEFP_H
@@ -45,6 +48,7 @@
 
 #include <libxml/tree.h>
 #include <glib-object.h>
+#include <gtk/gtk.h>
 #include <gtk/gtkmain.h>
 #include <gtk/gtksignal.h>
 #include <gtk/gtkwindow.h>
@@ -113,8 +117,6 @@ using Inkscape::Extension::Internal::PrintWin32;
 #include "widgets/icon.h"
 #include "ui/widget/panel.h"
 
-
-#include <png.h>
 #include <errno.h>
 
 enum {
@@ -163,13 +165,13 @@ enum {
 
 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_pdf(SPDocument* doc, gchar const* uri, char const *mime);
+static void sp_do_export_png(Document *doc);
+static void do_export_ps_pdf(Document* doc, gchar const* uri, char const *mime);
 #ifdef WIN32
-static void do_export_emf(SPDocument* doc, gchar const* uri, char const *mime);
+static void do_export_emf(Document* 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_dimension (Document *doc, bool extent, Geom::Dim2 const axis, const gchar *id);
+static void do_query_all (Document *doc);
 static void do_query_all_recurse (SPObject *o);
 
 static gchar *sp_global_printer = NULL;
@@ -289,7 +291,7 @@ struct poptOption options[] = {
 
     {"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_("Resolution for exporting to bitmap and for rasterization of filters in PS/EPS/PDF (default 90)"),
      N_("DPI")},
 
     {"export-area", 'a',
@@ -448,7 +450,7 @@ struct poptOption options[] = {
 
     {"shell", 0,
      POPT_ARG_NONE, &sp_shell, SP_ARG_SHELL,
-     N_("Start Inkscape in interative shell mode."),
+     N_("Start Inkscape in interactive shell mode."),
      NULL},
 
     POPT_AUTOHELP POPT_TABLEEND
@@ -467,10 +469,12 @@ gchar * blankParam = g_strdup("");
 static Glib::ustring _win32_getExePath()
 {
     char exeName[MAX_PATH+1];
+    // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
     GetModuleFileName(NULL, exeName, MAX_PATH);
     char *slashPos = strrchr(exeName, '\\');
-    if (slashPos)
+    if (slashPos) {
         *slashPos = '\0';
+    }
     Glib::ustring s = exeName;
     return s;
 }
@@ -481,6 +485,7 @@ static Glib::ustring _win32_getExePath()
  */
 static int _win32_set_inkscape_env(const Glib::ustring &exePath)
 {
+    // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
 
     char *oldenv = getenv("PATH");
     Glib::ustring tmp = "PATH=";
@@ -529,7 +534,7 @@ static int set_extensions_env()
         tmp += oldenv;
     }
     g_setenv("PYTHONPATH", tmp.c_str(), TRUE);
-    
+
     return 0;
 }
 
@@ -557,6 +562,7 @@ main(int argc, char **argv)
       HKCR\svgfile\shell\open\command is a good example
     */
     Glib::ustring homedir = _win32_getExePath();
+    // TODO these should use xxxW() calls explicitly and convert UTF-16 <--> UTF-8
     SetCurrentDirectory(homedir.c_str());
     _win32_set_inkscape_env(homedir);
     RegistryTool rt;
@@ -608,6 +614,7 @@ main(int argc, char **argv)
     gboolean use_gui;
 
 #ifndef WIN32
+    // TODO use g_getenv() and g_setenv() that use filename encoding, which is UTF-8 on Windows
     use_gui = (getenv("DISPLAY") != NULL);
 #else
     use_gui = TRUE;
@@ -799,7 +806,7 @@ int sp_common_main( int argc, char const **argv, GSList **flDest )
 
 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 */
+    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) {
@@ -822,9 +829,69 @@ snooper(GdkEvent *event, gpointer /*data*/) {
             break;
         }
     }
+
+    if (inkscape_trackalt()) {
+        // MacOS X with X11 has some problem with the default
+        // xmodmapping.  A ~/.xmodmap solution does not work reliably due
+        // to the way we package our executable in a .app that can launch
+        // X11 or use an already-running X11.  The same problem has been
+        // reported on Linux but there is no .app/X11 to get in the way
+        // of ~/.xmodmap fixes.  So we make this a preference.
+        //
+        // For some reason, Gdk senses changes in Alt (Mod1) state for
+        // many message types, but not for keystrokes!  So this ugly hack
+        // tracks what the state of Alt-pressing is, and ensures
+        // GDK_MOD1_MASK is in the event->key.state as appropriate.
+        //
+        static gboolean altL_pressed = FALSE;
+        static gboolean altR_pressed = FALSE;
+        static gboolean alt_pressed = FALSE;
+        guint get_group0_keyval(GdkEventKey* event);
+        guint keyval = 0;
+        switch (event->type) {
+        case GDK_MOTION_NOTIFY:
+            alt_pressed = TRUE && (event->motion.state & GDK_MOD1_MASK);
+            break;
+        case GDK_BUTTON_PRESS:
+            alt_pressed = TRUE && (event->button.state & GDK_MOD1_MASK);
+            break;
+        case GDK_KEY_PRESS:
+            keyval = get_group0_keyval(&event->key);
+            if (keyval == GDK_Alt_L) altL_pressed = TRUE;
+            if (keyval == GDK_Alt_R) altR_pressed = TRUE;
+            alt_pressed = alt_pressed || altL_pressed || altR_pressed;
+            alt_pressed = alt_pressed || (event->button.state & GDK_MOD1_MASK);
+            if (alt_pressed)
+                event->key.state |= GDK_MOD1_MASK;
+            else
+                event->key.state &= ~GDK_MOD1_MASK;
+            break;
+        case GDK_KEY_RELEASE:
+            keyval = get_group0_keyval(&event->key);
+            if (keyval == GDK_Alt_L) altL_pressed = FALSE;
+            if (keyval == GDK_Alt_R) altR_pressed = FALSE;
+            if (!altL_pressed && !altR_pressed)
+                alt_pressed = FALSE;
+            break;
+        default:
+            break;
+        }
+        //printf("alt_pressed: %s\n", alt_pressed? "+" : "-");
+    }
+
     gtk_main_do_event (event);
 }
 
+static std::vector<Glib::ustring> getDirectorySet(const gchar* userDir, const gchar* const * systemDirs) {
+    std::vector<Glib::ustring> listing;
+    listing.push_back(userDir);
+    for ( const char* const* cur = systemDirs; *cur; cur++ )
+    {
+        listing.push_back(*cur);
+    }
+    return listing;
+}
+
 int
 sp_main_gui(int argc, char const **argv)
 {
@@ -834,8 +901,24 @@ sp_main_gui(int argc, char const **argv)
     int retVal = sp_common_main( argc, argv, &fl );
     g_return_val_if_fail(retVal == 0, 1);
 
+    // Add possible icon entry directories
+    std::vector<Glib::ustring> dataDirs = getDirectorySet( g_get_user_data_dir(),
+                                                           g_get_system_data_dirs() );
+    for (std::vector<Glib::ustring>::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it)
+    {
+        std::vector<Glib::ustring> listing;
+        listing.push_back(*it);
+        listing.push_back("inkscape");
+        listing.push_back("icons");
+        Glib::ustring dir = Glib::build_filename(listing);
+        gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), dir.c_str());
+    }
+
     // Add our icon directory to the search path for icon theme lookups.
+    gchar *usericondir = profile_path("icons");
+    gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), usericondir);
     gtk_icon_theme_append_search_path(gtk_icon_theme_get_default(), INKSCAPE_PIXMAPDIR);
+    g_free(usericondir);
 
     gdk_event_handler_set((GdkEventFunc)snooper, NULL, NULL);
     Inkscape::Debug::log_display_config();
@@ -879,7 +962,7 @@ void sp_process_file_list(GSList *fl)
 {
     while (fl) {
         const gchar *filename = (gchar *)fl->data;
-        SPDocument *doc = Inkscape::Extension::open(NULL, filename);
+        Document *doc = Inkscape::Extension::open(NULL, filename);
         if (doc == NULL) {
             doc = Inkscape::Extension::open(Inkscape::Extension::db.get(SP_MODULE_KEY_INPUT_SVG), filename);
         }
@@ -905,7 +988,8 @@ void sp_process_file_list(GSList *fl)
                 rdoc = sp_repr_document_new("svg:svg");
                 repr = rdoc->root();
                 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);
+                sp_repr_save_rebased_file(repr->document(), sp_export_svg, SP_SVG_NS_URI,
+                                          doc->base, sp_export_svg);
             }
             if (sp_export_ps) {
                 do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript");
@@ -1043,7 +1127,7 @@ int sp_main_console(int argc, char const **argv)
 }
 
 static void
-do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const gchar *id)
+do_query_dimension (Document *doc, bool extent, Geom::Dim2 const axis, const gchar *id)
 {
     SPObject *o = NULL;
 
@@ -1083,7 +1167,7 @@ do_query_dimension (SPDocument *doc, bool extent, Geom::Dim2 const axis, const g
 }
 
 static void
-do_query_all (SPDocument *doc)
+do_query_all (Document *doc)
 {
     SPObject *o = NULL;
 
@@ -1121,7 +1205,7 @@ do_query_all_recurse (SPObject *o)
 
 
 static void
-sp_do_export_png(SPDocument *doc)
+sp_do_export_png(Document *doc)
 {
     const gchar *filename = NULL;
     gdouble dpi = 0.0;
@@ -1333,7 +1417,7 @@ sp_do_export_png(SPDocument *doc)
  *  \param mime MIME type to export as.
  */
 
-static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime)
+static void do_export_ps_pdf(Document* doc, gchar const* uri, char const* mime)
 {
     Inkscape::Extension::DB::OutputList o;
     Inkscape::Extension::db.get_output_list(o);
@@ -1373,19 +1457,19 @@ static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime
     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);
     }
 
-    if (!sp_export_area_drawing && !sp_export_area_canvas && !sp_export_id) { 
+    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 (...) {}
-        } 
+        }
     }
 
     if (sp_export_text_to_path) {
@@ -1398,6 +1482,17 @@ static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime
         (*i)->set_param_bool("blurToBitmap", FALSE);
     } else {
         (*i)->set_param_bool("blurToBitmap", TRUE);
+
+        gdouble dpi = 90.0;
+        if (sp_export_dpi) {
+            dpi = atof(sp_export_dpi);
+            if ((dpi < 1) || (dpi > 10000.0)) {
+                g_warning("DPI value %s out of range [1 - 10000]. Using 90 dpi instead.", sp_export_dpi);
+                dpi = 90;
+            }
+        }
+
+        (*i)->set_param_int("resolution", (int) dpi);
     }
 
     (*i)->save(doc, uri);
@@ -1412,7 +1507,7 @@ static void do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const* mime
  *  \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)
+static void do_export_emf(Document* doc, gchar const* uri, char const* mime)
 {
     Inkscape::Extension::DB::OutputList o;
     Inkscape::Extension::db.get_output_list(o);