| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element
> container) | 827 PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element
> container) |
| 828 { | 828 { |
| 829 if (!container) | 829 if (!container) |
| 830 return 0; | 830 return 0; |
| 831 | 831 |
| 832 document().updateLayoutIgnorePendingStylesheets(); | 832 document().updateLayoutIgnorePendingStylesheets(); |
| 833 | 833 |
| 834 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 424
4964. | 834 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 424
4964. |
| 835 ASSERT(container->renderer()); | 835 ASSERT(container->renderer()); |
| 836 | 836 |
| 837 RefPtr<Node> placeholder = createBlockPlaceholderElement(&document()); | 837 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); |
| 838 appendNode(placeholder, container); | 838 appendNode(placeholder, container); |
| 839 return placeholder.release(); | 839 return placeholder.release(); |
| 840 } | 840 } |
| 841 | 841 |
| 842 PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po
s) | 842 PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po
s) |
| 843 { | 843 { |
| 844 if (pos.isNull()) | 844 if (pos.isNull()) |
| 845 return 0; | 845 return 0; |
| 846 | 846 |
| 847 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 42
44964. | 847 // Should assert isBlockFlow || isInlineFlow when deletion improves. See 42
44964. |
| 848 ASSERT(pos.deprecatedNode()->renderer()); | 848 ASSERT(pos.deprecatedNode()->renderer()); |
| 849 | 849 |
| 850 RefPtr<Node> placeholder = createBlockPlaceholderElement(&document()); | 850 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); |
| 851 insertNodeAt(placeholder, pos); | 851 insertNodeAt(placeholder, pos); |
| 852 return placeholder.release(); | 852 return placeholder.release(); |
| 853 } | 853 } |
| 854 | 854 |
| 855 PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* cont
ainer) | 855 PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* cont
ainer) |
| 856 { | 856 { |
| 857 if (!container) | 857 if (!container) |
| 858 return 0; | 858 return 0; |
| 859 | 859 |
| 860 document().updateLayoutIgnorePendingStylesheets(); | 860 document().updateLayoutIgnorePendingStylesheets(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 881 if (p.anchorNode()->hasTagName(brTag)) { | 881 if (p.anchorNode()->hasTagName(brTag)) { |
| 882 removeNode(p.anchorNode()); | 882 removeNode(p.anchorNode()); |
| 883 return; | 883 return; |
| 884 } | 884 } |
| 885 | 885 |
| 886 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); | 886 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); |
| 887 } | 887 } |
| 888 | 888 |
| 889 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const
Position& position) | 889 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const
Position& position) |
| 890 { | 890 { |
| 891 RefPtr<Element> paragraphElement = createDefaultParagraphElement(&document()
); | 891 RefPtr<Element> paragraphElement = createDefaultParagraphElement(document())
; |
| 892 paragraphElement->appendChild(createBreakElement(&document())); | 892 paragraphElement->appendChild(createBreakElement(document())); |
| 893 insertNodeAt(paragraphElement, position); | 893 insertNodeAt(paragraphElement, position); |
| 894 return paragraphElement.release(); | 894 return paragraphElement.release(); |
| 895 } | 895 } |
| 896 | 896 |
| 897 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 897 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
| 898 // it, and return that block. Otherwise return 0. | 898 // it, and return that block. Otherwise return 0. |
| 899 PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessar
y(const Position& pos) | 899 PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessar
y(const Position& pos) |
| 900 { | 900 { |
| 901 if (pos.isNull()) | 901 if (pos.isNull()) |
| 902 return 0; | 902 return 0; |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 // baz | 1119 // baz |
| 1120 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would | 1120 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th
at would |
| 1121 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1121 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
| 1122 // Must recononicalize these two VisiblePositions after the pruning above. | 1122 // Must recononicalize these two VisiblePositions after the pruning above. |
| 1123 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); | 1123 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); |
| 1124 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); | 1124 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); |
| 1125 | 1125 |
| 1126 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv
alent().deprecatedNode()) | 1126 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv
alent().deprecatedNode()) |
| 1127 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph == afterParagraph)) { | 1127 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar
agraph)) || beforeParagraph == afterParagraph)) { |
| 1128 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1128 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1129 insertNodeAt(createBreakElement(&document()), beforeParagraph.deepEquiva
lent()); | 1129 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); |
| 1130 } | 1130 } |
| 1131 } | 1131 } |
| 1132 | 1132 |
| 1133 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor) | 1133 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph
ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest
ination, bool preserveSelection, bool preserveStyle, Node* constrainingAncestor) |
| 1134 { | 1134 { |
| 1135 ASSERT(isStartOfParagraph(startOfParagraphToMove)); | 1135 ASSERT(isStartOfParagraph(startOfParagraphToMove)); |
| 1136 ASSERT(isEndOfParagraph(endOfParagraphToMove)); | 1136 ASSERT(isEndOfParagraph(endOfParagraphToMove)); |
| 1137 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, pr
eserveSelection, preserveStyle, constrainingAncestor); | 1137 moveParagraphs(startOfParagraphToMove, endOfParagraphToMove, destination, pr
eserveSelection, preserveStyle, constrainingAncestor); |
| 1138 } | 1138 } |
| 1139 | 1139 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 // foo^ | 1214 // foo^ |
| 1215 // <div>bar</div> | 1215 // <div>bar</div> |
| 1216 // baz | 1216 // baz |
| 1217 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would | 1217 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. That
would |
| 1218 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. | 1218 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br
. |
| 1219 // Must recononicalize these two VisiblePositions after the pruning above. | 1219 // Must recononicalize these two VisiblePositions after the pruning above. |
| 1220 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); | 1220 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); |
| 1221 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); | 1221 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); |
| 1222 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph == afterParagraph)) { | 1222 if (beforeParagraph.isNotNull() && (!isEndOfParagraph(beforeParagraph) || be
foreParagraph == afterParagraph)) { |
| 1223 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. | 1223 // FIXME: Trim text between beforeParagraph and afterParagraph if they a
ren't equal. |
| 1224 insertNodeAt(createBreakElement(&document()), beforeParagraph.deepEquiva
lent()); | 1224 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival
ent()); |
| 1225 // Need an updateLayout here in case inserting the br has split a text n
ode. | 1225 // Need an updateLayout here in case inserting the br has split a text n
ode. |
| 1226 document().updateLayoutIgnorePendingStylesheets(); | 1226 document().updateLayoutIgnorePendingStylesheets(); |
| 1227 } | 1227 } |
| 1228 | 1228 |
| 1229 RefPtr<Range> startToDestinationRange(Range::create(&document(), firstPositi
onInNode(document().documentElement()), destination.deepEquivalent().parentAncho
redEquivalent())); | 1229 RefPtr<Range> startToDestinationRange(Range::create(&document(), firstPositi
onInNode(document().documentElement()), destination.deepEquivalent().parentAncho
redEquivalent())); |
| 1230 destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(),
true); | 1230 destinationIndex = TextIterator::rangeLength(startToDestinationRange.get(),
true); |
| 1231 | 1231 |
| 1232 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); | 1232 setEndingSelection(VisibleSelection(destination, originalIsDirectional)); |
| 1233 ASSERT(endingSelection().isCaretOrRange()); | 1233 ASSERT(endingSelection().isCaretOrRange()); |
| 1234 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::MovingParagraph; | 1234 ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::S
electReplacement | ReplaceSelectionCommand::MovingParagraph; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1277 RefPtr<Element> newBlock = 0; | 1277 RefPtr<Element> newBlock = 0; |
| 1278 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { | 1278 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { |
| 1279 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth
er list item | 1279 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth
er list item |
| 1280 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA
fterNode(listNode.get())) { | 1280 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA
fterNode(listNode.get())) { |
| 1281 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item | 1281 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item |
| 1282 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b
ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section | 1282 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b
ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section |
| 1283 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. | 1283 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. |
| 1284 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b
ecome <ul><li> <div><br></div> hello</li></ul> at the end | 1284 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b
ecome <ul><li> <div><br></div> hello</li></ul> at the end |
| 1285 splitElement(toElement(blockEnclosingList), listNode); | 1285 splitElement(toElement(blockEnclosingList), listNode); |
| 1286 removeNodePreservingChildren(listNode->parentNode()); | 1286 removeNodePreservingChildren(listNode->parentNode()); |
| 1287 newBlock = createListItemElement(&document()); | 1287 newBlock = createListItemElement(document()); |
| 1288 } | 1288 } |
| 1289 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. | 1289 // If listNode does NOT appear at the end of the outer list item, th
en behave as if in a regular paragraph. |
| 1290 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->
hasTagName(ulTag)) { | 1290 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList->
hasTagName(ulTag)) { |
| 1291 newBlock = createListItemElement(&document()); | 1291 newBlock = createListItemElement(document()); |
| 1292 } | 1292 } |
| 1293 } | 1293 } |
| 1294 if (!newBlock) | 1294 if (!newBlock) |
| 1295 newBlock = createDefaultParagraphElement(&document()); | 1295 newBlock = createDefaultParagraphElement(document()); |
| 1296 | 1296 |
| 1297 RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(e
mptyListItem.get())->previousElementSibling(): emptyListItem->previousSibling(); | 1297 RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? toElement(e
mptyListItem.get())->previousElementSibling(): emptyListItem->previousSibling(); |
| 1298 RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(empty
ListItem.get())->nextElementSibling(): emptyListItem->nextSibling(); | 1298 RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? toElement(empty
ListItem.get())->nextElementSibling(): emptyListItem->nextSibling(); |
| 1299 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) { | 1299 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) { |
| 1300 // If emptyListItem follows another list item or nested list, split the
list node. | 1300 // If emptyListItem follows another list item or nested list, split the
list node. |
| 1301 if (isListItem(previousListNode.get()) || isListElement(previousListNode
.get())) | 1301 if (isListItem(previousListNode.get()) || isListElement(previousListNode
.get())) |
| 1302 splitElement(toElement(listNode.get()), emptyListItem); | 1302 splitElement(toElement(listNode.get()), emptyListItem); |
| 1303 | 1303 |
| 1304 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. | 1304 // If emptyListItem is followed by other list item or nested list, then
insert newBlock before the list node. |
| 1305 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. | 1305 // Because we have splitted the element, emptyListItem is the first elem
ent in the list node. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1336 return false; | 1336 return false; |
| 1337 | 1337 |
| 1338 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) | 1338 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) |
| 1339 return false; | 1339 return false; |
| 1340 | 1340 |
| 1341 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); | 1341 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); |
| 1342 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. | 1342 // Only move forward if there's nothing before the caret, or if there's unqu
oted content before it. |
| 1343 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) | 1343 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) |
| 1344 return false; | 1344 return false; |
| 1345 | 1345 |
| 1346 RefPtr<Node> br = createBreakElement(&document()); | 1346 RefPtr<Node> br = createBreakElement(document()); |
| 1347 // We want to replace this quoted paragraph with an unquoted one, so insert
a br | 1347 // We want to replace this quoted paragraph with an unquoted one, so insert
a br |
| 1348 // to hold the caret before the highest blockquote. | 1348 // to hold the caret before the highest blockquote. |
| 1349 insertNodeBefore(br, highestBlockquote); | 1349 insertNodeBefore(br, highestBlockquote); |
| 1350 VisiblePosition atBR(positionBeforeNode(br.get())); | 1350 VisiblePosition atBR(positionBeforeNode(br.get())); |
| 1351 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert | 1351 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc
kquote>, insert |
| 1352 // a second one. | 1352 // a second one. |
| 1353 if (!isStartOfParagraph(atBR)) | 1353 if (!isStartOfParagraph(atBR)) |
| 1354 insertNodeBefore(createBreakElement(&document()), br); | 1354 insertNodeBefore(createBreakElement(document()), br); |
| 1355 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); | 1355 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional())
); |
| 1356 | 1356 |
| 1357 // If this is an empty paragraph there must be a line break here. | 1357 // If this is an empty paragraph there must be a line break here. |
| 1358 if (!lineBreakExistsAtVisiblePosition(caret)) | 1358 if (!lineBreakExistsAtVisiblePosition(caret)) |
| 1359 return false; | 1359 return false; |
| 1360 | 1360 |
| 1361 Position caretPos(caret.deepEquivalent().downstream()); | 1361 Position caretPos(caret.deepEquivalent().downstream()); |
| 1362 // A line break is either a br or a preserved newline. | 1362 // A line break is either a br or a preserved newline. |
| 1363 ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedN
ode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveN
ewline())); | 1363 ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedN
ode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveN
ewline())); |
| 1364 | 1364 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1457 // Do not split a node when doing so introduces an empty node. | 1457 // Do not split a node when doing so introduces an empty node. |
| 1458 VisiblePosition positionInParent = firstPositionInNode(node->parentNode(
)); | 1458 VisiblePosition positionInParent = firstPositionInNode(node->parentNode(
)); |
| 1459 VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.get())
; | 1459 VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.get())
; |
| 1460 if (positionInParent != positionInNode) | 1460 if (positionInParent != positionInNode) |
| 1461 splitElement(toElement(node->parentNode()), node); | 1461 splitElement(toElement(node->parentNode()), node); |
| 1462 } | 1462 } |
| 1463 | 1463 |
| 1464 return node.release(); | 1464 return node.release(); |
| 1465 } | 1465 } |
| 1466 | 1466 |
| 1467 PassRefPtr<Element> createBlockPlaceholderElement(Document* document) | 1467 PassRefPtr<Element> createBlockPlaceholderElement(Document& document) |
| 1468 { | 1468 { |
| 1469 RefPtr<Element> breakNode = document->createElement(brTag, false); | 1469 RefPtr<Element> breakNode = document.createElement(brTag, false); |
| 1470 return breakNode.release(); | 1470 return breakNode.release(); |
| 1471 } | 1471 } |
| 1472 | 1472 |
| 1473 } // namespace WebCore | 1473 } // namespace WebCore |
| OLD | NEW |