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"
namespace WebCore {
using namespace HTMLNames;
BreakBlockquoteCommand::BreakBlockquoteCommand(Document *document)
: CompositeEditCommand(document)
{
}
void BreakBlockquoteCommand::doApply()
{
DeprecatedPtrList<Node> ancestors;
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;
for (Node *node = startNode->parentNode(); node; node = node->parentNode()) {
if (isMailBlockquote(node))
topBlockquote = node;
}
if (!topBlockquote || !topBlockquote->parentNode())
return;
}
for (Node *node = startNode->parentNode(); node != topBlockquote; node = node->parentNode())
ancestors.prepend(node);
RefPtr<Node> clonedBlockquote = topBlockquote->cloneNode(false);
insertNodeAfter(clonedBlockquote.get(), breakNode.get());
RefPtr<Node> clonedAncestor = clonedBlockquote;
for (DeprecatedPtrListIterator<Node> it(ancestors); it.current(); ++it) {
RefPtr<Node> clonedChild = it.current()->cloneNode(false); appendNode(clonedChild.get(), clonedAncestor.get());
clonedAncestor = clonedChild;
}
Node *moveNode = startNode;
while (moveNode) {
Node *next = moveNode->nextSibling();
removeNode(moveNode);
appendNode(moveNode, clonedAncestor.get());
moveNode = next;
}
addBlockPlaceholderIfNeeded(ancestors.last());
Node *ancestor, *clonedParent;
for (ancestor = ancestors.last(), 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(Position(breakNode.get(), 0), DOWNSTREAM);
rebalanceWhitespace();
}
}