⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 range.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
            return 0;           // A is equal to B        if (offsetA < offsetB)            return -1;          // A is before B        else            return 1;           // A is after B    }    // case 2: node C (container B or an ancestor) is a child node of A    Node* c = containerB;    while (c && c->parentNode() != containerA)        c = c->parentNode();    if (c) {        int offsetC = 0;        Node* n = containerA->firstChild();        while (n != c && offsetC < offsetA) {            offsetC++;            n = n->nextSibling();        }        if (offsetA <= offsetC)            return -1;              // A is before B        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;        Node* 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    Node* commonAncestor = commonAncestorContainer(containerA, containerB);    if (!commonAncestor)        return 0;    Node* childA = containerA;    while (childA && childA->parentNode() != commonAncestor)        childA = childA->parentNode();    if (!childA)        childA = commonAncestor;    Node* childB = containerB;    while (childB && childB->parentNode() != commonAncestor)        childB = childB->parentNode();    if (!childB)        childB = commonAncestor;    if (childA == childB)        return 0; // A is equal to B    Node* n = commonAncestor->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_NOT_REACHED();    return 0;}short Range::compareBoundaryPoints(const Position& a, const Position& b){    return compareBoundaryPoints(a.container.get(), a.posOffset, b.container.get(), b.posOffset);}bool Range::boundaryPointsValid() const{    return m_start.container() && compareBoundaryPoints(m_start.container(), m_start.offset(), m_end.container(), m_end.offset()) <= 0;}void Range::deleteContents(ExceptionCode& ec){    checkDeleteExtract(ec);    if (ec)        return;    processContents(DELETE_CONTENTS, ec);}bool Range::intersectsNode(Node* refNode, ExceptionCode& ec){    // http://developer.mozilla.org/en/docs/DOM:range.intersectsNode    // Returns a bool if the node intersects the range.    if (!refNode) {        ec = NOT_FOUND_ERR;        return false;    }        if (!m_start.container() && refNode->attached()            || m_start.container() && !refNode->attached()            || refNode->document() != m_ownerDocument) {        // Firefox doesn't throw an exception for these cases; it returns false.        return false;    }    Node* parentNode = refNode->parentNode();    int nodeIndex = refNode->nodeIndex();        if (!parentNode) {        // if the node is the top document we should return NODE_BEFORE_AND_AFTER        // but we throw to match firefox behavior        ec = NOT_FOUND_ERR;        return false;    }    if (comparePoint(parentNode, nodeIndex, ec) < 0 && // starts before start        comparePoint(parentNode, nodeIndex + 1, ec) < 0) { // ends before start        return false;    } else if (comparePoint(parentNode, nodeIndex, ec) > 0 && // starts after end               comparePoint(parentNode, nodeIndex + 1, ec) > 0) { // ends after end        return false;    }        return true; // all other cases}PassRefPtr<DocumentFragment> Range::processContents(ActionType action, ExceptionCode& ec){    // FIXME: To work properly with mutation events, we will have to take into account    // situations where the tree is being transformed while we work on it - ugh!    RefPtr<DocumentFragment> fragment;    if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)        fragment = new DocumentFragment(m_ownerDocument.get());        ec = 0;    if (collapsed(ec))        return fragment.release();    if (ec)        return 0;    Node* commonRoot = commonAncestorContainer(ec);    if (ec)        return 0;    ASSERT(commonRoot);    // what is the highest node that partially selects the start of the range?    Node* partialStart = 0;    if (m_start.container() != commonRoot) {        partialStart = m_start.container();        while (partialStart->parentNode() != commonRoot)            partialStart = partialStart->parentNode();    }    // what is the highest node that partially selects the end of the range?    Node* partialEnd = 0;    if (m_end.container() != commonRoot) {        partialEnd = m_end.container();        while (partialEnd->parentNode() != commonRoot)            partialEnd = partialEnd->parentNode();    }    // Simple case: the start and end containers are the same. We just grab    // everything >= start offset and < end offset    if (m_start.container() == m_end.container()) {        Node::NodeType startNodeType = m_start.container()->nodeType();        if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true));                c->deleteData(m_end.offset(), c->length() - m_end.offset(), ec);                c->deleteData(0, m_start.offset(), ec);                fragment->appendChild(c.release(), ec);            }            if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)                static_cast<CharacterData*>(m_start.container())->deleteData(m_start.offset(), m_end.offset() - m_start.offset(), ec);        } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true));                c->setData(c->data().substring(m_start.offset(), m_end.offset() - m_start.offset()), ec);                fragment->appendChild(c.release(), ec);            }            if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {                ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container());                String data(pi->data());                data.remove(m_start.offset(), m_end.offset() - m_start.offset());                pi->setData(data, ec);            }        } else {            Node* n = m_start.container()->firstChild();            int i;            for (i = 0; n && i < m_start.offset(); i++) // skip until start offset                n = n->nextSibling();            int endOffset = m_end.offset();            while (n && i < endOffset) { // delete until end offset                Node* next = n->nextSibling();                if (action == EXTRACT_CONTENTS)                    fragment->appendChild(n, ec); // will remove n from its parent                else if (action == CLONE_CONTENTS)                    fragment->appendChild(n->cloneNode(true), ec);                else                    m_start.container()->removeChild(n, ec);                n = next;                i++;            }        }        return fragment.release();    }    // Complex case: Start and end containers are different.    // There are three possiblities here:    // 1. Start container == commonRoot (End container must be a descendant)    // 2. End container == commonRoot (Start container must be a descendant)    // 3. Neither is commonRoot, they are both descendants    //    // In case 3, we grab everything after the start (up until a direct child    // of commonRoot) into leftContents, and everything before the end (up until    // a direct child of commonRoot) into rightContents. Then we process all    // commonRoot 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 commonRoot.    //    // These are deleted, cloned, or extracted (i.e. both) depending on action.    RefPtr<Node> leftContents;    if (m_start.container() != commonRoot) {        // process the left-hand side of the range, up until the last ancestor of        // start container before commonRoot        Node::NodeType startNodeType = m_start.container()->nodeType();        if (startNodeType == Node::TEXT_NODE || startNodeType == Node::CDATA_SECTION_NODE || startNodeType == Node::COMMENT_NODE) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_start.container()->cloneNode(true));                c->deleteData(0, m_start.offset(), ec);                leftContents = c.release();            }            if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)                static_cast<CharacterData*>(m_start.container())->deleteData(                    m_start.offset(), static_cast<CharacterData*>(m_start.container())->length() - m_start.offset(), ec);        } else if (startNodeType == Node::PROCESSING_INSTRUCTION_NODE) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_start.container()->cloneNode(true));                c->setData(c->data().substring(m_start.offset()), ec);                leftContents = c.release();            }            if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {                ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_start.container());                String data(pi->data());                pi->setData(data.left(m_start.offset()), ec);            }        } else {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)                leftContents = m_start.container()->cloneNode(false);            Node* n = m_start.container()->firstChild();            for (int i = 0; n && i < m_start.offset(); i++) // skip until start offset                n = n->nextSibling();            while (n) { // process until end                Node* next = n->nextSibling();                if (action == EXTRACT_CONTENTS)                    leftContents->appendChild(n, ec); // will remove n from start container                else if (action == CLONE_CONTENTS)                    leftContents->appendChild(n->cloneNode(true), ec);                else                    m_start.container()->removeChild(n, ec);                n = next;            }        }        Node* leftParent = m_start.container()->parentNode();        Node* n = m_start.container()->nextSibling();        for (; leftParent != commonRoot; leftParent = leftParent->parentNode()) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<Node> leftContentsParent = leftParent->cloneNode(false);                leftContentsParent->appendChild(leftContents,ec);                leftContents = leftContentsParent;            }            Node* next;            for (; n; n = next) {                next = n->nextSibling();                if (action == EXTRACT_CONTENTS)                    leftContents->appendChild(n,ec); // will remove n from leftParent                else if (action == CLONE_CONTENTS)                    leftContents->appendChild(n->cloneNode(true),ec);                else                    leftParent->removeChild(n,ec);            }            n = leftParent->nextSibling();        }    }    RefPtr<Node> rightContents;    if (m_end.container() != commonRoot) {        // delete the right-hand side of the range, up until the last ancestor of        // end container before commonRoot        Node::NodeType endNodeType = m_end.container()->nodeType();        if (endNodeType == Node::TEXT_NODE || endNodeType == Node::CDATA_SECTION_NODE || endNodeType == Node::COMMENT_NODE) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<CharacterData> c = static_pointer_cast<CharacterData>(m_end.container()->cloneNode(true));                c->deleteData(m_end.offset(), static_cast<CharacterData*>(m_end.container())->length() - m_end.offset(), ec);                rightContents = c;            }            if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS)                static_cast<CharacterData*>(m_end.container())->deleteData(0, m_end.offset(), ec);        } else if (endNodeType == Node::PROCESSING_INSTRUCTION_NODE) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<ProcessingInstruction> c = static_pointer_cast<ProcessingInstruction>(m_end.container()->cloneNode(true));                c->setData(c->data().left(m_end.offset()), ec);                rightContents = c.release();            }            if (action == EXTRACT_CONTENTS || action == DELETE_CONTENTS) {                ProcessingInstruction* pi = static_cast<ProcessingInstruction*>(m_end.container());                pi->setData(pi->data().substring(m_end.offset()), ec);            }        } else {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS)                rightContents = m_end.container()->cloneNode(false);            Node* n = m_end.container()->firstChild();            if (n && m_end.offset()) {                for (int i = 0; i + 1 < m_end.offset(); i++) { // skip to end.offset()                    Node* next = n->nextSibling();                    if (!next)                        break;                    n = next;                }                Node* prev;                for (; n; n = prev) {                    prev = n->previousSibling();                    if (action == EXTRACT_CONTENTS)                        rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent                    else if (action == CLONE_CONTENTS)                        rightContents->insertBefore(n->cloneNode(true), rightContents->firstChild(), ec);                    else                        m_end.container()->removeChild(n, ec);                }            }        }        Node* rightParent = m_end.container()->parentNode();        Node* n = m_end.container()->previousSibling();        for (; rightParent != commonRoot; rightParent = rightParent->parentNode()) {            if (action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) {                RefPtr<Node> rightContentsParent = rightParent->cloneNode(false);                rightContentsParent->appendChild(rightContents,ec);                rightContents = rightContentsParent;            }            Node* prev;            for (; n; n = prev) {                prev = n->previousSibling();                if (action == EXTRACT_CONTENTS)                    rightContents->insertBefore(n, rightContents->firstChild(), ec); // will remove n from its parent                else if (action == CLONE_CONTENTS)                    rightContents->insertBefore(n->cloneNode(true), rightContents->firstChild(), ec);                else                    rightParent->removeChild(n, ec);            }            n = rightParent->previousSibling();        }    }    // delete all children of commonRoot between the start and end container    Node* processStart; // child of commonRoot    if (m_start.container() == commonRoot) {        processStart = m_start.container()->firstChild();        for (int i = 0; i < m_start.offset(); i++)            processStart = processStart->nextSibling();    } else {        processStart = m_start.container();        while (processStart->parentNode() != commonRoot)            processStart = processStart->parentNode();        processStart = processStart->nextSibling();    }    Node* processEnd; // child of commonRoot    if (m_end.container() == commonRoot) {        processEnd = m_end.container()->firstChild();        for (int i = 0; i < m_end.offset(); i++)            processEnd = processEnd->nextSibling();    } else {        processEnd = m_end.container();        while (processEnd->parentNode() != commonRoot)            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, ec);    Node* next;    Node* n;    if (processStart) {        for (n = processStart; n && n != processEnd; n = next) {            next = n->nextSibling();            if (action == EXTRACT_CONTENTS)                fragment->appendChild(n, ec); // will remove from commonRoot            else if (action == CLONE_CONTENTS)                fragment->appendChild(n->cloneNode(true), ec);            else                commonRoot->removeChild(n, ec);        }    }    if ((action == EXTRACT_CONTENTS || action == CLONE_CONTENTS) && rightContents)        fragment->appendChild(rightContents, ec);    return fragment.release();}PassRefPtr<DocumentFragment> Range::extractContents(ExceptionCode& ec){    checkDeleteExtract(ec);    if (ec)        return 0;    return processContents(EXTRACT_CONTENTS, ec);}PassRefPtr<DocumentFragment> Range::cloneContents(ExceptionCode& ec){    if (!m_start.container()) {        ec = INVALID_STATE_ERR;        return 0;    }    return processContents(CLONE_CONTENTS, ec);}void Range::insertNode(PassRefPtr<Node> prpNewNode, ExceptionCode& ec){    RefPtr<Node> newNode = prpNewNode;    ec = 0;    if (!m_start.container()) {        ec = INVALID_STATE_ERR;        return;    }    if (!newNode) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -