diff --git a/src/uri-references.cpp b/src/uri-references.cpp
index c9482839d56a5452579583549712eb6ba1b9395d..d979fe29230da90439f3955e835504b8c8f7f067 100644 (file)
--- a/src/uri-references.cpp
+++ b/src/uri-references.cpp
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <cstring>
+#include <string>
+
#include "document.h"
#include "sp-object.h"
#include "uri.h"
#include "uri-references.h"
+#include "extract-uri.h"
#include <sigc++/functors/mem_fun.h>
-static gchar *uri_to_id(SPDocument *document, const gchar *uri);
-
namespace Inkscape {
URIReference::URIReference(SPObject *owner)
- : _owner(owner), _owner_document(NULL), _obj(NULL), _uri(NULL)
+ : _owner(owner), _owner_document(NULL), _obj(NULL), _uri(NULL)
{
- g_assert(_owner != NULL);
- /* FIXME !!! attach to owner's destroy signal to clean up in case */
+ g_assert(_owner != NULL);
+ /* FIXME !!! attach to owner's destroy signal to clean up in case */
}
URIReference::URIReference(SPDocument *owner_document)
- : _owner(NULL), _owner_document(owner_document), _obj(NULL), _uri(NULL)
+ : _owner(NULL), _owner_document(owner_document), _obj(NULL), _uri(NULL)
{
- g_assert(_owner_document != NULL);
+ g_assert(_owner_document != NULL);
}
-URIReference::~URIReference() {
- detach();
+URIReference::~URIReference()
+{
+ detach();
}
void URIReference::attach(const URI &uri) throw(BadURIException)
{
- SPDocument *document;
- if (_owner) {
- document = SP_OBJECT_DOCUMENT(_owner);
- } else if (_owner_document) {
- document = _owner_document;
- } else {
- g_assert_not_reached();
- }
- gchar const *fragment = uri.getFragment();
- if ( !uri.isRelative() || uri.getQuery() || !fragment ) {
- throw UnsupportedURIException();
- }
-
- /* FIXME !!! real xpointer support should be delegated to document */
- /* for now this handles the minimal xpointer form that SVG 1.0
- * requires of us
- */
- gchar *id;
- if (!strncmp(fragment, "xpointer(", 9)) {
- /* FIXME !!! this is wasteful */
- /* FIXME: It looks as though this is including "))" in the id. I suggest moving
- the strlen calculation and validity testing to before strdup, and copying just
- the id without the "))". -- pjrm */
- if (!strncmp(fragment, "xpointer(id(", 12)) {
- id = g_strdup(fragment+12);
- size_t const len = strlen(id);
- if ( len < 3 || strcmp(id+len-2, "))") ) {
- g_free(id);
- throw MalformedURIException();
- }
- } else {
- throw UnsupportedURIException();
- }
- } else {
- id = g_strdup(fragment);
- }
-
- /* FIXME !!! validate id as an NCName somewhere */
-
- if (_uri) {
- delete _uri;
- }
- _uri = new URI(uri);
-
- _connection.disconnect();
- _setObject(document->getObjectById(id));
- _connection = document->connectIdChanged(id, sigc::mem_fun(*this, &URIReference::_setObject));
-
- g_free(id);
+ SPDocument *document;
+ if (_owner) {
+ document = SP_OBJECT_DOCUMENT(_owner);
+ } else if (_owner_document) {
+ document = _owner_document;
+ } else {
+ g_assert_not_reached();
+ }
+
+ gchar const *fragment = uri.getFragment();
+ if ( !uri.isRelative() || uri.getQuery() || !fragment ) {
+ throw UnsupportedURIException();
+ }
+
+ /* FIXME !!! real xpointer support should be delegated to document */
+ /* for now this handles the minimal xpointer form that SVG 1.0
+ * requires of us
+ */
+ gchar *id;
+ if (!strncmp(fragment, "xpointer(", 9)) {
+ /* FIXME !!! this is wasteful */
+ /* FIXME: It looks as though this is including "))" in the id. I suggest moving
+ the strlen calculation and validity testing to before strdup, and copying just
+ the id without the "))". -- pjrm */
+ if (!strncmp(fragment, "xpointer(id(", 12)) {
+ id = g_strdup(fragment+12);
+ size_t const len = strlen(id);
+ if ( len < 3 || strcmp(id+len-2, "))") ) {
+ g_free(id);
+ throw MalformedURIException();
+ }
+ } else {
+ throw UnsupportedURIException();
+ }
+ } else {
+ id = g_strdup(fragment);
+ }
+
+ /* FIXME !!! validate id as an NCName somewhere */
+
+ if (_uri) {
+ delete _uri;
+ }
+ _uri = new URI(uri);
+
+ _connection.disconnect();
+ _setObject(document->getObjectById(id));
+ _connection = document->connectIdChanged(id, sigc::mem_fun(*this, &URIReference::_setObject));
+
+ g_free(id);
}
-void URIReference::detach() {
- _connection.disconnect();
- delete _uri;
- _uri = NULL;
- _setObject(NULL);
+void URIReference::detach()
+{
+ _connection.disconnect();
+ delete _uri;
+ _uri = NULL;
+ _setObject(NULL);
}
-void URIReference::_setObject(SPObject *obj) {
- if ( obj && !_acceptObject(obj) ) {
- obj = NULL;
- }
-
- if ( obj == _obj ) return;
-
- SPObject *old_obj=_obj;
- _obj = obj;
-
- _release_connection.disconnect();
- if (_obj) {
- sp_object_href(_obj, _owner);
- _release_connection = _obj->connectRelease(sigc::mem_fun(*this, &URIReference::_release));
- }
- _changed_signal.emit(old_obj, _obj);
- if (old_obj) {
- /* release the old object _after_ the signal emission */
- sp_object_hunref(old_obj, _owner);
- }
+void URIReference::_setObject(SPObject *obj)
+{
+ if ( obj && !_acceptObject(obj) ) {
+ obj = NULL;
+ }
+
+ if ( obj == _obj ) return;
+
+ SPObject *old_obj=_obj;
+ _obj = obj;
+
+ _release_connection.disconnect();
+ if (_obj) {
+ sp_object_href(_obj, _owner);
+ _release_connection = _obj->connectRelease(sigc::mem_fun(*this, &URIReference::_release));
+ }
+ _changed_signal.emit(old_obj, _obj);
+ if (old_obj) {
+ /* release the old object _after_ the signal emission */
+ sp_object_hunref(old_obj, _owner);
+ }
}
/* If an object is deleted, current semantics require that we release
* it on its "release" signal, rather than later, when its ID is actually
* unregistered from the document.
*/
-void URIReference::_release(SPObject *obj) {
- g_assert( _obj == obj );
- _setObject(NULL);
+void URIReference::_release(SPObject *obj)
+{
+ g_assert( _obj == obj );
+ _setObject(NULL);
}
} /* namespace Inkscape */
-static gchar *
-uri_to_id(SPDocument *document, const gchar *uri)
-{
- const gchar *e;
- gchar *id;
- gint len;
-
- g_return_val_if_fail (document != NULL, NULL);
-
- if (!uri) return NULL;
- /* fixme: xpointer, everything */
- if (strncmp (uri, "url(#", 5)) return NULL;
- e = uri + 5;
- while (*e) {
- if (*e == ')') break;
- if (!isalnum (*e) && (*e != '_') && (*e != '-') && (*e != ':') && (*e != '.')) return NULL;
- e += 1;
- if (!*e) return NULL;
- }
- len = e - uri - 5;
- if (len < 1) return NULL;
+SPObject* sp_css_uri_reference_resolve( SPDocument *document, const gchar *uri )
+{
+ SPObject* ref = 0;
- id = (gchar*)g_new(gchar, len + 1);
- memcpy (id, uri + 5, len);
- id[len] = '\0';
+ if ( document && uri && ( strncmp(uri, "url(", 4) == 0 ) ) {
+ gchar *trimmed = extract_uri( uri );
+ if ( trimmed ) {
+ ref = sp_uri_reference_resolve( document, trimmed );
+ g_free( trimmed );
+ }
+ }
- return id;
+ return ref;
}
SPObject *
sp_uri_reference_resolve (SPDocument *document, const gchar *uri)
{
- gchar *id;
+ SPObject* ref = 0;
- id = uri_to_id(document, uri);
- if (!id) return NULL;
+ if ( uri && (*uri == '#') ) {
+ ref = document->getObjectById( uri + 1 );
+ }
- SPObject *ref;
- ref = document->getObjectById(id);
- g_free(id);
- return ref;
+ return ref;
}
-