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

📄 replaceselectioncommand.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2005, 2006, 2008 Apple 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 "ReplaceSelectionCommand.h"#include "ApplyStyleCommand.h"#include "BeforeTextInsertedEvent.h"#include "BreakBlockquoteCommand.h" #include "CSSComputedStyleDeclaration.h"#include "CSSProperty.h"#include "CSSPropertyNames.h"#include "CSSValueKeywords.h"#include "Document.h"#include "DocumentFragment.h"#include "EditingText.h"#include "EventNames.h"#include "Element.h"#include "Frame.h"#include "HTMLElement.h"#include "HTMLInterchange.h"#include "HTMLInputElement.h"#include "HTMLNames.h"#include "SelectionController.h"#include "SmartReplace.h"#include "TextIterator.h"#include "htmlediting.h"#include "markup.h"#include "visible_units.h"#include <wtf/StdLibExtras.h>namespace WebCore {using namespace HTMLNames;enum EFragmentType { EmptyFragment, SingleTextNodeFragment, TreeFragment };// --- ReplacementFragment helper classclass ReplacementFragment : Noncopyable {public:    ReplacementFragment(Document*, DocumentFragment*, bool matchStyle, const VisibleSelection&);    Node* firstChild() const;    Node* lastChild() const;    bool isEmpty() const;        bool hasInterchangeNewlineAtStart() const { return m_hasInterchangeNewlineAtStart; }    bool hasInterchangeNewlineAtEnd() const { return m_hasInterchangeNewlineAtEnd; }        void removeNode(PassRefPtr<Node>);    void removeNodePreservingChildren(Node*);private:    PassRefPtr<Node> insertFragmentForTestRendering(Node* context);    void removeUnrenderedNodes(Node*);    void restoreTestRenderingNodesToFragment(Node*);    void removeInterchangeNodes(Node*);        void insertNodeBefore(PassRefPtr<Node> node, Node* refNode);    RefPtr<Document> m_document;    RefPtr<DocumentFragment> m_fragment;    bool m_matchStyle;    bool m_hasInterchangeNewlineAtStart;    bool m_hasInterchangeNewlineAtEnd;};static bool isInterchangeNewlineNode(const Node *node){    DEFINE_STATIC_LOCAL(String, interchangeNewlineClassString, (AppleInterchangeNewline));    return node && node->hasTagName(brTag) &&            static_cast<const Element *>(node)->getAttribute(classAttr) == interchangeNewlineClassString;}static bool isInterchangeConvertedSpaceSpan(const Node *node){    DEFINE_STATIC_LOCAL(String, convertedSpaceSpanClassString, (AppleConvertedSpace));    return node->isHTMLElement() &&            static_cast<const HTMLElement *>(node)->getAttribute(classAttr) == convertedSpaceSpanClassString;}ReplacementFragment::ReplacementFragment(Document* document, DocumentFragment* fragment, bool matchStyle, const VisibleSelection& selection)    : m_document(document),      m_fragment(fragment),      m_matchStyle(matchStyle),       m_hasInterchangeNewlineAtStart(false),       m_hasInterchangeNewlineAtEnd(false){    if (!m_document)        return;    if (!m_fragment)        return;    if (!m_fragment->firstChild())        return;        Element* editableRoot = selection.rootEditableElement();    ASSERT(editableRoot);    if (!editableRoot)        return;        Node* shadowAncestorNode = editableRoot->shadowAncestorNode();        if (!editableRoot->inlineEventListenerForType(eventNames().webkitBeforeTextInsertedEvent) &&        // FIXME: Remove these checks once textareas and textfields actually register an event handler.        !(shadowAncestorNode && shadowAncestorNode->renderer() && shadowAncestorNode->renderer()->isTextControl()) &&        editableRoot->isContentRichlyEditable()) {        removeInterchangeNodes(m_fragment.get());        return;    }    Node* styleNode = selection.base().node();    RefPtr<Node> holder = insertFragmentForTestRendering(styleNode);        RefPtr<Range> range = VisibleSelection::selectionFromContentsOfNode(holder.get()).toNormalizedRange();    String text = plainText(range.get());    // Give the root a chance to change the text.    RefPtr<BeforeTextInsertedEvent> evt = BeforeTextInsertedEvent::create(text);    ExceptionCode ec = 0;    editableRoot->dispatchEvent(evt, ec);    ASSERT(ec == 0);    if (text != evt->text() || !editableRoot->isContentRichlyEditable()) {        restoreTestRenderingNodesToFragment(holder.get());        removeNode(holder);        m_fragment = createFragmentFromText(selection.toNormalizedRange().get(), evt->text());        if (!m_fragment->firstChild())            return;        holder = insertFragmentForTestRendering(styleNode);    }        removeInterchangeNodes(holder.get());        removeUnrenderedNodes(holder.get());    restoreTestRenderingNodesToFragment(holder.get());    removeNode(holder);}bool ReplacementFragment::isEmpty() const{    return (!m_fragment || !m_fragment->firstChild()) && !m_hasInterchangeNewlineAtStart && !m_hasInterchangeNewlineAtEnd;}Node *ReplacementFragment::firstChild() const {     return m_fragment ? m_fragment->firstChild() : 0; }Node *ReplacementFragment::lastChild() const {     return m_fragment ? m_fragment->lastChild() : 0; }void ReplacementFragment::removeNodePreservingChildren(Node *node){    if (!node)        return;    while (RefPtr<Node> n = node->firstChild()) {        removeNode(n);        insertNodeBefore(n.release(), node);    }    removeNode(node);}void ReplacementFragment::removeNode(PassRefPtr<Node> node){    if (!node)        return;        Node *parent = node->parentNode();    if (!parent)        return;        ExceptionCode ec = 0;    parent->removeChild(node.get(), ec);    ASSERT(ec == 0);}void ReplacementFragment::insertNodeBefore(PassRefPtr<Node> node, Node* refNode){    if (!node || !refNode)        return;            Node* parent = refNode->parentNode();    if (!parent)        return;            ExceptionCode ec = 0;    parent->insertBefore(node, refNode, ec);    ASSERT(ec == 0);}PassRefPtr<Node> ReplacementFragment::insertFragmentForTestRendering(Node* context){    Node* body = m_document->body();    if (!body)        return 0;    RefPtr<StyledElement> holder = createDefaultParagraphElement(m_document.get());        ExceptionCode ec = 0;    // Copy the whitespace and user-select style from the context onto this element.    // FIXME: We should examine other style properties to see if they would be appropriate to consider during the test rendering.    Node* n = context;    while (n && !n->isElementNode())        n = n->parentNode();    if (n) {        RefPtr<CSSComputedStyleDeclaration> conFontStyle = computedStyle(n);        CSSStyleDeclaration* style = holder->style();        style->setProperty(CSSPropertyWhiteSpace, conFontStyle->getPropertyValue(CSSPropertyWhiteSpace), false, ec);        ASSERT(ec == 0);        style->setProperty(CSSPropertyWebkitUserSelect, conFontStyle->getPropertyValue(CSSPropertyWebkitUserSelect), false, ec);        ASSERT(ec == 0);    }        holder->appendChild(m_fragment, ec);    ASSERT(ec == 0);        body->appendChild(holder.get(), ec);    ASSERT(ec == 0);        m_document->updateLayoutIgnorePendingStylesheets();        return holder.release();}void ReplacementFragment::restoreTestRenderingNodesToFragment(Node *holder){    if (!holder)        return;        ExceptionCode ec = 0;    while (RefPtr<Node> node = holder->firstChild()) {        holder->removeChild(node.get(), ec);        ASSERT(ec == 0);        m_fragment->appendChild(node.get(), ec);        ASSERT(ec == 0);    }}void ReplacementFragment::removeUnrenderedNodes(Node* holder){    Vector<Node*> unrendered;    for (Node* node = holder->firstChild(); node; node = node->traverseNextNode(holder))

⌨️ 快捷键说明

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