| 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 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 805 | 805 |
| 806 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) | 806 void CompositeEditCommand::deleteInsignificantTextDownstream(const Position& pos
) |
| 807 { | 807 { |
| 808 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale
nt().downstream(); | 808 Position end = VisiblePosition(pos, VP_DEFAULT_AFFINITY).next().deepEquivale
nt().downstream(); |
| 809 deleteInsignificantText(pos, end); | 809 deleteInsignificantText(pos, end); |
| 810 } | 810 } |
| 811 | 811 |
| 812 PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element
> container) | 812 PassRefPtr<Node> CompositeEditCommand::appendBlockPlaceholder(PassRefPtr<Element
> container) |
| 813 { | 813 { |
| 814 if (!container) | 814 if (!container) |
| 815 return 0; | 815 return nullptr; |
| 816 | 816 |
| 817 document().updateLayoutIgnorePendingStylesheets(); | 817 document().updateLayoutIgnorePendingStylesheets(); |
| 818 | 818 |
| 819 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 819 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 820 ASSERT(container->renderer()); | 820 ASSERT(container->renderer()); |
| 821 | 821 |
| 822 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); | 822 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); |
| 823 appendNode(placeholder, container); | 823 appendNode(placeholder, container); |
| 824 return placeholder.release(); | 824 return placeholder.release(); |
| 825 } | 825 } |
| 826 | 826 |
| 827 PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po
s) | 827 PassRefPtr<Node> CompositeEditCommand::insertBlockPlaceholder(const Position& po
s) |
| 828 { | 828 { |
| 829 if (pos.isNull()) | 829 if (pos.isNull()) |
| 830 return 0; | 830 return nullptr; |
| 831 | 831 |
| 832 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. | 832 // Should assert isRenderBlockFlow || isInlineFlow when deletion improves. S
ee 4244964. |
| 833 ASSERT(pos.deprecatedNode()->renderer()); | 833 ASSERT(pos.deprecatedNode()->renderer()); |
| 834 | 834 |
| 835 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); | 835 RefPtr<Node> placeholder = createBlockPlaceholderElement(document()); |
| 836 insertNodeAt(placeholder, pos); | 836 insertNodeAt(placeholder, pos); |
| 837 return placeholder.release(); | 837 return placeholder.release(); |
| 838 } | 838 } |
| 839 | 839 |
| 840 PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* cont
ainer) | 840 PassRefPtr<Node> CompositeEditCommand::addBlockPlaceholderIfNeeded(Element* cont
ainer) |
| 841 { | 841 { |
| 842 if (!container) | 842 if (!container) |
| 843 return 0; | 843 return nullptr; |
| 844 | 844 |
| 845 document().updateLayoutIgnorePendingStylesheets(); | 845 document().updateLayoutIgnorePendingStylesheets(); |
| 846 | 846 |
| 847 RenderObject* renderer = container->renderer(); | 847 RenderObject* renderer = container->renderer(); |
| 848 if (!renderer || !renderer->isRenderBlockFlow()) | 848 if (!renderer || !renderer->isRenderBlockFlow()) |
| 849 return 0; | 849 return nullptr; |
| 850 | 850 |
| 851 // append the placeholder to make sure it follows | 851 // append the placeholder to make sure it follows |
| 852 // any unrendered blocks | 852 // any unrendered blocks |
| 853 RenderBlock* block = toRenderBlock(renderer); | 853 RenderBlock* block = toRenderBlock(renderer); |
| 854 if (block->height() == 0 || (block->isListItem() && block->isEmpty())) | 854 if (block->height() == 0 || (block->isListItem() && block->isEmpty())) |
| 855 return appendBlockPlaceholder(container); | 855 return appendBlockPlaceholder(container); |
| 856 | 856 |
| 857 return 0; | 857 return nullptr; |
| 858 } | 858 } |
| 859 | 859 |
| 860 // Assumes that the position is at a placeholder and does the removal without mu
ch checking. | 860 // Assumes that the position is at a placeholder and does the removal without mu
ch checking. |
| 861 void CompositeEditCommand::removePlaceholderAt(const Position& p) | 861 void CompositeEditCommand::removePlaceholderAt(const Position& p) |
| 862 { | 862 { |
| 863 ASSERT(lineBreakExistsAtPosition(p)); | 863 ASSERT(lineBreakExistsAtPosition(p)); |
| 864 | 864 |
| 865 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. | 865 // We are certain that the position is at a line break, but it may be a br o
r a preserved newline. |
| 866 if (p.anchorNode()->hasTagName(brTag)) { | 866 if (p.anchorNode()->hasTagName(brTag)) { |
| 867 removeNode(p.anchorNode()); | 867 removeNode(p.anchorNode()); |
| 868 return; | 868 return; |
| 869 } | 869 } |
| 870 | 870 |
| 871 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); | 871 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); |
| 872 } | 872 } |
| 873 | 873 |
| 874 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const
Position& position) | 874 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const
Position& position) |
| 875 { | 875 { |
| 876 RefPtr<Element> paragraphElement = createDefaultParagraphElement(document())
; | 876 RefPtr<Element> paragraphElement = createDefaultParagraphElement(document())
; |
| 877 paragraphElement->appendChild(createBreakElement(document())); | 877 paragraphElement->appendChild(createBreakElement(document())); |
| 878 insertNodeAt(paragraphElement, position); | 878 insertNodeAt(paragraphElement, position); |
| 879 return paragraphElement.release(); | 879 return paragraphElement.release(); |
| 880 } | 880 } |
| 881 | 881 |
| 882 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into | 882 // If the paragraph is not entirely within it's own block, create one and move t
he paragraph into |
| 883 // it, and return that block. Otherwise return 0. | 883 // it, and return that block. Otherwise return 0. |
| 884 PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessar
y(const Position& pos) | 884 PassRefPtr<Node> CompositeEditCommand::moveParagraphContentsToNewBlockIfNecessar
y(const Position& pos) |
| 885 { | 885 { |
| 886 if (pos.isNull()) | 886 if (pos.isNull()) |
| 887 return 0; | 887 return nullptr; |
| 888 | 888 |
| 889 document().updateLayoutIgnorePendingStylesheets(); | 889 document().updateLayoutIgnorePendingStylesheets(); |
| 890 | 890 |
| 891 // It's strange that this function is responsible for verifying that pos has
not been invalidated | 891 // It's strange that this function is responsible for verifying that pos has
not been invalidated |
| 892 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. | 892 // by an earlier call to this function. The caller, applyBlockStyle, should
do this. |
| 893 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); | 893 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); |
| 894 VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos)); | 894 VisiblePosition visibleParagraphStart(startOfParagraph(visiblePos)); |
| 895 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); | 895 VisiblePosition visibleParagraphEnd = endOfParagraph(visiblePos); |
| 896 VisiblePosition next = visibleParagraphEnd.next(); | 896 VisiblePosition next = visibleParagraphEnd.next(); |
| 897 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; | 897 VisiblePosition visibleEnd = next.isNotNull() ? next : visibleParagraphEnd; |
| 898 | 898 |
| 899 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream(); | 899 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream(); |
| 900 Position upstreamEnd = visibleEnd.deepEquivalent().upstream(); | 900 Position upstreamEnd = visibleEnd.deepEquivalent().upstream(); |
| 901 | 901 |
| 902 // If there are no VisiblePositions in the same block as pos then | 902 // If there are no VisiblePositions in the same block as pos then |
| 903 // upstreamStart will be outside the paragraph | 903 // upstreamStart will be outside the paragraph |
| 904 if (comparePositions(pos, upstreamStart) < 0) | 904 if (comparePositions(pos, upstreamStart) < 0) |
| 905 return 0; | 905 return nullptr; |
| 906 | 906 |
| 907 // Perform some checks to see if we need to perform work in this function. | 907 // Perform some checks to see if we need to perform work in this function. |
| 908 if (isBlock(upstreamStart.deprecatedNode())) { | 908 if (isBlock(upstreamStart.deprecatedNode())) { |
| 909 // If the block is the root editable element, always move content to a n
ew block, | 909 // If the block is the root editable element, always move content to a n
ew block, |
| 910 // since it is illegal to modify attributes on the root editable element
for editing. | 910 // since it is illegal to modify attributes on the root editable element
for editing. |
| 911 if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamSt
art)) { | 911 if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamSt
art)) { |
| 912 // If the block is the root editable element and it contains no visi
ble content, create a new | 912 // If the block is the root editable element and it contains no visi
ble content, create a new |
| 913 // block but don't try and move content into it, since there's nothi
ng for moveParagraphs to move. | 913 // block but don't try and move content into it, since there's nothi
ng for moveParagraphs to move. |
| 914 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(upstream
Start.deprecatedNode()->renderer())) | 914 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(upstream
Start.deprecatedNode()->renderer())) |
| 915 return insertNewDefaultParagraphElementAt(upstreamStart); | 915 return insertNewDefaultParagraphElementAt(upstreamStart); |
| 916 } else if (isBlock(upstreamEnd.deprecatedNode())) { | 916 } else if (isBlock(upstreamEnd.deprecatedNode())) { |
| 917 if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.depr
ecatedNode())) { | 917 if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.depr
ecatedNode())) { |
| 918 // If the paragraph end is a descendant of paragraph start, then
we need to run | 918 // If the paragraph end is a descendant of paragraph start, then
we need to run |
| 919 // the rest of this function. If not, we can bail here. | 919 // the rest of this function. If not, we can bail here. |
| 920 return 0; | 920 return nullptr; |
| 921 } | 921 } |
| 922 } else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart
.deprecatedNode()) { | 922 } else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart
.deprecatedNode()) { |
| 923 // The visibleEnd. It must be an ancestor of the paragraph start. | 923 // The visibleEnd. It must be an ancestor of the paragraph start. |
| 924 // We can bail as we have a full block to work with. | 924 // We can bail as we have a full block to work with. |
| 925 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock
(upstreamEnd.deprecatedNode()))); | 925 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock
(upstreamEnd.deprecatedNode()))); |
| 926 return 0; | 926 return nullptr; |
| 927 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { | 927 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { |
| 928 // At the end of the editable region. We can bail here as well. | 928 // At the end of the editable region. We can bail here as well. |
| 929 return 0; | 929 return nullptr; |
| 930 } | 930 } |
| 931 } | 931 } |
| 932 | 932 |
| 933 RefPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart); | 933 RefPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart); |
| 934 | 934 |
| 935 bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTa
gName(brTag); | 935 bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTa
gName(brTag); |
| 936 | 936 |
| 937 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(f
irstPositionInNode(newBlock.get()))); | 937 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(f
irstPositionInNode(newBlock.get()))); |
| 938 | 938 |
| 939 if (newBlock->lastChild() && newBlock->lastChild()->hasTagName(brTag) && !en
dWasBr) | 939 if (newBlock->lastChild() && newBlock->lastChild()->hasTagName(brTag) && !en
dWasBr) |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1170 Position end = endOfParagraphToMove.deepEquivalent().upstream(); | 1170 Position end = endOfParagraphToMove.deepEquivalent().upstream(); |
| 1171 | 1171 |
| 1172 // start and end can't be used directly to create a Range; they are "editing
positions" | 1172 // start and end can't be used directly to create a Range; they are "editing
positions" |
| 1173 Position startRangeCompliant = start.parentAnchoredEquivalent(); | 1173 Position startRangeCompliant = start.parentAnchoredEquivalent(); |
| 1174 Position endRangeCompliant = end.parentAnchoredEquivalent(); | 1174 Position endRangeCompliant = end.parentAnchoredEquivalent(); |
| 1175 RefPtr<Range> range = Range::create(document(), startRangeCompliant.deprecat
edNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.depre
catedNode(), endRangeCompliant.deprecatedEditingOffset()); | 1175 RefPtr<Range> range = Range::create(document(), startRangeCompliant.deprecat
edNode(), startRangeCompliant.deprecatedEditingOffset(), endRangeCompliant.depre
catedNode(), endRangeCompliant.deprecatedEditingOffset()); |
| 1176 | 1176 |
| 1177 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It | 1177 // FIXME: This is an inefficient way to preserve style on nodes in the parag
raph to move. It |
| 1178 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. | 1178 // shouldn't matter though, since moved paragraphs will usually be quite sma
ll. |
| 1179 RefPtr<DocumentFragment> fragment = startOfParagraphToMove != endOfParagraph
ToMove ? | 1179 RefPtr<DocumentFragment> fragment = startOfParagraphToMove != endOfParagraph
ToMove ? |
| 1180 createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotA
nnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : 0; | 1180 createFragmentFromMarkup(document(), createMarkup(range.get(), 0, DoNotA
nnotateForInterchange, true, DoNotResolveURLs, constrainingAncestor), "") : null
ptr; |
| 1181 | 1181 |
| 1182 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move | 1182 // A non-empty paragraph's style is moved when we copy and move it. We don'
t move |
| 1183 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style | 1183 // anything if we're given an empty paragraph, but an empty paragraph can ha
ve style |
| 1184 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. | 1184 // too, <div><b><br></b></div> for example. Save it so that we can preserve
it later. |
| 1185 RefPtr<EditingStyle> styleInEmptyParagraph; | 1185 RefPtr<EditingStyle> styleInEmptyParagraph; |
| 1186 if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) { | 1186 if (startOfParagraphToMove == endOfParagraphToMove && preserveStyle) { |
| 1187 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); | 1187 styleInEmptyParagraph = EditingStyle::create(startOfParagraphToMove.deep
Equivalent()); |
| 1188 styleInEmptyParagraph->mergeTypingStyle(&document()); | 1188 styleInEmptyParagraph->mergeTypingStyle(&document()); |
| 1189 // The moved paragraph should assume the block style of the destination. | 1189 // The moved paragraph should assume the block style of the destination. |
| 1190 styleInEmptyParagraph->removeBlockProperties(); | 1190 styleInEmptyParagraph->removeBlockProperties(); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1257 style->mergeTypingStyle(&document()); | 1257 style->mergeTypingStyle(&document()); |
| 1258 | 1258 |
| 1259 RefPtr<ContainerNode> listNode = emptyListItem->parentNode(); | 1259 RefPtr<ContainerNode> listNode = emptyListItem->parentNode(); |
| 1260 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? | 1260 // FIXME: Can't we do something better when the immediate parent wasn't a li
st node? |
| 1261 if (!listNode | 1261 if (!listNode |
| 1262 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag)) | 1262 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag)) |
| 1263 || !listNode->rendererIsEditable() | 1263 || !listNode->rendererIsEditable() |
| 1264 || listNode == emptyListItem->rootEditableElement()) | 1264 || listNode == emptyListItem->rootEditableElement()) |
| 1265 return false; | 1265 return false; |
| 1266 | 1266 |
| 1267 RefPtr<Element> newBlock = 0; | 1267 RefPtr<Element> newBlock = nullptr; |
| 1268 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { | 1268 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { |
| 1269 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth
er list item | 1269 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth
er list item |
| 1270 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA
fterNode(listNode.get())) { | 1270 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA
fterNode(listNode.get())) { |
| 1271 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item | 1271 // If listNode appears at the end of the outer list item, then m
ove listNode outside of this list item |
| 1272 // 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 | 1272 // 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 |
| 1273 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. | 1273 // If listNode does NOT appear at the end, then we should consid
er it as a regular paragraph. |
| 1274 // 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 | 1274 // 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 |
| 1275 splitElement(toElement(blockEnclosingList), listNode); | 1275 splitElement(toElement(blockEnclosingList), listNode); |
| 1276 removeNodePreservingChildren(listNode->parentNode()); | 1276 removeNodePreservingChildren(listNode->parentNode()); |
| 1277 newBlock = createListItemElement(document()); | 1277 newBlock = createListItemElement(document()); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1454 return node.release(); | 1454 return node.release(); |
| 1455 } | 1455 } |
| 1456 | 1456 |
| 1457 PassRefPtr<Element> createBlockPlaceholderElement(Document& document) | 1457 PassRefPtr<Element> createBlockPlaceholderElement(Document& document) |
| 1458 { | 1458 { |
| 1459 RefPtr<Element> breakNode = document.createElement(brTag, false); | 1459 RefPtr<Element> breakNode = document.createElement(brTag, false); |
| 1460 return breakNode.release(); | 1460 return breakNode.release(); |
| 1461 } | 1461 } |
| 1462 | 1462 |
| 1463 } // namespace WebCore | 1463 } // namespace WebCore |
| OLD | NEW |