📄 dom2_rangeimpl.cpp
字号:
m_startContainer->nodeType() == Node::CDATA_SECTION_NODE || m_startContainer->nodeType() == Node::COMMENT_NODE) { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true,exceptioncode)); c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_endOffset,exceptioncode); c->deleteData(0,m_startOffset,exceptioncode); fragment->appendChild(c,exceptioncode); } if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) static_cast<CharacterDataImpl*>(m_startContainer)->deleteData(m_startOffset,m_endOffset-m_startOffset,exceptioncode); } else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) { // ### operate just on data ? } else { NodeImpl *n = m_startContainer->firstChild(); unsigned long i; for(i = 0; i < m_startOffset; i++) // skip until m_startOffset n = n->nextSibling(); while (n && i < m_endOffset) { // delete until m_endOffset NodeImpl *next = n->nextSibling(); if (action == EXTRACT_CONTENTS) fragment->appendChild(n,exceptioncode); // will remove n from it's parent else if (action == CLONE_CONTENTS) fragment->appendChild(n->cloneNode(true,exceptioncode),exceptioncode); else m_startContainer->removeChild(n,exceptioncode); n = next; i++; } } collapse(true,exceptioncode); return fragment; } // Complex case: Start and end containers are different. // There are three possiblities here: // 1. Start container == cmnRoot (End container must be a descendant) // 2. End container == cmnRoot (Start container must be a descendant) // 3. Neither is cmnRoot, they are both descendants // // In case 3, we grab everything after the start (up until a direct child // of cmnRoot) into leftContents, and everything before the end (up until // a direct child of cmnRoot) into rightContents. Then we process all // cmnRoot children between leftContents and rightContents // // In case 1 or 2, we skip either processing of leftContents or rightContents, // in which case the last lot of nodes either goes from the first or last // child of cmnRoot. // // These are deleted, cloned, or extracted (i.e. both) depending on action. NodeImpl *leftContents = 0; if (m_startContainer != cmnRoot) { // process the left-hand side of the range, up until the last ancestor of // m_startContainer before cmnRoot if(m_startContainer->nodeType() == Node::TEXT_NODE || m_startContainer->nodeType() == Node::CDATA_SECTION_NODE || m_startContainer->nodeType() == Node::COMMENT_NODE) { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_startContainer->cloneNode(true,exceptioncode)); c->deleteData(0,m_startOffset,exceptioncode); leftContents = c; } if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) static_cast<CharacterDataImpl*>(m_startContainer)->deleteData( m_startOffset,static_cast<CharacterDataImpl*>(m_startContainer)->length()-m_startOffset,exceptioncode); } else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) { // ### operate just on data ? // leftContents = ... } else { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) leftContents = m_startContainer->cloneNode(false,exceptioncode); NodeImpl *n = m_startContainer->firstChild(); unsigned long i; for(i = 0; i < m_startOffset; i++) // skip until m_startOffset n = n->nextSibling(); while (n) { // process until end NodeImpl *next = n->nextSibling(); if (action == EXTRACT_CONTENTS) leftContents->appendChild(n,exceptioncode); // will remove n from m_startContainer else if (action == CLONE_CONTENTS) leftContents->appendChild(n->cloneNode(true,exceptioncode),exceptioncode); else m_startContainer->removeChild(n,exceptioncode); n = next; } } NodeImpl *leftParent = m_startContainer->parentNode(); NodeImpl *n = m_startContainer->nextSibling(); for (; leftParent != cmnRoot; leftParent = leftParent->parentNode()) { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { NodeImpl *leftContentsParent = leftParent->cloneNode(false,exceptioncode); leftContentsParent->appendChild(leftContents,exceptioncode); leftContents = leftContentsParent; } NodeImpl *next; for (; n; n = next ) { next = n->nextSibling(); if (action == EXTRACT_CONTENTS) leftContents->appendChild(n,exceptioncode); // will remove n from leftParent else if (action == CLONE_CONTENTS) leftContents->appendChild(n->cloneNode(true,exceptioncode),exceptioncode); else leftParent->removeChild(n,exceptioncode); } n = leftParent->nextSibling(); } } NodeImpl *rightContents = 0; if (m_endContainer != cmnRoot) { // delete the right-hand side of the range, up until the last ancestor of // m_endContainer before cmnRoot if(m_endContainer->nodeType() == Node::TEXT_NODE || m_endContainer->nodeType() == Node::CDATA_SECTION_NODE || m_endContainer->nodeType() == Node::COMMENT_NODE) { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { CharacterDataImpl *c = static_cast<CharacterDataImpl*>(m_endContainer->cloneNode(true,exceptioncode)); c->deleteData(m_endOffset,static_cast<CharacterDataImpl*>(m_endContainer)->length()-m_endOffset,exceptioncode); rightContents = c; } if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) static_cast<CharacterDataImpl*>(m_endContainer)->deleteData(0,m_endOffset,exceptioncode); } else if (m_startContainer->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) { // ### operate just on data ? // rightContents = ... } else { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) rightContents = m_endContainer->cloneNode(false,exceptioncode); NodeImpl *n = m_endContainer->firstChild(); unsigned long i; for(i = 0; i+1 < m_endOffset; i++) // skip to m_endOffset n = n->nextSibling(); NodeImpl *prev; for (; n; n = prev ) { prev = n->previousSibling(); if (action == EXTRACT_CONTENTS) rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from it's parent else if (action == CLONE_CONTENTS) rightContents->insertBefore(n->cloneNode(true,exceptioncode),rightContents->firstChild(),exceptioncode); else m_endContainer->removeChild(n,exceptioncode); } } NodeImpl *rightParent = m_endContainer->parentNode(); NodeImpl *n = m_endContainer->previousSibling(); for (; rightParent != cmnRoot; rightParent = rightParent->parentNode()) { if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) { NodeImpl *rightContentsParent = rightParent->cloneNode(false,exceptioncode); rightContentsParent->appendChild(rightContents,exceptioncode); rightContents = rightContentsParent; } NodeImpl *prev; for (; n; n = prev ) { prev = n->previousSibling(); if (action == EXTRACT_CONTENTS) rightContents->insertBefore(n,rightContents->firstChild(),exceptioncode); // will remove n from it's parent else if (action == CLONE_CONTENTS) rightContents->insertBefore(n->cloneNode(true,exceptioncode),rightContents->firstChild(),exceptioncode); else rightParent->removeChild(n,exceptioncode); } n = rightParent->previousSibling(); } } // delete all children of cmnRoot between the start and end container NodeImpl *processStart; // child of cmnRooot if (m_startContainer == cmnRoot) { unsigned long i; processStart = m_startContainer->firstChild(); for (i = 0; i < m_startOffset; i++) processStart = processStart->nextSibling(); } else { processStart = m_startContainer; while (processStart->parentNode() != cmnRoot) processStart = processStart->parentNode(); processStart = processStart->nextSibling(); } NodeImpl *processEnd; // child of cmnRooot if (m_endContainer == cmnRoot) { unsigned long i; processEnd = m_endContainer->firstChild(); for (i = 0; i < m_endOffset; i++) processEnd = processEnd->nextSibling(); } else { processEnd = m_endContainer; while (processEnd->parentNode() != cmnRoot) processEnd = processEnd->parentNode(); } // Now add leftContents, stuff in between, and rightContents to the fragment // (or just delete the stuff in between) if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && leftContents) fragment->appendChild(leftContents,exceptioncode); NodeImpl *next; NodeImpl *n; if (processStart) { for (n = processStart; n && n != processEnd; n = next) { next = n->nextSibling(); if (action == EXTRACT_CONTENTS) fragment->appendChild(n,exceptioncode); // will remove from cmnRoot else if (action == CLONE_CONTENTS) fragment->appendChild(n->cloneNode(true,exceptioncode),exceptioncode); else cmnRoot->removeChild(n,exceptioncode); } } if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents) fragment->appendChild(rightContents,exceptioncode); // collapse to the proper position - see spec section 2.6 if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) { if (!partialStart && !partialEnd) collapse(true,exceptioncode); else if (partialStart) { setStartContainer(partialStart->parentNode()); setEndContainer(partialStart->parentNode()); m_startOffset = m_endOffset = partialStart->nodeIndex()+1; } else if (partialEnd) { setStartContainer(partialEnd->parentNode()); setEndContainer(partialEnd->parentNode()); m_startOffset = m_endOffset = partialEnd->nodeIndex(); } } return fragment;}DocumentFragmentImpl *RangeImpl::extractContents( int &exceptioncode ){ if (m_detached) { exceptioncode = DOMException::INVALID_STATE_ERR; return 0; } checkDeleteExtract(exceptioncode); if (exceptioncode) return 0; return processContents(EXTRACT_CONTENTS,exceptioncode);}DocumentFragmentImpl *RangeImpl::cloneContents( int &exceptioncode ){ if (m_detached) { exceptioncode = DOMException::INVALID_STATE_ERR; return 0; } return processContents(CLONE_CONTENTS,exceptioncode);}void RangeImpl::insertNode( NodeImpl *newNode, int &exceptioncode ){ if (m_detached) { exceptioncode = DOMException::INVALID_STATE_ERR; return; } // NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of // the Range is read-only. NodeImpl *n = m_startContainer; while (n && !n->isReadOnly()) n = n->parentNode(); if (n) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return; } n = m_endContainer; while (n && !n->isReadOnly()) n = n->parentNode(); if (n) { exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR; return; } // WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were // not created from the same document. if (newNode->getDocument() != m_startContainer->getDocument()) { exceptioncode = DOMException::WRONG_DOCUMENT_ERR; return; } // HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that // does not allow children of the type of newNode or if newNode is an ancestor of the container. // an extra one here - if a text node is going to split, it must have a parent to insert into if (m_startContainer->nodeType() == Node::TEXT_NODE && !m_startContainer->parentNode()) { exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return; } // In the case where the container is a text node, we check against the container's parent, because // text nodes get split up upon insertion. NodeImpl *checkAgainst; if (m_startContainer->nodeType() == Node::TEXT_NODE) checkAgainst = m_startContainer->parentNode(); else checkAgainst = m_startContainer; if (newNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) { // check each child node, not the DocumentFragment itself NodeImpl *c; for (c = newNode->firstChild(); c; c = c->nextSibling()) { if (!checkAgainst->childTypeAllowed(c->nodeType())) { exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return; } } } else { if (!checkAgainst->childTypeAllowed(newNode->nodeType())) { exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return; } } for (n = m_startContainer; n; n = n->parentNode()) { if (n == newNode) { exceptioncode = DOMException::HIERARCHY_REQUEST_ERR; return; } } // INVALID_NODE_TYPE_ERR: Raised if newNode is an Attr, Entity, Notation, or Document node. if( newNode->nodeType() == Node::ATTRIBUTE_NODE || newNode->nodeType() == Node::ENTITY_NODE || newNode->nodeType() == Node::NOTATION_NODE || newNode->nodeType() == Node::DOCUMENT_NODE) { exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET; return; } if( m_startContainer->nodeType() == Node::TEXT_NODE || m_startContainer->nodeType() == Node::CDATA_SECTION_NODE ) { TextImpl *newText = static_cast<TextImpl*>(m_startContainer)->splitText(m_startOffset,exceptioncode); if (exceptioncode) return; m_startContainer->parentNode()->insertBefore( newNode, newText, exceptioncode ); } else { m_startContainer->insertBefore( newNode, m_startContainer->childNode( m_startOffset ), exceptioncode ); }}DOMString RangeImpl::toString( int &exceptioncode ){ if (m_detached) { exceptioncode = DOMException::INVALID_STATE_ERR; return DOMString(); } DOMString text = ""; NodeImpl *n = m_startContainer; while(n) { if(n->nodeType() == DOM::Node::TEXT_NODE || n->nodeType() == DOM::Node::CDATA_SECTION_NODE) { DOMString str = static_cast<TextImpl *>(n)->data().copy(); if (n == m_endContainer) str.truncate(m_endOffset); if (n == m_startContainer) str.remove(0,m_startOffset); text += str; if (n == m_endContainer) break; } else if (n->parentNode() == m_endContainer && !n->nextSibling()) { break; } //if (n == m_endContainer) break; NodeImpl *next = n->firstChild(); if (!next) next = n->nextSibling(); while( !next && n->parentNode() ) { n = n->parentNode(); next = n->nextSibling(); } n = next; } return text;}DOMString RangeImpl::toHTML( ){ // ### implement me!!!! return DOMString();}void RangeImpl::detach( int &exceptioncode ){ if (m_detached) { exceptioncode = DOMException::INVALID_STATE_ERR; return; } if (m_startContainer) m_startContainer->deref(); m_startContainer = 0; if (m_endContainer) m_endContainer->deref(); m_endContainer = 0; m_detached = true;}bool RangeImpl::isDetached() const{ return m_detached;}void RangeImpl::checkNodeWOffset( NodeImpl *n, int offset, int &exceptioncode) const{ if( offset < 0 ) { exceptioncode = DOMException::INDEX_SIZE_ERR; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -