diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index 8cd01c226745a702176d442cf896372eabc28110..8b31ba2670a95a78b86350fa20f3498e481b5b23 100644 (file)
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
# include "config.h"
#endif
+#include <errno.h>
#include <map>
#include "debug/simple-event.h"
#include <glibmm/i18n.h>
#include <gtk/gtkmain.h>
#include <gtk/gtkmessagedialog.h>
+#include <gtkmm/messagedialog.h>
#include <signal.h>
#include <string>
-#include "application/application.h"
-#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"
# FORWARD DECLARATIONS
################################*/
-gboolean inkscape_app_use_gui( Inkscape::Application const * app );
-
static void inkscape_class_init (Inkscape::ApplicationClass *klass);
static void inkscape_init (SPObject *object);
static void inkscape_dispose (GObject *object);
gboolean use_gui; // may want to consider a virtual function
// for overriding things like the warning dlg's
guint mapalt;
+ guint trackalt;
};
struct Inkscape::ApplicationClass {
static void (* abrt_handler) (int) = SIG_DFL;
static void (* fpe_handler) (int) = SIG_DFL;
static void (* ill_handler) (int) = SIG_DFL;
+#ifndef WIN32
static void (* bus_handler) (int) = SIG_DFL;
+#endif
-#define INKSCAPE_PROFILE_DIR "Inkscape"
+#define INKSCAPE_PROFILE_DIR "inkscape"
+#define INKSCAPE_PROFILE_DIR_047DEV "Inkscape"
#define INKSCAPE_LEGACY_PROFILE_DIR ".inkscape"
#define MENUS_FILE "menus.xml"
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",
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",
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",
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",
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",
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",
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",
new (&inkscape->document_set) std::map<SPDocument *, int>();
inkscape->menus = sp_repr_read_mem (_(menus_skeleton), MENUS_SKELETON_SIZE, NULL);
-
inkscape->desktops = NULL;
-
inkscape->dialogs_toggle = TRUE;
-
- inkscape->mapalt=GDK_MOD1_MASK;
+ inkscape->mapalt = GDK_MOD1_MASK;
+ inkscape->trackalt = FALSE;
}
static void
}
}
+guint
+inkscape_trackalt() {
+ return inkscape->trackalt;
+}
+
+void inkscape_trackalt(guint trackvalue)
+{
+ inkscape->trackalt = trackvalue;
+}
+
+
static void
inkscape_activate_desktop_private (Inkscape::Application */*inkscape*/, SPDesktop *desktop)
{
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<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
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));
count++;
}
}
+ g_free(curdir);
+ g_free(inkscapedir);
savednames = g_slist_reverse (savednames);
failednames = g_slist_reverse (failednames);
}
}
- Inkscape::Preferences::unload();
+ // do not save the preferences since they can be in a corrupted state
+ Inkscape::Preferences::unload(false);
fprintf (stderr, "Emergency save completed. Inkscape will close now.\n");
fprintf (stderr, "If you can reproduce this crash, please file a bug at www.inkscape.org\n");
}
*(b + pos) = '\0';
- if ( inkscape_get_instance() && inkscape_app_use_gui( inkscape_get_instance() ) ) {
+ if ( inkscape_get_instance() && inkscape_use_gui() ) {
GtkWidget *msgbox = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s", b);
gtk_dialog_run (GTK_DIALOG (msgbox));
gtk_widget_destroy (msgbox);
}
+class InkErrorHandler : public Inkscape::ErrorReporter {
+public:
+ InkErrorHandler(bool useGui) : Inkscape::ErrorReporter(),
+ _useGui(useGui)
+ {}
+ virtual ~InkErrorHandler() {}
+
+ virtual void handleError( Glib::ustring const& primary, Glib::ustring const& secondary ) const
+ {
+ if (_useGui) {
+ Gtk::MessageDialog err(primary, false, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_OK, true);
+ err.set_secondary_text(secondary);
+ err.run();
+ } else {
+ g_message("%s", primary.data());
+ g_message("%s", secondary.data());
+ }
+ }
+
+private:
+ bool _useGui;
+};
void
inkscape_application_init (const gchar *argv0, gboolean use_gui)
inkscape->use_gui = use_gui;
inkscape->argv0 = g_strdup(argv0);
- /* Load the preferences and menus; Later menu layout should be merged into prefs */
+ /* Load the preferences and menus */
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->load(use_gui, false);
- inkscape_load_menus(inkscape);
- sp_input_load_from_preferences();
-
+ InkErrorHandler* handler = new InkErrorHandler(use_gui);
+ prefs->setErrorHandler(handler);
+ {
+ Glib::ustring msg;
+ Glib::ustring secondary;
+ if (prefs->getLastError( msg, secondary )) {
+ handler->handleError(msg, secondary);
+ }
+ }
+
+ if (use_gui) {
+ inkscape_load_menus(inkscape);
+ Inkscape::DeviceManager::getManager().loadConfig();
+ }
+
/* set language for user interface according setting in preferences */
- Glib::ustring i18n = prefs->getString("/i18n/language");
- if(!i18n.empty())
+ Glib::ustring ui_language = prefs->getString("/ui/language");
+ if(!ui_language.empty())
{
- setenv("LANGUAGE", i18n, 1);
+ setenv("LANGUAGE", ui_language, 1);
}
/* DebugDialog redirection. On Linux, default to OFF, on Win32, default to ON.
}
/* Check for global remapping of Alt key */
- if(use_gui)
+ if (use_gui)
{
inkscape_mapalt(guint(prefs->getInt("/options/mapalt/value", 0)));
+ inkscape_trackalt(guint(prefs->getInt("/options/trackalt/value", 0)));
}
/* Initialize the extensions */
return inkscape;
}
-gboolean inkscape_app_use_gui( Inkscape::Application const * app )
+gboolean inkscape_use_gui()
{
- return app->use_gui;
+ return inkscape_get_instance()->use_gui;
}
/**
*/
bool inkscape_load_menus (Inkscape::Application */*inkscape*/)
{
+ // TODO fix that fn is being leaked
gchar *fn = profile_path(MENUS_FILE);
- gchar *menus_xml = NULL; gsize len = 0;
+ gchar *menus_xml = NULL;
+ gsize len = 0;
if (g_file_get_contents(fn, &menus_xml, &len, NULL)) {
// load the menus_xml file
INKSCAPE->menus = sp_repr_read_mem(menus_xml, len, NULL);
g_free(menus_xml);
- if (INKSCAPE->menus) return true;
+ if (INKSCAPE->menus) {
+ return true;
+ }
}
INKSCAPE->menus = sp_repr_read_mem(menus_skeleton, MENUS_SKELETON_SIZE, NULL);
- if (INKSCAPE->menus) return true;
- return false;
+ return (INKSCAPE->menus != 0);
}
void
inkscape_selection_modified (Inkscape::Selection *selection, guint flags)
{
- if (Inkscape::NSApplication::Application::getNewGui()) {
- Inkscape::NSApplication::Editor::selectionModified (selection, flags);
- return;
- }
g_return_if_fail (selection != NULL);
if (DESKTOP_IS_ACTIVE (selection->desktop())) {
void
inkscape_selection_changed (Inkscape::Selection * selection)
{
- if (Inkscape::NSApplication::Application::getNewGui()) {
- Inkscape::NSApplication::Editor::selectionChanged (selection);
- return;
- }
g_return_if_fail (selection != NULL);
if (DESKTOP_IS_ACTIVE (selection->desktop())) {
void
inkscape_subselection_changed (SPDesktop *desktop)
{
- if (Inkscape::NSApplication::Application::getNewGui()) {
- Inkscape::NSApplication::Editor::subSelectionChanged (desktop);
- return;
- }
g_return_if_fail (desktop != NULL);
if (DESKTOP_IS_ACTIVE (desktop)) {
void
inkscape_selection_set (Inkscape::Selection * selection)
{
- if (Inkscape::NSApplication::Application::getNewGui()) {
- Inkscape::NSApplication::Editor::selectionSet (selection);
- return;
- }
g_return_if_fail (selection != NULL);
if (DESKTOP_IS_ACTIVE (selection->desktop())) {
void
inkscape_eventcontext_set (SPEventContext * eventcontext)
{
- if (Inkscape::NSApplication::Application::getNewGui()) {
- Inkscape::NSApplication::Editor::eventContextSet (eventcontext);
- return;
- }
g_return_if_fail (eventcontext != NULL);
g_return_if_fail (SP_IS_EVENT_CONTEXT (eventcontext));
inkscape_add_desktop (SPDesktop * desktop)
{
g_return_if_fail (desktop != NULL);
-
- if (Inkscape::NSApplication::Application::getNewGui())
- {
- Inkscape::NSApplication::Editor::addDesktop (desktop);
- return;
- }
g_return_if_fail (inkscape != NULL);
g_assert (!g_slist_find (inkscape->desktops, desktop));
inkscape_remove_desktop (SPDesktop * desktop)
{
g_return_if_fail (desktop != NULL);
- if (Inkscape::NSApplication::Application::getNewGui())
- {
- Inkscape::NSApplication::Editor::removeDesktop (desktop);
- return;
- }
g_return_if_fail (inkscape != NULL);
g_assert (g_slist_find (inkscape->desktops, desktop));
inkscape_activate_desktop (SPDesktop * desktop)
{
g_return_if_fail (desktop != NULL);
- if (Inkscape::NSApplication::Application::getNewGui())
- {
- Inkscape::NSApplication::Editor::activateDesktop (desktop);
- return;
- }
g_return_if_fail (inkscape != NULL);
if (DESKTOP_IS_ACTIVE (desktop)) {
inkscape_reactivate_desktop (SPDesktop * desktop)
{
g_return_if_fail (desktop != NULL);
- if (Inkscape::NSApplication::Application::getNewGui())
- {
- Inkscape::NSApplication::Editor::reactivateDesktop (desktop);
- return;
- }
g_return_if_fail (inkscape != NULL);
if (DESKTOP_IS_ACTIVE (desktop))
void
inkscape_dialogs_hide ()
{
- if (Inkscape::NSApplication::Application::getNewGui())
- Inkscape::NSApplication::Editor::hideDialogs();
- else
- {
- g_signal_emit (G_OBJECT (inkscape), inkscape_signals[DIALOGS_HIDE], 0);
- inkscape->dialogs_toggle = FALSE;
- }
+ g_signal_emit (G_OBJECT (inkscape), inkscape_signals[DIALOGS_HIDE], 0);
+ inkscape->dialogs_toggle = FALSE;
}
void
inkscape_dialogs_unhide ()
{
- if (Inkscape::NSApplication::Application::getNewGui())
- Inkscape::NSApplication::Editor::unhideDialogs();
- else
- {
- g_signal_emit (G_OBJECT (inkscape), inkscape_signals[DIALOGS_UNHIDE], 0);
- inkscape->dialogs_toggle = TRUE;
- }
+ g_signal_emit (G_OBJECT (inkscape), inkscape_signals[DIALOGS_UNHIDE], 0);
+ inkscape->dialogs_toggle = TRUE;
}
{
g_return_if_fail (document != NULL);
- if (!Inkscape::NSApplication::Application::getNewGui())
- {
- // 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<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
- iter != inkscape->document_set.end();
- ++iter) {
- if (iter->first == document) {
- // found this document in list, increase its count
- iter->second ++;
- }
- }
- }
- }
- else
- {
- Inkscape::NSApplication::Editor::addDocument (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<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
+ iter != inkscape->document_set.end();
+ ++iter) {
+ if (iter->first == document) {
+ // found this document in list, increase its count
+ iter->second ++;
+ }
+ }
}
}
{
g_return_val_if_fail (document != NULL, false);
- if (!Inkscape::NSApplication::Application::getNewGui())
- {
- for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
- iter != inkscape->document_set.end();
- ++iter) {
- if (iter->first == document) {
- // found this document in list, decrease its count
- iter->second --;
- if (iter->second < 1) {
- // this was the last one, remove the pair from list
- inkscape->document_set.erase (iter);
- return true;
- } else {
- return false;
- }
+ for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
+ iter != inkscape->document_set.end();
+ ++iter) {
+ if (iter->first == document) {
+ // found this document in list, decrease its count
+ iter->second --;
+ if (iter->second < 1) {
+ // this was the last one, remove the pair from list
+ inkscape->document_set.erase (iter);
+ return true;
+ } else {
+ return false;
}
}
}
- else
- {
- Inkscape::NSApplication::Editor::removeDocument (document);
- }
return false;
}
SPDesktop *
inkscape_active_desktop (void)
{
- if (Inkscape::NSApplication::Application::getNewGui())
- return Inkscape::NSApplication::Editor::getActiveDesktop();
-
if (inkscape->desktops == NULL) {
return NULL;
}
SPDocument *
inkscape_active_document (void)
{
- if (Inkscape::NSApplication::Application::getNewGui())
- return Inkscape::NSApplication::Editor::getActiveDocument();
-
if (SP_ACTIVE_DESKTOP) {
return sp_desktop_document (SP_ACTIVE_DESKTOP);
}
profile_path(const char *filename)
{
static const gchar *prefdir = NULL;
+
+
if (!prefdir) {
+ // First check for a custom environment variable for a "portable app"
+ gchar const *val = g_getenv("INKSCAPE_PORTABLE_PROFILE_DIR");
+ if (val) {
+ prefdir = g_strdup(val);
+ }
+
#ifdef HAS_SHGetSpecialFolderLocation
// prefer c:\Documents and Settings\UserName\Application Data\ to
// c:\Documents and Settings\userName\;
if (!prefdir) {
prefdir = g_build_filename(g_get_user_config_dir(), INKSCAPE_PROFILE_DIR, NULL);
gchar * legacyDir = homedir_path(INKSCAPE_LEGACY_PROFILE_DIR);
+ gchar * dev47Dir = g_build_filename(g_get_user_config_dir(), INKSCAPE_PROFILE_DIR_047DEV, NULL);
- // TODO here is a point to hook in preference migration
+ bool needsMigration = ( !Inkscape::IO::file_test( prefdir, G_FILE_TEST_EXISTS ) && Inkscape::IO::file_test( legacyDir, G_FILE_TEST_EXISTS ) );
+ 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 ) );
+ if (needsRenameWarning) {
+ g_warning("Preferences need to be copied from %s to %s", legacyDir, prefdir);
+ }
- if ( !Inkscape::IO::file_test( prefdir, G_FILE_TEST_EXISTS ) && Inkscape::IO::file_test( legacyDir, G_FILE_TEST_EXISTS ) ) {
- prefdir = legacyDir;
+ g_free(legacyDir);
+ legacyDir = 0;
+ g_free(dev47Dir);
+ dev47Dir = 0;
+ // In case the XDG user config dir of the moment does not yet exist...
+ int mode = S_IRWXU;
+#ifdef S_IRGRP
+ mode |= S_IRGRP;
+#endif
+#ifdef S_IXGRP
+ mode |= S_IXGRP;
+#endif
+#ifdef S_IXOTH
+ mode |= S_IXOTH;
+#endif
+ 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 {
- g_free(legacyDir);
- legacyDir = 0;
+ 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);
+ }
}
}
}
}
}
-
-
/*
Local Variables:
mode:c++