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

📄 dom_position.cpp

📁 khtml在gtk上的移植版本
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#include "dom_position.h"#include "helper.h"#include "htmltags.h"#include "qstring.h"#include "rendering/render_block.h"#include "rendering/render_line.h"#include "rendering/render_object.h"#include "rendering/render_style.h"#include "rendering/render_text.h"#include "xml/dom_positioniterator.h"#include "xml/dom_elementimpl.h"#include "xml/dom_nodeimpl.h"#if KWIQ#include <stdio.h>#endif#if APPLE_CHANGES && !KWIQ#include "KWQAssertions.h"#include "KWQLogging.h"#else#define ASSERT(assertion) assert(assertion)#define LOG(channel, formatAndArgs...) ((void)0)#endifusing khtml::InlineBox;using khtml::InlineFlowBox;using khtml::InlineTextBox;using khtml::RenderBlock;using khtml::RenderObject;using khtml::RenderText;using khtml::RootInlineBox;namespace DOM {static bool renderersOnDifferentLine(RenderObject *r1, long o1, RenderObject *r2, long o2){    InlineBox *b1 = r1 ? r1->inlineBox(o1) : 0;    InlineBox *b2 = r2 ? r2->inlineBox(o2) : 0;    return (b1 && b2 && b1->root() != b2->root());}static NodeImpl *nextRenderedEditable(NodeImpl *node){    while (1) {        node = node->nextEditable();        if (!node)            return 0;        if (!node->renderer())            continue;        if (node->renderer()->inlineBox(0))            return node;    }    return 0;}static NodeImpl *previousRenderedEditable(NodeImpl *node){    while (1) {        node = node->previousEditable();        if (!node)            return 0;        if (!node->renderer())            continue;        if (node->renderer()->inlineBox(0))            return node;    }    return 0;}Position::Position(NodeImpl *node, long offset)     : m_node(0), m_offset(offset) {     if (node) {        m_node = node;        m_node->ref();    }};Position::Position(const Position &o)    : m_node(0), m_offset(o.offset()) {    if (o.node()) {        m_node = o.node();        m_node->ref();    }}Position::~Position() {    if (m_node) {        m_node->deref();    }}Position &Position::operator=(const Position &o){    if (m_node) {        m_node->deref();    }    m_node = o.node();    if (m_node) {        m_node->ref();    }    m_offset = o.offset();        return *this;}ElementImpl *Position::element() const{    if (isEmpty())        return 0;            NodeImpl *n = node();    for (; n && !n->isElementNode(); n = n->parentNode()); //loop            return static_cast<ElementImpl *>(n);}long Position::renderedOffset() const{    if (!node()->isTextNode())        return offset();       if (!node()->renderer())        return offset();                        long result = 0;    RenderText *textRenderer = static_cast<RenderText *>(node()->renderer());    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {        long start = box->m_start;        long end = box->m_start + box->m_len;        if (offset() < start)            return result;        if (offset() <= end) {            result += offset() - start;            return result;        }        result += box->m_len;    }    return result;}Position Position::equivalentLeafPosition() const{    if (isEmpty())        return Position();    if (!node()->renderer() || !node()->renderer()->firstChild())        return *this;        NodeImpl *n = node();    int count = 0;    while (1) {        n = n->nextLeafNode();        if (!n || !n->inSameContainingBlockFlowElement(node()))            return *this;        if (count + n->maxOffset() >= offset()) {            count = offset() - count;            break;        }        count += n->maxOffset();    }    return Position(n, count);}Position Position::previousRenderedEditablePosition() const{    if (isEmpty())        return Position();    if (node()->isContentEditable() && node()->hasChildNodes() == false && inRenderedContent())        return *this;    NodeImpl *n = node();    while (1) {        n = n->previousEditable();        if (!n)            return Position();        if (n->renderer() && n->renderer()->style()->visibility() == khtml::VISIBLE)            break;    }        return Position(n, 0);}Position Position::nextRenderedEditablePosition() const{    if (isEmpty())        return Position();    if (node()->isContentEditable() && node()->hasChildNodes() == false && inRenderedContent())        return *this;    NodeImpl *n = node();    while (1) {        n = n->nextEditable();        if (!n)            return Position();        if (n->renderer() && n->renderer()->style()->visibility() == khtml::VISIBLE)            break;    }        return Position(n, 0);}Position Position::previousCharacterPosition() const{    if (isEmpty())        return Position();    NodeImpl *fromRootEditableElement = node()->rootEditableElement();    PositionIterator it(*this);    bool atStartOfLine = isFirstRenderedPositionOnLine();        while (!it.atStart()) {        Position pos = it.previous();        if (pos.node()->rootEditableElement() != fromRootEditableElement)            return *this;        if (atStartOfLine) {            if (pos.inRenderedContent())                return pos;        }        else if (rendersInDifferentPosition(pos))            return pos;    }        return *this;}Position Position::nextCharacterPosition() const{    if (isEmpty())        return Position();    NodeImpl *fromRootEditableElement = node()->rootEditableElement();    PositionIterator it(*this);    bool atEndOfLine = isLastRenderedPositionOnLine();        while (!it.atEnd()) {        Position pos = it.next();        if (pos.node()->rootEditableElement() != fromRootEditableElement)            return *this;        if (atEndOfLine) {            if (pos.inRenderedContent())                return pos;        }        else if (rendersInDifferentPosition(pos))            return pos;    }        return *this;}Position Position::previousWordPosition() const{    if (isEmpty())        return Position();    Position pos = *this;    for (PositionIterator it(*this); !it.atStart(); it.previous()) {        if (it.current().node()->nodeType() == Node::TEXT_NODE || it.current().node()->nodeType() == Node::CDATA_SECTION_NODE) {            DOMString t = it.current().node()->nodeValue();            QChar *chars = t.unicode();            uint len = t.length();            int start, end;            khtml::findWordBoundary(chars, len, it.current().offset(), &start, &end);            pos = Position(it.current().node(), start);        }        else {            pos = Position(it.current().node(), it.current().node()->caretMinOffset());        }        if (pos != *this)            return pos;        it.setPosition(pos);    }        return *this;}Position Position::nextWordPosition() const{    if (isEmpty())        return Position();    Position pos = *this;    for (PositionIterator it(*this); !it.atEnd(); it.next()) {        if (it.current().node()->nodeType() == Node::TEXT_NODE || it.current().node()->nodeType() == Node::CDATA_SECTION_NODE) {            DOMString t = it.current().node()->nodeValue();            QChar *chars = t.unicode();            uint len = t.length();            int start, end;            khtml::findWordBoundary(chars, len, it.current().offset(), &start, &end);            pos = Position(it.current().node(), end);        }        else {            pos = Position(it.current().node(), it.current().node()->caretMaxOffset());        }        if (pos != *this)            return pos;        it.setPosition(pos);    }        return *this;}Position Position::previousLinePosition(int x) const{    if (!node())        return Position();    if (!node()->renderer())        return *this;    InlineBox *box = node()->renderer()->inlineBox(offset());    if (!box)        return *this;    RenderBlock *containingBlock = 0;    RootInlineBox *root = box->root()->prevRootBox();    if (root) {        containingBlock = node()->renderer()->containingBlock();    }    else {        // This containing editable block does not have a previous line.        // Need to move back to previous containing editable block in this root editable        // block and find the last root line box in that block.        NodeImpl *startBlock = node()->enclosingBlockFlowElement();        NodeImpl *n = node()->previousEditable();        while (n && startBlock == n->enclosingBlockFlowElement())            n = n->previousEditable();        if (n) {            while (n && !Position(n, n->caretMaxOffset()).inRenderedContent())                n = n->previousEditable();            if (n && n->inSameRootEditableElement(node())) {                ASSERT(n->renderer());                box = n->renderer()->inlineBox(n->caretMaxOffset());                ASSERT(box);                // previous root line box found                root = box->root();                containingBlock = n->renderer()->containingBlock();            }        }    }        if (root) {        int absx, absy;        containingBlock->absolutePosition(absx, absy);        RenderObject *renderer = root->closestLeafChildForXPos(x, absx)->object();        return renderer->positionForCoordinates(x, absy + root->topOverflow());    }        return *this;}Position Position::nextLinePosition(int x) const{    if (!node())        return Position();    if (!node()->renderer())        return *this;    InlineBox *box = node()->renderer()->inlineBox(offset());    if (!box)        return *this;    RenderBlock *containingBlock = 0;    RootInlineBox *root = box->root()->nextRootBox();    if (root) {        containingBlock = node()->renderer()->containingBlock();    }    else {        // This containing editable block does not have a next line.        // Need to move forward to next containing editable block in this root editable        // block and find the first root line box in that block.        NodeImpl *startBlock = node()->enclosingBlockFlowElement();        NodeImpl *n = node()->nextEditable();        while (n && startBlock == n->enclosingBlockFlowElement())            n = n->nextEditable();        if (n) {            while (n && !Position(n, n->caretMinOffset()).inRenderedContent())                n = n->nextEditable();            if (n && n->inSameRootEditableElement(node())) {                ASSERT(n->renderer());                box = n->renderer()->inlineBox(n->caretMinOffset());                ASSERT(box);                // previous root line box found                root = box->root();                containingBlock = n->renderer()->containingBlock();            }        }    }        if (root) {        int absx, absy;        containingBlock->absolutePosition(absx, absy);        RenderObject *renderer = root->closestLeafChildForXPos(x, absx)->object();        return renderer->positionForCoordinates(x, absy + root->topOverflow());    }    return *this;}Position Position::equivalentUpstreamPosition() const{    if (!node())        return Position();    NodeImpl *block = node()->enclosingBlockFlowElement();        PositionIterator it(*this);                for (; !it.atStart(); it.previous()) {           NodeImpl *currentBlock = it.current().node()->enclosingBlockFlowElement();        if (block != currentBlock)

⌨️ 快捷键说明

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