summaryrefslogtreecommitdiffstats
path: root/src/xml
diff options
context:
space:
mode:
authorMartin Owens <doctormo@gmail.com>2014-03-27 01:33:44 +0000
committerMartin Owens <doctormo@gmail.com>2014-03-27 01:33:44 +0000
commit5a4fb2325f60d292b47330f540b26a3279341c90 (patch)
treed2aa7967be25450b83e625025366c618101ae49f /src/xml
parentThe Polar Arrange Tab of the Arrange Dialog now hides the parametric (diff)
parentRemove Snap menu item and improve grid menu item text (diff)
downloadinkscape-5a4fb2325f60d292b47330f540b26a3279341c90.tar.gz
inkscape-5a4fb2325f60d292b47330f540b26a3279341c90.zip
Commit a merge to trunk, with probabal errors
(bzr r11073.1.36)
Diffstat (limited to 'src/xml')
-rw-r--r--src/xml/Makefile_insert3
-rw-r--r--src/xml/composite-node-observer.cpp8
-rw-r--r--src/xml/composite-node-observer.h2
-rw-r--r--src/xml/event-fns.h2
-rw-r--r--src/xml/event.cpp591
-rw-r--r--src/xml/helper-observer.cpp14
-rw-r--r--src/xml/node-fns.cpp1
-rw-r--r--src/xml/node.h16
-rw-r--r--src/xml/quote-test.h5
-rw-r--r--src/xml/quote.cpp29
-rw-r--r--src/xml/quote.h3
-rw-r--r--src/xml/rebase-hrefs.h2
-rw-r--r--src/xml/repr-css.cpp60
-rw-r--r--src/xml/repr-io.cpp140
-rw-r--r--src/xml/repr-sorting.cpp12
-rw-r--r--src/xml/repr-util.cpp80
-rw-r--r--src/xml/repr.h29
-rw-r--r--src/xml/simple-node.cpp7
18 files changed, 546 insertions, 458 deletions
diff --git a/src/xml/Makefile_insert b/src/xml/Makefile_insert
index b10f2448b..da55d7f7e 100644
--- a/src/xml/Makefile_insert
+++ b/src/xml/Makefile_insert
@@ -40,8 +40,7 @@ ink_common_sources += \
xml/subtree.cpp \
xml/subtree.h \
xml/text-node.h \
- xml/invalid-operation-exception.h \
- xml/xml-forward.h
+ xml/invalid-operation-exception.h
# ######################
# ### CxxTest stuff ####
diff --git a/src/xml/composite-node-observer.cpp b/src/xml/composite-node-observer.cpp
index 36fe469de..7343ab1a8 100644
--- a/src/xml/composite-node-observer.cpp
+++ b/src/xml/composite-node-observer.cpp
@@ -277,7 +277,13 @@ struct vector_data_matches {
bool operator()(NodeObserver const &observer) {
VectorNodeObserver const *vo=dynamic_cast<VectorNodeObserver const *>(&observer);
- return vo && vo->data == data;
+ bool OK = false;
+ if (vo) {
+ if (vo && vo->data == data) {
+ OK = true;
+ }
+ }
+ return OK;
}
};
diff --git a/src/xml/composite-node-observer.h b/src/xml/composite-node-observer.h
index 96825d607..3e4b1673a 100644
--- a/src/xml/composite-node-observer.h
+++ b/src/xml/composite-node-observer.h
@@ -23,7 +23,7 @@ namespace Inkscape {
namespace XML {
-class NodeEventVector;
+struct NodeEventVector;
/**
* @brief An observer that relays notifications to multiple other observers
diff --git a/src/xml/event-fns.h b/src/xml/event-fns.h
index 65c65c48c..5e3b43ad8 100644
--- a/src/xml/event-fns.h
+++ b/src/xml/event-fns.h
@@ -4,7 +4,7 @@
namespace Inkscape {
namespace XML {
-class Document;
+struct Document;
class Event;
class NodeObserver;
diff --git a/src/xml/event.cpp b/src/xml/event.cpp
index 23251eac6..9a760ccc5 100644
--- a/src/xml/event.cpp
+++ b/src/xml/event.cpp
@@ -32,246 +32,247 @@ int Inkscape::XML::Event::_next_serial=0;
void
sp_repr_begin_transaction (Inkscape::XML::Document *doc)
{
- using Inkscape::Debug::SimpleEvent;
- using Inkscape::Debug::EventTracker;
- using Inkscape::Debug::Event;
+ using Inkscape::Debug::SimpleEvent;
+ using Inkscape::Debug::EventTracker;
+ using Inkscape::Debug::Event;
- EventTracker<SimpleEvent<Event::XML> > tracker("begin-transaction");
+ EventTracker<SimpleEvent<Event::XML> > tracker("begin-transaction");
- g_assert(doc != NULL);
- doc->beginTransaction();
+ g_assert(doc != NULL);
+ doc->beginTransaction();
}
void
sp_repr_rollback (Inkscape::XML::Document *doc)
{
- using Inkscape::Debug::SimpleEvent;
- using Inkscape::Debug::EventTracker;
- using Inkscape::Debug::Event;
+ using Inkscape::Debug::SimpleEvent;
+ using Inkscape::Debug::EventTracker;
+ using Inkscape::Debug::Event;
- EventTracker<SimpleEvent<Event::XML> > tracker("rollback");
+ EventTracker<SimpleEvent<Event::XML> > tracker("rollback");
- g_assert(doc != NULL);
- doc->rollback();
+ g_assert(doc != NULL);
+ doc->rollback();
}
void
sp_repr_commit (Inkscape::XML::Document *doc)
{
- using Inkscape::Debug::SimpleEvent;
- using Inkscape::Debug::EventTracker;
- using Inkscape::Debug::Event;
+ using Inkscape::Debug::SimpleEvent;
+ using Inkscape::Debug::EventTracker;
+ using Inkscape::Debug::Event;
- EventTracker<SimpleEvent<Event::XML> > tracker("commit");
+ EventTracker<SimpleEvent<Event::XML> > tracker("commit");
- g_assert(doc != NULL);
- doc->commit();
+ g_assert(doc != NULL);
+ doc->commit();
}
Inkscape::XML::Event *
sp_repr_commit_undoable (Inkscape::XML::Document *doc)
{
- using Inkscape::Debug::SimpleEvent;
- using Inkscape::Debug::EventTracker;
- using Inkscape::Debug::Event;
+ using Inkscape::Debug::SimpleEvent;
+ using Inkscape::Debug::EventTracker;
+ using Inkscape::Debug::Event;
- EventTracker<SimpleEvent<Event::XML> > tracker("commit");
+ EventTracker<SimpleEvent<Event::XML> > tracker("commit");
- g_assert(doc != NULL);
- return doc->commitUndoable();
+ g_assert(doc != NULL);
+ return doc->commitUndoable();
}
namespace {
class LogPerformer : public Inkscape::XML::NodeObserver {
public:
- typedef Inkscape::XML::Node Node;
-
- static LogPerformer &instance() {
- static LogPerformer singleton;
- return singleton;
- }
-
- void notifyChildAdded(Node &parent, Node &child, Node *ref) {
- parent.addChild(&child, ref);
- }
-
- void notifyChildRemoved(Node &parent, Node &child, Node */*old_ref*/) {
- parent.removeChild(&child);
- }
-
- void notifyChildOrderChanged(Node &parent, Node &child,
- Node */*old_ref*/, Node *new_ref)
- {
- parent.changeOrder(&child, new_ref);
- }
-
- void notifyAttributeChanged(Node &node, GQuark name,
- Inkscape::Util::ptr_shared<char> /*old_value*/,
- Inkscape::Util::ptr_shared<char> new_value)
- {
- node.setAttribute(g_quark_to_string(name), new_value);
- }
-
- void notifyContentChanged(Node &node,
- Inkscape::Util::ptr_shared<char> /*old_value*/,
- Inkscape::Util::ptr_shared<char> new_value)
- {
- node.setContent(new_value);
- }
+ typedef Inkscape::XML::Node Node;
+
+ static LogPerformer &instance() {
+ static LogPerformer singleton;
+ return singleton;
+ }
+
+ void notifyChildAdded(Node &parent, Node &child, Node *ref) {
+ parent.addChild(&child, ref);
+ }
+
+ void notifyChildRemoved(Node &parent, Node &child, Node */*old_ref*/) {
+ parent.removeChild(&child);
+ }
+
+ void notifyChildOrderChanged(Node &parent, Node &child,
+ Node */*old_ref*/, Node *new_ref)
+ {
+ parent.changeOrder(&child, new_ref);
+ }
+
+ void notifyAttributeChanged(Node &node, GQuark name,
+ Inkscape::Util::ptr_shared<char> /*old_value*/,
+ Inkscape::Util::ptr_shared<char> new_value)
+ {
+ node.setAttribute(g_quark_to_string(name), new_value);
+ }
+
+ void notifyContentChanged(Node &node,
+ Inkscape::Util::ptr_shared<char> /*old_value*/,
+ Inkscape::Util::ptr_shared<char> new_value)
+ {
+ node.setContent(new_value);
+ }
};
}
void Inkscape::XML::undo_log_to_observer(
- Inkscape::XML::Event const *log,
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::Event const *log,
+ Inkscape::XML::NodeObserver &observer
) {
- for ( Event const *action = log ; action ; action = action->next ) {
- action->undoOne(observer);
- }
+ for ( Event const *action = log ; action ; action = action->next ) {
+ action->undoOne(observer);
+ }
}
-void
-sp_repr_undo_log (Inkscape::XML::Event *log)
+void sp_repr_undo_log (Inkscape::XML::Event *log)
{
- using Inkscape::Debug::SimpleEvent;
- using Inkscape::Debug::EventTracker;
- using Inkscape::Debug::Event;
+ using Inkscape::Debug::SimpleEvent;
+ using Inkscape::Debug::EventTracker;
+ using Inkscape::Debug::Event;
- EventTracker<SimpleEvent<Event::XML> > tracker("undo-log");
+ EventTracker<SimpleEvent<Event::XML> > tracker("undo-log");
- if (log && log->repr) {
- g_assert(!log->repr->document()->inTransaction());
- }
+ if (log) {
+ if (log->repr) {
+ g_assert(!log->repr->document()->inTransaction());
+ }
+ }
- Inkscape::XML::undo_log_to_observer(log, LogPerformer::instance());
+ Inkscape::XML::undo_log_to_observer(log, LogPerformer::instance());
}
void Inkscape::XML::EventAdd::_undoOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyChildRemoved(*this->repr, *this->child, this->ref);
+ observer.notifyChildRemoved(*this->repr, *this->child, this->ref);
}
void Inkscape::XML::EventDel::_undoOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyChildAdded(*this->repr, *this->child, this->ref);
+ observer.notifyChildAdded(*this->repr, *this->child, this->ref);
}
void Inkscape::XML::EventChgAttr::_undoOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyAttributeChanged(*this->repr, this->key, this->newval, this->oldval);
+ observer.notifyAttributeChanged(*this->repr, this->key, this->newval, this->oldval);
}
void Inkscape::XML::EventChgContent::_undoOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyContentChanged(*this->repr, this->newval, this->oldval);
+ observer.notifyContentChanged(*this->repr, this->newval, this->oldval);
}
void Inkscape::XML::EventChgOrder::_undoOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyChildOrderChanged(*this->repr, *this->child, this->newref, this->oldref);
+ observer.notifyChildOrderChanged(*this->repr, *this->child, this->newref, this->oldref);
}
void Inkscape::XML::replay_log_to_observer(
- Inkscape::XML::Event const *log,
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::Event const *log,
+ Inkscape::XML::NodeObserver &observer
) {
- List<Inkscape::XML::Event const &> reversed =
- reverse_list<Inkscape::XML::Event::ConstIterator>(log, NULL);
- for ( ; reversed ; ++reversed ) {
- reversed->replayOne(observer);
- }
+ List<Inkscape::XML::Event const &> reversed =
+ reverse_list<Inkscape::XML::Event::ConstIterator>(log, NULL);
+ for ( ; reversed ; ++reversed ) {
+ reversed->replayOne(observer);
+ }
}
void
sp_repr_replay_log (Inkscape::XML::Event *log)
{
- using Inkscape::Debug::SimpleEvent;
- using Inkscape::Debug::EventTracker;
- using Inkscape::Debug::Event;
+ using Inkscape::Debug::SimpleEvent;
+ using Inkscape::Debug::EventTracker;
+ using Inkscape::Debug::Event;
- EventTracker<SimpleEvent<Event::XML> > tracker("replay-log");
+ EventTracker<SimpleEvent<Event::XML> > tracker("replay-log");
- if (log) {
- if (log->repr->document()) {
- g_assert(!log->repr->document()->inTransaction());
- }
- }
+ if (log) {
+ if (log->repr->document()) {
+ g_assert(!log->repr->document()->inTransaction());
+ }
+ }
- Inkscape::XML::replay_log_to_observer(log, LogPerformer::instance());
+ Inkscape::XML::replay_log_to_observer(log, LogPerformer::instance());
}
void Inkscape::XML::EventAdd::_replayOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyChildAdded(*this->repr, *this->child, this->ref);
+ observer.notifyChildAdded(*this->repr, *this->child, this->ref);
}
void Inkscape::XML::EventDel::_replayOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyChildRemoved(*this->repr, *this->child, this->ref);
+ observer.notifyChildRemoved(*this->repr, *this->child, this->ref);
}
void Inkscape::XML::EventChgAttr::_replayOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyAttributeChanged(*this->repr, this->key, this->oldval, this->newval);
+ observer.notifyAttributeChanged(*this->repr, this->key, this->oldval, this->newval);
}
void Inkscape::XML::EventChgContent::_replayOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyContentChanged(*this->repr, this->oldval, this->newval);
+ observer.notifyContentChanged(*this->repr, this->oldval, this->newval);
}
void Inkscape::XML::EventChgOrder::_replayOne(
- Inkscape::XML::NodeObserver &observer
+ Inkscape::XML::NodeObserver &observer
) const {
- observer.notifyChildOrderChanged(*this->repr, *this->child, this->oldref, this->newref);
+ observer.notifyChildOrderChanged(*this->repr, *this->child, this->oldref, this->newref);
}
Inkscape::XML::Event *
sp_repr_coalesce_log (Inkscape::XML::Event *a, Inkscape::XML::Event *b)
{
- Inkscape::XML::Event *action;
- Inkscape::XML::Event **prev_ptr;
+ Inkscape::XML::Event *action;
+ Inkscape::XML::Event **prev_ptr;
- if (!b) return a;
- if (!a) return b;
+ if (!b) return a;
+ if (!a) return b;
- /* find the earliest action in the second log */
- /* (also noting the pointer that references it, so we can
- * replace it later) */
- prev_ptr = &b;
- for ( action = b ; action->next ; action = action->next ) {
- prev_ptr = &action->next;
- }
+ /* find the earliest action in the second log */
+ /* (also noting the pointer that references it, so we can
+ * replace it later) */
+ prev_ptr = &b;
+ for ( action = b ; action->next ; action = action->next ) {
+ prev_ptr = &action->next;
+ }
- /* add the first log after it */
- action->next = a;
+ /* add the first log after it */
+ action->next = a;
- /* optimize the result */
- *prev_ptr = action->optimizeOne();
+ /* optimize the result */
+ *prev_ptr = action->optimizeOne();
- return b;
+ return b;
}
void
sp_repr_free_log (Inkscape::XML::Event *log)
{
- while (log) {
- Inkscape::XML::Event *action;
- action = log;
- log = action->next;
- delete action;
- }
+ while (log) {
+ Inkscape::XML::Event *action;
+ action = log;
+ log = action->next;
+ delete action;
+ }
}
namespace {
@@ -280,199 +281,211 @@ template <typename T> struct ActionRelations;
template <>
struct ActionRelations<Inkscape::XML::EventAdd> {
- typedef Inkscape::XML::EventDel Opposite;
+ typedef Inkscape::XML::EventDel Opposite;
};
template <>
struct ActionRelations<Inkscape::XML::EventDel> {
- typedef Inkscape::XML::EventAdd Opposite;
+ typedef Inkscape::XML::EventAdd Opposite;
};
template <typename A>
Inkscape::XML::Event *cancel_add_or_remove(A *action) {
- typedef typename ActionRelations<A>::Opposite Opposite;
- Opposite *opposite=dynamic_cast<Opposite *>(action->next);
-
- if ( opposite && opposite->repr == action->repr &&
- opposite->child == action->child &&
- opposite->ref == action->ref )
- {
- Inkscape::XML::Event *remaining=opposite->next;
-
- delete opposite;
- delete action;
-
- return remaining;
- } else {
- return action;
- }
+ typedef typename ActionRelations<A>::Opposite Opposite;
+ Opposite *opposite=dynamic_cast<Opposite *>(action->next);
+
+ bool OK = false;
+ if (opposite){
+ if (opposite->repr == action->repr &&
+ opposite->child == action->child &&
+ opposite->ref == action->ref ) {
+ OK = true;
+ }
+ }
+ if (OK){
+ Inkscape::XML::Event *remaining=opposite->next;
+
+ delete opposite;
+ delete action;
+
+ return remaining;
+ } else {
+ return action;
+ }
}
-
}
Inkscape::XML::Event *Inkscape::XML::EventAdd::_optimizeOne() {
- return cancel_add_or_remove(this);
+ return cancel_add_or_remove(this);
}
Inkscape::XML::Event *Inkscape::XML::EventDel::_optimizeOne() {
- return cancel_add_or_remove(this);
+ return cancel_add_or_remove(this);
}
Inkscape::XML::Event *Inkscape::XML::EventChgAttr::_optimizeOne() {
- Inkscape::XML::EventChgAttr *chg_attr=dynamic_cast<Inkscape::XML::EventChgAttr *>(this->next);
-
- /* consecutive chgattrs on the same key can be combined */
- if ( chg_attr && chg_attr->repr == this->repr &&
- chg_attr->key == this->key )
- {
- /* replace our oldval with the prior action's */
- this->oldval = chg_attr->oldval;
-
- /* discard the prior action */
- this->next = chg_attr->next;
- delete chg_attr;
- }
-
- return this;
+ Inkscape::XML::EventChgAttr *chg_attr=dynamic_cast<Inkscape::XML::EventChgAttr *>(this->next);
+
+ /* consecutive chgattrs on the same key can be combined */
+ if ( chg_attr) {
+ if ( chg_attr->repr == this->repr &&
+ chg_attr->key == this->key )
+ {
+ /* replace our oldval with the prior action's */
+ this->oldval = chg_attr->oldval;
+
+ /* discard the prior action */
+ this->next = chg_attr->next;
+ delete chg_attr;
+ }
+ }
+
+ return this;
}
Inkscape::XML::Event *Inkscape::XML::EventChgContent::_optimizeOne() {
- Inkscape::XML::EventChgContent *chg_content=dynamic_cast<Inkscape::XML::EventChgContent *>(this->next);
+ Inkscape::XML::EventChgContent *chg_content=dynamic_cast<Inkscape::XML::EventChgContent *>(this->next);
- /* consecutive content changes can be combined */
- if ( chg_content && chg_content->repr == this->repr ) {
- /* replace our oldval with the prior action's */
- this->oldval = chg_content->oldval;
+ /* consecutive content changes can be combined */
+ if (chg_content) {
+ if (chg_content->repr == this->repr ) {
+ /* replace our oldval with the prior action's */
+ this->oldval = chg_content->oldval;
- /* get rid of the prior action*/
- this->next = chg_content->next;
- delete chg_content;
- }
+ /* get rid of the prior action*/
+ this->next = chg_content->next;
+ delete chg_content;
+ }
+ }
- return this;
+ return this;
}
Inkscape::XML::Event *Inkscape::XML::EventChgOrder::_optimizeOne() {
- Inkscape::XML::EventChgOrder *chg_order=dynamic_cast<Inkscape::XML::EventChgOrder *>(this->next);
-
- /* consecutive chgorders for the same child may be combined or
- * canceled out */
- if ( chg_order && chg_order->repr == this->repr &&
- chg_order->child == this->child )
- {
- if ( chg_order->oldref == this->newref ) {
- /* cancel them out */
- Inkscape::XML::Event *after=chg_order->next;
-
- delete chg_order;
- delete this;
-
- return after;
- } else {
- /* combine them */
- this->oldref = chg_order->oldref;
-
- /* get rid of the other one */
- this->next = chg_order->next;
- delete chg_order;
-
- return this;
- }
- } else {
- return this;
- }
+ Inkscape::XML::EventChgOrder *chg_order=dynamic_cast<Inkscape::XML::EventChgOrder *>(this->next);
+
+ /* consecutive chgorders for the same child may be combined or
+ * canceled out */
+ bool OK = false;
+ if (chg_order) {
+ if (chg_order->repr == this->repr &&
+ chg_order->child == this->child ){
+ OK = true;
+ }
+ }
+ if (OK) {
+ if ( chg_order->oldref == this->newref ) {
+ /* cancel them out */
+ Inkscape::XML::Event *after=chg_order->next;
+
+ delete chg_order;
+ delete this;
+
+ return after;
+ } else {
+ /* combine them */
+ this->oldref = chg_order->oldref;
+
+ /* get rid of the other one */
+ this->next = chg_order->next;
+ delete chg_order;
+
+ return this;
+ }
+ } else {
+ return this;
+ }
}
namespace {
class LogPrinter : public Inkscape::XML::NodeObserver {
public:
- typedef Inkscape::XML::Node Node;
-
- static LogPrinter &instance() {
- static LogPrinter singleton;
- return singleton;
- }
-
- static Glib::ustring node_to_string(Node const &node) {
- Glib::ustring result;
- char const *type_name=NULL;
- switch (node.type()) {
- case Inkscape::XML::DOCUMENT_NODE:
- type_name = "Document";
- break;
- case Inkscape::XML::ELEMENT_NODE:
- type_name = "Element";
- break;
- case Inkscape::XML::TEXT_NODE:
- type_name = "Text";
- break;
- case Inkscape::XML::COMMENT_NODE:
- type_name = "Comment";
- break;
- default:
- g_assert_not_reached();
- }
- char buffer[40];
- result.append("#<");
- result.append(type_name);
- result.append(":");
- snprintf(buffer, 40, "0x%p", &node);
- result.append(buffer);
- result.append(">");
-
- return result;
- }
-
- static Glib::ustring ref_to_string(Node *ref) {
- if (ref) {
- return node_to_string(*ref);
- } else {
- return "beginning";
- }
- }
-
- void notifyChildAdded(Node &parent, Node &child, Node *ref) {
- g_warning("Event: Added %s to %s after %s", node_to_string(parent).c_str(), node_to_string(child).c_str(), ref_to_string(ref).c_str());
- }
-
- void notifyChildRemoved(Node &parent, Node &child, Node */*ref*/) {
- g_warning("Event: Removed %s from %s", node_to_string(parent).c_str(), node_to_string(child).c_str());
- }
-
- void notifyChildOrderChanged(Node &parent, Node &child,
- Node */*old_ref*/, Node *new_ref)
- {
- g_warning("Event: Moved %s after %s in %s", node_to_string(child).c_str(), ref_to_string(new_ref).c_str(), node_to_string(parent).c_str());
- }
-
- void notifyAttributeChanged(Node &node, GQuark name,
- Inkscape::Util::ptr_shared<char> /*old_value*/,
- Inkscape::Util::ptr_shared<char> new_value)
- {
- if (new_value) {
- g_warning("Event: Set attribute %s to \"%s\" on %s", g_quark_to_string(name), new_value.pointer(), node_to_string(node).c_str());
- } else {
- g_warning("Event: Unset attribute %s on %s", g_quark_to_string(name), node_to_string(node).c_str());
- }
- }
-
- void notifyContentChanged(Node &node,
- Inkscape::Util::ptr_shared<char> /*old_value*/,
- Inkscape::Util::ptr_shared<char> new_value)
- {
- if (new_value) {
- g_warning("Event: Set content of %s to \"%s\"", node_to_string(node).c_str(), new_value.pointer());
- } else {
- g_warning("Event: Unset content of %s", node_to_string(node).c_str());
- }
- }
+ typedef Inkscape::XML::Node Node;
+
+ static LogPrinter &instance() {
+ static LogPrinter singleton;
+ return singleton;
+ }
+
+ static Glib::ustring node_to_string(Node const &node) {
+ Glib::ustring result;
+ char const *type_name=NULL;
+ switch (node.type()) {
+ case Inkscape::XML::DOCUMENT_NODE:
+ type_name = "Document";
+ break;
+ case Inkscape::XML::ELEMENT_NODE:
+ type_name = "Element";
+ break;
+ case Inkscape::XML::TEXT_NODE:
+ type_name = "Text";
+ break;
+ case Inkscape::XML::COMMENT_NODE:
+ type_name = "Comment";
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ char buffer[40];
+ result.append("#<");
+ result.append(type_name);
+ result.append(":");
+ snprintf(buffer, 40, "0x%p", &node);
+ result.append(buffer);
+ result.append(">");
+
+ return result;
+ }
+
+ static Glib::ustring ref_to_string(Node *ref) {
+ if (ref) {
+ return node_to_string(*ref);
+ } else {
+ return "beginning";
+ }
+ }
+
+ void notifyChildAdded(Node &parent, Node &child, Node *ref) {
+ g_warning("Event: Added %s to %s after %s", node_to_string(parent).c_str(), node_to_string(child).c_str(), ref_to_string(ref).c_str());
+ }
+
+ void notifyChildRemoved(Node &parent, Node &child, Node */*ref*/) {
+ g_warning("Event: Removed %s from %s", node_to_string(parent).c_str(), node_to_string(child).c_str());
+ }
+
+ void notifyChildOrderChanged(Node &parent, Node &child,
+ Node */*old_ref*/, Node *new_ref)
+ {
+ g_warning("Event: Moved %s after %s in %s", node_to_string(child).c_str(), ref_to_string(new_ref).c_str(), node_to_string(parent).c_str());
+ }
+
+ void notifyAttributeChanged(Node &node, GQuark name,
+ Inkscape::Util::ptr_shared<char> /*old_value*/,
+ Inkscape::Util::ptr_shared<char> new_value)
+ {
+ if (new_value) {
+ g_warning("Event: Set attribute %s to \"%s\" on %s", g_quark_to_string(name), new_value.pointer(), node_to_string(node).c_str());
+ } else {
+ g_warning("Event: Unset attribute %s on %s", g_quark_to_string(name), node_to_string(node).c_str());
+ }
+ }
+
+ void notifyContentChanged(Node &node,
+ Inkscape::Util::ptr_shared<char> /*old_value*/,
+ Inkscape::Util::ptr_shared<char> new_value)
+ {
+ if (new_value) {
+ g_warning("Event: Set content of %s to \"%s\"", node_to_string(node).c_str(), new_value.pointer());
+ } else {
+ g_warning("Event: Unset content of %s", node_to_string(node).c_str());
+ }
+ }
};
}
-void
-sp_repr_debug_print_log(Inkscape::XML::Event const *log) {
- Inkscape::XML::replay_log_to_observer(log, LogPrinter::instance());
+void sp_repr_debug_print_log(Inkscape::XML::Event const *log) {
+ Inkscape::XML::replay_log_to_observer(log, LogPrinter::instance());
}
diff --git a/src/xml/helper-observer.cpp b/src/xml/helper-observer.cpp
index ce902ba75..c54dd8e74 100644
--- a/src/xml/helper-observer.cpp
+++ b/src/xml/helper-observer.cpp
@@ -13,10 +13,16 @@ void SignalObserver::set(SPObject* o)
{
// XML Tree being used direcly in this function in the following code
// while it shouldn't be
- if(_oldsel && _oldsel->getRepr())
- _oldsel->getRepr()->removeObserver(*this);
- if(o && o->getRepr())
- o->getRepr()->addObserver(*this);
+ if(_oldsel) {
+ if (_oldsel->getRepr()) {
+ _oldsel->getRepr()->removeObserver(*this);
+ }
+ }
+ if(o) {
+ if (o->getRepr()) {
+ o->getRepr()->addObserver(*this);
+ }
+ }
_oldsel = o;
}
diff --git a/src/xml/node-fns.cpp b/src/xml/node-fns.cpp
index 20e9fbc38..eb3870978 100644
--- a/src/xml/node-fns.cpp
+++ b/src/xml/node-fns.cpp
@@ -9,6 +9,7 @@
#include "xml/node-iterators.h"
#include "util/find-if-before.h"
+#include "node-fns.h"
namespace Inkscape {
namespace XML {
diff --git a/src/xml/node.h b/src/xml/node.h
index e83d8a7b7..c1977b0a8 100644
--- a/src/xml/node.h
+++ b/src/xml/node.h
@@ -19,6 +19,7 @@
#define SEEN_INKSCAPE_XML_NODE_H
#include <glibmm/value.h>
+#include <glibmm/ustring.h>
#include "gc-anchored.h"
#include "util/list.h"
@@ -194,6 +195,7 @@ public:
*/
virtual void setContent(gchar const *value)=0;
+ //@{
/**
* @brief Change an attribute of this node
*
@@ -204,7 +206,19 @@ public:
* @param is_interactive Ignored
*/
virtual void setAttribute(gchar const *key, gchar const *value, bool is_interactive=false)=0;
-
+
+ void setAttribute(char const *key, Glib::ustring const &value, bool is_interactive=false)
+ {
+ setAttribute(key, value.empty() ? NULL : value.c_str(), is_interactive);
+ }
+
+ void setAttribute(Glib::ustring const &key, Glib::ustring const &value, bool is_interactive=false)
+ {
+ setAttribute( key.empty() ? NULL : key.c_str(),
+ value.empty() ? NULL : value.c_str(), is_interactive);
+ }
+ //@}
+
/**
* @brief Directly set the integer GQuark code for the name of the node
*
diff --git a/src/xml/quote-test.h b/src/xml/quote-test.h
index bd5c1f54c..bc01ec4e9 100644
--- a/src/xml/quote-test.h
+++ b/src/xml/quote-test.h
@@ -7,10 +7,7 @@
#include <cstring>
#include <functional>
-/* mental disclaims all responsibility for this evil idea for testing
- static functions. The main disadvantages are that we retain any
- #define's and `using' directives of the included file. */
-#include "quote.cpp"
+#include "quote.h"
class XmlQuoteTest : public CxxTest::TestSuite
{
diff --git a/src/xml/quote.cpp b/src/xml/quote.cpp
index 51f9ffb97..02c12dfb0 100644
--- a/src/xml/quote.cpp
+++ b/src/xml/quote.cpp
@@ -13,22 +13,25 @@
#include <cstring>
#include <glib.h>
+#include "quote.h"
/** \return strlen(xml_quote_strdup(\a val)) (without doing the malloc).
* \pre val != NULL
*/
-static size_t
+size_t
xml_quoted_strlen(char const *val)
{
size_t ret = 0;
- for (; *val != '\0'; val++) {
- switch (*val) {
- case '"': ret += sizeof("&quot;") - 1; break;
- case '&': ret += sizeof("&amp;") - 1; break;
- case '<': ret += sizeof("&lt;") - 1; break;
- case '>': ret += sizeof("&gt;") - 1; break;
- default: ++ret; break;
+ if (val != NULL) {
+ for (; *val != '\0'; val++) {
+ switch (*val) {
+ case '"': ret += sizeof("&quot;") - 1; break;
+ case '&': ret += sizeof("&amp;") - 1; break;
+ case '<': ret += sizeof("&lt;") - 1; break;
+ case '>': ret += sizeof("&gt;") - 1; break;
+ default: ++ret; break;
+ }
}
}
return ret;
@@ -42,11 +45,11 @@ xml_quoted_strlen(char const *val)
static void
xml_quote(char *dest, char const *src)
{
-#define COPY_LIT(_lit) do { \
- size_t cpylen = sizeof(_lit "") - 1; \
- memcpy(dest, _lit, cpylen); \
- dest += cpylen; \
- } while(0)
+#define COPY_LIT(_lit) do { \
+ size_t cpylen = sizeof(_lit "") - 1; \
+ memcpy(dest, _lit, cpylen); \
+ dest += cpylen; \
+ } while(0)
for (; *src != '\0'; ++src) {
switch (*src) {
diff --git a/src/xml/quote.h b/src/xml/quote.h
index 597272cd3..8e3bca0eb 100644
--- a/src/xml/quote.h
+++ b/src/xml/quote.h
@@ -1,6 +1,9 @@
#ifndef SEEN_XML_QUOTE_H
#define SEEN_XML_QUOTE_H
+#include <stddef.h>
+
+size_t xml_quoted_strlen(char const *val);
char *xml_quote_strdup(char const *src);
diff --git a/src/xml/rebase-hrefs.h b/src/xml/rebase-hrefs.h
index adb09e52a..5baf96516 100644
--- a/src/xml/rebase-hrefs.h
+++ b/src/xml/rebase-hrefs.h
@@ -4,7 +4,7 @@
#include <glib.h>
#include "util/list.h"
#include "xml/attribute-record.h"
-struct SPDocument;
+class SPDocument;
namespace Inkscape {
namespace XML {
diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp
index 19f3f1d6c..24e2db9e1 100644
--- a/src/xml/repr-css.cpp
+++ b/src/xml/repr-css.cpp
@@ -27,6 +27,7 @@
#include "xml/repr.h"
#include "xml/simple-document.h"
#include "xml/simple-node.h"
+#include "xml/sp-css-attr.h"
#include "style.h"
#include "libcroco/cr-sel-eng.h"
@@ -270,10 +271,9 @@ double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double def
/**
* Write a style attribute string from a list of properties stored in an SPCSAttr object.
*/
-gchar *sp_repr_css_write_string(SPCSSAttr *css)
+void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str)
{
- Glib::ustring buffer;
-
+ str.clear();
for ( List<AttributeRecord const> iter = css->attributeList() ;
iter ; ++iter )
{
@@ -281,28 +281,21 @@ gchar *sp_repr_css_write_string(SPCSSAttr *css)
continue;
}
- buffer.append(g_quark_to_string(iter->key));
- buffer.push_back(':');
+ str.append(g_quark_to_string(iter->key));
+ str.push_back(':');
if (!strcmp(g_quark_to_string(iter->key), "font-family")
|| !strcmp(g_quark_to_string(iter->key), "-inkscape-font-specification")) {
// we only quote font-family/font-specification, as SPStyle does
- gchar *t = g_strdup (iter->value);
- g_free (t);
- gchar *val_quoted = css2_escape_quote (iter->value);
- if (val_quoted) {
- buffer.append(val_quoted);
- g_free (val_quoted);
- }
+ Glib::ustring val_quoted = css2_escape_quote (iter->value);
+ str.append(val_quoted);
} else {
- buffer.append(iter->value); // unquoted
+ str.append(iter->value); // unquoted
}
if (rest(iter)) {
- buffer.push_back(';');
+ str.push_back(';');
}
}
-
- return (buffer.empty() ? NULL : g_strdup (buffer.c_str()));
}
/**
@@ -314,17 +307,16 @@ void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
g_assert(css != NULL);
g_assert(attr != NULL);
- gchar *value = sp_repr_css_write_string(css);
+ Glib::ustring value;
+ sp_repr_css_write_string(css, value);
/*
* If the new value is different from the old value, this will sometimes send a signal via
* CompositeNodeObserver::notiftyAttributeChanged() which results in calling
- * SPObject::sp_object_repr_attr_changed and thus updates the object's SPStyle. This update
+ * SPObject::repr_attr_changed and thus updates the object's SPStyle. This update
* results in another call to repr->setAttribute().
*/
- repr->setAttribute(attr, value);
-
- if (value) g_free (value);
+ repr->setAttribute(attr, value.c_str());
}
/**
@@ -360,12 +352,32 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con
guchar *const str_value_unsigned = cr_term_to_string(decl->value);
gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned);
gchar *value_unquoted = attribute_unquote (str_value); // libcroco returns strings quoted in ""
+ Glib::ustring value_unquoted2 = value_unquoted ? value_unquoted : Glib::ustring();
+ Glib::ustring units;
+
+ /*
+ * Problem with parsing of units em and ex, like font-size "1.2em" and "3.4ex"
+ * stringstream thinks they are in scientific "e" notation and fails
+ * Must be a better way using std::fixed, precision etc
+ *
+ * HACK for now is to strip off em and ex units and add them back at the end
+ */
+ int le = value_unquoted2.length();
+ if (le > 2) {
+ units = value_unquoted2.substr(le-2, 2);
+ if ((units == "em") || (units == "ex")) {
+ value_unquoted2 = value_unquoted2.substr(0, le-2);
+ }
+ else {
+ units.clear();
+ }
+ }
// libcroco uses %.17f for formatting... leading to trailing zeros or small rounding errors.
// CSSOStringStream is used here to write valid CSS (as in sp_style_write_string). This has
// the additional benefit of respecting the numerical precission set in the SVG Output
// preferences. We assume any numerical part comes first (if not, the whole string is copied).
- std::stringstream ss( value_unquoted );
+ std::stringstream ss( value_unquoted2 );
double number = 0;
std::string characters;
std::string temp;
@@ -379,6 +391,10 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con
Inkscape::CSSOStringStream os;
if( number_valid ) os << number;
os << characters;
+ if (!units.empty()) {
+ os << units;
+ //g_message("sp_repr_css_merge_from_decl looks like em or ex units %s --> %s", str_value, os.str().c_str());
+ }
((Node *) css)->setAttribute(decl->property->stryng->str, os.str().c_str(), false);
g_free(value_unquoted);
g_free(str_value);
diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp
index b85e58899..0319bb5e3 100644
--- a/src/xml/repr-io.cpp
+++ b/src/xml/repr-io.cpp
@@ -37,6 +37,8 @@
#include "preferences.h"
+#include <glibmm/miscutils.h>
+
using Inkscape::IO::Writer;
using Inkscape::Util::List;
using Inkscape::Util::cons;
@@ -76,11 +78,14 @@ public:
XmlSource()
: filename(0),
encoding(0),
- fp(0),
+ fp(NULL),
firstFewLen(0),
+ LoadEntities(false),
+ cachedData(),
+ cachedPos(0),
dummy("x"),
- instr(0),
- gzin(0)
+ instr(NULL),
+ gzin(NULL)
{
for (int k=0;k<4;k++)
{
@@ -96,7 +101,9 @@ public:
}
}
- int setFile( char const * filename );
+ int setFile( char const * filename, bool load_entities );
+
+ xmlDocPtr readXml();
static int readCb( void * context, char * buffer, int len );
static int closeCb( void * context );
@@ -110,12 +117,15 @@ private:
FILE* fp;
unsigned char firstFew[4];
int firstFewLen;
+ bool LoadEntities; // Checks for SYSTEM Entities (requires cached data)
+ std::string cachedData;
+ unsigned int cachedPos;
Inkscape::URI dummy;
Inkscape::IO::UriInputStream* instr;
Inkscape::IO::GzipInputStream* gzin;
};
-int XmlSource::setFile(char const *filename)
+int XmlSource::setFile(char const *filename, bool load_entities=false)
{
int retVal = -1;
@@ -172,14 +182,62 @@ int XmlSource::setFile(char const *filename)
retVal = 0; // no error
}
}
+ if(load_entities) {
+ this->cachedData = std::string("");
+ this->cachedPos = 0;
+
+ // First get data from file in typical way (cache it all)
+ char *buffer = new char [4096];
+ while(true) {
+ int len = this->read(buffer, 4096);
+ if(len <= 0) break;
+ buffer[len] = 0;
+ this->cachedData += buffer;
+ }
+ delete[] buffer;
+
+ // Check for SYSTEM or PUBLIC entities and remove them from the cache
+ GMatchInfo *info;
+ gint start, end;
+ GRegex *regex = g_regex_new(
+ "<!ENTITY\\s+[^>\\s]+\\s+(SYSTEM|PUBLIC\\s+\"[^>\"]+\")\\s+\"[^>\"]+\"\\s*>",
+ G_REGEX_CASELESS, G_REGEX_MATCH_NEWLINE_ANY, NULL);
+
+ g_regex_match (regex, this->cachedData.c_str(), G_REGEX_MATCH_NEWLINE_ANY, &info);
+
+ while (g_match_info_matches (info)) {
+ if (g_match_info_fetch_pos (info, 1, &start, &end))
+ this->cachedData.erase(start, end - start);
+ g_match_info_next (info, NULL);
+ }
+ g_match_info_free(info);
+ g_regex_unref(regex);
+ }
+ // Do this after loading cache, so reads don't return cache to fill cache.
+ this->LoadEntities = load_entities;
return retVal;
}
+xmlDocPtr XmlSource::readXml()
+{
+ int parse_options = XML_PARSE_HUGE | XML_PARSE_RECOVER;
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool allowNetAccess = prefs->getBool("/options/externalresources/xml/allow_net_access", false);
+ if (!allowNetAccess) parse_options |= XML_PARSE_NONET;
+
+ // Allow NOENT only if we're filtering out SYSTEM and PUBLIC entities
+ if (LoadEntities) parse_options |= XML_PARSE_NOENT;
+
+ return xmlReadIO( readCb, closeCb, this,
+ filename, getEncoding(), parse_options);
+}
int XmlSource::readCb( void * context, char * buffer, int len )
{
int retVal = -1;
+
if ( context ) {
XmlSource* self = static_cast<XmlSource*>(context);
retVal = self->read( buffer, len );
@@ -201,7 +259,15 @@ int XmlSource::read( char *buffer, int len )
int retVal = 0;
size_t got = 0;
- if ( firstFewLen > 0 ) {
+ if ( LoadEntities ) {
+ if (cachedPos >= cachedData.length()) {
+ return -1;
+ } else {
+ retVal = cachedData.copy(buffer, len, cachedPos);
+ cachedPos += retVal;
+ return retVal; // Do NOT continue.
+ }
+ } else if ( firstFewLen > 0 ) {
int some = (len < firstFewLen) ? len : firstFewLen;
memcpy( buffer, firstFew, some );
if ( len < firstFewLen ) {
@@ -268,7 +334,10 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns)
xmlSubstituteEntitiesDefault(1);
g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS ), NULL);
+ if (!Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS )) {
+ g_warning("Can't open file: %s (doesn't exist)", filename);
+ return NULL;
+ }
/* fixme: A file can disappear at any time, including between now and when we actually try to
* open it. Get rid of the above test once we're sure that we correctly handle
* non-existence. */
@@ -297,16 +366,20 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns)
XmlSource src;
if ( (src.setFile(filename) == 0) ) {
- doc = xmlReadIO( XmlSource::readCb,
- XmlSource::closeCb,
- &src,
- localFilename,
- src.getEncoding(),
- XML_PARSE_NOENT | XML_PARSE_HUGE);
+ doc = src.readXml();
+ rdoc = sp_repr_do_read( doc, default_ns );
+ // For some reason, failed ns loading results in this
+ // We try a system check version of load with NOENT for adobe
+ if(rdoc && strcmp(rdoc->root()->name(), "ns:svg") == 0) {
+ xmlFreeDoc( doc );
+ src.setFile(filename, true);
+ doc = src.readXml();
+ rdoc = sp_repr_do_read( doc, default_ns );
+ }
}
}
- rdoc = sp_repr_do_read( doc, default_ns );
+
if ( doc ) {
xmlFreeDoc( doc );
}
@@ -471,13 +544,19 @@ Document *sp_repr_do_read (xmlDocPtr doc, const gchar *default_ns)
gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *name, const gchar */*default_ns*/, GHashTable *prefix_map)
{
const xmlChar *prefix;
- if ( ns && ns->href ) {
- prefix = reinterpret_cast<const xmlChar*>( sp_xml_ns_uri_prefix(reinterpret_cast<const gchar*>(ns->href),
- reinterpret_cast<const char*>(ns->prefix)) );
- void* p0 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(prefix));
- void* p1 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(ns->href));
- g_hash_table_insert( prefix_map, p0, p1 );
- } else {
+ if (ns){
+ if (ns->href ) {
+ prefix = reinterpret_cast<const xmlChar*>( sp_xml_ns_uri_prefix(reinterpret_cast<const gchar*>(ns->href),
+ reinterpret_cast<const char*>(ns->prefix)) );
+ void* p0 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(prefix));
+ void* p1 = reinterpret_cast<gpointer>(const_cast<xmlChar *>(ns->href));
+ g_hash_table_insert( prefix_map, p0, p1 );
+ }
+ else {
+ prefix = NULL;
+ }
+ }
+ else {
prefix = NULL;
}
@@ -490,7 +569,6 @@ gint sp_repr_qualified_name (gchar *p, gint len, xmlNsPtr ns, const xmlChar *nam
static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gchar *default_ns, GHashTable *prefix_map)
{
- Node *repr, *crepr;
xmlAttrPtr prop;
xmlNodePtr child;
gchar c[256];
@@ -530,7 +608,7 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc
}
sp_repr_qualified_name (c, 256, node->ns, node->name, default_ns, prefix_map);
- repr = xml_doc->createElement(c);
+ Node *repr = xml_doc->createElement(c);
/* TODO remember node->ns->prefix if node->ns != NULL */
for (prop = node->properties; prop != NULL; prop = prop->next) {
@@ -547,7 +625,7 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc
child = node->xmlChildrenNode;
for (child = node->xmlChildrenNode; child != NULL; child = child->next) {
- crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map);
+ Node *crepr = sp_repr_svg_read_node (xml_doc, child, default_ns, prefix_map);
if (crepr) {
repr->appendChild(crepr);
Inkscape::GC::release(crepr);
@@ -600,10 +678,10 @@ Glib::ustring sp_repr_save_buf(Document *doc)
sp_repr_save_writer(doc, &outs, SP_INKSCAPE_NS_URI, 0, 0);
- outs.close();
- Glib::ustring buf = souts.getString();
+ outs.close();
+ Glib::ustring buf = souts.getString();
- return buf;
+ return buf;
}
@@ -934,15 +1012,15 @@ void sp_repr_write_stream_element( Node * repr, Writer & out,
// THIS DOESN'T APPEAR TO DO ANYTHING. Can it be commented out or deleted?
{
GQuark const href_key = g_quark_from_static_string("xlink:href");
- GQuark const absref_key = g_quark_from_static_string("sodipodi:absref");
+ //GQuark const absref_key = g_quark_from_static_string("sodipodi:absref");
gchar const *xxHref = 0;
- gchar const *xxAbsref = 0;
+ //gchar const *xxAbsref = 0;
for ( List<AttributeRecord const> ai(attributes); ai; ++ai ) {
if ( ai->key == href_key ) {
xxHref = ai->value;
- } else if ( ai->key == absref_key ) {
- xxAbsref = ai->value;
+ //} else if ( ai->key == absref_key ) {
+ //xxAbsref = ai->value;
}
}
diff --git a/src/xml/repr-sorting.cpp b/src/xml/repr-sorting.cpp
index 056236d33..09a39acb2 100644
--- a/src/xml/repr-sorting.cpp
+++ b/src/xml/repr-sorting.cpp
@@ -2,6 +2,7 @@
#include "util/longest-common-suffix.h"
#include "xml/repr.h"
#include "xml/node-iterators.h"
+#include "repr-sorting.h"
static bool same_repr(Inkscape::XML::Node const &a, Inkscape::XML::Node const &b)
{
@@ -13,9 +14,14 @@ Inkscape::XML::Node const *LCA(Inkscape::XML::Node const *a, Inkscape::XML::Node
{
using Inkscape::Algorithms::longest_common_suffix;
Inkscape::XML::Node const *ancestor = longest_common_suffix<Inkscape::XML::NodeConstParentIterator>(
- a, b, NULL, &same_repr
- );
- if ( ancestor && ancestor->type() != Inkscape::XML::DOCUMENT_NODE ) {
+ a, b, NULL, &same_repr);
+ bool OK = false;
+ if (ancestor) {
+ if (ancestor->type() != Inkscape::XML::DOCUMENT_NODE) {
+ OK = true;
+ }
+ }
+ if ( OK ) {
return ancestor;
} else {
return NULL;
diff --git a/src/xml/repr-util.cpp b/src/xml/repr-util.cpp
index 6899e77ee..12280ea5a 100644
--- a/src/xml/repr-util.cpp
+++ b/src/xml/repr-util.cpp
@@ -69,71 +69,6 @@ static void sp_xml_ns_register_defaults();
static char *sp_xml_ns_auto_prefix(char const *uri);
/*#####################
-# UTILITY
-#####################*/
-
-/**
- * Locale-independent double to string conversion
- */
-unsigned int sp_xml_dtoa(gchar *buf, double val, unsigned int tprec, unsigned int fprec, unsigned int padf)
-{
- double dival, fval, epsilon;
- int idigits, ival, i;
- i = 0;
- if (val < 0.0) {
- buf[i++] = '-';
- val = -val;
- }
- /* Determine number of integral digits */
- if (val >= 1.0) {
- idigits = (int) floor(log10(val));
- } else {
- idigits = 0;
- }
- /* Determine the actual number of fractional digits */
- fprec = MAX(fprec, tprec - idigits);
- /* Find epsilon */
- epsilon = 0.5 * pow(10.0, - (double) fprec);
- /* Round value */
- val += epsilon;
- /* Extract integral and fractional parts */
- dival = floor(val);
- ival = (int) dival;
- fval = val - dival;
- /* Write integra */
- if (ival > 0) {
- char c[32];
- int j;
- j = 0;
- while (ival > 0) {
- c[32 - (++j)] = '0' + (ival % 10);
- ival /= 10;
- }
- memcpy(buf + i, &c[32 - j], j);
- i += j;
- tprec -= j;
- } else {
- buf[i++] = '0';
- tprec -= 1;
- }
- if ((fprec > 0) && (padf || (fval > epsilon))) {
- buf[i++] = '.';
- while ((fprec > 0) && (padf || (fval > epsilon))) {
- fval *= 10.0;
- dival = floor(fval);
- fval -= dival;
- buf[i++] = '0' + (int) dival;
- fprec -= 1;
- }
-
- }
- buf[i] = 0;
- return i;
-}
-
-
-
-/*#####################
# MAIN
#####################*/
@@ -261,8 +196,13 @@ gchar const *sp_xml_ns_uri_prefix(gchar const *uri, gchar const *suggested)
GQuark const prefix_key=g_quark_from_string(suggested);
SPXMLNs *found=namespaces;
- while ( found && found->prefix != prefix_key ) {
- found = found->next;
+ while (found) {
+ if (found->prefix != prefix_key) {
+ found = found->next;
+ }
+ else {
+ break;
+ }
}
if (found) { // prefix already used?
@@ -492,13 +432,11 @@ unsigned int sp_repr_get_int(Inkscape::XML::Node *repr, gchar const *key, int *v
unsigned int sp_repr_get_double(Inkscape::XML::Node *repr, gchar const *key, double *val)
{
- gchar const *v;
-
g_return_val_if_fail(repr != NULL, FALSE);
g_return_val_if_fail(key != NULL, FALSE);
g_return_val_if_fail(val != NULL, FALSE);
- v = repr->attribute(key);
+ gchar const *v = repr->attribute(key);
if (v != NULL) {
*val = g_ascii_strtod(v, NULL);
@@ -584,6 +522,8 @@ unsigned int sp_repr_get_point(Inkscape::XML::Node *repr, gchar const *key, Geom
gchar const *v = repr->attribute(key);
+ g_return_val_if_fail(v != NULL, FALSE);
+
gchar ** strarray = g_strsplit(v, ",", 2);
if (strarray && strarray[0] && strarray[1]) {
diff --git a/src/xml/repr.h b/src/xml/repr.h
index 86a798e3e..e691eaa7f 100644
--- a/src/xml/repr.h
+++ b/src/xml/repr.h
@@ -14,16 +14,11 @@
#ifndef SEEN_SP_REPR_H
#define SEEN_SP_REPR_H
-#include <stdio.h>
#include <glib.h>
-#include "gc-anchored.h"
+#include <glibmm/quark.h>
#include "xml/node.h"
#include "xml/document.h"
-#include "xml/sp-css-attr.h"
-#include "io/inkscapestream.h"
-
-#include <2geom/forward.h>
#define SP_SODIPODI_NS_URI "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
#define SP_BROKEN_SODIPODI_NS_URI "http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
@@ -35,6 +30,18 @@
#define SP_OLD_CC_NS_URI "http://web.resource.org/cc/"
#define SP_DC_NS_URI "http://purl.org/dc/elements/1.1/"
+class SPCSSAttr;
+
+namespace Inkscape {
+namespace IO {
+class Writer;
+} // namespace IO
+} // namespace Inkscape
+
+namespace Geom {
+class Point;
+}
+
/* SPXMLNs */
char const *sp_xml_ns_uri_prefix(gchar const *uri, gchar const *suggested);
char const *sp_xml_ns_prefix_uri(gchar const *prefix);
@@ -79,7 +86,7 @@ void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name);
bool sp_repr_css_property_is_unset(SPCSSAttr *css, gchar const *name);
double sp_repr_css_double_property(SPCSSAttr *css, gchar const *name, double defval);
-gchar *sp_repr_css_write_string(SPCSSAttr *css);
+void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str);
void sp_repr_css_set(Inkscape::XML::Node *repr, SPCSSAttr *css, gchar const *key);
void sp_repr_css_merge(SPCSSAttr *dst, SPCSSAttr *src);
void sp_repr_css_attr_add_from_string(SPCSSAttr *css, const gchar *data);
@@ -91,9 +98,11 @@ void sp_repr_css_print(SPCSSAttr *css);
/* Utility finctions */
/// Remove \a repr from children of its parent node.
inline void sp_repr_unparent(Inkscape::XML::Node *repr) {
- Inkscape::XML::Node *parent=repr->parent();
- if (parent) {
- parent->removeChild(repr);
+ if (repr) {
+ Inkscape::XML::Node *parent=repr->parent();
+ if (parent) {
+ parent->removeChild(repr);
+ }
}
}
diff --git a/src/xml/simple-node.cpp b/src/xml/simple-node.cpp
index c197d648b..4965f81c8 100644
--- a/src/xml/simple-node.cpp
+++ b/src/xml/simple-node.cpp
@@ -318,8 +318,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_
// Check usefulness of attributes on elements in the svg namespace, optionally don't add them to tree.
Glib::ustring element = g_quark_to_string(_name);
- //g_warning("setAttribute: %s: %s: %s", element.c_str(), name, value);
-
+ // g_message("setAttribute: %s: %s: %s", element.c_str(), name, value);
gchar* cleaned_value = g_strdup( value );
// Only check elements in SVG name space and don't block setting attribute to NULL.
@@ -347,7 +346,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_
// tree (and thus has no parent), default values will not be tested.
if( !strcmp( name, "style" ) && (flags >= SP_ATTR_CLEAN_STYLE_WARN) ) {
g_free( cleaned_value );
- cleaned_value = sp_attribute_clean_style( this, value, flags );
+ cleaned_value = g_strdup( sp_attribute_clean_style( this, value, flags ).c_str() );
// if( g_strcmp0( value, cleaned_value ) ) {
// g_warning( "SimpleNode::setAttribute: %s", id.c_str() );
// g_warning( " original: %s", value);
@@ -401,9 +400,7 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_
_observers.notifyAttributeChanged(*this, key, old_value, new_value);
//g_warning( "setAttribute notified: %s: %s: %s: %s", name, element.c_str(), old_value, new_value );
}
-
g_free( cleaned_value );
-
}
void SimpleNode::addChild(Node *generic_child, Node *generic_ref) {