summaryrefslogtreecommitdiffstats
path: root/src/dialogs/rdf.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/dialogs/rdf.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/dialogs/rdf.cpp')
-rw-r--r--src/dialogs/rdf.cpp1002
1 files changed, 1002 insertions, 0 deletions
diff --git a/src/dialogs/rdf.cpp b/src/dialogs/rdf.cpp
new file mode 100644
index 000000000..d9949c05b
--- /dev/null
+++ b/src/dialogs/rdf.cpp
@@ -0,0 +1,1002 @@
+/**
+ * \brief RDF manipulation functions
+ *
+ * FIXME: move these to xml/ instead of dialogs/
+ *
+ * Authors:
+ * Kees Cook <kees@outflux.net>
+ *
+ * Copyright (C) 2004 Kees Cook <kees@outflux.net>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+
+#include "xml/repr.h"
+#include "rdf.h"
+#include "sp-item-group.h"
+
+/*
+
+ Example RDF XML from various places...
+
+<rdf:RDF xmlns="http://web.resource.org/cc/"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<Work rdf:about="">
+ <dc:title>title of work</dc:title>
+ <dc:date>year</dc:date>
+ <dc:description>description of work</dc:description>
+ <dc:creator><Agent>
+ <dc:title>creator</dc:title>
+ </Agent></dc:creator>
+ <dc:rights><Agent>
+ <dc:title>holder</dc:title>
+ </Agent></dc:rights>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:source rdf:resource="source"/>
+ <license rdf:resource="http://creativecommons.org/licenses/by/2.0/"
+/>
+</Work>
+
+
+ <rdf:RDF xmlns="http://web.resource.org/cc/"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <Work rdf:about="">
+ <dc:title>SVG Road Signs</dc:title>
+ <dc:rights><Agent>
+ <dc:title>John Cliff</dc:title>
+ </Agent></dc:rights>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <license rdf:resource="http://web.resource.org/cc/PublicDomain" />
+ </Work>
+
+ <License rdf:about="http://web.resource.org/cc/PublicDomain">
+ <permits rdf:resource="http://web.resource.org/cc/Reproduction" />
+ <permits rdf:resource="http://web.resource.org/cc/Distribution" />
+ <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+ </License>
+
+</rdf:RDF>
+
+
+Bag example:
+
+<dc:subject>
+<rdf:Bag>
+<rdf:li>open clip art logo</rdf:li>
+<rdf:li>images</rdf:li>
+<rdf:li>logo</rdf:li>
+<rdf:li>clip art</rdf:li>
+<rdf:li>ocal</rdf:li>
+<rdf:li>logotype</rdf:li>
+<rdf:li>filetype</rdf:li>
+</rdf:Bag>
+</dc:subject>
+
+
+*/
+
+struct rdf_double_t rdf_license_empty [] = {
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:requires", "http://web.resource.org/cc/Attribution", },
+ { "cc:permits", "http://web.resource.org/cc/DerivativeWorks", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_sa [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:requires", "http://web.resource.org/cc/Attribution", },
+ { "cc:permits", "http://web.resource.org/cc/DerivativeWorks", },
+ { "cc:requires", "http://web.resource.org/cc/ShareAlike", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nd [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:requires", "http://web.resource.org/cc/Attribution", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nc [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:requires", "http://web.resource.org/cc/Attribution", },
+ { "cc:prohibits", "http://web.resource.org/cc/CommercialUse", },
+ { "cc:permits", "http://web.resource.org/cc/DerivativeWorks", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nc_sa [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:requires", "http://web.resource.org/cc/Attribution", },
+ { "cc:prohibits", "http://web.resource.org/cc/CommercialUse", },
+ { "cc:permits", "http://web.resource.org/cc/DerivativeWorks", },
+ { "cc:requires", "http://web.resource.org/cc/ShareAlike", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_cc_a_nc_nd [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:requires", "http://web.resource.org/cc/Attribution", },
+ { "cc:prohibits", "http://web.resource.org/cc/CommercialUse", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_gpl [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:permits", "http://web.resource.org/cc/DerivativeWorks", },
+ { "cc:requires", "http://web.resource.org/cc/ShareAlike", },
+ { "cc:requires", "http://web.resource.org/cc/SourceCode", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_pd [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:permits", "http://web.resource.org/cc/DerivativeWorks", },
+ { NULL, NULL }
+};
+
+struct rdf_double_t rdf_license_freeart [] = {
+ { "cc:permits", "http://web.resource.org/cc/Reproduction", },
+ { "cc:permits", "http://web.resource.org/cc/Distribution", },
+ { "cc:permits", "http://web.resource.org/cc/DerivativeWorks", },
+ { "cc:requires", "http://web.resource.org/cc/ShareAlike", },
+ { "cc:requires", "http://web.resource.org/cc/Notice", },
+ { "cc:requires", "http://web.resource.org/cc/Attribution", },
+ { NULL, NULL }
+};
+
+struct rdf_license_t rdf_licenses [] = {
+ { "CC Attribution",
+ "http://creativecommons.org/licenses/by/2.0/",
+ rdf_license_cc_a,
+ },
+
+ { "CC Attribution-ShareAlike",
+ "http://creativecommons.org/licenses/by-sa/2.0/",
+ rdf_license_cc_a_sa,
+ },
+
+ { "CC Attribution-NoDerivs",
+ "http://creativecommons.org/licenses/by-nd/2.0/",
+ rdf_license_cc_a_nd,
+ },
+
+ { "CC Attribution-NonCommercial",
+ "http://creativecommons.org/licenses/by-nc/2.0/",
+ rdf_license_cc_a_nc,
+ },
+
+ { "CC Attribution-NonCommercial-ShareAlike",
+ "http://creativecommons.org/licenses/by-nc-sa/2.0/",
+ rdf_license_cc_a_nc_sa,
+ },
+
+ { "CC Attribution-NonCommercial-NoDerivs",
+ "http://creativecommons.org/licenses/by-nc-nd/2.0/",
+ rdf_license_cc_a_nc_nd,
+ },
+
+ { "GNU General Public License",
+ "http://creativecommons.org/licenses/GPL/2.0/",
+ rdf_license_gpl,
+ },
+
+ { "GNU Lesser General Public License",
+ "http://creativecommons.org/licenses/LGPL/2.1/",
+ rdf_license_gpl,
+ },
+
+ { "Public Domain",
+ "http://web.resource.org/cc/PublicDomain",
+ rdf_license_pd,
+ },
+
+ { "FreeArt",
+ "http://artlibre.org/licence.php/lalgb.html",
+ rdf_license_freeart,
+ },
+
+ { NULL, NULL, rdf_license_empty, }
+};
+
+#define XML_TAG_NAME_SVG "svg:svg"
+#define XML_TAG_NAME_METADATA "svg:metadata"
+#define XML_TAG_NAME_RDF "rdf:RDF"
+#define XML_TAG_NAME_WORK "cc:Work"
+#define XML_TAG_NAME_LICENSE "cc:License"
+
+// Remember when using the "title" and "tip" elements to pass them through
+// the localization functions when you use them!
+struct rdf_work_entity_t rdf_work_entities [] = {
+ { "title", N_("Title"), "dc:title", RDF_CONTENT,
+ N_("Name by which this document is formally known."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "date", N_("Date"), "dc:date", RDF_CONTENT,
+ N_("Date associated with the creation of this document (YYYY-MM-DD)."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "format", N_("Format"), "dc:format", RDF_CONTENT,
+ N_("The physical or digital manifestation of this document (MIME type)."), RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
+ },
+ { "type", N_("Type"), "dc:type", RDF_RESOURCE,
+ N_("Type of document (DCMI Type)."), RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
+ },
+
+ { "creator", N_("Creator"), "dc:creator", RDF_AGENT,
+ N_("Name of entity primarily responsible for making the content of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "rights", N_("Rights"), "dc:rights", RDF_AGENT,
+ N_("Name of entity with rights to the Intellectual Property of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "publisher", N_("Publisher"), "dc:publisher", RDF_AGENT,
+ N_("Name of entity responsible for making this document available."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+
+ { "identifier", N_("Identifier"), "dc:identifier", RDF_CONTENT,
+ N_("Unique URI to reference this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "source", N_("Source"), "dc:source", RDF_CONTENT,
+ N_("Unique URI to reference the source of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "relation", N_("Relation"), "dc:relation", RDF_CONTENT,
+ N_("Unique URI to a related document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "language", N_("Language"), "dc:language", RDF_CONTENT,
+ N_("Two-letter language tag with optional subtags for the language of this document. (e.g. 'en-GB')"), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ { "subject", N_("Keywords"), "dc:subject", RDF_BAG,
+ N_("The topic of this document as comma-separated key words, phrases, or classifications."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+ // TRANSLATORS: "Coverage": the spatial or temporal characteristics of the content.
+ // For info, see Appendix D of http://www.w3.org/TR/1998/WD-rdf-schema-19980409/
+ { "coverage", N_("Coverage"), "dc:coverage", RDF_CONTENT,
+ N_("Extent or scope of this document."), RDF_FORMAT_LINE, RDF_EDIT_GENERIC,
+ },
+
+ { "description", N_("Description"), "dc:description", RDF_CONTENT,
+ N_("A short account of the content of this document."), RDF_FORMAT_MULTILINE, RDF_EDIT_GENERIC,
+ },
+
+ // FIXME: need to handle 1 agent per line of input
+ { "contributor", N_("Contributors"), "dc:contributor", RDF_AGENT,
+ N_("Names of entities responsible for making contributions to the content of this document."), RDF_FORMAT_MULTILINE, RDF_EDIT_GENERIC,
+ },
+
+ // TRANSLATORS: URL to a page that defines the license for the document
+ { "license_uri", N_("URI"), "cc:license", RDF_RESOURCE,
+ // TRANSLATORS: this is where you put a URL to a page that defines the license
+ N_("URI to this document's license's namespace definition."), RDF_FORMAT_LINE, RDF_EDIT_SPECIAL,
+ },
+
+ // TRANSLATORS: fragment of XML representing the license of the document
+ { "license_fragment", N_("Fragment"), "License", RDF_XML,
+ N_("XML fragment for the RDF 'License' section."), RDF_FORMAT_MULTILINE, RDF_EDIT_SPECIAL,
+ },
+
+ { NULL, NULL, NULL, RDF_CONTENT,
+ NULL, RDF_FORMAT_LINE, RDF_EDIT_HARDCODED,
+ }
+};
+
+/**
+ * \brief Retrieves a known RDF/Work entity by name
+ * \return A pointer to an RDF/Work entity
+ * \param name The desired RDF/Work entity
+ *
+ */
+struct rdf_work_entity_t *
+rdf_find_entity(gchar const * name)
+{
+ struct rdf_work_entity_t *entity;
+ for (entity=rdf_work_entities; entity->name; entity++) {
+ if (strcmp(entity->name,name)==0) break;
+ }
+ if (entity->name) return entity;
+ return NULL;
+}
+
+/*
+ * Takes the inkscape rdf struct and spits out a static RDF, which is only
+ * useful for testing. We must merge the rdf struct into the XML DOM for
+ * changes to be saved.
+ */
+/*
+
+ Since g_markup_printf_escaped doesn't exist for most people's glib
+ right now, this function will remain commented out since it's only
+ for generic debug anyway. --Kees
+
+gchar *
+rdf_string(struct rdf_t * rdf)
+{
+ gulong overall=0;
+ gchar *string=NULL;
+
+ gchar *rdf_head="\
+<rdf:RDF xmlns=\"http://web.resource.org/cc/\"\
+ xmlns:dc=\"http://purl.org/dc/elements/1.1/\"\
+ xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\
+";
+ gchar *work_head="\
+<Work rdf:about=\"\">\
+ <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/StillImage\" />\
+";
+ gchar *work_title=NULL;
+ gchar *work_date=NULL;
+ gchar *work_description=NULL;
+ gchar *work_creator=NULL;
+ gchar *work_owner=NULL;
+ gchar *work_source=NULL;
+ gchar *work_license=NULL;
+ gchar *license_head=NULL;
+ gchar *license=NULL;
+ gchar *license_end="</License>\n";
+ gchar *work_end="</Work>\n";
+ gchar *rdf_end="</rdf:RDF>\n";
+
+ if (rdf && rdf->work_title && rdf->work_title[0]) {
+ work_title=g_markup_printf_escaped(" <dc:title>%s</dc:title>\n",
+ rdf->work_title);
+ overall+=strlen(work_title);
+ }
+ if (rdf && rdf->work_date && rdf->work_date[0]) {
+ work_date=g_markup_printf_escaped(" <dc:date>%s</dc:date>\n",
+ rdf->work_date);
+ overall+=strlen(work_date);
+ }
+ if (rdf && rdf->work_description && rdf->work_description[0]) {
+ work_description=g_markup_printf_escaped(" <dc:description>%s</dc:description>\n",
+ rdf->work_description);
+ overall+=strlen(work_description);
+ }
+ if (rdf && rdf->work_creator && rdf->work_creator[0]) {
+ work_creator=g_markup_printf_escaped(" <dc:creator><Agent>\
+ <dc:title>%s</dc:title>\
+ </Agent></dc:creator>\n",
+ rdf->work_creator);
+ overall+=strlen(work_creator);
+ }
+ if (rdf && rdf->work_owner && rdf->work_owner[0]) {
+ work_owner=g_markup_printf_escaped(" <dc:rights><Agent>\
+ <dc:title>%s</dc:title>\
+ </Agent></dc:rights>\n",
+ rdf->work_owner);
+ overall+=strlen(work_owner);
+ }
+ if (rdf && rdf->work_source && rdf->work_source[0]) {
+ work_source=g_markup_printf_escaped(" <dc:source rdf:resource=\"%s\" />\n",
+ rdf->work_source);
+ overall+=strlen(work_source);
+ }
+ if (rdf && rdf->license && rdf->license->work_rdf && rdf->license->work_rdf[0]) {
+ work_license=g_markup_printf_escaped(" <license rdf:resource=\"%s\" />\n",
+ rdf->license->work_rdf);
+ overall+=strlen(work_license);
+
+ license_head=g_markup_printf_escaped("<License rdf:about=\"%s\">\n",
+ rdf->license->work_rdf);
+ overall+=strlen(license_head);
+ overall+=strlen(rdf->license->license_rdf);
+ overall+=strlen(license_end);
+ }
+
+ overall+=strlen(rdf_head)+strlen(rdf_end);
+ overall+=strlen(work_head)+strlen(work_end);
+
+ overall++; // NULL term
+
+ if (!(string=(gchar*)g_malloc(overall))) {
+ return NULL;
+ }
+
+ string[0]='\0';
+ strcat(string,rdf_head);
+ strcat(string,work_head);
+
+ if (work_title) strcat(string,work_title);
+ if (work_date) strcat(string,work_date);
+ if (work_description) strcat(string,work_description);
+ if (work_creator) strcat(string,work_creator);
+ if (work_owner) strcat(string,work_owner);
+ if (work_source) strcat(string,work_source);
+ if (work_license) strcat(string,work_license);
+
+ strcat(string,work_end);
+ if (license_head) {
+ strcat(string,license_head);
+ strcat(string,rdf->license->license_rdf);
+ strcat(string,license_end);
+ }
+ strcat(string,rdf_end);
+
+ return string;
+}
+*/
+
+
+/**
+ * \brief Pull the text out of an RDF entity, depends on how it's stored
+ * \return A pointer to the entity's static contents as a string
+ * \param repr The XML element to extract from
+ * \param entity The desired RDF/Work entity
+ *
+ */
+const gchar *
+rdf_get_repr_text ( Inkscape::XML::Node * repr, struct rdf_work_entity_t * entity )
+{
+ g_return_val_if_fail (repr != NULL, NULL);
+ g_return_val_if_fail (entity != NULL, NULL);
+ static gchar * bag = NULL;
+ gchar * holder = NULL;
+
+ Inkscape::XML::Node * temp=NULL;
+ switch (entity->datatype) {
+ case RDF_CONTENT:
+ temp = sp_repr_children(repr);
+ if ( temp == NULL ) return NULL;
+
+ return temp->content();
+
+ case RDF_AGENT:
+ temp = sp_repr_lookup_name ( repr, "cc:Agent", 1 );
+ if ( temp == NULL ) return NULL;
+
+ temp = sp_repr_lookup_name ( temp, "dc:title", 1 );
+ if ( temp == NULL ) return NULL;
+
+ temp = sp_repr_children(temp);
+ if ( temp == NULL ) return NULL;
+
+ return temp->content();
+
+ case RDF_RESOURCE:
+ return repr->attribute("rdf:resource");
+
+ case RDF_XML:
+ return "xml goes here";
+
+ case RDF_BAG:
+ /* clear the static string. yucky. */
+ if (bag) g_free(bag);
+ bag = NULL;
+
+ temp = sp_repr_lookup_name ( repr, "rdf:Bag", 1 );
+ if ( temp == NULL ) {
+ /* backwards compatible: read contents */
+ temp = sp_repr_children(repr);
+ if ( temp == NULL ) return NULL;
+
+ return temp->content();
+ }
+
+ for ( temp = sp_repr_children(temp) ;
+ temp ;
+ temp = sp_repr_next(temp) ) {
+ if (!strcmp(temp->name(),"rdf:li") &&
+ temp->firstChild()) {
+ const gchar * str = temp->firstChild()->content();
+ if (bag) {
+ holder = bag;
+ bag = g_strconcat(holder, ", ", str, NULL);
+ g_free(holder);
+ }
+ else {
+ bag = g_strdup(str);
+ }
+ }
+ }
+ return bag;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
+unsigned int
+rdf_set_repr_text ( Inkscape::XML::Node * repr,
+ struct rdf_work_entity_t * entity,
+ gchar const * text )
+{
+ g_return_val_if_fail ( repr != NULL, 0);
+ g_return_val_if_fail ( entity != NULL, 0);
+ g_return_val_if_fail ( text != NULL, 0);
+ gchar * str = NULL;
+ gchar** strlist = NULL;
+ int i;
+
+ Inkscape::XML::Node * temp=NULL;
+ Inkscape::XML::Node * child=NULL;
+ Inkscape::XML::Node * parent=repr;
+ switch (entity->datatype) {
+ case RDF_CONTENT:
+ temp = sp_repr_children(parent);
+ if ( temp == NULL ) {
+ temp = sp_repr_new_text( text );
+ g_return_val_if_fail (temp != NULL, 0);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+
+ return TRUE;
+ }
+ else {
+ temp->setContent(text);
+ return TRUE;
+ }
+
+ case RDF_AGENT:
+ temp = sp_repr_lookup_name ( parent, "cc:Agent", 1 );
+ if ( temp == NULL ) {
+ temp = sp_repr_new ( "cc:Agent" );
+ g_return_val_if_fail (temp != NULL, 0);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+ }
+ parent = temp;
+
+ temp = sp_repr_lookup_name ( parent, "dc:title", 1 );
+ if ( temp == NULL ) {
+ temp = sp_repr_new ( "dc:title" );
+ g_return_val_if_fail (temp != NULL, 0);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+ }
+ parent = temp;
+
+ temp = sp_repr_children(parent);
+ if ( temp == NULL ) {
+ temp = sp_repr_new_text( text );
+ g_return_val_if_fail (temp != NULL, 0);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+
+ return TRUE;
+ }
+ else {
+ temp->setContent(text);
+ return TRUE;
+ }
+
+ case RDF_RESOURCE:
+ parent->setAttribute("rdf:resource", text );
+ return true;
+
+ case RDF_XML:
+ return 1;
+
+ case RDF_BAG:
+ /* find/create the rdf:Bag item */
+ temp = sp_repr_lookup_name ( parent, "rdf:Bag", 1 );
+ if ( temp == NULL ) {
+ /* backward compatibility: drop the dc:subject contents */
+ while ( (temp = sp_repr_children( parent )) ) {
+ parent->removeChild(temp);
+ }
+
+ temp = sp_repr_new ( "rdf:Bag" );
+ g_return_val_if_fail (temp != NULL, 0);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+ }
+ parent = temp;
+
+ /* toss all the old list items */
+ while ( (temp = sp_repr_children( parent )) ) {
+ parent->removeChild(temp);
+ }
+
+ /* chop our list up on commas */
+ strlist = g_strsplit( text, ",", 0);
+
+ for (i = 0; (str = strlist[i]); i++) {
+ temp = sp_repr_new ( "rdf:li" );
+ g_return_val_if_fail (temp != NULL, 0);
+
+ parent->appendChild(temp);
+ Inkscape::GC::release(temp);
+
+ child = sp_repr_new_text( g_strstrip(str) );
+ g_return_val_if_fail (child != NULL, 0);
+
+ temp->appendChild(child);
+ Inkscape::GC::release(child);
+ }
+ g_strfreev( strlist );
+
+ return 1;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+Inkscape::XML::Node *
+rdf_get_rdf_root_repr ( SPDocument * doc, bool build )
+{
+ g_return_val_if_fail (doc != NULL, NULL);
+ g_return_val_if_fail (doc->rroot != NULL, NULL);
+
+ Inkscape::XML::Node * rdf = sp_repr_lookup_name ( doc->rroot, XML_TAG_NAME_RDF );
+
+ if (rdf == NULL) {
+ //printf("missing XML '%s'\n",XML_TAG_NAME_RDF);
+ if (!build) return NULL;
+
+ Inkscape::XML::Node * svg = sp_repr_lookup_name ( doc->rroot, XML_TAG_NAME_SVG );
+ g_return_val_if_fail ( svg != NULL, NULL );
+
+ Inkscape::XML::Node * parent = sp_repr_lookup_name ( svg, XML_TAG_NAME_METADATA );
+ if ( parent == NULL ) {
+ parent = sp_repr_new( XML_TAG_NAME_METADATA );
+ g_return_val_if_fail ( parent != NULL, NULL);
+
+ svg->appendChild(parent);
+ Inkscape::GC::release(parent);
+ }
+
+ rdf = sp_repr_new( XML_TAG_NAME_RDF );
+ g_return_val_if_fail (rdf != NULL, NULL);
+
+ parent->appendChild(rdf);
+ Inkscape::GC::release(rdf);
+ }
+
+ /*
+ * some implementations do not put RDF stuff inside <metadata>,
+ * so we need to check for it and add it if we don't see it
+ */
+ Inkscape::XML::Node * want_metadata = sp_repr_parent ( rdf );
+ g_return_val_if_fail (want_metadata != NULL, NULL);
+ if (strcmp( want_metadata->name(), XML_TAG_NAME_METADATA )) {
+ Inkscape::XML::Node * metadata = sp_repr_new( XML_TAG_NAME_METADATA );
+ g_return_val_if_fail (metadata != NULL, NULL);
+
+ /* attach the metadata node */
+ want_metadata->appendChild(metadata);
+ Inkscape::GC::release(metadata);
+
+ /* move the RDF into it */
+ Inkscape::GC::anchor(rdf);
+ sp_repr_unparent ( rdf );
+ metadata->appendChild(rdf);
+ Inkscape::GC::release(rdf);
+ }
+
+ return rdf;
+}
+
+Inkscape::XML::Node *
+rdf_get_xml_repr( SPDocument * doc, gchar const * name, bool build )
+{
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (doc != NULL, NULL);
+ g_return_val_if_fail (doc->rroot != NULL, NULL);
+
+ Inkscape::XML::Node * rdf = rdf_get_rdf_root_repr ( doc, build );
+ if (!rdf) return NULL;
+
+ Inkscape::XML::Node * xml = sp_repr_lookup_name ( rdf, name );
+ if (xml == NULL) {
+ //printf("missing XML '%s'\n",name);
+ if (!build) return NULL;
+
+ xml = sp_repr_new( name );
+ g_return_val_if_fail (xml != NULL, NULL);
+
+ xml->setAttribute("rdf:about", "" );
+
+ rdf->appendChild(xml);
+ Inkscape::GC::release(xml);
+ }
+
+ return xml;
+}
+
+Inkscape::XML::Node *
+rdf_get_work_repr( SPDocument * doc, gchar const * name, bool build )
+{
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (doc != NULL, NULL);
+ g_return_val_if_fail (doc->rroot != NULL, NULL);
+
+ Inkscape::XML::Node * work = rdf_get_xml_repr ( doc, XML_TAG_NAME_WORK, build );
+ if (!work) return NULL;
+
+ Inkscape::XML::Node * item = sp_repr_lookup_name ( work, name, 1 );
+ if (item == NULL) {
+ //printf("missing XML '%s'\n",name);
+ if (!build) return NULL;
+
+ item = sp_repr_new( name );
+ g_return_val_if_fail (item != NULL, NULL);
+
+ work->appendChild(item);
+ Inkscape::GC::release(item);
+ }
+
+ return item;
+}
+
+
+
+/**
+ * \brief Retrieves a known RDF/Work entity's contents from the document XML by name
+ * \return A pointer to the entity's static contents as a string, or NULL if no entity exists
+ * \param entity The desired RDF/Work entity
+ *
+ */
+const gchar *
+rdf_get_work_entity(SPDocument * doc, struct rdf_work_entity_t * entity)
+{
+ g_return_val_if_fail (doc != NULL, NULL);
+ if ( entity == NULL ) return NULL;
+ //printf("want '%s'\n",entity->title);
+
+ Inkscape::XML::Node * item;
+ if ( entity->datatype == RDF_XML ) {
+ item = rdf_get_xml_repr ( doc, entity->tag, FALSE );
+ }
+ else {
+ item = rdf_get_work_repr( doc, entity->tag, FALSE );
+ }
+ if ( item == NULL ) return NULL;
+
+ const gchar * result = rdf_get_repr_text ( item, entity );
+ //printf("found '%s' == '%s'\n", entity->title, result );
+ return result;
+}
+
+/**
+ * \brief Stores a string into a named RDF/Work entity in the document XML
+ * \param entity The desired RDF/Work entity to replace
+ * \param string The string to replace the entity contents with
+ *
+ */
+unsigned int
+rdf_set_work_entity(SPDocument * doc, struct rdf_work_entity_t * entity,
+ const gchar * text)
+{
+ g_return_val_if_fail ( entity != NULL, 0 );
+ if (text == NULL) {
+ // FIXME: on a "NULL" text, delete the entity. For now, blank it.
+ text="";
+ }
+
+ /*
+ printf("changing '%s' (%s) to '%s'\n",
+ entity->title,
+ entity->tag,
+ text);
+ */
+
+ Inkscape::XML::Node * item = rdf_get_work_repr( doc, entity->tag, TRUE );
+ g_return_val_if_fail ( item != NULL, 0 );
+
+ return rdf_set_repr_text ( item, entity, text );
+}
+
+#undef DEBUG_MATCH
+
+bool
+rdf_match_license ( Inkscape::XML::Node * repr, struct rdf_license_t * license )
+{
+ g_assert ( repr != NULL );
+ g_assert ( license != NULL );
+
+ bool result=TRUE;
+#ifdef DEBUG_MATCH
+ printf("checking against '%s'\n",license->name);
+#endif
+
+ int count = 0;
+ for (struct rdf_double_t * details = license->details;
+ details->name; details++ ) {
+ count++;
+ }
+ bool * matched = (bool*)calloc(count,sizeof(bool));
+
+ for (Inkscape::XML::Node * current = sp_repr_children ( repr );
+ current;
+ current = sp_repr_next ( current ) ) {
+
+ gchar const * attr = current->attribute("rdf:resource");
+ if ( attr == NULL ) continue;
+
+#ifdef DEBUG_MATCH
+ printf("\texamining '%s' => '%s'\n", current->name(), attr);
+#endif
+
+ bool found_match=FALSE;
+ for (int i=0; i<count; i++) {
+ // skip already matched items
+ if (matched[i]) continue;
+
+#ifdef DEBUG_MATCH
+ printf("\t\t'%s' vs '%s'\n", current->name(), license->details[i].name);
+ printf("\t\t'%s' vs '%s'\n", attr, license->details[i].resource);
+#endif
+
+ if (!strcmp( current->name(),
+ license->details[i].name ) &&
+ !strcmp( attr,
+ license->details[i].resource )) {
+ matched[i]=TRUE;
+ found_match=TRUE;
+#ifdef DEBUG_MATCH
+ printf("\t\tgood!\n");
+#endif
+ break;
+ }
+ }
+ if (!found_match) {
+ // if we checked each known item of the license
+ // and didn't find it, we must abort
+ result=FALSE;
+#ifdef DEBUG_MATCH
+ printf("\t\tno '%s' element matched XML (bong)!\n",license->name);
+#endif
+ break;
+ }
+ }
+#ifdef DEBUG_MATCH
+ if (result) printf("\t\tall XML found matching elements!\n");
+#endif
+ for (int i=0; result && i<count; i++) {
+ // scan looking for an unmatched item
+ if (matched[i]==0) {
+ result=FALSE;
+#ifdef DEBUG_MATCH
+ printf("\t\tnot all '%s' elements used to match (bong)!\n", license->name);
+#endif
+ }
+ }
+
+#ifdef DEBUG_MATCH
+ printf("\t\tall '%s' elements used to match!\n",license->name);
+#endif
+
+ free(matched);
+
+#ifdef DEBUG_MATCH
+ if (result) printf("matched '%s'\n",license->name);
+#endif
+ return result;
+}
+
+/**
+ * \brief Attempts to match and retrieve a known RDF/License from the document XML
+ * \return A pointer to the static RDF license structure
+ *
+ */
+struct rdf_license_t *
+rdf_get_license(SPDocument * document)
+{
+ Inkscape::XML::Node * repr = rdf_get_xml_repr ( document, XML_TAG_NAME_LICENSE, FALSE );
+ if (repr) {
+ for (struct rdf_license_t * license = rdf_licenses;
+ license->name; license++ ) {
+ if ( rdf_match_license ( repr, license ) ) return license;
+ }
+ }
+#ifdef DEBUG_MATCH
+ else {
+ printf("no license XML\n");
+ }
+#endif
+ return NULL;
+}
+
+/**
+ * \brief Stores an RDF/License XML in the document XML
+ * \param document Which document to update
+ * \param license The desired RDF/License structure to store; NULL drops old license, so can be used for proprietary license.
+ *
+ */
+void
+rdf_set_license(SPDocument * document, struct rdf_license_t const * license)
+{
+ // drop old license section
+ Inkscape::XML::Node * repr = rdf_get_xml_repr ( document, XML_TAG_NAME_LICENSE, FALSE );
+ if (repr) sp_repr_unparent(repr);
+
+ if (!license) return;
+
+ // build new license section
+ repr = rdf_get_xml_repr ( document, XML_TAG_NAME_LICENSE, TRUE );
+ g_assert ( repr );
+
+ repr->setAttribute("rdf:about", license->uri );
+
+ for (struct rdf_double_t * detail = license->details;
+ detail->name; detail++) {
+ Inkscape::XML::Node * child = sp_repr_new( detail->name );
+ g_assert ( child != NULL );
+
+ child->setAttribute("rdf:resource", detail->resource );
+ repr->appendChild(child);
+ Inkscape::GC::release(child);
+ }
+}
+
+struct rdf_entity_default_t {
+ gchar const * name;
+ gchar const * text;
+};
+struct rdf_entity_default_t rdf_defaults[] = {
+ { "format", "image/svg+xml", },
+ { "type", "http://purl.org/dc/dcmitype/StillImage", },
+ { NULL, NULL, }
+};
+
+void
+rdf_set_defaults ( SPDocument * document )
+{
+ g_assert ( document != NULL );
+
+ // Create metadata node if it doesn't already exist
+ if (!sp_item_group_get_child_by_name ((SPGroup *) document->root, NULL,
+ XML_TAG_NAME_METADATA)) {
+ // create repr
+ Inkscape::XML::Node * rnew = sp_repr_new (XML_TAG_NAME_METADATA);
+ // insert into the document
+ document->rroot->addChild(rnew, NULL);
+ // clean up
+ Inkscape::GC::release(rnew);
+ }
+
+ /* install defaults */
+ for ( struct rdf_entity_default_t * rdf_default = rdf_defaults;
+ rdf_default->name;
+ rdf_default++) {
+ struct rdf_work_entity_t * entity = rdf_find_entity ( rdf_default->name );
+ g_assert ( entity != NULL );
+
+ if ( rdf_get_work_entity ( document, entity ) == NULL ) {
+ rdf_set_work_entity ( document, entity, rdf_default->text );
+ }
+ }
+}
+
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :