inkscape.h File Reference

Go to the source code of this file.

Namespaces

namespace  Inkscape
 

Note: We must limit Java or JVM-specific code to this file and to dobinding.cpp.


namespace  Inkscape::XML
 

Inkscape XML tree


Defines

#define INKSCAPE   inkscape_get_instance()
#define SP_ACTIVE_EVENTCONTEXT   inkscape_active_event_context ()
#define SP_ACTIVE_DOCUMENT   inkscape_active_document ()
#define SP_ACTIVE_DESKTOP   inkscape_active_desktop ()

Functions

void inkscape_autosave_init ()
void inkscape_application_init (const gchar *argv0, gboolean use_gui)
bool inkscape_load_config (const gchar *filename, Inkscape::XML::Document *config, const gchar *skeleton, unsigned int skel_size, const gchar *e_notreg, const gchar *e_notxml, const gchar *e_notsp, const gchar *warn)
bool inkscape_load_menus (Inkscape::Application *inkscape)
 Menus management.
bool inkscape_save_menus (Inkscape::Application *inkscape)
Inkscape::XML::Nodeinkscape_get_menus (Inkscape::Application *inkscape)
Inkscape::Applicationinkscape_get_instance ()
 Returns the current Inkscape::Application global object.
SPDesktopinkscape_find_desktop_by_dkey (unsigned int dkey)
SPEventContextinkscape_active_event_context (void)
SPDocumentinkscape_active_document (void)
SPDesktopinkscape_active_desktop (void)
bool inkscape_is_sole_desktop_for_document (SPDesktop const &desktop)
gchar * homedir_path (const char *filename)
gchar * profile_path (const char *filename)
 Get, or guess, or decide the location where the preferences.xml file should be located.
void inkscape_activate_desktop (SPDesktop *desktop)
void inkscape_switch_desktops_next ()
void inkscape_switch_desktops_prev ()
void inkscape_get_all_desktops (std::list< SPDesktop * > &listbuf)
void inkscape_dialogs_hide ()
void inkscape_dialogs_unhide ()
void inkscape_dialogs_toggle ()
void inkscape_external_change ()
void inkscape_subselection_changed (SPDesktop *desktop)
void inkscape_refresh_display (Inkscape::Application *inkscape)
void inkscape_exit (Inkscape::Application *inkscape)
 Handler for Inkscape's Exit verb.

Define Documentation

#define INKSCAPE   inkscape_get_instance()

Definition at line 30 of file inkscape.h.

Referenced by Inkscape::UI::Dialog::AlignAndDistribute::AlignAndDistribute(), clonetiler_dialog(), clonetiler_dialog_destroy(), Inkscape::UI::Dialog::DesktopTracker::connect(), Inkscape::UI::Dialog::PanelDialog< Behavior::FloatingBehavior >::create(), Inkscape::UI::Dialog::Dialog::Dialog(), Inkscape::UI::Dialog::DesktopTracker::disconnect(), Inkscape::UI::Widget::Dock::Dock(), Inkscape::Extension::Effect::Effect(), Inkscape::UI::Dialog::FilterEffectsDialog::FilterModifier::FilterModifier(), homedir_path(), Inkscape::UI::Widget::ImageIcon::init(), inkscape_crash_handler(), inkscape_exit(), inkscape_load_menus(), Inkscape::UI::Widget::ObjectCompositeSettings::ObjectCompositeSettings(), on_destroy(), Inkscape::UI::Dialog::PanelDialog< Behavior::FloatingBehavior >::PanelDialog(), Inkscape::UI::Dialog::PanelDialog< Behavior >::PanelDialog(), sp_document_create(), sp_export_dialog(), sp_export_dialog_area_box(), sp_export_dialog_destroy(), sp_find_dialog_destroy(), sp_find_dialog_old(), sp_gradient_vector_dialog_destroy(), sp_gradient_vector_editor_new(), sp_item_dialog(), sp_item_dialog_destroy(), sp_item_widget_new(), sp_select_toolbox_prep(), sp_stroke_style_line_widget_new(), sp_text_edit_dialog(), sp_text_edit_dialog_destroy(), sp_ui_main_menubar(), sp_xml_tree_dialog(), Inkscape::UI::Dialog::SVGPreview::SVGPreview(), Inkscape::UI::Dialog::TileDialog::TileDialog(), Inkscape::UI::Dialog::Transformation::Transformation(), Inkscape::UI::Dialog::AlignAndDistribute::~AlignAndDistribute(), Inkscape::UI::Widget::ObjectCompositeSettings::~ObjectCompositeSettings(), SPDocument::~SPDocument(), and Inkscape::UI::Dialog::Transformation::~Transformation().

