📄 htmlediting_impl.cpp
字号:
/* * 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 "htmlediting_impl.h"#include "cssproperties.h"#include "css/css_valueimpl.h"#include "dom/css_value.h"#include "dom/dom_position.h"#include "html/html_elementimpl.h"#include "html/html_imageimpl.h"#include "htmlattrs.h"#include "htmltags.h"#include "khtml_part.h"#include "khtmlview.h"#include "qptrlist.h"#include "rendering/render_object.h"#include "rendering/render_style.h"#include "rendering/render_text.h"#include "xml/dom_docimpl.h"#include "xml/dom_elementimpl.h"#include "xml/dom_positioniterator.h"#include "xml/dom_nodeimpl.h"#include "xml/dom_selection.h"#include "xml/dom_stringimpl.h"#include "xml/dom_textimpl.h"#include "xml/dom2_rangeimpl.h"#include "xml/dom2_viewsimpl.h"#if APPLE_CHANGES#include "KWQAssertions.h"#include "KWQLogging.h"#endifusing DOM::AttrImpl;using DOM::CSSPrimitiveValue;using DOM::CSSPrimitiveValueImpl;using DOM::CSSProperty;using DOM::CSSStyleDeclarationImpl;using DOM::CSSValueImpl;using DOM::DocumentFragmentImpl;using DOM::DocumentImpl;using DOM::DOMString;using DOM::DOMStringImpl;using DOM::EditingTextImpl;using DOM::PositionIterator;using DOM::ElementImpl;using DOM::HTMLElementImpl;using DOM::HTMLImageElementImpl;using DOM::NamedAttrMapImpl;using DOM::Node;using DOM::NodeImpl;using DOM::NodeListImpl;using DOM::Position;using DOM::Range;using DOM::RangeImpl;using DOM::Selection;using DOM::TextImpl;using DOM::TreeWalkerImpl;namespace khtml {static inline bool isNBSP(const QChar &c){ return c == QChar(0xa0);}static inline bool isWS(const QChar &c){ return c.isSpace() && c != QChar(0xa0);}static inline bool isWS(const DOMString &text){ if (text.length() != 1) return false; return isWS(text[0]);}static inline bool isWS(const Position &pos){ if (!pos.node()) return false; if (!pos.node()->isTextNode()) return false; const DOMString &string = static_cast<TextImpl *>(pos.node())->data(); return isWS(string[pos.offset()]);}static bool shouldPruneNode(NodeImpl *node){ if (!node) return false; RenderObject *renderer = node->renderer(); if (!renderer) return true; if (node->hasChildNodes()) return false; if (node->rootEditableElement() == node) return false; if (renderer->isBR() || renderer->isReplaced()) return false; if (node->isTextNode()) { TextImpl *text = static_cast<TextImpl *>(node); if (text->length() == 0) return true; return false; } if (!node->isHTMLElement() && !node->isXMLElementNode()) return false; if (node->id() == ID_BODY) return false; if (!node->isContentEditable()) return false; return true;}static Position leadingWhitespacePosition(const Position &pos){ ASSERT(pos.notEmpty()); Selection selection(pos); Position prev = pos.previousCharacterPosition(); if (prev != pos && prev.node()->inSameContainingBlockFlowElement(pos.node()) && prev.node()->isTextNode()) { DOMString string = static_cast<TextImpl *>(prev.node())->data(); if (isWS(string[prev.offset()])) return prev; } return Position();}static Position trailingWhitespacePosition(const Position &pos){ ASSERT(pos.notEmpty()); if (pos.node()->isTextNode()) { TextImpl *textNode = static_cast<TextImpl *>(pos.node()); if (pos.offset() >= (long)textNode->length()) { Position next = pos.nextCharacterPosition(); if (next != pos && next.node()->inSameContainingBlockFlowElement(pos.node()) && next.node()->isTextNode()) { DOMString string = static_cast<TextImpl *>(next.node())->data(); if (isWS(string[0])) return next; } } else { DOMString string = static_cast<TextImpl *>(pos.node())->data(); if (isWS(string[pos.offset()])) return pos; } } return Position();}static bool textNodesAreJoinable(TextImpl *text1, TextImpl *text2){ ASSERT(text1); ASSERT(text2); return (text1->nextSibling() == text2);}static DOMString &nonBreakingSpaceString(){ static DOMString nonBreakingSpaceString = QString(QChar(0xa0)); return nonBreakingSpaceString;}static DOMString &styleSpanClassString(){ static DOMString styleSpanClassString = "khtml-style-span"; return styleSpanClassString;}static void debugPosition(const char *prefix, const Position &pos){ LOG(Editing, "%s%s %p : %d", prefix, getTagName(pos.node()->id()).string().latin1(), pos.node(), pos.offset());}//------------------------------------------------------------------------------------------// EditCommandImplEditCommandImpl::EditCommandImpl(DocumentImpl *document) : SharedCommandImpl(), m_document(document), m_state(NotApplied), m_parent(0){ ASSERT(m_document); ASSERT(m_document->part()); m_document->ref(); m_startingSelection = m_document->part()->selection(); m_endingSelection = m_startingSelection;}EditCommandImpl::~EditCommandImpl(){ ASSERT(m_document); m_document->deref();}int EditCommandImpl::commandID() const{ return EditCommandID;}void EditCommandImpl::apply(){ ASSERT(m_document); ASSERT(m_document->part()); ASSERT(state() == NotApplied); doApply(); m_state = Applied; if (!isCompositeStep()) { EditCommand cmd(this); m_document->part()->appliedEditing(cmd); }}void EditCommandImpl::unapply(){ ASSERT(m_document); ASSERT(m_document->part()); ASSERT(state() == Applied); doUnapply(); m_state = NotApplied; if (!isCompositeStep()) { EditCommand cmd(this); m_document->part()->unappliedEditing(cmd); }}void EditCommandImpl::reapply(){ ASSERT(m_document); ASSERT(m_document->part()); ASSERT(state() == NotApplied); doReapply(); m_state = Applied; if (!isCompositeStep()) { EditCommand cmd(this); m_document->part()->reappliedEditing(cmd); }}void EditCommandImpl::doReapply(){ doApply();}void EditCommandImpl::setStartingSelection(const Selection &s){ m_startingSelection = s; EditCommand cmd = parent(); while (cmd.notNull()) { cmd.handle()->m_startingSelection = s; cmd = cmd.parent(); }}void EditCommandImpl::setEndingSelection(const Selection &s){ m_endingSelection = s; EditCommand cmd = parent(); while (cmd.notNull()) { cmd.handle()->m_endingSelection = s; cmd = cmd.parent(); }}EditCommand EditCommandImpl::parent() const{ return m_parent;}void EditCommandImpl::setParent(const EditCommand &cmd){ m_parent = cmd;}//------------------------------------------------------------------------------------------// CompositeEditCommandImplCompositeEditCommandImpl::CompositeEditCommandImpl(DocumentImpl *document) : EditCommandImpl(document){}CompositeEditCommandImpl::~CompositeEditCommandImpl(){}int CompositeEditCommandImpl::commandID() const{ return CompositeEditCommandID;}void CompositeEditCommandImpl::doUnapply(){ if (m_cmds.count() == 0) { return; } for (int i = m_cmds.count() - 1; i >= 0; --i) m_cmds[i]->unapply(); setState(NotApplied);}void CompositeEditCommandImpl::doReapply(){ if (m_cmds.count() == 0) { return; } for (QValueList<EditCommand>::ConstIterator it = m_cmds.begin(); it != m_cmds.end(); ++it) (*it)->reapply(); setState(Applied);}//// sugary-sweet convenience functions to help create and apply edit commands in composite commands//void CompositeEditCommandImpl::applyCommandToComposite(EditCommand &cmd){ cmd.setStartingSelection(endingSelection()); cmd.setEndingSelection(endingSelection()); cmd.setParent(this); cmd.apply(); m_cmds.append(cmd);}void CompositeEditCommandImpl::insertNodeBefore(NodeImpl *insertChild, NodeImpl *refChild){ InsertNodeBeforeCommand cmd(document(), insertChild, refChild); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::insertNodeAfter(NodeImpl *insertChild, NodeImpl *refChild){ if (refChild->parentNode()->lastChild() == refChild) { appendNode(refChild->parentNode(), insertChild); } else { ASSERT(refChild->nextSibling()); insertNodeBefore(insertChild, refChild->nextSibling());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -