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

📄 dom_selection.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            break;        case BASE:            pos = base();            break;        case EXTENT:            pos = extent();            break;    }    KHTMLPart *part = pos.node()->getDocument()->part();    if (!part)        return x;            if (recalc || part->xPosForVerticalArrowNavigation() == KHTMLPart::NoXPosForVerticalArrowNavigation) {        int y, w, h;        pos.node()->renderer()->caretPos(pos.offset(), true, x, y, w, h);        part->setXPosForVerticalArrowNavigation(x);    }    else {        x = part->xPosForVerticalArrowNavigation();    }    return x;}void Selection::clear(){    assignBaseAndExtent(emptyPosition(), emptyPosition());    validate();}void Selection::setBase(const Position &pos){    assignBase(pos);    validate();}void Selection::setExtent(const Position &pos){    assignExtent(pos);    validate();}void Selection::setBaseAndExtent(const Position &base, const Position &extent){    assignBaseAndExtent(base, extent);    validate();}void Selection::setStart(const Position &pos){    assignStart(pos);    validate();}void Selection::setEnd(const Position &pos){    assignEnd(pos);    validate();}void Selection::setStartAndEnd(const Position &start, const Position &end){    assignStartAndEnd(start, end);    validate();}void Selection::setNeedsLayout(bool flag){    m_needsCaretLayout = flag;}Range Selection::toRange() const{    if (isEmpty())        return Range();    // Make sure we have an updated layout since this function is called    // in the course of running edit commands which modify the DOM.    // Failing to call this can result in equivalentXXXPosition calls returning    // incorrect results.    start().node()->getDocument()->updateLayout();    Position s, e;    if (state() == CARET) {        // If the selection is a caret, move the range start upstream. This helps us match        // the conventions of text editors tested, which make style determinations based        // on the character before the caret, if any.         s = start().equivalentUpstreamPosition().equivalentRangeCompliantPosition();        e = s;    }    else {        // If the selection is a range, select the minimum range that encompasses the selection.        // Again, this is to match the conventions of text editors tested, which make style         // determinations based on the first character of the selection.         // For instance, this operation helps to make sure that the "X" selected below is the         // only thing selected. The range should not be allowed to "leak" out to the end of the         // previous text node, or to the beginning of the next text node, each of which has a         // different style.        //         // On a treasure map, <b>X</b> marks the spot.        //                       ^ selected        //        ASSERT(state() == RANGE);        s = start().equivalentDownstreamPosition();        e = end().equivalentUpstreamPosition();        if ((s.node() == e.node() && s.offset() > e.offset()) || !nodeIsBeforeNode(s.node(), e.node())) {            // Make sure the start is before the end.            // The end can wind up before the start if collapsed whitespace is the only thing selected.            Position tmp = s;            s = e;            e = tmp;        }        s = s.equivalentRangeCompliantPosition();        e = e.equivalentRangeCompliantPosition();    }    return Range(Node(s.node()), s.offset(), Node(e.node()), e.offset());}void Selection::layoutCaret(){    if (isEmpty() || !start().node()->renderer()) {        m_caretX = m_caretY = m_caretSize = 0;    }    else {        // EDIT FIXME: Enhance call to pass along selection         // upstream/downstream affinity to get the right position.        int w;        start().node()->renderer()->caretPos(start().offset(), true, m_caretX, m_caretY, w, m_caretSize);    }    m_needsCaretLayout = false;}QRect Selection::getRepaintRect() const{    if (m_needsCaretLayout) {        const_cast<Selection *>(this)->layoutCaret();    }    // EDIT FIXME: fudge a bit to make sure we don't leave behind artifacts    return QRect(m_caretX - 1, m_caretY - 1, 3, m_caretSize + 2);}void Selection::needsCaretRepaint(){    if (isEmpty())        return;    if (!start().node()->getDocument())        return;    KHTMLView *v = start().node()->getDocument()->view();    if (!v)        return;    if (m_needsCaretLayout) {        // repaint old position and calculate new position        v->updateContents(getRepaintRect(), false);        layoutCaret();                // EDIT FIXME: This is an unfortunate hack.        // Basically, we can't trust this layout position since we         // can't guarantee that the check to see if we are in unrendered         // content will work at this point. We may have to wait for        // a layout and re-render of the document to happen. So, resetting this        // flag will cause another caret layout to happen the first time        // that we try to paint the caret after this call. That one will work since        // it happens after the document has accounted for any editing        // changes which may have been done.        // And, we need to leave this layout here so the caret moves right         // away after clicking.        m_needsCaretLayout = true;    }    v->updateContents(getRepaintRect(), false);}void Selection::paintCaret(QPainter *p, const QRect &rect){    if (isEmpty())        return;    if (m_state != CARET)        return;    if (m_needsCaretLayout) {        Position pos = start();        if (!pos.inRenderedContent()) {            moveToRenderedContent();        }        layoutCaret();    }    QRect caretRect(m_caretX, m_caretY, 1, m_caretSize);    if (caretRect.intersects(rect)) {        QPen pen = p->pen();        pen.setStyle(Qt::SolidLine);        pen.setColor(Qt::black);        pen.setWidth(1);        p->setPen(pen);        p->drawLine(caretRect.left(), caretRect.top(), caretRect.left(), caretRect.bottom());    }}void Selection::validate(ETextGranularity granularity){    // move the base and extent nodes to their equivalent leaf positions    bool baseAndExtentEqual = base() == extent();    if (base().notEmpty()) {        Position pos = base().equivalentLeafPosition();        assignBase(pos);        if (baseAndExtentEqual)            assignExtent(pos);    }    if (extent().notEmpty() && !baseAndExtentEqual) {        assignExtent(extent().equivalentLeafPosition());    }    // make sure we do not have a dangling start or end    if (base().isEmpty() && extent().isEmpty()) {        assignStartAndEnd(emptyPosition(), emptyPosition());        m_baseIsStart = true;    }    else if (base().isEmpty() || extent().isEmpty()) {        m_baseIsStart = true;    }    else {        // adjust m_baseIsStart as needed        if (base().node() == extent().node()) {            if (base().offset() > extent().offset())                m_baseIsStart = false;            else                 m_baseIsStart = true;        }        else if (nodeIsBeforeNode(base().node(), extent().node()))            m_baseIsStart = true;        else            m_baseIsStart = false;    }    // calculate the correct start and end positions    if (granularity == CHARACTER) {        if (m_baseIsStart)            assignStartAndEnd(base(), extent());        else            assignStartAndEnd(extent(), base());    }    else if (granularity == WORD) {        int baseStartOffset = base().offset();        int baseEndOffset = base().offset();        int extentStartOffset = extent().offset();        int extentEndOffset = extent().offset();        if (base().notEmpty() && (base().node()->nodeType() == Node::TEXT_NODE || base().node()->nodeType() == Node::CDATA_SECTION_NODE)) {            DOMString t = base().node()->nodeValue();            QChar *chars = t.unicode();            uint len = t.length();            findWordBoundary(chars, len, base().offset(), &baseStartOffset, &baseEndOffset);        }        if (extent().notEmpty() && (extent().node()->nodeType() == Node::TEXT_NODE || extent().node()->nodeType() == Node::CDATA_SECTION_NODE)) {            DOMString t = extent().node()->nodeValue();            QChar *chars = t.unicode();            uint len = t.length();            findWordBoundary(chars, len, extent().offset(), &extentStartOffset, &extentEndOffset);        }        if (m_baseIsStart) {            assignStart(Position(base().node(), baseStartOffset));            assignEnd(Position(extent().node(), extentEndOffset));        }        else {            assignStart(Position(extent().node(), extentStartOffset));            assignEnd(Position(base().node(), baseEndOffset));        }    }    else {  // granularity == LINE         Selection baseSelection = *this;        Selection extentSelection = *this;        if (base().notEmpty() && (base().node()->nodeType() == Node::TEXT_NODE || base().node()->nodeType() == Node::CDATA_SECTION_NODE)) {            if (startAndEndLineNodesIncludingNode(base().node(), base().offset(), baseSelection)) {                assignStart(Position(baseSelection.base().node(), baseSelection.base().offset()));                assignEnd(Position(baseSelection.extent().node(), baseSelection.extent().offset()));            }        }        if (extent().notEmpty() && (extent().node()->nodeType() == Node::TEXT_NODE || extent().node()->nodeType() == Node::CDATA_SECTION_NODE)) {            if (startAndEndLineNodesIncludingNode(extent().node(), extent().offset(), extentSelection)) {                assignStart(Position(extentSelection.base().node(), extentSelection.base().offset()));                assignEnd(Position(extentSelection.extent().node(), extentSelection.extent().offset()));            }        }        if (m_baseIsStart) {            assignStart(baseSelection.start());            assignEnd(extentSelection.end());        }        else {            assignStart(extentSelection.start());            assignEnd(baseSelection.end());        }    }    // adjust the state    if (start().isEmpty() && end().isEmpty())        m_state = NONE;    else if (start() == end())        m_state = CARET;    else        m_state = RANGE;    m_needsCaretLayout = true;    #if EDIT_DEBUG    debugPosition();#endif}bool Selection::moveToRenderedContent(){    if (isEmpty())        return false;            if (m_state != CARET)        return false;    Position pos = start();

⌨️ 快捷键说明

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