#define SP_ACTIVE_DESKTOP   inkscape_active_desktop ()

Definition at line 53 of file inkscape.h.

Referenced by Inkscape::UI::Dialogs::LayerPropertiesDialog::_apply(), Inkscape::UI::Dialog::Dialog::_getSelection(), Inkscape::UI::Dialog::Dialog::_onKeyPress(), clonetiler_dialog(), clonetiler_external_change(), desktop_ensure_active(), file_save(), Inkscape::UI::Widget::PageSizer::fire_fit_canvas_to_selection_or_drawing(), get_node_tool(), Inkscape::UI::Dialog::DesktopTracker::handleHierarchyChange(), inkscape_active_document(), inkscape_active_event_context(), inkscape_autosave(), Inkscape::LivePathEffect::PathParam::on_edit_button_click(), Inkscape::LivePathEffect::PathParam::on_link_button_click(), Inkscape::LivePathEffect::PathParam::on_paste_button_click(), on_picker_color_changed(), Inkscape::Extension::PrefDialog::on_response(), on_window_key_press(), Inkscape::Extension::PrefDialog::PrefDialog(), Inkscape::Extension::PrefDialog::preview_toggle(), Inkscape::UI::Widget::PageSizer::setDim(), Inkscape::UI::Widget::ObjectCompositeSettings::setSubject(), Inkscape::UI::Widget::sp_color_picker_color_mod(), sp_connector_graph_layout(), sp_export_area_toggled(), sp_export_detect_size(), sp_export_export_clicked(), sp_export_find_default_selection(), sp_export_selection_changed(), sp_export_selection_modified(), sp_export_update_checkbuttons(), sp_file_save(), sp_file_save_a_copy(), sp_file_save_as(), sp_file_save_document(), sp_guide_description(), sp_item_widget_hidden_toggled(), sp_item_widget_label_changed(), sp_item_widget_new(), sp_item_widget_sensitivity_toggled(), sp_lpe_item_perform_path_effect(), sp_select_toolbox_prep(), sp_stroke_style_line_update(), sp_ted_get_selected_text_count(), sp_ted_get_selected_text_item(), sp_text_align_mode_changed(), sp_text_description(), sp_text_dx_value_changed(), sp_text_dy_value_changed(), sp_text_edit_dialog_apply(), sp_text_edit_dialog_read_selection(), sp_text_fontfamily_value_changed(), sp_text_fontsize_value_changed(), sp_text_letterspacing_value_changed(), sp_text_lineheight_value_changed(), sp_text_orientation_mode_changed(), sp_text_rotation_value_changed(), sp_text_script_changed(), sp_text_style_changed(), sp_text_toolbox_selection_changed(), sp_text_wordspacing_value_changed(), sp_transientize(), sp_ui_close_all(), sp_ui_overwrite_file(), and sp_xmlview_content_changed().

#define SP_ACTIVE_DOCUMENT   inkscape_active_document ()
#define SP_ACTIVE_EVENTCONTEXT   inkscape_active_event_context ()

Definition at line 47 of file inkscape.h.


Function Documentation

gchar* homedir_path ( const char *  filename  ) 

Definition at line 1377 of file inkscape.cpp.

References INKSCAPE, and NULL.

Referenced by create_filepath_from_id(), profile_path(), and sp_selection_create_bitmap_copy().

{
    static const gchar *homedir = NULL;
    if (!homedir) {
        homedir = g_get_home_dir();
    }
    if (!homedir) {
        homedir = g_path_get_dirname(INKSCAPE->argv0);
    }
    return g_build_filename(homedir, filename, NULL);
}

void inkscape_activate_desktop ( SPDesktop desktop  ) 

Definition at line 1034 of file inkscape.cpp.

References ACTIVATE_DESKTOP, Inkscape::NSApplication::Editor::activateDesktop(), CHANGE_SELECTION, current, DESKTOP_IS_ACTIVE, Inkscape::Application::desktops, Inkscape::NSApplication::Application::getNewGui(), inkscape_signals, NULL, SET_EVENTCONTEXT, SET_SELECTION, sp_desktop_event_context(), and sp_desktop_selection().

