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

📄 visibleselection.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2004, 2005, 2006 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 "config.h"#include "VisibleSelection.h"#include "CharacterNames.h"#include "CString.h"#include "Document.h"#include "Element.h"#include "htmlediting.h"#include "TextIterator.h"#include "VisiblePosition.h"#include "visible_units.h"#include "Range.h"#include <wtf/Assertions.h>#include <stdio.h>namespace WebCore {VisibleSelection::VisibleSelection()    : m_affinity(DOWNSTREAM)    , m_granularity(CharacterGranularity)    , m_selectionType(NoSelection)    , m_baseIsFirst(true){}VisibleSelection::VisibleSelection(const Position& pos, EAffinity affinity)    : m_base(pos)    , m_extent(pos)    , m_affinity(affinity)    , m_granularity(CharacterGranularity){    validate();}VisibleSelection::VisibleSelection(const Position& base, const Position& extent, EAffinity affinity)    : m_base(base)    , m_extent(extent)    , m_affinity(affinity)    , m_granularity(CharacterGranularity){    validate();}VisibleSelection::VisibleSelection(const VisiblePosition& pos)    : m_base(pos.deepEquivalent())    , m_extent(pos.deepEquivalent())    , m_affinity(pos.affinity())    , m_granularity(CharacterGranularity){    validate();}VisibleSelection::VisibleSelection(const VisiblePosition& base, const VisiblePosition& extent)    : m_base(base.deepEquivalent())    , m_extent(extent.deepEquivalent())    , m_affinity(base.affinity())    , m_granularity(CharacterGranularity){    validate();}VisibleSelection::VisibleSelection(const Range* range, EAffinity affinity)    : m_base(range->startPosition())    , m_extent(range->endPosition())    , m_affinity(affinity)    , m_granularity(CharacterGranularity){    validate();}VisibleSelection VisibleSelection::selectionFromContentsOfNode(Node* node){    return VisibleSelection(Position(node, 0), Position(node, maxDeepOffset(node)), DOWNSTREAM);}void VisibleSelection::setBase(const Position& position){    m_base = position;    validate();}void VisibleSelection::setBase(const VisiblePosition& visiblePosition){    m_base = visiblePosition.deepEquivalent();    validate();}void VisibleSelection::setExtent(const Position& position){    m_extent = position;    validate();}void VisibleSelection::setExtent(const VisiblePosition& visiblePosition){    m_extent = visiblePosition.deepEquivalent();    validate();}PassRefPtr<Range> VisibleSelection::firstRange() const{    if (isNone())        return 0;    Position start = rangeCompliantEquivalent(m_start);    Position end = rangeCompliantEquivalent(m_end);    return Range::create(start.node()->document(), start, end);}PassRefPtr<Range> VisibleSelection::toNormalizedRange() const{    if (isNone())        return 0;    // 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.    m_start.node()->document()->updateLayout();    // Check again, because updating layout can clear the selection.    if (isNone())        return 0;    Position s, e;    if (isCaret()) {        // 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 = rangeCompliantEquivalent(m_start.upstream());        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(isRange());        s = m_start.downstream();        e = m_end.upstream();        if (Range::compareBoundaryPoints(s.node(), s.offset(), e.node(), e.offset()) > 0) {            // 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 = rangeCompliantEquivalent(s);        e = rangeCompliantEquivalent(e);    }    // VisibleSelections are supposed to always be valid.  This constructor will ASSERT    // if a valid range could not be created, which is fine for this callsite.    return Range::create(s.node()->document(), s, e);}bool VisibleSelection::expandUsingGranularity(TextGranularity granularity){    if (isNone())        return false;    m_granularity = granularity;    validate();    return true;}static PassRefPtr<Range> makeSearchRange(const Position& pos){    Node* n = pos.node();    if (!n)        return 0;    Document* d = n->document();    Node* de = d->documentElement();    if (!de)        return 0;    Node* boundary = n->enclosingBlockFlowElement();    if (!boundary)        return 0;    RefPtr<Range> searchRange(Range::create(d));    ExceptionCode ec = 0;    Position start(rangeCompliantEquivalent(pos));    searchRange->selectNodeContents(boundary, ec);    searchRange->setStart(start.node(), start.offset(), ec);    ASSERT(!ec);    if (ec)        return 0;    return searchRange.release();}void VisibleSelection::appendTrailingWhitespace(){    RefPtr<Range> searchRange = makeSearchRange(m_end);    if (!searchRange)        return;    CharacterIterator charIt(searchRange.get(), true);    for (; charIt.length(); charIt.advance(1)) {        UChar c = charIt.characters()[0];        if (!isSpaceOrNewline(c) && c != noBreakSpace)            break;        m_end = charIt.range()->endPosition();    }}void VisibleSelection::setBaseAndExtentToDeepEquivalents(){    // Move the selection to rendered positions, if possible.    bool baseAndExtentEqual = m_base == m_extent;    if (m_base.isNotNull()) {        m_base = VisiblePosition(m_base, m_affinity).deepEquivalent();        if (baseAndExtentEqual)            m_extent = m_base;    }    if (m_extent.isNotNull() && !baseAndExtentEqual)        m_extent = VisiblePosition(m_extent, m_affinity).deepEquivalent();    // Make sure we do not have a dangling base or extent.    if (m_base.isNull() && m_extent.isNull())        m_baseIsFirst = true;    else if (m_base.isNull()) {        m_base = m_extent;        m_baseIsFirst = true;    } else if (m_extent.isNull()) {        m_extent = m_base;        m_baseIsFirst = true;    } else        m_baseIsFirst = comparePositions(m_base, m_extent) <= 0;}void VisibleSelection::setStartAndEndFromBaseAndExtentRespectingGranularity(){    if (m_baseIsFirst) {        m_start = m_base;        m_end = m_extent;    } else {        m_start = m_extent;        m_end = m_base;    }    switch (m_granularity) {        case CharacterGranularity:            // Don't do any expansion.            break;        case WordGranularity: {            // General case: Select the word the caret is positioned inside of, or at the start of (RightWordIfOnBoundary).            // Edge case: If the caret is after the last word in a soft-wrapped line or the last word in            // the document, select that last word (LeftWordIfOnBoundary).            // Edge case: If the caret is after the last word in a paragraph, select from the the end of the            // last word to the line break (also RightWordIfOnBoundary);            VisiblePosition start = VisiblePosition(m_start, m_affinity);            VisiblePosition originalEnd(m_end, m_affinity);            EWordSide side = RightWordIfOnBoundary;            if (isEndOfDocument(start) || (isEndOfLine(start) && !isStartOfLine(start) && !isEndOfParagraph(start)))                side = LeftWordIfOnBoundary;            m_start = startOfWord(start, side).deepEquivalent();            side = RightWordIfOnBoundary;            if (isEndOfDocument(originalEnd) || (isEndOfLine(originalEnd) && !isStartOfLine(originalEnd) && !isEndOfParagraph(originalEnd)))                side = LeftWordIfOnBoundary;                            VisiblePosition wordEnd(endOfWord(originalEnd, side));            VisiblePosition end(wordEnd);                        if (isEndOfParagraph(originalEnd)) {                // Select the paragraph break (the space from the end of a paragraph to the start of                 // the next one) to match TextEdit.                end = wordEnd.next();                                if (Node* table = isFirstPositionAfterTable(end)) {                    // The paragraph break after the last paragraph in the last cell of a block table ends                    // at the start of the paragraph after the table.                    if (isBlock(table))                        end = end.next(true);                    else                        end = wordEnd;                }                                if (end.isNull())                    end = wordEnd;                                }                            m_end = end.deepEquivalent();            break;        }        case SentenceGranularity: {            m_start = startOfSentence(VisiblePosition(m_start, m_affinity)).deepEquivalent();            m_end = endOfSentence(VisiblePosition(m_end, m_affinity)).deepEquivalent();            break;        }        case LineGranularity: {            m_start = startOfLine(VisiblePosition(m_start, m_affinity)).deepEquivalent();

⌨️ 快捷键说明

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