Code

Fix self-snapping when dragging the transformation center of a selection containing...
[inkscape.git] / src / inkscape.cpp
index c2c45d3bbc0bb60a5cb86f8b705a1e590bcf6c57..c10581a9161e683a7cf052b0b68b43df7fe41965 100644 (file)
@@ -49,14 +49,14 @@ using Inkscape::Extension::Internal::PrintWin32;
 #include "application/editor.h"
 #include "desktop.h"
 #include "desktop-handles.h"
-#include "dialogs/input.h"
+#include "device-manager.h"
 #include "document.h"
 #include "event-context.h"
 #include "extension/db.h"
 #include "extension/init.h"
 #include "extension/output.h"
 #include "extension/system.h"
-#include "helper/sp-marshal.h"
+//#include "helper/sp-marshal.h"
 #include "inkscape-private.h"
 #include "io/sys.h"
 #include "message-stack.h"
@@ -105,7 +105,7 @@ static void inkscape_deactivate_desktop_private (Inkscape::Application *inkscape
 struct Inkscape::Application {
     GObject object;
     Inkscape::XML::Document *menus;
-    std::map<Document *, int> document_set;
+    std::map<SPDocument *, int> document_set;
     GSList *desktops;
     gchar *argv0;
     gboolean dialogs_toggle;
@@ -126,7 +126,7 @@ struct Inkscape::ApplicationClass {
     void (* set_eventcontext) (Inkscape::Application * inkscape, SPEventContext * eventcontext);
     void (* activate_desktop) (Inkscape::Application * inkscape, SPDesktop * desktop);
     void (* deactivate_desktop) (Inkscape::Application * inkscape, SPDesktop * desktop);
-    void (* destroy_document) (Inkscape::Application *inkscape, Document *doc);
+    void (* destroy_document) (Inkscape::Application *inkscape, SPDocument *doc);
     void (* color_set) (Inkscape::Application *inkscape, SPColor *color, double opacity);
     void (* shut_down) (Inkscape::Application *inkscape);
     void (* dialogs_hide) (Inkscape::Application *inkscape);
@@ -193,7 +193,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
                                G_SIGNAL_RUN_FIRST,
                                G_STRUCT_OFFSET (Inkscape::ApplicationClass, modify_selection),
                                NULL, NULL,
-                               sp_marshal_NONE__POINTER_UINT,
+                               g_cclosure_marshal_VOID__UINT_POINTER,
                                G_TYPE_NONE, 2,
                                G_TYPE_POINTER, G_TYPE_UINT);
     inkscape_signals[CHANGE_SELECTION] = g_signal_new ("change_selection",
@@ -201,7 +201,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
                                G_SIGNAL_RUN_FIRST,
                                G_STRUCT_OFFSET (Inkscape::ApplicationClass, change_selection),
                                NULL, NULL,
-                               sp_marshal_NONE__POINTER,
+                               g_cclosure_marshal_VOID__POINTER,
                                G_TYPE_NONE, 1,
                                G_TYPE_POINTER);
     inkscape_signals[CHANGE_SUBSELECTION] = g_signal_new ("change_subselection",
@@ -209,7 +209,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
                                G_SIGNAL_RUN_FIRST,
                                G_STRUCT_OFFSET (Inkscape::ApplicationClass, change_subselection),
                                NULL, NULL,
-                               sp_marshal_NONE__POINTER,
+                               g_cclosure_marshal_VOID__POINTER,
                                G_TYPE_NONE, 1,
                                G_TYPE_POINTER);
     inkscape_signals[SET_SELECTION] =    g_signal_new ("set_selection",
@@ -217,7 +217,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
                                G_SIGNAL_RUN_FIRST,
                                G_STRUCT_OFFSET (Inkscape::ApplicationClass, set_selection),
                                NULL, NULL,
-                               sp_marshal_NONE__POINTER,
+                               g_cclosure_marshal_VOID__POINTER,
                                G_TYPE_NONE, 1,
                                G_TYPE_POINTER);
     inkscape_signals[SET_EVENTCONTEXT] = g_signal_new ("set_eventcontext",
@@ -225,7 +225,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
                                G_SIGNAL_RUN_FIRST,
                                G_STRUCT_OFFSET (Inkscape::ApplicationClass, set_eventcontext),
                                NULL, NULL,
-                               sp_marshal_NONE__POINTER,
+                               g_cclosure_marshal_VOID__POINTER,
                                G_TYPE_NONE, 1,
                                G_TYPE_POINTER);
     inkscape_signals[ACTIVATE_DESKTOP] = g_signal_new ("activate_desktop",
@@ -233,7 +233,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
                                G_SIGNAL_RUN_FIRST,
                                G_STRUCT_OFFSET (Inkscape::ApplicationClass, activate_desktop),
                                NULL, NULL,
-                               sp_marshal_NONE__POINTER,
+                               g_cclosure_marshal_VOID__POINTER,
                                G_TYPE_NONE, 1,
                                G_TYPE_POINTER);
     inkscape_signals[DEACTIVATE_DESKTOP] = g_signal_new ("deactivate_desktop",
@@ -241,7 +241,7 @@ inkscape_class_init (Inkscape::ApplicationClass * klass)
                                G_SIGNAL_RUN_FIRST,
                                G_STRUCT_OFFSET (Inkscape::ApplicationClass, deactivate_desktop),
                                NULL, NULL,
-                               sp_marshal_NONE__POINTER,
+                               g_cclosure_marshal_VOID__POINTER,
                                G_TYPE_NONE, 1,
                                G_TYPE_POINTER);
     inkscape_signals[SHUTDOWN_SIGNAL] =        g_signal_new ("shut_down",
@@ -326,11 +326,11 @@ static gint inkscape_autosave(gpointer)
     gint docnum = 0;
 
     SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Autosaving documents..."));
-    for (std::map<Document*,int>::iterator iter = inkscape->document_set.begin();
+    for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
           iter != inkscape->document_set.end();
           ++iter) {
 
-        Document *doc = iter->first;
+        SPDocument *doc = iter->first;
 
         ++docnum;
 
@@ -463,7 +463,7 @@ inkscape_init (SPObject * object)
         g_assert_not_reached ();
     }
 
-    new (&inkscape->document_set) std::map<Document *, int>();
+    new (&inkscape->document_set) std::map<SPDocument *, int>();
 
     inkscape->menus = sp_repr_read_mem (_(menus_skeleton), MENUS_SKELETON_SIZE, NULL);
     inkscape->desktops = NULL;
@@ -595,58 +595,68 @@ inkscape_crash_handler (int /*signum*/)
     strftime (sptstr, 256, "%Y_%m_%d_%H_%M_%S", sptm);
 
     gint count = 0;
+    gchar *curdir = g_get_current_dir(); // This one needs to be freed explicitly
+    gchar *inkscapedir = g_path_get_dirname(INKSCAPE->argv0); // Needs to be freed
     GSList *savednames = NULL;
     GSList *failednames = NULL;
-    for (std::map<Document*,int>::iterator iter = inkscape->document_set.begin();
+    for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
           iter != inkscape->document_set.end();
           ++iter) {
-        Document *doc = iter->first;
+        SPDocument *doc = iter->first;
         Inkscape::XML::Node *repr;
         repr = sp_document_repr_root (doc);
         if (doc->isModifiedSinceSave()) {
-            const gchar *docname, *d0, *d;
-            gchar n[64], c[1024];
-            FILE *file;
+            const gchar *docname;
 
             /* originally, the document name was retrieved from
              * the sodipod:docname attribute */
             docname = doc->name;
             if (docname) {
-                /* fixme: Quick hack to remove emergency file suffix */
-                d0 = strrchr ((char*)docname, '.');
+                /* Removes an emergency save suffix if present: /(.*)\.[0-9_]*\.[0-9_]*\.[~\.]*$/\1/ */
+                const char* d0 = strrchr ((char*)docname, '.');
                 if (d0 && (d0 > docname)) {
-                    d0 = strrchr ((char*)(d0 - 1), '.');
-                    if (d0 && (d0 > docname)) {
-                        d = d0;
-                        while (isdigit (*d) || (*d == '.') || (*d == '_')) d += 1;
-                        if (*d) {
-                            memcpy (n, docname, MIN (d0 - docname - 1, 64));
-                            n[63] = '\0';
-                            docname = n;
-                        }
+                    const char* d = d0;
+                    unsigned int dots = 0;
+                    while ((isdigit (*d) || *d=='_' || *d=='.') && d>docname && dots<2) {
+                        d -= 1;
+                        if (*d=='.') dots++;
+                    }
+                    if (*d=='.' && d>docname && dots==2) {
+                        char n[64];
+                        size_t len = MIN (d - docname, 63);
+                        memcpy (n, docname, len);
+                        n[len] = '\0';
+                        docname = n;
                     }
                 }
             }
-
             if (!docname || !*docname) docname = "emergency";
-            // try saving to the profile location
+
+            // Emergency filename
+            char c[1024];
             g_snprintf (c, 1024, "%.256s.%s.%d.svg", docname, sptstr, count);
-            gchar * location = homedir_path(c);
-            Inkscape::IO::dump_fopen_call(location, "E");
-            file = Inkscape::IO::fopen_utf8name(location, "w");
-            g_free(location);
-            if (!file) {
-                // try saving to /tmp
-                g_snprintf (c, 1024, "/tmp/inkscape-%.256s.%s.%d.svg", docname, sptstr, count);
-                Inkscape::IO::dump_fopen_call(c, "G");
-                file = Inkscape::IO::fopen_utf8name(c, "w");
-            }
-            if (!file) {
-                // try saving to the current directory
-                g_snprintf (c, 1024, "inkscape-%.256s.%s.%d.svg", docname, sptstr, count);
-                Inkscape::IO::dump_fopen_call(c, "F");
-                file = Inkscape::IO::fopen_utf8name(c, "w");
+
+            // Find a location
+            const char* locations[] = {
+                doc->base,
+                g_get_home_dir(),
+                g_get_tmp_dir(),
+                curdir,
+                inkscapedir
+            };
+            FILE *file = 0;
+            for(size_t i=0; i<sizeof(locations)/sizeof(*locations); i++) {
+                if (!locations[i]) continue; // It seems to be okay, but just in case
+                gchar * filename = g_build_filename(locations[i], c, NULL);
+                Inkscape::IO::dump_fopen_call(filename, "E");
+                file = Inkscape::IO::fopen_utf8name(filename, "w");
+                if (file) {
+                    g_snprintf (c, 1024, "%s", filename); // we want the complete path to be stored in c (for reporting purposes)
+                    break;
+                }
             }
+
+            // Save
             if (file) {
                 sp_repr_save_stream (repr->document(), file, SP_SVG_NS_URI);
                 savednames = g_slist_prepend (savednames, g_strdup (c));
@@ -657,6 +667,8 @@ inkscape_crash_handler (int /*signum*/)
             count++;
         }
     }
+    g_free(curdir);
+    g_free(inkscapedir);
 
     savednames = g_slist_reverse (savednames);
     failednames = g_slist_reverse (failednames);
@@ -799,8 +811,10 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui)
         }
     }
 
-    inkscape_load_menus(inkscape);
-    sp_input_load_from_preferences();
+    if (use_gui) {
+        inkscape_load_menus(inkscape);
+        Inkscape::DeviceManager::getManager().loadConfig();
+    }
 
     /* set language for user interface according setting in preferences */
     Glib::ustring ui_language = prefs->getString("/ui/language");
@@ -1219,7 +1233,7 @@ inkscape_external_change ()
  * fixme: These need probably signals too
  */
 void
-inkscape_add_document (Document *document)
+inkscape_add_document (SPDocument *document)
 {
     g_return_if_fail (document != NULL);
 
@@ -1228,7 +1242,7 @@ inkscape_add_document (Document *document)
         // try to insert the pair into the list
         if (!(inkscape->document_set.insert(std::make_pair(document, 1)).second)) {
             //insert failed, this key (document) is already in the list
-            for (std::map<Document*,int>::iterator iter = inkscape->document_set.begin();
+            for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
                    iter != inkscape->document_set.end();
                    ++iter) {
                 if (iter->first == document) {
@@ -1247,13 +1261,13 @@ inkscape_add_document (Document *document)
 
 // returns true if this was last reference to this document, so you can delete it
 bool
-inkscape_remove_document (Document *document)
+inkscape_remove_document (SPDocument *document)
 {
     g_return_val_if_fail (document != NULL, false);
 
     if (!Inkscape::NSApplication::Application::getNewGui())
     {
-        for (std::map<Document*,int>::iterator iter = inkscape->document_set.begin();
+        for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
                   iter != inkscape->document_set.end();
                   ++iter) {
             if (iter->first == document) {
@@ -1290,7 +1304,7 @@ inkscape_active_desktop (void)
     return (SPDesktop *) inkscape->desktops->data;
 }
 
-Document *
+SPDocument *
 inkscape_active_document (void)
 {
     if (Inkscape::NSApplication::Application::getNewGui())
@@ -1304,13 +1318,13 @@ inkscape_active_document (void)
 }
 
 bool inkscape_is_sole_desktop_for_document(SPDesktop const &desktop) {
-    Document const* document = desktop.doc();
+    SPDocument const* document = desktop.doc();
     if (!document) {
         return false;
     }
     for ( GSList *iter = inkscape->desktops ; iter ; iter = iter->next ) {
         SPDesktop *other_desktop=(SPDesktop *)iter->data;
-        Document *other_document=other_desktop->doc();
+        SPDocument *other_document=other_desktop->doc();
         if ( other_document == document && other_desktop != &desktop ) {
             return false;
         }
@@ -1449,6 +1463,7 @@ profile_path(const char *filename)
             if (needsMigration) {
                 // TODO here is a point to hook in preference migration
                 g_warning("Preferences need to be migrated from 0.46 or older %s to %s", legacyDir, prefdir);
+                Inkscape::Preferences::migrate( legacyDir, prefdir );
             }
 
             bool needsRenameWarning = ( !Inkscape::IO::file_test( prefdir, G_FILE_TEST_EXISTS ) && Inkscape::IO::file_test( dev47Dir, G_FILE_TEST_EXISTS ) );
@@ -1474,6 +1489,13 @@ profile_path(const char *filename)
             if ( g_mkdir_with_parents(prefdir, mode) == -1 ) {
                 int problem = errno;
                 g_warning("Unable to create profile directory (%s) (%d)", g_strerror(problem), problem);
+            } else {
+                gchar const *userDirs[] = {"keys", "templates", "icons", "extensions", "palettes", NULL};
+                for (gchar const** name = userDirs; *name; ++name) {
+                    gchar *dir = g_build_filename(prefdir, *name, NULL);
+                    g_mkdir_with_parents(dir, mode);
+                    g_free(dir);
+                }
             }
         }
     }