{
    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)) {
        return;
    }

    g_assert (g_slist_find (inkscape->desktops, desktop));

    SPDesktop *current = (SPDesktop *) inkscape->desktops->data;

    g_signal_emit (G_OBJECT (inkscape), inkscape_signals[DEACTIVATE_DESKTOP], 0, current);

    inkscape->desktops = g_slist_remove (inkscape->desktops, desktop);
    inkscape->desktops = g_slist_prepend (inkscape->desktops, desktop);

    g_signal_emit (G_OBJECT (inkscape), inkscape_signals[ACTIVATE_DESKTOP], 0, desktop);
    g_signal_emit (G_OBJECT (inkscape), inkscape_signals[SET_EVENTCONTEXT], 0, sp_desktop_event_context (desktop));
    g_signal_emit (G_OBJECT (inkscape), inkscape_signals[SET_SELECTION], 0, sp_desktop_selection (desktop));
    g_signal_emit (G_OBJECT (inkscape), inkscape_signals[CHANGE_SELECTION], 0, sp_desktop_selection (desktop));
}

SPEventContext* inkscape_active_event_context ( void   ) 

Definition at line 1336 of file inkscape.cpp.

References SP_ACTIVE_DESKTOP, and sp_desktop_event_context().

Referenced by persp3d_set(), and Box3D::VPDrag::updateBoxHandles().

{
    if (SP_ACTIVE_DESKTOP) {
        return sp_desktop_event_context (SP_ACTIVE_DESKTOP);
    }

    return NULL;
}

void inkscape_application_init ( const gchar *  argv0,
gboolean  use_gui 
)

Definition at line 786 of file inkscape.cpp.

References abrt_handler, Inkscape::Application::argv0, bus_handler, DEFAULT_LOG_REDIRECT, fpe_handler, Inkscape::Preferences::get(), Inkscape::Preferences::getBool(), Inkscape::UI::Dialog::DebugDialog::getInstance(), Inkscape::Preferences::getInt(), Inkscape::Preferences::getLastError(), Inkscape::DeviceManager::getManager(), Inkscape::Preferences::getString(), InkErrorHandler::handleError(), ill_handler, Inkscape::Extension::init(), inkscape_autosave_init(), inkscape_crash_handler(), inkscape_load_menus(), inkscape_mapalt(), inkscape_trackalt(), NULL, segv_handler, Inkscape::Preferences::setErrorHandler(), SP_TYPE_INKSCAPE, TRUE, and Inkscape::Application::use_gui.

Referenced by Inkscape::UI::Widget::ImageIcon::init(), sp_main_console(), sp_main_gui(), and Inkscape::UI::Dialog::SVGPreview::SVGPreview().

{
    inkscape = (Inkscape::Application *)g_object_new (SP_TYPE_INKSCAPE, NULL);
    /* fixme: load application defaults */

    segv_handler = signal (SIGSEGV, inkscape_crash_handler);
    abrt_handler = signal (SIGABRT, inkscape_crash_handler);
    fpe_handler  = signal (SIGFPE,  inkscape_crash_handler);
    ill_handler  = signal (SIGILL,  inkscape_crash_handler);
#ifndef WIN32
    bus_handler  = signal (SIGBUS,  inkscape_crash_handler);
#endif

    inkscape->use_gui = use_gui;
    inkscape->argv0 = g_strdup(argv0);

    /* Load the preferences and menus */
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    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 ui_language = prefs->getString("/ui/language");
    if(!ui_language.empty())
    {
        setenv("LANGUAGE", ui_language, 1);
    }

    /* DebugDialog redirection.  On Linux, default to OFF, on Win32, default to ON.
     * Use only if use_gui is enabled
     */
#ifdef WIN32
#define DEFAULT_LOG_REDIRECT true
#else
#define DEFAULT_LOG_REDIRECT false
#endif

    if (use_gui == TRUE && prefs->getBool("/dialogs/debug/redirect", DEFAULT_LOG_REDIRECT))
    {
        Inkscape::UI::Dialog::DebugDialog::getInstance()->captureLogMessages();
    }

    /* Check for global remapping of Alt key */
    if (use_gui)
    {
        inkscape_mapalt(guint(prefs->getInt("/options/mapalt/value", 0)));
        inkscape_trackalt(guint(prefs->getInt("/options/trackalt/value", 0)));
    }

    /* Initialize the extensions */
    Inkscape::Extension::init();

    inkscape_autosave_init();

    return;
}

void inkscape_autosave_init (  ) 

Definition at line 429 of file inkscape.cpp.

References Inkscape::Preferences::get(), Inkscape::Preferences::getBool(), Inkscape::Preferences::getInt(), inkscape_autosave(), and NULL.

Referenced by inkscape_application_init().

