📄 htmlediting_impl.cpp
字号:
}}void CompositeEditCommandImpl::insertNodeAt(NodeImpl *insertChild, NodeImpl *refChild, long offset){ if (refChild->hasChildNodes() || (refChild->renderer() && refChild->renderer()->isBlockFlow())) { NodeImpl *child = refChild->firstChild(); for (long i = 0; child && i < offset; i++) child = child->nextSibling(); if (child) insertNodeBefore(insertChild, child); else appendNode(refChild, insertChild); } else if (refChild->caretMinOffset() >= offset) { insertNodeBefore(insertChild, refChild); } else if (refChild->isTextNode() && refChild->caretMaxOffset() > offset) { splitTextNode(static_cast<TextImpl *>(refChild), offset); insertNodeBefore(insertChild, refChild); } else { insertNodeAfter(insertChild, refChild); }}void CompositeEditCommandImpl::appendNode(NodeImpl *parent, NodeImpl *appendChild){ AppendNodeCommand cmd(document(), parent, appendChild); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::removeNode(NodeImpl *removeChild){ RemoveNodeCommand cmd(document(), removeChild); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::removeNodeAndPrune(NodeImpl *pruneNode, NodeImpl *stopNode){ RemoveNodeAndPruneCommand cmd(document(), pruneNode, stopNode); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::removeNodePreservingChildren(NodeImpl *removeChild){ RemoveNodePreservingChildrenCommand cmd(document(), removeChild); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::splitTextNode(TextImpl *text, long offset){ SplitTextNodeCommand cmd(document(), text, offset); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::joinTextNodes(TextImpl *text1, TextImpl *text2){ JoinTextNodesCommand cmd(document(), text1, text2); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::inputText(const DOMString &text){ InputTextCommand cmd(document()); applyCommandToComposite(cmd); cmd.input(text);}void CompositeEditCommandImpl::insertText(TextImpl *node, long offset, const DOMString &text){ InsertTextCommand cmd(document(), node, offset, text); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::deleteText(TextImpl *node, long offset, long count){ DeleteTextCommand cmd(document(), node, offset, count); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::replaceText(TextImpl *node, long offset, long count, const DOMString &replacementText){ DeleteTextCommand deleteCommand(document(), node, offset, count); applyCommandToComposite(deleteCommand); InsertTextCommand insertCommand(document(), node, offset, replacementText); applyCommandToComposite(insertCommand);}void CompositeEditCommandImpl::deleteSelection(){ if (endingSelection().state() == Selection::RANGE) { DeleteSelectionCommand cmd(document()); applyCommandToComposite(cmd); }}void CompositeEditCommandImpl::deleteSelection(const Selection &selection){ if (selection.state() == Selection::RANGE) { DeleteSelectionCommand cmd(document(), selection); applyCommandToComposite(cmd); }}void CompositeEditCommandImpl::deleteCollapsibleWhitespace(){ DeleteCollapsibleWhitespaceCommand cmd(document()); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::deleteCollapsibleWhitespace(const Selection &selection){ DeleteCollapsibleWhitespaceCommand cmd(document(), selection); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::removeCSSProperty(CSSStyleDeclarationImpl *decl, int property){ RemoveCSSPropertyCommand cmd(document(), decl, property); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::removeNodeAttribute(ElementImpl *element, int attribute){ RemoveNodeAttributeCommand cmd(document(), element, attribute); applyCommandToComposite(cmd);}void CompositeEditCommandImpl::setNodeAttribute(ElementImpl *element, int attribute, const DOMString &value){ SetNodeAttributeCommand cmd(document(), element, attribute, value); applyCommandToComposite(cmd);}ElementImpl *CompositeEditCommandImpl::createTypingStyleElement() const{ int exceptionCode = 0; ElementImpl *styleElement = document()->createHTMLElement("SPAN", exceptionCode); ASSERT(exceptionCode == 0); styleElement->setAttribute(ATTR_STYLE, document()->part()->typingStyle()->cssText().implementation(), exceptionCode); ASSERT(exceptionCode == 0); styleElement->setAttribute(ATTR_CLASS, styleSpanClassString()); ASSERT(exceptionCode == 0); return styleElement;}//==========================================================================================// Concrete commands//------------------------------------------------------------------------------------------// AppendNodeCommandImplAppendNodeCommandImpl::AppendNodeCommandImpl(DocumentImpl *document, NodeImpl *parentNode, NodeImpl *appendChild) : EditCommandImpl(document), m_parentNode(parentNode), m_appendChild(appendChild){ ASSERT(m_parentNode); m_parentNode->ref(); ASSERT(m_appendChild); m_appendChild->ref();}AppendNodeCommandImpl::~AppendNodeCommandImpl(){ if (m_parentNode) m_parentNode->deref(); if (m_appendChild) m_appendChild->deref();}int AppendNodeCommandImpl::commandID() const{ return AppendNodeCommandID;}void AppendNodeCommandImpl::doApply(){ ASSERT(m_parentNode); ASSERT(m_appendChild); int exceptionCode = 0; m_parentNode->appendChild(m_appendChild, exceptionCode); ASSERT(exceptionCode == 0);}void AppendNodeCommandImpl::doUnapply(){ ASSERT(m_parentNode); ASSERT(m_appendChild); ASSERT(state() == Applied); int exceptionCode = 0; m_parentNode->removeChild(m_appendChild, exceptionCode); ASSERT(exceptionCode == 0);}//------------------------------------------------------------------------------------------// ApplyStyleCommandImplApplyStyleCommandImpl::ApplyStyleCommandImpl(DocumentImpl *document, CSSStyleDeclarationImpl *style) : CompositeEditCommandImpl(document), m_style(style){ ASSERT(m_style); m_style->ref();}ApplyStyleCommandImpl::~ApplyStyleCommandImpl(){ ASSERT(m_style); m_style->deref();}int ApplyStyleCommandImpl::commandID() const{ return ApplyStyleCommandID;}void ApplyStyleCommandImpl::doApply(){ if (endingSelection().state() != Selection::RANGE) return; // adjust to the positions we want to use for applying style Position start(endingSelection().start().equivalentDownstreamPosition().equivalentRangeCompliantPosition()); Position end(endingSelection().end().equivalentUpstreamPosition()); // remove style from the selection removeStyle(start, end); bool splitStart = splitTextAtStartIfNeeded(start, end); if (splitStart) { start = endingSelection().start(); end = endingSelection().end(); } splitTextAtEndIfNeeded(start, end); start = endingSelection().start(); end = endingSelection().end(); if (start.node() == end.node()) { // simple case...start and end are the same node applyStyleIfNeeded(start.node(), end.node()); } else { NodeImpl *node = start.node(); while (1) { if (node->childNodeCount() == 0 && node->renderer() && node->renderer()->isInline()) { NodeImpl *runStart = node; while (1) { if (runStart->parentNode() != node->parentNode() || node->isHTMLElement() || node == end.node() || (node->renderer() && !node->renderer()->isInline())) { applyStyleIfNeeded(runStart, node); break; } node = node->traverseNextNode(); } } if (node == end.node()) break; node = node->traverseNextNode(); } }}//------------------------------------------------------------------------------------------// ApplyStyleCommandImpl: style-removal helpersbool ApplyStyleCommandImpl::isHTMLStyleNode(HTMLElementImpl *elem){ for (QPtrListIterator<CSSProperty> it(*(style()->values())); it.current(); ++it) { CSSProperty *property = it.current(); switch (property->id()) { case CSS_PROP_FONT_WEIGHT: if (elem->id() == ID_B) return true; break; case CSS_PROP_FONT_STYLE: if (elem->id() == ID_I) return true; break; } } return false;}void ApplyStyleCommandImpl::removeHTMLStyleNode(HTMLElementImpl *elem){ // This node can be removed. // EDIT FIXME: This does not handle the case where the node // has attributes. But how often do people add attributes to <B> tags? // Not so often I think. ASSERT(elem); removeNodePreservingChildren(elem);}void ApplyStyleCommandImpl::removeCSSStyle(HTMLElementImpl *elem){ ASSERT(elem); CSSStyleDeclarationImpl *decl = elem->inlineStyleDecl(); if (!decl) return; for (QPtrListIterator<CSSProperty> it(*(style()->values())); it.current(); ++it) { CSSProperty *property = it.current(); if (decl->getPropertyCSSValue(property->id())) removeCSSProperty(decl, property->id()); } if (elem->id() == ID_SPAN) { // Check to see if the span is one we added to apply style. // If it is, and there are no more attributes on the span other than our // class marker, remove the span. NamedAttrMapImpl *map = elem->attributes(); if (map && map->length() == 1 && elem->getAttribute(ATTR_CLASS) == styleSpanClassString()) removeNodePreservingChildren(elem); }}void ApplyStyleCommandImpl::removeStyle(const Position &start, const Position &end){ NodeImpl *node = start.node(); while (1) { NodeImpl *next = node->traverseNextNode(); if (node->isHTMLElement() && nodeFullySelected(node)) { HTMLElementImpl *elem = static_cast<HTMLElementImpl *>(node); if (isHTMLStyleNode(elem)) removeHTMLStyleNode(elem); else removeCSSStyle(elem); } if (node == end.node()) break; node = next; }}bool ApplyStyleCommandImpl::nodeFullySelected(const NodeImpl *node) const{ ASSERT(node); Position end(endingSelection().end().equivalentUpstreamPosition()); if (node == end.node()) return end.offset() >= node->caretMaxOffset(); for (NodeImpl *child = node->lastChild(); child; child = child->lastChild()) { if (child == end.node()) return end.offset() >= child->caretMaxOffset(); } return !node->isAncestor(end.node());}//------------------------------------------------------------------------------------------// ApplyStyleCommandImpl: style-application helpersbool ApplyStyleCommandImpl::splitTextAtStartIfNeeded(const Position &start, const Position &end){ if (start.node()->isTextNode() && start.offset() > start.node()->caretMinOffset() && start.offset() < start.node()->caretMaxOffset()) { long endOffsetAdjustment = start.node() == end.node() ? start.offset() : 0; TextImpl *text = static_cast<TextImpl *>(start.node()); SplitTextNodeCommand cmd(document(), text, start.offset()); applyCommandToComposite(cmd); setEndingSelection(Selection(Position(start.node(), 0), Position(end.node(), end.offset() - endOffsetAdjustment))); return true; } return false;}NodeImpl *ApplyStyleCommandImpl::splitTextAtEndIfNeeded(const Position &start, const Position &end){ if (end.node()->isTextNode() && end.offset() > end.node()->caretMinOffset() && end.offset() < end.node()->caretMaxOffset()) { TextImpl *text = static_cast<TextImpl *>(end.node()); SplitTextNodeCommand cmd(document(), text, end.offset()); applyCommandToComposite(cmd); NodeImpl *startNode = start.node() == end.node() ? cmd.node()->previousSibling() : start.node(); ASSERT(startNode); setEndingSelection(Selection(Position(startNode, start.offset()), Position(cmd.node()->previousSibling(), cmd.node()->previousSibling()->caretMaxOffset()))); return cmd.node()->previousSibling(); } return end.node();}void ApplyStyleCommandImpl::surroundNodeRangeWithElement(NodeImpl *startNode, NodeImpl *endNode, ElementImpl *element){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -