DOMString AttrImpl::getValue() { if (value.child == null) { return 0; // return ""; } if (hasStringValue()) { // change value into a DOMString* DOMString *x = (value.str == null ?(value.str = new (getOwnerDocument()->getMemoryManager()) DOMString()) :value.str ); // return the DOMString it points to return *x; } ChildNode *firstChild = value.child; ChildNode *node = firstChild->nextSibling; if (node == null) { return firstChild->getNodeValue().clone(); } int length = 0; for (node = firstChild; node != null; node = node->nextSibling) length += node->getNodeValue().length(); DOMString retString; retString.reserve(length); for (node = firstChild; node != null; node = node->nextSibling) { retString.appendData(node->getNodeValue()); }; return retString; };
ChildNode * Composite::GetPrevChild(ChildNode const * pNode, ID idMatch) { for (ChildNode * pSrchNode = GetPrevChild(pNode); pSrchNode; pSrchNode = GetPrevChild(pSrchNode)) { if (pSrchNode->GetChunk()->m_idCk == idMatch && !pSrchNode->GetChunk()->IsUnknown()) return pSrchNode; } return NULL; }
ChildNode * Composite::GetLastChild(ID idMatch) const { for (ChildNode * pSrchNode = m_pLast; pSrchNode; pSrchNode = GetPrevChild(pSrchNode)) { if (pSrchNode->GetChunk()->m_idCk == idMatch && !pSrchNode->GetChunk()->IsUnknown()) return pSrchNode; } return NULL; }
void Attr::setOwnerDocument(Document * doc) { Node::setOwnerDocument(doc); for (ChildNode * child = text; child != null; child = child->nextSibling) { child->setOwnerDocument(doc); } setId(); }
bool List::EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const { for (ChildNode * pNode = GetFirstChild(); pNode; pNode = GetNextChild(pNode)) { Composite const * pComposite = static_cast<Composite const *>(pNode->GetChunk()); if (pComposite->m_idData == idData && !pComposite->EnumChildren(idData,idChunk,pfnCallback,pData)) return false; } return true; }
bool Composite::EnumChildren(ID idData, ID idChunk, bool (* pfnCallback) (Chunk *, void *), void * pData) const { if (m_idData != idData) return true; for (ChildNode * pNode = GetFirstChild(idChunk); pNode; pNode = GetNextChild(pNode,idChunk)) { if (!pfnCallback(pNode->GetChunk(),pData)) return false; } return true; }
void ParentNode::setReadOnly(bool readOnl, bool deep) { NodeImpl::setReadOnly(readOnl, deep); if (deep) // Recursively set kids for (ChildNode *mykid = firstChild; mykid != null; mykid = mykid->nextSibling) if(! (mykid->isEntityReference())) mykid->setReadOnly(readOnl,true); };
void ParentNode::setReadOnly(bool readOnl, bool deep) { NodeImpl::setReadOnly(readOnl, deep); if (deep) // Recursively set kids for (ChildNode *mykid = firstChild; mykid != null; mykid = mykid->nextSibling) if(! (mykid->isEntityReference())) mykid->setReadOnly(readOnl,true); } /* SPEC_CPU: removed extra ';' for C++98 standards compliance -- yag */
void AttrImpl::setReadOnly(bool readOnl, bool deep) { NodeImpl::setReadOnly(readOnl, deep); if (deep) { if (hasStringValue()) { return; } // Recursively set kids for (ChildNode *mykid = value.child; mykid != null; mykid = mykid->nextSibling) if(! (mykid->isEntityReference())) mykid->setReadOnly(readOnl,true); } }
Chunk * Composite::GetProperty(ChildNode const * pNode, ID idProp) const { // search backward for ID ChildNode * pFindNode = GetPrevChild(pNode, idProp); if (pFindNode) return pFindNode->GetChunk(); // if not found, search parent backwards, for "PROP ...." then get that // and if not in the parent, search its parent similarly // provided all these parents are of type LIST .... for (Composite const * pThis = this; pThis->m_pParent && pThis->m_pParent->m_idCk == ID("LIST"); pThis = pThis->m_pParent) { if (pThis->m_pNode) { for (ChildNode * pFindProp = pThis->m_pParent->GetPrevChild(pThis->m_pNode,"PROP"); pFindProp; pFindProp = pThis->m_pParent->GetPrevChild(pFindProp,"PROP")) { Composite * pProp = static_cast<Composite *>(pFindProp->GetChunk()); if (pProp->m_idData == m_idData) { ChildNode * pFindNode = pProp->GetLastChild(idProp); if (pFindNode) return pFindNode->GetChunk(); } } } } return NULL; }
Node * Attr::internalRemoveChild(Node * oldChild) throw(DOMException) { Document * owner = getOwnerDocument(); if (isReadOnly()) throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR); if (oldChild != null && oldChild->getParentNode() != this) throw DOMException(DOMException::NOT_FOUND_ERR); owner->removedChildNode(oldChild); ChildNode * oldInternal = dynamic_cast<ChildNode*>(oldChild); if (oldInternal == text) { text->isFirstChild(false); text = dynamic_cast<Text*>(text->nextSibling); if (text != null) { text->isFirstChild(true); text->previousSibling = oldInternal->previousSibling; } } else { ChildNode * prev = oldInternal->previousSibling; ChildNode * next = oldInternal->nextSibling; prev->nextSibling = next; if (next != null) { text->previousSibling = prev; } else { next->previousSibling = prev; } } //ChildNode * oldPreviousSibling = oldInternal->previousSibling; oldInternal->ownerNode = owner; oldInternal->isOwned(false); oldInternal->nextSibling = null; oldInternal->previousSibling = null; changed(); return oldInternal; }
void Composite::Serialize(Archive * pArchv) { pArchv->Transfer(m_idData); if (pArchv->m_bIsLoading) { DeleteAllChildren(); while (pArchv->GetSize()) { Chunk * pChunk = LoadChunk(pArchv); InsertChildLast(pChunk); pChunk->Release(); } } else { for (ChildNode * pNode = m_pFirst; pNode; pNode = GetNextChild(pNode)) { pNode->GetChunk()->Write(pArchv); } } }
NodeImpl *ParentNode::removeChild(NodeImpl *oldChild) { if (ownerDocument->getErrorChecking()) { if (isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } if (oldChild == null || oldChild->getParentNode() != this) { throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null); } } //fix other ranges for change before deleting the node if (getOwnerDocument() != null) { typedef RefVectorOf<RangeImpl> RangeImpls; RangeImpls* ranges = this->getOwnerDocument()->getRanges(); if (ranges != null) { unsigned int sz = ranges->size(); if (sz != 0) { for (unsigned int i =0; i<sz; i++) { if (ranges->elementAt(i) != null) ranges->elementAt(i)->updateRangeForDeletedNode(oldChild); } } } } ChildNode * oldInternal = (ChildNode *) oldChild; // update cached length if we have any if (fCachedLength != -1) { fCachedLength--; } if (fCachedChildIndex != -1) { // if the removed node is the cached node // move the cache to its (soon former) previous sibling if (fCachedChild == oldInternal) { fCachedChildIndex--; fCachedChild = (ChildNode *)oldInternal->getPreviousSibling(); } else { // otherwise just invalidate the cache fCachedChildIndex = -1; } } // Patch linked list around oldChild // Note: lastChild == firstChild->previousSibling if (oldInternal == firstChild) { // removing first child oldInternal->isFirstChild(false); firstChild = oldInternal->nextSibling; if (firstChild != null) { firstChild->isFirstChild(true); firstChild->previousSibling = oldInternal->previousSibling; } } else { ChildNode *prev = oldInternal->previousSibling; ChildNode *next = oldInternal->nextSibling; prev->nextSibling = next; if (next == null) { // removing last child firstChild->previousSibling = prev; } else { // removing some other child in the middle next->previousSibling = prev; } } // Remove oldInternal's references to tree oldInternal->ownerNode = ownerDocument; oldInternal->isOwned(false); oldInternal->nextSibling = null; oldInternal->previousSibling = null; changed(); return oldInternal; };
NodeImpl *ParentNode::insertBefore(NodeImpl *newChild, NodeImpl *refChild) { bool errorChecking = ownerDocument->getErrorChecking(); if (newChild->isDocumentFragmentImpl()) { // SLOW BUT SAFE: We could insert the whole subtree without // juggling so many next/previous pointers. (Wipe out the // parent's child-list, patch the parent pointers, set the // ends of the list.) But we know some subclasses have special- // case behavior they add to insertBefore(), so we don't risk it. // This approch also takes fewer bytecodes. // NOTE: If one of the children is not a legal child of this // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children // have been transferred. (Alternative behaviors would be to // reparent up to the first failure point or reparent all those // which are acceptable to the target node, neither of which is // as robust. PR-DOM-0818 isn't entirely clear on which it // recommends????? // No need to check kids for right-document; if they weren't, // they wouldn't be kids of that DocFrag. if (errorChecking) { for (NodeImpl *kid = newChild->getFirstChild(); // Prescan kid != null; kid = kid->getNextSibling()) { if (!DocumentImpl::isKidOK(this, kid)) { throw DOM_DOMException( DOM_DOMException::HIERARCHY_REQUEST_ERR, null); } } } while (newChild->hasChildNodes()) { // Move insertBefore(newChild->getFirstChild(),refChild); } return newChild; } // it's a no-op if refChild is the same as newChild if (refChild == newChild) { return newChild; } if (errorChecking) { if (isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } if (newChild->getOwnerDocument() != ownerDocument) { throw DOM_DOMException(DOM_DOMException::WRONG_DOCUMENT_ERR, null); } if (!DocumentImpl::isKidOK(this, newChild)) { throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR, null); } // refChild must be a child of this node (or null) if (refChild != null && refChild->getParentNode() != this) { throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null); } // Prevent cycles in the tree // newChild cannot be ancestor of this Node, // and actually cannot be this bool treeSafe = true; for (NodeImpl *a = this; treeSafe && a != null; a = a->getParentNode()) { treeSafe = (newChild != a); } if (!treeSafe) { throw DOM_DOMException(DOM_DOMException::HIERARCHY_REQUEST_ERR, null); } } // Convert to internal type, to avoid repeated casting ChildNode * newInternal = (ChildNode *)newChild; NodeImpl *oldparent = newInternal->getParentNode(); if (oldparent != null) { oldparent->removeChild(newInternal); } // Convert to internal type, to avoid repeated casting ChildNode *refInternal = (ChildNode *)refChild; // Attach up newInternal->ownerNode = this; newInternal->isOwned(true); // Attach before and after // Note: firstChild.previousSibling == lastChild!! if (firstChild == null) { // this our first and only child firstChild = newInternal; newInternal->isFirstChild(true); newInternal->previousSibling = newInternal; } else { if (refInternal == null) { // this is an append ChildNode *lastChild = firstChild->previousSibling; lastChild->nextSibling = newInternal; newInternal->previousSibling = lastChild; firstChild->previousSibling = newInternal; } else { // this is an insert if (refChild == firstChild) { // at the head of the list firstChild->isFirstChild(false); newInternal->nextSibling = firstChild; newInternal->previousSibling = firstChild->previousSibling; firstChild->previousSibling = newInternal; firstChild = newInternal; newInternal->isFirstChild(true); } else { // somewhere in the middle ChildNode *prev = refInternal->previousSibling; newInternal->nextSibling = refInternal; prev->nextSibling = newInternal; refInternal->previousSibling = newInternal; newInternal->previousSibling = prev; } } } changed(); // update cached length if we have any if (fCachedLength != -1) { fCachedLength++; } if (fCachedChildIndex != -1) { // if we happen to insert just before the cached node, update // the cache to the new node to match the cached index if (fCachedChild == refInternal) { fCachedChild = newInternal; } else { // otherwise just invalidate the cache fCachedChildIndex = -1; } } if (this->getOwnerDocument() != null) { typedef RefVectorOf<RangeImpl> RangeImpls; RangeImpls* ranges = this->getOwnerDocument()->getRanges(); if ( ranges != null) { unsigned int sz = ranges->size(); for (unsigned int i =0; i<sz; i++) { ranges->elementAt(i)->updateRangeForInsertedNode(newInternal); } } } return newInternal; };
NodeImpl *AttrImpl::removeChild(NodeImpl *oldChild) { DocumentImpl *ownerDocument = getOwnerDocument(); if (ownerDocument->getErrorChecking()) { if (isReadOnly()) { throw DOM_DOMException( DOM_DOMException::NO_MODIFICATION_ALLOWED_ERR, null); } if (oldChild == null || oldChild->getParentNode() != this) { throw DOM_DOMException(DOM_DOMException::NOT_FOUND_ERR, null); } } // fix other ranges for change before deleting the node if (getOwnerDocument() != null) { typedef RefVectorOf<RangeImpl> RangeImpls; RangeImpls* ranges = this->getOwnerDocument()->getRanges(); if (ranges != null) { unsigned int sz = ranges->size(); if (sz != 0) { for (unsigned int i =0; i<sz; i++) { if (ranges->elementAt(i) != null) ranges->elementAt(i)->updateRangeForDeletedNode(oldChild); } } } } ChildNode * oldInternal = (ChildNode *) oldChild; // Patch linked list around oldChild // Note: lastChild == firstChild->previousSibling if (oldInternal == value.child) { // removing first child oldInternal->isFirstChild(false); value.child = oldInternal->nextSibling; // firstChild = oldInternal->nextSibling ChildNode *firstChild = value.child; if (firstChild != null) { firstChild->isFirstChild(true); firstChild->previousSibling = oldInternal->previousSibling; } } else { ChildNode *prev = oldInternal->previousSibling; ChildNode *next = oldInternal->nextSibling; prev->nextSibling = next; if (next == null) { // removing last child ChildNode *firstChild = value.child; firstChild->previousSibling = prev; } else { // removing some other child in the middle next->previousSibling = prev; } } // Remove oldInternal's references to tree oldInternal->ownerNode = getOwnerDocument(); oldInternal->isOwned(false); oldInternal->nextSibling = null; oldInternal->previousSibling = null; changed(); return oldInternal; };
Node* Node::removeChild(Node *oldChild) { //ASSERT(0); #if 0 // Do this first? { CComQIPtr<INotifySend> cp = thisNode; if (cp) { cp->FireOnChanged(NOTIFY_REMOVE, oldChild, DISPID_UNKNOWN); } } #endif Document* ownerDocument = oldChild->get_ownerDocument(); if (ownerDocument) { ASSERT(ownerDocument != NULL); DocumentEvent* ownerDocumentEvent = dynamic_cast<DocumentEvent*>(ownerDocument); ASSERT(ownerDocumentEvent != NULL); MutationEvent* evt = dynamic_cast<MutationEvent*>(ownerDocumentEvent->createEvent(S("MutationEvent"))); // Create a DOMNodeRemoved event evt->initMutationEvent(S("DOMNodeRemoved"), true, false, this, nullptr, nullptr, nullptr, CHANGE_UNKNOWN); EventTarget* target = dynamic_cast<EventTarget*>(oldChild); target->dispatchEvent(evt); NodeRemovedFromDocument(oldChild); } // Do the work ChildNode* previous = oldChild->get_previousSibling(); ChildNode* next = oldChild->get_nextSibling(); if (previous != NULL) previous->set_nextSibling(next); else m_firstChild = next; if (next != NULL) next->set_previousSibling(previous); else m_lastChild = previous; oldChild->set_previousSibling(nullptr); oldChild->set_nextSibling(nullptr); for (int i = 0; i < m_childNodes->m_items.GetSize(); ++i) { if (m_childNodes->m_items[i] == oldChild) { #if 0 ASSERT(0); ///////// CComQIPtr<INotifySend, &IID_INotifySend> cp = (IUnknown*)oldChild; if (cp) { CComQIPtr<INotifyGet, &IID_INotifyGet> get = (IUnknown*)thisNode; if (get) { cp->Unadvise(get); } } #endif ///////// // m_childNodes->m_items.erase(&m_childNodes->m_items[i]); m_childNodes->m_items.RemoveAt(i); break; } } oldChild->set_parentNode(NULL); return oldChild; }
Node* Node::insertNode(Node* _newChild, Node* _pBefore) { ChildNode* newChild = dynamic_cast<ChildNode*>(_newChild); ChildNode* pBefore = dynamic_cast<ChildNode*>(_pBefore); Node* pPrevParent = newChild->get_parentNode(); if (pPrevParent) { pPrevParent->removeChild(newChild); } ChildNode* pAfter; if (pBefore) pAfter = pBefore->get_previousSibling(); else pAfter = m_lastChild; newChild->set_nextSibling(pBefore); newChild->set_previousSibling(pAfter); if (pAfter == NULL) m_firstChild = newChild; else pAfter->set_nextSibling(newChild); if (pBefore == NULL) m_lastChild = newChild; else pBefore->set_previousSibling(newChild); if (pBefore) { for (int i = 0; i < m_childNodes->m_items.GetSize(); i++) { if (m_childNodes->m_items[i] == pBefore) { m_childNodes->m_items.InsertAt(i, newChild); // m_childNodes->m_items.insert(&m_childNodes->m_items[i], newChild); break; } } } else { m_childNodes->m_items.Add(newChild); } // Set new child node's parent to this element newChild->set_parentNode(this); // TRACE("TODO\n"); #if 0 // Update computed xmlspace for inserted child(ren) CComQIPtr<ILDOMElement> newElement((IUnknown*)newChild); if (newElement) { CComBSTR xmlspace; newElement->getAttribute(OLESTR("xml:space"), &xmlspace); if (xmlspace.Length()==0) // inherit from parent { CComQIPtr<CLDOMElementImplImpl>((IUnknown*)newChild)->m_xmlspace = m_xmlspace; } else // explicitly set { CComQIPtr<CLDOMElementImplImpl>((IUnknown*)newChild)->m_xmlspace = cmpbstr(xmlspace, OLESTR("preserve")) == 0; } // TODO, update recursively for newChild } #endif // SMIL Animation (TODO, not very well thought trough) #if 0 { CLDOMDocument* pDocument = static_cast<CLDOMDocument*>(static_cast<CLDOMDocumentImpl<ILDOMDocument>*>(m_ownerDocument)); if (pDocument) { CComQIPtr<ILDOMElement> newElement = newChild; if (newElement) { // SMIL Animation (connect animate/set etc. elements to the elements they target) pDocument->BuildAnimationListForAllElements(newElement, pDocument->m_documentElement); // Set baseVal/animVal from attributes and parse 'style' attributes pDocument->UpdateAnimationElements(newElement); } } } #endif // TRACE("TODO\n"); #if 0 // Timing stuff (TODO) { ElementTimeImplImpl* elementTimeImpl((IUnknown*)newChild); if (elementTimeImpl) { elementTimeImpl->CalculateTimeBeforeParent(); CComPtr<ILElementTimeContainer> parentTimeContainer; elementTimeImpl->get_parentTimeContainer(&parentTimeContainer); CComQIPtr<CLElementTimeContainerImplImpl> parentTimeContainerImpl((IUnknown*)parentTimeContainer); if (parentTimeContainerImpl) { parentTimeContainerImpl->RecalculateTime(); } elementTimeImpl->CalculateTimeAfterParent(); } } CComQIPtr<ILAnimationElement, &IID_ILAnimationElement> animation = (IUnknown*)newChild; if (animation) { CComQIPtr<CLAnimationElementImplImpl> pAnimation((IUnknown*)animation); pAnimation->SetValuesFromAttributes(); } #endif { #if 0 // TODO for (int i = 0; i < m_pNodes.GetSize(); i++) { ASSERT(0); m_pNodes[i]->OnInsertedChild(newChild); } #endif #if 0 if (TRUE) // TODO, probably remove this (use above loop only) { CComQIPtr<INotifySend, &IID_INotifySend> cp = newChild; if (cp) { CComQIPtr<INotifyGet, &IID_INotifyGet> get = (IUnknown*)thisNode; if (get) { DWORD cookie; cp->Advise(get, &cookie); } cp->FireOnChanged(NOTIFY_ADD, newChild, DISPID_UNKNOWN); } } #endif } // CComPtr<ILDOMDocument> ownerDocument; // newChild->get_ownerDocument(&ownerDocument); // if (ownerDocument) { //////////////////////////////// // create an event notification DocumentEvent* ownerDocumentEvent = dynamic_cast<DocumentEvent*>(m_ownerDocument); if (ownerDocumentEvent == NULL) ownerDocumentEvent = dynamic_cast<DocumentEvent*>(this); if (ownerDocumentEvent) { MutationEvent* event = dynamic_cast<MutationEvent*>(ownerDocumentEvent->createEvent(S("MutationEvent"))); EventTarget* eventTarget = dynamic_cast<EventTarget*>(newChild); // event->initMutationEvent(S("DOMNodeInserted"), true, false, this, nullptr, nullptr, nullptr, CHANGE_UNKNOWN); bool doDefault = eventTarget->dispatchEvent(event); if (IsDocumentOrPartOfDocument(this)) { // Send "DOMNodeInsertedIntoDocument" to the node and it's children NodeInsertedIntoDocument(newChild); } } { Node* p = this; while (p) { if (p->m_pNode) { p->m_pNode->m_bArrangeValid = false; } p = p->get_parentNode(); } } #if 0 // event->initMutationEvent(OLESTR("DOMSubtreeModified"), VARIANT_TRUE, VARIANT_FALSE, thisNode, NULL, NULL, NULL, CHANGE_UNKNOWN); eventTarget->dispatchEvent(event, &doDefault); #endif } return newChild; }