{
    static guint32 autosave_timeout_id = 0;
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();

    // Turn off any previously initiated timeouts
    if ( autosave_timeout_id ) {
        g_source_remove(autosave_timeout_id);
        autosave_timeout_id = 0;
    }

    // g_debug("options.autosave.enable = %d", prefs->getBool("/options/autosave/enable", true));
    // Is autosave enabled?
    if (!prefs->getBool("/options/autosave/enable", true)){
        autosave_timeout_id = 0;
    } else {
        // Turn on autosave
        guint32 timeout = prefs->getInt("/options/autosave/interval", 10) * 60;
        // g_debug("options.autosave.interval = %d", prefs->getInt("/options/autosave/interval", 10));
#if GLIB_CHECK_VERSION(2,14,0)
        autosave_timeout_id = g_timeout_add_seconds(timeout, inkscape_autosave, NULL);
#else
        autosave_timeout_id = g_timeout_add(timeout * 1000, inkscape_autosave, NULL);
#endif
    }
}

void inkscape_dialogs_toggle (  ) 
void inkscape_exit ( Inkscape::Application  ) 

Handler for Inkscape's Exit verb.

This emits the shutdown signal, saves the preferences if appropriate, and quits.

Definition at line 1365 of file inkscape.cpp.

References INKSCAPE, inkscape_signals, SHUTDOWN_SIGNAL, and Inkscape::Preferences::unload().

Referenced by inkscape_remove_desktop().

{
    g_assert (INKSCAPE);

    //emit shutdown signal so that dialogs could remember layout
    g_signal_emit (G_OBJECT (INKSCAPE), inkscape_signals[SHUTDOWN_SIGNAL], 0);

    Inkscape::Preferences::unload();
    gtk_main_quit ();
}

void inkscape_external_change (  ) 

Definition at line 1225 of file inkscape.cpp.

References EXTERNAL_CHANGE, inkscape_signals, and NULL.

Referenced by sp_document_redo(), and sp_document_undo().

{
    g_return_if_fail (inkscape != NULL);

    g_signal_emit (G_OBJECT (inkscape), inkscape_signals[EXTERNAL_CHANGE], 0);
}

SPDesktop* inkscape_find_desktop_by_dkey ( unsigned int  dkey  ) 

Definition at line 1085 of file inkscape.cpp.

References Inkscape::Application::desktops, and polyhedron_3d::r.

Referenced by inkscape_next_desktop(), and inkscape_prev_desktop().

{
    for (GSList *r = inkscape->desktops; r; r = r->next) {
        if (((SPDesktop *) r->data)->dkey == dkey)
            return ((SPDesktop *) r->data);
    }
    return NULL;
}

void inkscape_get_all_desktops ( std::list< SPDesktop * > &  listbuf  ) 

Definition at line 1514 of file inkscape.cpp.

References Inkscape::Application::desktops, and NULL.

Referenced by Inkscape::Whiteboard::ChooseDesktop::doSetup(), and Inkscape::CmdLineAction::idle().

{
    for(GSList* l = inkscape->desktops; l != NULL; l = l->next) {
        listbuf.push_back(static_cast< SPDesktop* >(l->data));
    }
}

Inkscape::Application* inkscape_get_instance (  ) 

Returns the current Inkscape::Application global object.

Definition at line 859 of file inkscape.cpp.

Referenced by Inkscape::createSuiteAndDocument(), and inkscape_crash_handler().

{
        return inkscape;
}

Inkscape::XML::Node* inkscape_get_menus ( Inkscape::Application inkscape  ) 

Definition at line 1506 of file inkscape.cpp.

References Inkscape::XML::Node::firstChild(), Inkscape::Application::menus, Inkscape::XML::Node::name(), and Inkscape::XML::Node::root().

Referenced by Inkscape::Extension::Effect::Effect(), and sp_ui_main_menubar().

{
    Inkscape::XML::Node *repr = inkscape->menus->root();
    g_assert (!(strcmp (repr->name(), "inkscape")));
    return repr->firstChild();
}

bool inkscape_is_sole_desktop_for_document ( SPDesktop const &  desktop  ) 

Definition at line 1320 of file inkscape.cpp.

References Inkscape::Application::desktops, and Inkscape::UI::View::View::doc().

Referenced by SPDesktopWidget::shutdown().

                                                                     {
    SPDocument const* document = desktop.doc();
    if (!document) {
        return false;
    }
    for ( GSList *iter = inkscape->desktops ; iter ; iter = iter->next ) {
        SPDesktop *other_desktop=(SPDesktop *)iter->data;
        SPDocument *other_document=other_desktop->doc();
        if ( other_document == document && other_desktop != &desktop ) {
            return false;
        }
    }
    return true;
}

