htmlediting_impl.cpp
来自「手机浏览器源码程序,功能强大」· C++ 代码 · 共 1,886 行 · 第 1/5 页
CPP
1,886 行
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());
}
}
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
//------------------------------------------------------------------------------------------
// AppendNodeCommandImpl
AppendNodeCommandImpl::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);
}
//------------------------------------------------------------------------------------------
// ApplyStyleCommandImpl
ApplyStyleCommandImpl::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 helpers
bool 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());
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?