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 |