📄 dom2_rangeimpl.cpp
字号:
else return 1; // A is after B
}
// case 3: node C (container A or an ancestor) is a child node of B
c = containerA;
while (c && c->parentNode() != containerB)
c = c->parentNode();
if (c) {
int offsetC = 0;
NodeImpl *n = containerB->firstChild();
while (n != c && offsetC < offsetB) {
offsetC++;
n = n->nextSibling();
}
if( offsetC < offsetB ) return -1; // A is before B
else return 1; // A is after B
}
// case 4: containers A & B are siblings, or children of siblings
// ### we need to do a traversal here instead
NodeImpl *cmnRoot = commonAncestorContainer(containerA,containerB);
NodeImpl *childA = containerA;
while (childA && childA->parentNode() != cmnRoot)
childA = childA->parentNode();
if (!childA)
childA = cmnRoot;
NodeImpl *childB = containerB;
while (childB && childB->parentNode() != cmnRoot)
childB = childB->parentNode();
if (!childB)
childB = cmnRoot;
if (childA == childB)
return 0; // A is equal to B
NodeImpl *n = cmnRoot->firstChild();
while (n) {
if (n == childA)
return -1; // A is before B
if (n == childB)
return 1; // A is after B
n = n->nextSibling();
}
// Should never reach this point.
assert(0);
return 0;
}
short RangeImpl::compareBoundaryPoints( const Position &a, const Position &b )
{
return compareBoundaryPoints(a.node(), a.offset(), b.node(), b.offset());
}
bool RangeImpl::boundaryPointsValid( ) const
{
return compareBoundaryPoints( m_startContainer, m_startOffset, m_endContainer, m_endOffset ) <= 0;
}
void RangeImpl::deleteContents( int &exceptioncode ) {
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
checkDeleteExtract(exceptioncode);
if (exceptioncode)
return;
processContents(DELETE_CONTENTS,exceptioncode);
}
DocumentFragmentImpl *RangeImpl::processContents ( ActionType action, int &exceptioncode )
{
// ### when mutation events are implemented, we will have to take into account
// situations where the tree is being transformed while we delete - ugh!
// ### perhaps disable node deletion notification for this range while we do this?
if (collapsed(exceptioncode))
return 0;
if (exceptioncode)
return 0;
NodeImpl *cmnRoot = commonAncestorContainer(exceptioncode);
if (exceptioncode)
return 0;
// what is the highest node that partially selects the start of the range?
NodeImpl *partialStart = 0;
if (m_startContainer != cmnRoot) {
partialStart = m_startContainer;
while (partialStart->parentNode() != cmnRoot)
partialStart = partialStart->parentNode();
}
// what is the highest node that partially selects the end of the range?
NodeImpl *partialEnd = 0;
if (m_endContainer != cmnRoot) {
partialEnd = m_endContainer;
while (partialEnd->parentNode() != cmnRoot)
partialEnd = partialEnd->parentNode();
}
DocumentFragmentImpl *fragment = 0;
if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)
fragment = new DocumentFragmentImpl(m_ownerDocument);
// Simple case: the start and end containers are the same. We just grab
// everything >= start offset and < end offset
if (m_startContainer == m_endContainer) {
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));
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; n && 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);
else
m_startContainer->removeChild(n,exceptioncode);
n = next;
i++;
}
}
if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)
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));
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);
NodeImpl *n = m_startContainer->firstChild();
for (unsigned long i = 0; n && 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);
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);
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);
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));
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);
NodeImpl *n = m_endContainer->firstChild();
if (n && m_endOffset) {
for (unsigned long i = 0; i+1 < m_endOffset; i++) { // skip to m_endOffset
NodeImpl *next = n->nextSibling();
if (!next)
break;
n = next;
}
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),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);
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),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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -