BreakBlockquoteCommand.cpp [plain text]
#include "config.h"
#include "BreakBlockquoteCommand.h"
#include "Element.h"
#include "HTMLNames.h"
#include "Text.h"
#include "VisiblePosition.h"
#include "htmlediting.h"
#include "RenderListItem.h"
namespace WebCore {
using namespace HTMLNames;
BreakBlockquoteCommand::BreakBlockquoteCommand(Document *document)
: CompositeEditCommand(document)
{
}
void BreakBlockquoteCommand::doApply()
{
Selection selection = endingSelection();
if (selection.isNone())
return;
Position pos = selection.start();
EAffinity affinity = selection.affinity();
if (selection.isRange()) {
deleteSelection(false, false);
pos = endingSelection().start().upstream();
affinity = endingSelection().affinity();
}
Node *startNode = pos.node();
Node *topBlockquote = 0;
for (Node *node = startNode->parentNode(); node; node = node->parentNode()) {
if (isMailBlockquote(node))
topBlockquote = node;
}
if (!topBlockquote || !topBlockquote->parentNode())
return;
RefPtr<Element> breakNode = createBreakElement(document());
insertNodeAfter(breakNode.get(), topBlockquote);
if (!isLastVisiblePositionInNode(VisiblePosition(pos, affinity), topBlockquote)) {
Node *newStartNode = 0;
if (startNode->isTextNode()) {
Text *textNode = static_cast<Text *>(startNode);
if ((unsigned)pos.offset() >= textNode->length()) {
newStartNode = startNode->traverseNextNode();
ASSERT(newStartNode);
} else if (pos.offset() > 0)
splitTextNode(textNode, pos.offset());
} else if (startNode->hasTagName(brTag)) {
newStartNode = startNode->traverseNextNode();
ASSERT(newStartNode);
} else if (pos.offset() > 0) {
newStartNode = startNode->traverseNextNode();
ASSERT(newStartNode);
}
if (newStartNode) {
startNode = newStartNode;
topBlockquote = 0;
for (Node *node = startNode->parentNode(); node; node = node->parentNode()) {
if (isMailBlockquote(node))
topBlockquote = node;
}
if (!topBlockquote || !topBlockquote->parentNode()) {
setEndingSelection(Selection(VisiblePosition(Position(startNode, 0))));
return;
}
}
Vector<Node*> ancestors;
for (Node* node = startNode->parentNode(); node != topBlockquote; node = node->parentNode())
ancestors.append(node);
RefPtr<Node> clonedBlockquote = topBlockquote->cloneNode(false);
insertNodeAfter(clonedBlockquote.get(), breakNode.get());
RefPtr<Node> clonedAncestor = clonedBlockquote;
for (size_t i = ancestors.size(); i != 0; --i) {
RefPtr<Node> clonedChild = ancestors[i - 1]->cloneNode(false); if (clonedChild->isElementNode() && clonedChild->hasTagName(olTag)) {
Node* listChildNode = i > 1 ? ancestors[i - 2] : startNode;
while (listChildNode && !listChildNode->hasTagName(liTag))
listChildNode = listChildNode->nextSibling();
if (listChildNode && listChildNode->renderer())
setNodeAttribute(static_cast<Element*>(clonedChild.get()), startAttr, String::number(static_cast<RenderListItem*>(listChildNode->renderer())->value()));
}
appendNode(clonedChild.get(), clonedAncestor.get());
clonedAncestor = clonedChild;
}
Node *moveNode = startNode;
while (moveNode) {
Node *next = moveNode->nextSibling();
removeNode(moveNode);
appendNode(moveNode, clonedAncestor.get());
moveNode = next;
}
if (!ancestors.isEmpty()) {
addBlockPlaceholderIfNeeded(ancestors.first());
Node* ancestor;
Node* clonedParent;
for (ancestor = ancestors.first(), clonedParent = clonedAncestor->parentNode();
ancestor && ancestor != topBlockquote;
ancestor = ancestor->parentNode(), clonedParent = clonedParent->parentNode()) {
moveNode = ancestor->nextSibling();
while (moveNode) {
Node *next = moveNode->nextSibling();
removeNode(moveNode);
appendNode(moveNode, clonedParent);
moveNode = next;
}
}
}
addBlockPlaceholderIfNeeded(clonedBlockquote.get());
}
setEndingSelection(Selection(Position(breakNode.get(), 0), DOWNSTREAM));
rebalanceWhitespace();
}
}