diff options
Diffstat (limited to 'quanta/parsers/node.cpp')
-rw-r--r-- | quanta/parsers/node.cpp | 559 |
1 files changed, 559 insertions, 0 deletions
diff --git a/quanta/parsers/node.cpp b/quanta/parsers/node.cpp new file mode 100644 index 00000000..0831a67c --- /dev/null +++ b/quanta/parsers/node.cpp @@ -0,0 +1,559 @@ +/*************************************************************************** + node.cpp - description + ------------------- + begin : Sun Apr 16 2000 + copyright : (C) 2000 by Dmitry Poplavsky <[email protected]> + (C) 2001-2003 Andras Mantia <[email protected]> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ +//qt includes +#include <qlistview.h> +#include <qdom.h> + +#include <kdebug.h> + +#include "node.h" +#include "tag.h" +#include "qtag.h" +#include "quantacommon.h" +#include "structtreetag.h" +#include "kafkacommon.h" + +QMap<Node*, int> nodes; //list of all created nodes. Used to do some own memory management and avoid double deletes, for whatever reason they happen... + +int NN = 0; //for debugging purposes: count the Node objects + +GroupElementMapList globalGroupMap; + +Node::Node(Node *parent) +{ + this->parent = parent; + prev = next = child = 0L; + tag = 0L; + mainListItem = 0L; + opened = false; + removeAll = true; + closesPrevious = false; + insideSpecial = false; + _closingNode = 0L; + m_rootNode = 0L; + m_leafNode = 0L; + m_groupElements.clear(); + NN++; +// if (nodes.contains(this) == 0) + nodes[this] = 1; +// else +// { +// kdError(24000) << "A node with this address " << this << " already exists!" << endl; +// } +} + +bool Node::deleteNode(Node *node) +{ + if (!node) + return true; + if (!nodes.contains(node)) + { + kdDebug(24000) << "Trying to delete a node with address " << node << " that was not allocated!" << endl; + return false; + } + delete node; + return true; +} + +Node::~Node() +{ +// if (!nodes.contains(this)) +// { +// kdError(24000) << "No node with this address " << this << " was allocated!" << endl; +// return; +// } + + //It has no use, except to know when it crash why it has crashed. + //If it has crashed here, the Node doesn't exist anymore. + // If it has crashed the next line, it is a GroupElements bug. + //FIXME: Andras: or it is a VPL undo/redo bug... + Q_ASSERT(tag); + if (tag) + tag->setCleanStrBuilt(false); + + detachNode(); + nodes.erase(this); + if (prev && prev->next == this) + prev->next = 0L; + if (parent && parent->child == this) + parent->child = 0L; + if (removeAll) + { + deleteNode(child); + child = 0L; + deleteNode(next); + next = 0L; + } else + { + if (next && next->prev == this) + next->prev = 0L; + if (child && child->parent == this) + child->parent = 0L; + } + + delete tag; + tag = 0L; + delete m_rootNode; + delete m_leafNode; + NN--; +} + +void Node::save(QDomElement& element) const +{ + //kdDebug(25001) << "Save:\n" << element.ownerDocument().toString() << endl; + QDomElement child_element; + if(next) + { + child_element = element.ownerDocument().createElement("nodeNext"); + element.appendChild(child_element); + next->save(child_element); + } + if(child) + { + child_element = element.ownerDocument().createElement("nodeChild"); + element.appendChild(child_element); + child->save(child_element); + } + if(_closingNode) + { + if(_closingNode != next) + { + child_element = element.ownerDocument().createElement("nodeClosing"); + element.appendChild(child_element); + _closingNode->save(child_element); + } + } + + Q_ASSERT(tag); + child_element = element.ownerDocument().createElement("tag"); + element.appendChild(child_element); + tag->save(child_element); + + element.setAttribute("closesPrevious", closesPrevious); // bool + element.setAttribute("opened", opened); // bool + element.setAttribute("removeAll", removeAll); // bool + element.setAttribute("insideSpecial", insideSpecial); // bool + element.setAttribute("specialInsideXml", specialInsideXml); // bool + element.setAttribute("fileName", fileName); // QString + +/* QString s_element; + QTextStream stream(&s_element, IO_WriteOnly); + element.save(stream, 3);*/ + //kdDebug(25001) << "Load:\n" << s_element << endl; + //kdDebug(25001) << "Save:\n" << element.ownerDocument().toString() << endl; +} + +bool Node::load(QDomElement const& element) +{ +/* QString s_element; + QTextStream stream(&s_element, IO_WriteOnly); + element.save(stream, 3);*/ + //kdDebug(25001) << "Load:\n" << s_element << endl; + + QDomNodeList list = element.childNodes(); + for(unsigned int i = 0; i != list.count(); ++i) + { + if(list.item(i).isElement()) + { + QDomElement e = list.item(i).toElement(); + if(e.tagName() == "nodeNext") + { + next = new Node(0); + next->prev = this; + next->parent = this->parent; + next->load(e); + } + else if(e.tagName() == "nodeChild") + { + child = new Node(0); + child->parent = this; + child->load(e); + } + else if(e.tagName() == "nodeClosing") + { + _closingNode = new Node(0); + _closingNode->load(e); + } + else if(e.tagName() == "tag") + { + tag = new Tag(); + tag->load(e); + } + } + } + + closesPrevious = QString(element.attribute("closesPrevious")).toInt(); // bool + opened = QString(element.attribute("opened")).toInt(); // bool + removeAll = QString(element.attribute("removeAll")).toInt(); // bool + insideSpecial = QString(element.attribute("insideSpecial")).toInt(); // bool + specialInsideXml = QString(element.attribute("specialInsideXml")).toInt(); // bool + fileName = element.attribute("fileName"); // QString + + //kafkaCommon::coutTree(this, 3); + + return true; +} + +Node *Node::nextSibling() +{ + Node *result = 0L; + if (child) + { + result = child; + } + else + if (next) + { + result = next; + } + else + { + Node *n = this; + while (n) + { + if (n->parent && n->parent->next) + { + result = n->parent->next; + break; + } + else + { + n = n->parent; + } + } + } + + return result; +} + + +Node *Node::previousSibling() +{ + Node *result = 0L; + if (prev) + { + Node *n = prev; + while (n->child) + { + n = n->child; + while (n->next) + n = n->next; + } + result = n; + } + else + { + result = parent; + } + + return result; +} + +Node *Node::nextNotChild() +{ + if (next) + return next; + else + { + Node *n = this; + while (n) + { + if (n->parent && n->parent->next) + { + n = n->parent->next; + break; + } + else + { + n = n->parent; + } + } + + return n; + } +} + +QString Node::nodeName() +{ + if(tag) + return tag->name; + return QString::null; +} + +QString Node::nodeValue() +{ + if(tag) + return tag->tagStr(); + return QString::null; +} + +void Node::setNodeValue(const QString &value) +{ + if(!tag) + tag = new Tag(); + tag->setStr(value); + kdDebug(24000) << "Node::setNodeValue: dtd is 0L for " << value << endl; +} + +Node* Node::lastChild() +{ + Node *n, *m = 0; + n = child; + while(n) + { + m = n; + n = n->next; + } + return m; +} + +Node *Node::nextNE() +{ + Node *n = next; + while(n && n->tag->type == Tag::Empty) + n = n->next; + return n; +} + +Node *Node::prevNE() +{ + Node *n = prev; + while(n && n->tag->type == Tag::Empty) + n = n->prev; + return n; +} + +Node *Node::firstChildNE() +{ + Node *n = child; + while(n && n->tag->type == Tag::Empty) + n = n->next; + return n; +} + +Node *Node::lastChildNE() +{ + Node *n = lastChild(); + while(n && n->tag->type == Tag::Empty) + n = n->prev; + return n; +} + +Node *Node::SPrev() +{ + Node *node = prev; + int bCol, bLine, eCol, eLine, col, line; + + if(parent) + { + parent->tag->beginPos(bLine, bCol); + parent->tag->endPos(eLine, eCol); + } + + while(node && node->tag->type != Tag::XmlTag && node->tag->type != Tag::Text) + { + if (parent && node->tag->type == Tag::ScriptTag) + { + //Check if it is an embedded ScriptTag. If it is, continue. + node->tag->beginPos(line, col); + if(QuantaCommon::isBetween(line, col, bLine, bCol, eLine, eCol) != 0) + break; + } + node = node->prev; + } + + return node; +} + +Node *Node::SNext() +{ + Node *node = next; + int bCol, bLine, eCol, eLine, col, line; + + if(parent) + { + tag->beginPos(bLine, bCol); + tag->endPos(eLine, eCol); + } + + while(node && node->tag->type != Tag::XmlTag && node->tag->type != Tag::Text) + { + if (parent && node->tag->type == Tag::ScriptTag) + { + //Check if it is an embedded ScriptTag. If it is, continue. + node->tag->beginPos(line, col); + if(QuantaCommon::isBetween(line, col, bLine, bCol, eLine, eCol) != 0) + break; + } + node = node->next; + } + + return node; +} + +Node *Node::SFirstChild() +{ + Node *node = child; + int bCol, bLine, eCol, eLine, col, line; + + tag->beginPos(bLine, bCol); + tag->endPos(eLine, eCol); + while(node && node->tag->type != Tag::XmlTag && node->tag->type != Tag::Text) + { + if(node->tag->type == Tag::ScriptTag) + { + //Check if it is an embedded ScriptTag. If it is, continue. + node->tag->beginPos(line, col); + if(QuantaCommon::isBetween(line, col, bLine, bCol, eLine, eCol) != 0) + break; + } + node = node->next; + } + + return node; +} + +Node *Node::SLastChild() +{ + Node *node = lastChild(); + int bCol, bLine, eCol, eLine, col, line; + + tag->beginPos(bLine, bCol); + tag->endPos(eLine, eCol); + while(node && node->tag->type != Tag::XmlTag && node->tag->type != Tag::Text) + { + if(node->tag->type == Tag::ScriptTag) + { + //Check if it is an embedded ScriptTag. If it is, continue. + node->tag->beginPos(line, col); + if(QuantaCommon::isBetween(line, col, bLine, bCol, eLine, eCol) != 0) + break; + } + node = node->prev; + } + + return node; +} + +bool Node::hasForChild(Node *node) +{ + //TODO: NOT EFFICIENT AT ALL!! Change by using kafkaCommon::getLocation() and compare! + Node *n; + bool goUp = false; + + if(child) + { + n = child; + goUp = false; + while(n) + { + if(n == node) + return true; + n = kafkaCommon::getNextNode(n, goUp, this); + } + } + return false; +} + +Node *Node::getClosingNode() +{ + Node* n = next; + + if(next && tag && (tag->type == Tag::XmlTag || tag->type == Tag::ScriptTag) && !tag->single) + { + while (n && n->tag->type == Tag::Empty) + n = n->next; + if (n && n->tag->type == Tag::XmlTagEnd && ((tag->type == Tag::XmlTag && QuantaCommon::closesTag(tag, n->tag)) || (tag->type == Tag::ScriptTag && n->tag->name.isEmpty()))) + return n; + } + return 0L; +} + +Node *Node::getOpeningNode() +{ + Node *n = prev; + if(prev && tag && tag->type == Tag::XmlTagEnd) + { + while(n && n->tag->type == Tag::Empty) + n = n->prev; + if(n && ((n->tag->type == Tag::XmlTag && QuantaCommon::closesTag(n->tag, tag)) + || (n->tag->type == Tag::ScriptTag && tag->name.isEmpty()))) + return n; + } + return 0L; +} + +int Node::size() +{ + int l = tag->size(); + l += 5*sizeof(Node*) + sizeof(QListViewItem*) + 2*sizeof(Tag*) + 2*sizeof(DOM::Node); + return l; +} + +void Node::operator =(Node* node) +{ + (*this) = (*node); + prev = 0L; + next = 0L; + parent = 0L; + child = 0L; + mainListItem = 0L; + m_groupElements.clear(); + setRootNode(0L); + setLeafNode(0L); + tag = new Tag(*(node->tag)); +} + +void Node::detachNode() +{ + if (nodes.contains(this) == 0) + { + kdError(24000) << "No node with this address " << this << " was allocated!" << endl; + return; + } + + int count = 0; + //kdDebug(24000) << &m_groupElements << " " << this << endl; + //Remove the references to this node from the list of group elements. + //They are actually stored in globalGroupMap. + for (QValueListIterator<GroupElement*> it = m_groupElements.begin(); it != m_groupElements.end(); ++it) + { + GroupElement *groupElement = (*it); + groupElement->node = 0L; + groupElement->deleted = true; + groupElement->group = 0L; +#ifdef DEBUG_PARSER + kdDebug(24001) << "GroupElement scheduled for deletion: " << groupElement << " "<< groupElement->tag->area().bLine << " " << groupElement->tag->area().bCol << " "<< groupElement->tag->area().eLine << " "<< groupElement->tag->area().eCol << " " << groupElement->tag->tagStr() << " " << groupElement->type << endl; +#endif + count++; + } +#ifdef DEBUG_PARSER + if (count > 0) + kdDebug(24001) << count << " GroupElement scheduled for deletion. " << &m_groupElements << endl; +#endif + + QValueListIterator<QListViewItem*> listItem; + for ( listItem = listItems.begin(); listItem != listItems.end(); ++listItem) + { + static_cast<StructTreeTag*>(*listItem)->node = 0L; + static_cast<StructTreeTag*>(*listItem)->groupTag = 0L; + } + mainListItem = 0L; + listItems.clear(); + m_groupElements.clear(); + //kdDebug(24000) << m_groupElements.count() << " " << this << endl; +} |