/*
5 * Authors: see git history
7 * Copyright (C) 2018 Authors
8 * Copyright 2003-2005 MenTaLguY <mental@rydia.net>
9 * Copyright 2003 Nathan Hurst
10 * Copyright 1999-2003 Lauris Kaplinski
11 * Copyright 2000-2002 Ximian Inc.
13 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
42std::shared_ptr<std::string> stringify_node(Node
const &
node) {
48 string = g_strdup_printf(
"element(%p)=%s(#%s)", &
node,
node.
name(),
id);
50 string = g_strdup_printf(
"element(%p)=%s", &
node,
node.
name());
57 string = g_strdup_printf(
"comment(%p)=<!--%s-->", &
node,
node.
content());
60 string = g_strdup_printf(
"document(%p)", &
node);
63 string = g_strdup_printf(
"unknown(%p)", &
node);
65 std::shared_ptr<std::string>
result = std::make_shared<std::string>(
string);
72class DebugXMLNode :
public DebugXML {
74 DebugXMLNode(Node
const &
node,
char const *
name)
77 _addProperty(
"node", stringify_node(
node));
81class DebugAddChild :
public DebugXMLNode {
83 DebugAddChild(Node
const &
node, Node
const &
child, Node
const *prev)
84 : DebugXMLNode(
node,
"add-child")
86 _addProperty(
"child", stringify_node(
child));
87 _addProperty(
"position", prev ? prev->position() + 1 : 0 );
91class DebugRemoveChild :
public DebugXMLNode {
93 DebugRemoveChild(Node
const &
node, Node
const &
child)
94 : DebugXMLNode(
node,
"remove-child")
96 _addProperty(
"child", stringify_node(
child));
100class DebugSetChildPosition :
public DebugXMLNode {
102 DebugSetChildPosition(Node
const &
node, Node
const &
child,
103 Node
const *old_prev, Node
const *new_prev)
104 : DebugXMLNode(
node,
"set-child-position")
106 _addProperty(
"child", stringify_node(
child));
108 unsigned old_position = ( old_prev ? old_prev->position() : 0 );
109 unsigned position = ( new_prev ? new_prev->position() : 0 );
110 if ( position > old_position ) {
114 _addProperty(
"position", position);
118class DebugSetContent :
public DebugXMLNode
122 : DebugXMLNode(
node,
"set-content")
124 _addProperty(
"content", content.
pointer());
128class DebugClearContent :
public DebugXMLNode
131 DebugClearContent(Node
const &
node)
132 : DebugXMLNode(
node,
"clear-content")
136class DebugSetAttribute :
public DebugXMLNode
140 : DebugXMLNode(
node,
"set-attribute")
142 _addProperty(
"name", g_quark_to_string(
name));
143 _addProperty(
"value", value.
pointer());
147class DebugClearAttribute :
public DebugXMLNode
151 : DebugXMLNode(
node,
"clear-attribute")
153 _addProperty(
"name", g_quark_to_string(
name));
157class DebugSetElementName :
public DebugXMLNode
161 : DebugXMLNode(
node,
"set-name")
163 _addProperty(
"name", g_quark_to_string(
name));
186 : _cached_position(
node._cached_position)
188 , _content(
node._content)
189 , _child_count(
node._child_count)
190 , _cached_positions_valid(
node._cached_positions_valid)
221 return g_quark_to_string(
_name);
229 g_return_val_if_fail(
name !=
nullptr, NULL);
235 if ( iter.key ==
key ) {
244 g_return_val_if_fail(
_parent !=
nullptr, 0);
252 sibling ; sibling = sibling->
_next )
254 sibling->_cached_position =
position;
259 return child._cached_position;
271 g_return_val_if_fail(partial_name !=
nullptr,
false);
275 gchar
const *
name = g_quark_to_string(iter.key);
276 if (std::strstr(
name, partial_name)) {
300 tracker.
set<DebugSetContent>(*
this, new_content);
302 tracker.
set<DebugClearContent>(*this);
319 g_assert(std::none_of(
name,
name + strlen(
name), [](
char c) {
return g_ascii_isspace(
c); }));
322 Glib::ustring element = g_quark_to_string(
_name);
324 gchar* cleaned_value = g_strdup( value );
328 if (value !=
nullptr && element.raw().starts_with(
"svg:")) {
331 if( prefs->
getBool(
"/options/svgoutput/check_on_editing") ) {
334 Glib::ustring
id = (id_char ==
nullptr ?
"" : id_char );
340 if( (attr_warn || attr_remove) && value !=
nullptr ) {
342 if( !is_useful && attr_remove ) {
343 g_free( cleaned_value );
351 g_free( cleaned_value );
366 if ( existing.key ==
key ) {
377 new_value = share_string(cleaned_value);
378 tracker.
set<DebugSetAttribute>(*
this,
key, new_value);
382 ref->value = new_value;
385 tracker.
set<DebugClearAttribute>(*
this,
key);
391 if ( new_value != old_value && (!old_value || !new_value || strcmp(old_value, new_value))) {
396 g_free( cleaned_value );
404 tracker.
set<DebugSetElementName>(*
this, new_code);
406 _name =
static_cast<int>(new_code);
408 if (new_code != old_code) {
415 g_assert(generic_child);
422 g_assert(!
ref ||
ref->_parent ==
this);
423 g_assert(!
child->_parent);
447 child->_cached_position =
ref->_cached_position + 1;
455 child->_setParent(
this);
464 g_assert(generic_child);
471 g_assert(
child->_parent ==
this);
498 g_assert(generic_child);
499 g_assert(generic_child->
document() == this->_document);
500 g_assert(!generic_ref || generic_ref->
document() == this->_document);
505 g_return_if_fail(
child->parent() ==
this);
507 g_return_if_fail(!
ref ||
ref->parent() ==
this);
555 g_return_if_fail(
_parent !=
nullptr);
562 sibling && pos ; sibling = sibling->_next )
564 if ( sibling !=
this ) {
591 std::cout <<
"XML Node Tree" << std::endl;
593 std::cout <<
"XML: ";
594 for (
unsigned i = 0; i < level; ++i) {
599 std::cout <<
id << std::endl;
601 std::cout <<
name() << std::endl;
604 child->recursivePrintTree( level+1 );
631 std::vector<Node *> to_delete;
640 to_delete.push_back(
child);
643 to_delete.push_back(
child);
646 for (
auto & i : to_delete) {
651 return g_strcmp0(a, b) == 0;
663 size_t sizeorig = orig_attrs.size();
664 size_t sizeother = other_attrs.size();
665 if (sizeother != sizeorig) {
668 for (
size_t i = 0; i < sizeorig; i++) {
669 const gchar * key_orig = g_quark_to_string(orig_attrs[i].
key);
673 const gchar * key_other = g_quark_to_string(other_attrs[i].
key);
675 !
string_equal(orig_attrs[i].value, other_attrs[i].value) != 0)
684 while (
child && other_child) {
685 if (!
child->equal(other_child, recursive, skip_ids)) {
689 other_child = other_child->
next();
691 if ((!
child && other_child) || (
child && !other_child)) {
699 g_return_if_fail(src !=
nullptr);
700 g_return_if_fail(
key !=
nullptr);
701 g_assert(src !=
this);
703 Node * srcp =
const_cast<Node *
>(src);
704 if (srcp->
equal(
this,
true)) {
718 gchar
const *
id =
child->attribute(
key);
721 if (rch && (!extension || rch->
equal(
child,
false))) {
731 guint pos =
child->position();
unsigned int sp_attribute_clean_get_prefs()
Get preferences.
void sp_attribute_clean_style(Node *repr, unsigned int flags)
Clean CSS style on an element.
bool sp_attribute_check_attribute(Glib::ustring const &element, Glib::ustring const &id, Glib::ustring const &attribute, bool warn)
Check one attribute on an element.
Utility functions related to parsing and validation of XML attributes.
@ SP_ATTRCLEAN_STYLE_WARN
@ SP_ATTRCLEAN_ATTR_REMOVE
Cairo::RefPtr< Cairo::Region > clean
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
char const * pointer() const
Key-value pair representing an attribute.
void add(NodeObserver &observer)
Add an observer to the list.
void remove(NodeObserver &observer)
Remove an observer from the list.
void notifyContentChanged(Node &node, Util::ptr_shared old_content, Util::ptr_shared new_content) override
Content change callback.
void notifyChildOrderChanged(Node &node, Node &child, Node *old_prev, Node *new_prev) override
Child order change callback.
void notifyElementNameChanged(Node &node, GQuark old_name, GQuark new_name) override
Element name change callback.
void notifyChildRemoved(Node &node, Node &child, Node *prev) override
Child removal callback.
void notifyChildAdded(Node &node, Node &child, Node *prev) override
Child addition callback.
void notifyAttributeChanged(Node &node, GQuark name, Util::ptr_shared old_value, Util::ptr_shared new_value) override
Attribute change callback.
Interface for XML node observers.
virtual void notifyElementNameChanged(Node &node, GQuark old_name, GQuark new_name)
Element name change callback.
virtual void notifyAttributeChanged(Node &node, GQuark name, Util::ptr_shared old_value, Util::ptr_shared new_value)
Attribute change callback.
virtual void notifyContentChanged(Node &node, Util::ptr_shared old_content, Util::ptr_shared new_content)
Content change callback.
virtual void notifyChildOrderChanged(Node &node, Node &child, Node *old_prev, Node *new_prev)
Child order change callback.
virtual void notifyChildRemoved(Node &node, Node &child, Node *prev)
Child removal callback.
virtual void notifyChildAdded(Node &node, Node &child, Node *prev)
Child addition callback.
Interface for refcounted XML nodes.
virtual Node * parent()=0
Get the parent of this node.
virtual Node * next()=0
Get the next sibling of this node.
Inkscape::XML::Node * sp_repr_lookup_child(Inkscape::XML::Node *repr, gchar const *key, gchar const *value)
Find an element node using an unique attribute.
virtual char const * name() const =0
Get the name of the element node.
virtual const AttributeVector & attributeList() const =0
Get a list of the node's attributes.
void addChildAtPos(Node *child, unsigned pos)
Insert another node as a child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual Node * duplicate(Document *doc) const =0
Create a duplicate of this node.
virtual Node * firstChild()=0
Get the first child of this node.
virtual unsigned position() const =0
Get the index of this node in parent's child order.
virtual bool equal(Node const *other, bool recursive, bool skip_ids=false)=0
Compare 2 nodes equality.
virtual void mergeFrom(Node const *src, char const *key, bool extension=false, bool clean=false)=0
Merge all children of another node with the current.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
virtual char const * content() const =0
Get the content of a text or comment node.
virtual Document * document()=0
Get the node's associated document.
virtual NodeType type() const =0
Get the type of the node.
Default implementation of the XML node stored in memory.
void cleanOriginal(Node *src, gchar const *key) override
bool _cached_positions_valid
Node * next() override
Get the next sibling of this node.
Inkscape::Util::ptr_shared _content
bool matchAttributeName(char const *partial_name) const override
Check whether this node has any attribute that matches a string.
Node * firstChild() override
Get the first child of this node.
void recursivePrintTree(unsigned level=0) override
Node * nthChild(unsigned index) override
Get the child of this node with a given index.
void setCodeUnsafe(int code) override
Set the integer GQuark code for the name of the node.
void setPosition(int pos) override
Set the position of this node in parent's child order.
SimpleNode * _first_child
Node * parent() override
Get the parent of this node.
bool equal(Node const *other, bool recursive, bool skip_ids=false) override
Compare 2 nodes equality.
int code() const override
Get the integer code corresponding to the node's name.
const AttributeVector & attributeList() const override
Get a list of the node's attributes.
char const * content() const override
Get the content of a text or comment node.
void removeChild(Node *child) override
Remove a child of this node.
CompositeNodeObserver _subtree_observers
CompositeNodeObserver _observers
SimpleNode(int code, Document *document)
AttributeVector _attributes
unsigned _cached_position
char const * name() const override
Get the name of the element node.
unsigned _childPosition(SimpleNode const &child) const
void synthesizeEvents(NodeObserver &observer) override
Generate a sequence of events corresponding to the state of this node.
void setAttributeImpl(char const *key, char const *value) override
void mergeFrom(Node const *src, char const *key, bool extension=false, bool clean=false) override
Merge all children of another node with the current.
void addChild(Node *child, Node *ref) override
Insert another node as a child of this node.
unsigned position() const override
Get the index of this node in parent's child order.
char const * attribute(char const *key) const override
Get the string representation of a node's attribute.
Node * root() override
Get the root node of this node's document.
void setContent(char const *value) override
Set the content of a text or comment node.
Document * document() override
Get the node's associated document.
void _setParent(SimpleNode *parent)
void changeOrder(Node *child, Node *ref) override
Move a given node in this node's child order.
NodeObserver const * observer
static char const *const parent
Inkscape::XML::Node * node
ptr_shared share_unsafe(char const *string)
ptr_shared share_string(char const *string)
bool string_equal(const gchar *a, const gchar *b)
@ DOCUMENT_NODE
Top-level document node. Do not confuse with the root node.
@ COMMENT_NODE
Comment node, e.g. <!– some comment –>.
@ ELEMENT_NODE
Regular element node, e.g. <group />.
@ TEXT_NODE
Text node, e.g. "Some text" in <group>Some text</group> is represented by a text node.
std::vector< AttributeRecord, Inkscape::GC::Alloc< AttributeRecord > > AttributeVector
Helper class to stream background task notifications as a series of messages.
Helper functions for XML nodes.
static cairo_user_data_key_t key
Singleton class to access the preferences file in a convenient way.
GC-managed XML node implementation.
Interface for XML documents.
virtual NodeObserver * logger()=0
Get the event logger for this document.