bool inkscape_load_config ( const gchar *  filename,
Inkscape::XML::Document config,
const gchar *  skeleton,
unsigned int  skel_size,
const gchar *  e_notreg,
const gchar *  e_notxml,
const gchar *  e_notsp,
const gchar *  warn 
)
bool inkscape_load_menus ( Inkscape::Application  ) 

Menus management.

Definition at line 873 of file inkscape.cpp.

References INKSCAPE, MENUS_FILE, menus_skeleton, MENUS_SKELETON_SIZE, NULL, profile_path(), and sp_repr_read_mem().

Referenced by inkscape_application_init().

{
    // TODO fix that fn is being leaked
    gchar *fn = profile_path(MENUS_FILE);
    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;
        }
    }
    INKSCAPE->menus = sp_repr_read_mem(menus_skeleton, MENUS_SKELETON_SIZE, NULL);
    return (INKSCAPE->menus != 0);
}

void inkscape_refresh_display ( Inkscape::Application inkscape  ) 

Definition at line 1352 of file inkscape.cpp.

References Inkscape::Application::desktops, and NULL.

{
    for (GSList *l = inkscape->desktops; l != NULL; l = l->next) {
        (static_cast<Inkscape::UI::View::View*>(l->data))->requestRedraw();
    }
}

bool inkscape_save_menus ( Inkscape::Application inkscape  ) 
void inkscape_subselection_changed ( SPDesktop desktop  ) 
void inkscape_switch_desktops_next (  ) 
void inkscape_switch_desktops_prev (  ) 
gchar* profile_path ( const char *  filename  ) 

Get, or guess, or decide the location where the preferences.xml file should be located.

Definition at line 1395 of file inkscape.cpp.

References Inkscape::IO::file_test(), homedir_path(), INKSCAPE_LEGACY_PROFILE_DIR, INKSCAPE_PROFILE_DIR, INKSCAPE_PROFILE_DIR_047DEV, Inkscape::Preferences::migrate(), polyhedron_3d::name, NULL, and dxf_input::val.

Referenced by Inkscape::Preferences::_load(), Inkscape::Extension::Extension::error_file_open(), Inkscape::Extension::ErrorFileNotice::ErrorFileNotice(), Inkscape::UI::Dialog::FileSaveDialogImplGtk::FileSaveDialogImplGtk(), Inkscape::Extension::Internal::Filter::Filter::filters_all_files(), Inkscape::ColorProfile::getProfileDirs(), icons_svg_paths(), inkscape_load_menus(), Inkscape::UI::Dialogs::loadEmUp(), Inkscape::Preferences::Preferences(), sp_file_new_default(), sp_main_gui(), and sp_menu_append_new_templates().

{
    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) {
            ITEMIDLIST *pidl = 0;
            if ( SHGetSpecialFolderLocation( NULL, CSIDL_APPDATA, &pidl ) == NOERROR ) {
                gchar * utf8Path = NULL;

                if ( PrintWin32::is_os_wide() ) {
                    wchar_t pathBuf[MAX_PATH+1];
                    g_assert(sizeof(wchar_t) == sizeof(gunichar2));

                    if ( SHGetPathFromIDListW( pidl, pathBuf ) ) {
                        utf8Path = g_utf16_to_utf8( (gunichar2*)(&pathBuf[0]), -1, NULL, NULL, NULL );
                    }
                } else {
                    char pathBuf[MAX_PATH+1];

                    if ( SHGetPathFromIDListA( pidl, pathBuf ) ) {
                        utf8Path = g_filename_to_utf8( pathBuf, -1, NULL, NULL, NULL );
                    }
                }

                if ( utf8Path ) {
                    if (!g_utf8_validate(utf8Path, -1, NULL)) {
                        g_warning( "SHGetPathFromIDList%c() resulted in invalid UTF-8", (PrintWin32::is_os_wide() ? 'W' : 'A') );
                        g_free( utf8Path );
                        utf8Path = 0;
                    } else {
                        prefdir = utf8Path;
                    }
                }


                /* not compiling yet...

                // Remember to free the list pointer
                IMalloc * imalloc = 0;
                if ( SHGetMalloc(&imalloc) == NOERROR) {
                    imalloc->lpVtbl->Free( imalloc, pidl );
                    imalloc->lpVtbl->Release( imalloc );
                }
                */
            }

            if (prefdir) {
                prefdir = g_build_filename(prefdir, INKSCAPE_PROFILE_DIR, NULL);
            }
        }
#endif
        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);

            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);
            }

            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 {
                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);
                }
            }
        }
    }
    return g_build_filename(prefdir, filename, NULL);
}