summaryrefslogtreecommitdiffstats
path: root/src/extension/db.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/extension/db.cpp327
1 files changed, 327 insertions, 0 deletions
diff --git a/src/extension/db.cpp b/src/extension/db.cpp
new file mode 100644
index 0000000..1fb8763
--- /dev/null
+++ b/src/extension/db.cpp
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Functions to keep a listing of all modules in the system. Has its
+ * own file mostly for abstraction reasons, but is pretty simple
+ * otherwise.
+ *
+ * Authors:
+ * Ted Gould <ted@gould.cx>
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ *
+ * Copyright (C) 2002-2004 Authors
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include "db.h"
+
+#include "implementation/script.h"
+#include "input.h"
+#include "output.h"
+#include "effect.h"
+
+/* Globals */
+
+/* Namespaces */
+
+namespace Inkscape {
+namespace Extension {
+
+/** This is the actual database object. There is only one of these */
+DB db;
+
+/* Types */
+
+DB::DB (void) = default;
+
+
+struct ModuleInputCmp {
+ bool operator()(Input* module1, Input* module2) const {
+
+ // Ensure SVG files are at top
+ int n1 = 0;
+ int n2 = 0;
+ // 12345678901234567890123456789012
+ if (strncmp(module1->get_id(),"org.inkscape.input.svg", 22) == 0) n1 = 1;
+ if (strncmp(module2->get_id(),"org.inkscape.input.svg", 22) == 0) n2 = 1;
+ if (strncmp(module1->get_id(),"org.inkscape.input.svgz", 23) == 0) n1 = 2;
+ if (strncmp(module2->get_id(),"org.inkscape.input.svgz", 23) == 0) n2 = 2;
+
+ if (n1 != 0 && n2 != 0) return (n1 < n2);
+ if (n1 != 0) return true;
+ if (n2 != 0) return false;
+
+ // GDK filetypenames begin with lower case letters and thus are sorted at the end.
+ // Special case "sK1" which starts with a lower case letter to keep it out of GDK region.
+ if (strncmp(module1->get_id(),"org.inkscape.input.sk1", 22) == 0) {
+ return ( strcmp("SK1", module2->get_filetypename()) <= 0 );
+ }
+ if (strncmp(module2->get_id(),"org.inkscape.input.sk1", 22) == 0) {
+ return ( strcmp(module1->get_filetypename(), "SK1" ) <= 0 );
+ }
+
+ return ( strcmp(module1->get_filetypename(), module2->get_filetypename()) <= 0 );
+ }
+};
+
+
+struct ModuleOutputCmp {
+ bool operator()(Output* module1, Output* module2) const {
+
+ // Ensure SVG files are at top
+ int n1 = 0;
+ int n2 = 0;
+ // 12345678901234567890123456789012
+ if (strncmp(module1->get_id(),"org.inkscape.output.png.inkscape", 32) == 0) n1 = 1;
+ if (strncmp(module2->get_id(),"org.inkscape.output.png.inkscape", 32) == 0) n2 = 1;
+ if (strncmp(module1->get_id(),"org.inkscape.output.svg.inkscape", 32) == 0) n1 = 1;
+ if (strncmp(module2->get_id(),"org.inkscape.output.svg.inkscape", 32) == 0) n2 = 1;
+ if (strncmp(module1->get_id(),"org.inkscape.output.svg.plain", 29) == 0) n1 = 2;
+ if (strncmp(module2->get_id(),"org.inkscape.output.svg.plain", 29) == 0) n2 = 2;
+ if (strncmp(module1->get_id(),"org.inkscape.output.svgz.inkscape", 33) == 0) n1 = 3;
+ if (strncmp(module2->get_id(),"org.inkscape.output.svgz.inkscape", 33) == 0) n2 = 3;
+ if (strncmp(module1->get_id(),"org.inkscape.output.svgz.plain", 30) == 0) n1 = 4;
+ if (strncmp(module2->get_id(),"org.inkscape.output.svgz.plain", 30) == 0) n2 = 4;
+ if (strncmp(module1->get_id(),"org.inkscape.output.scour", 25) == 0) n1 = 5;
+ if (strncmp(module2->get_id(),"org.inkscape.output.scour", 25) == 0) n2 = 5;
+ if (strncmp(module1->get_id(),"org.inkscape.output.ZIP", 23) == 0) n1 = 6;
+ if (strncmp(module2->get_id(),"org.inkscape.output.ZIP", 23) == 0) n2 = 6;
+ if (strncmp(module1->get_id(),"org.inkscape.output.LAYERS", 26) == 0) n1 = 7;
+ if (strncmp(module2->get_id(),"org.inkscape.output.LAYERS", 26) == 0) n2 = 7;
+
+ if (n1 != 0 && n2 != 0) return (n1 < n2);
+ if (n1 != 0) return true;
+ if (n2 != 0) return false;
+
+ // Special case "sK1" which starts with a lower case letter.
+ if (strncmp(module1->get_id(),"org.inkscape.output.sk1", 23) == 0) {
+ return ( strcmp("SK1", module2->get_filetypename()) <= 0 );
+ }
+ if (strncmp(module2->get_id(),"org.inkscape.output.sk1", 23) == 0) {
+ return ( strcmp(module1->get_filetypename(), "SK1" ) <= 0 );
+ }
+ // special case: two extensions for the same file type. I only one of them is a script, prefer the other one
+ if (Glib::ustring(module1->get_extension()).lowercase() == Glib::ustring(module2->get_extension()).lowercase()) {
+ bool module1_is_script = dynamic_cast<Inkscape::Extension::Implementation::Script *>(module1->get_imp());
+ bool module2_is_script = dynamic_cast<Inkscape::Extension::Implementation::Script *>(module2->get_imp());
+ if (module1_is_script != module2_is_script) {
+ return module1_is_script ? false : true;
+ }
+ }
+ return ( strcmp(module1->get_filetypename(), module2->get_filetypename()) <= 0 );
+ }
+};
+
+
+/**
+ \brief Add a module to the module database
+ \param module The module to be registered.
+*/
+void
+DB::register_ext (Extension *module)
+{
+ g_return_if_fail(module != nullptr);
+ g_return_if_fail(module->get_id() != nullptr);
+
+ // only add to list if it's a never-before-seen module
+ bool add_to_list =
+ ( moduledict.find(module->get_id()) == moduledict.end());
+
+ //printf("Registering: '%s' '%s' add:%d\n", module->get_id(), module->get_name(), add_to_list);
+ moduledict[module->get_id()] = module;
+
+ if (add_to_list) {
+ modulelist.push_back( module );
+ }
+}
+
+/**
+ \brief This function removes a module from the database
+ \param module The module to be removed.
+*/
+void
+DB::unregister_ext (Extension * module)
+{
+ g_return_if_fail(module != nullptr);
+ g_return_if_fail(module->get_id() != nullptr);
+
+ // printf("Extension DB: removing %s\n", module->get_id());
+ moduledict.erase(moduledict.find(module->get_id()));
+ // only remove if it's not there any more
+ if ( moduledict.find(module->get_id()) != moduledict.end())
+ modulelist.remove(module);
+}
+
+/**
+ \return A reference to the Inkscape::Extension::Extension specified by the input key.
+ \brief This function looks up a Inkscape::Extension::Extension by using its unique
+ id. It then returns a reference to that module.
+ \param key The unique ID of the module
+
+ Retrieves a module by name; if non-NULL, it refs the returned
+ module; the caller is responsible for releasing that reference
+ when it is no longer needed.
+*/
+Extension *
+DB::get (const gchar *key) const
+{
+ if (key == nullptr) return nullptr;
+
+ auto it = moduledict.find(key);
+ if (it == moduledict.end())
+ return nullptr;
+
+ Extension *mod = it->second;
+ assert(mod);
+
+ if ( !mod || mod->deactivated() )
+ return nullptr;
+
+ return mod;
+}
+
+/**
+ \return none
+ \brief A function to execute another function with every entry
+ in the database as a parameter.
+ \param in_func The function to execute for every module
+ \param in_data A data pointer that is also passed to in_func
+
+ Enumerates the modules currently in the database, calling a given
+ callback for each one.
+*/
+void
+DB::foreach (void (*in_func)(Extension * in_plug, gpointer in_data), gpointer in_data)
+{
+ std::list <Extension *>::iterator cur;
+
+ for (cur = modulelist.begin(); cur != modulelist.end(); ++cur) {
+ // printf("foreach: %s\n", (*cur)->get_id());
+ in_func((*cur), in_data);
+ }
+}
+
+/**
+ \return none
+ \brief The function to look at each module and see if it is
+ an input module, then add it to the list.
+ \param in_plug Module to be examined
+ \param data The list to be attached to
+
+ The first thing that is checked is if this module is an input
+ module. If it is, then it is added to the list which is passed
+ in through \c data.
+*/
+void
+DB::input_internal (Extension * in_plug, gpointer data)
+{
+ if (dynamic_cast<Input *>(in_plug)) {
+ InputList * ilist;
+ Input * imod;
+
+ imod = dynamic_cast<Input *>(in_plug);
+ ilist = reinterpret_cast<InputList *>(data);
+
+ ilist->push_back(imod);
+ // printf("Added to input list: %s\n", imod->get_id());
+ }
+}
+
+/**
+ \return none
+ \brief The function to look at each module and see if it is
+ an output module, then add it to the list.
+ \param in_plug Module to be examined
+ \param data The list to be attached to
+
+ The first thing that is checked is if this module is an output
+ module. If it is, then it is added to the list which is passed
+ in through \c data.
+*/
+void
+DB::output_internal (Extension * in_plug, gpointer data)
+{
+ if (dynamic_cast<Output *>(in_plug)) {
+ OutputList * olist;
+ Output * omod;
+
+ omod = dynamic_cast<Output *>(in_plug);
+ olist = reinterpret_cast<OutputList *>(data);
+
+ olist->push_back(omod);
+ // printf("Added to output list: %s\n", omod->get_id());
+ }
+
+ return;
+}
+
+/**
+ \return none
+ \brief The function to look at each module and see if it is
+ an effect module, then add it to the list.
+ \param in_plug Module to be examined
+ \param data The list to be attached to
+
+ The first thing that is checked is if this module is an effect
+ module. If it is, then it is added to the list which is passed
+ in through \c data.
+*/
+void
+DB::effect_internal (Extension * in_plug, gpointer data)
+{
+ if (dynamic_cast<Effect *>(in_plug)) {
+ EffectList * elist;
+ Effect * emod;
+
+ emod = dynamic_cast<Effect *>(in_plug);
+ elist = reinterpret_cast<EffectList *>(data);
+
+ elist->push_back(emod);
+ // printf("Added to effect list: %s\n", emod->get_id());
+ }
+
+ return;
+}
+
+/**
+ \brief Creates a list of all the Input extensions
+ \param ou_list The list that is used to put all the extensions in
+
+ Calls the database \c foreach function with \c input_internal.
+*/
+DB::InputList &
+DB::get_input_list (DB::InputList &ou_list)
+{
+ foreach(input_internal, (gpointer)&ou_list);
+ ou_list.sort( ModuleInputCmp() );
+ return ou_list;
+}
+
+/**
+ \brief Creates a list of all the Output extensions
+ \param ou_list The list that is used to put all the extensions in
+
+ Calls the database \c foreach function with \c output_internal.
+*/
+DB::OutputList &
+DB::get_output_list (DB::OutputList &ou_list)
+{
+ foreach(output_internal, (gpointer)&ou_list);
+ ou_list.sort( ModuleOutputCmp() );
+ return ou_list;
+}
+
+/**
+ \brief Creates a list of all the Effect extensions
+ \param ou_list The list that is used to put all the extensions in
+
+ Calls the database \c foreach function with \c effect_internal.
+*/
+DB::EffectList &
+DB::get_effect_list (DB::EffectList &ou_list)
+{
+ foreach(effect_internal, (gpointer)&ou_list);
+ return ou_list;
+}
+
+} } /* namespace Extension, Inkscape */