OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2005 Apple Computer, 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 15 matching lines...) Expand all Loading... | |
26 #include "core/editing/commands/DeleteSelectionCommand.h" | 26 #include "core/editing/commands/DeleteSelectionCommand.h" |
27 | 27 |
28 #include "core/HTMLNames.h" | 28 #include "core/HTMLNames.h" |
29 #include "core/dom/Document.h" | 29 #include "core/dom/Document.h" |
30 #include "core/dom/Element.h" | 30 #include "core/dom/Element.h" |
31 #include "core/dom/NodeTraversal.h" | 31 #include "core/dom/NodeTraversal.h" |
32 #include "core/dom/Text.h" | 32 #include "core/dom/Text.h" |
33 #include "core/editing/EditingBoundary.h" | 33 #include "core/editing/EditingBoundary.h" |
34 #include "core/editing/EditingUtilities.h" | 34 #include "core/editing/EditingUtilities.h" |
35 #include "core/editing/Editor.h" | 35 #include "core/editing/Editor.h" |
36 #include "core/editing/RelocatablePosition.h" | |
36 #include "core/editing/VisibleUnits.h" | 37 #include "core/editing/VisibleUnits.h" |
37 #include "core/frame/LocalFrame.h" | 38 #include "core/frame/LocalFrame.h" |
38 #include "core/html/HTMLBRElement.h" | 39 #include "core/html/HTMLBRElement.h" |
39 #include "core/html/HTMLInputElement.h" | 40 #include "core/html/HTMLInputElement.h" |
40 #include "core/html/HTMLStyleElement.h" | 41 #include "core/html/HTMLStyleElement.h" |
41 #include "core/html/HTMLTableRowElement.h" | 42 #include "core/html/HTMLTableRowElement.h" |
42 #include "core/layout/LayoutTableCell.h" | 43 #include "core/layout/LayoutTableCell.h" |
43 | 44 |
44 namespace blink { | 45 namespace blink { |
45 | 46 |
(...skipping 10 matching lines...) Expand all Loading... | |
56 if (!isHTMLTableRowElement(row)) | 57 if (!isHTMLTableRowElement(row)) |
57 return false; | 58 return false; |
58 | 59 |
59 for (Node* child = row->firstChild(); child; child = child->nextSibling()) { | 60 for (Node* child = row->firstChild(); child; child = child->nextSibling()) { |
60 if (isTableCell(child) && !isTableCellEmpty(child)) | 61 if (isTableCell(child) && !isTableCellEmpty(child)) |
61 return false; | 62 return false; |
62 } | 63 } |
63 return true; | 64 return true; |
64 } | 65 } |
65 | 66 |
66 DeleteSelectionCommand::DeleteSelectionCommand(Document& document, bool smartDel ete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool sanitizeMa rkup, InputEvent::InputType inputType) | 67 DeleteSelectionCommand::DeleteSelectionCommand(Document& document, bool smartDel ete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool sanitizeMa rkup, InputEvent::InputType inputType, const Position& referenceMovePosition) |
67 : CompositeEditCommand(document) | 68 : CompositeEditCommand(document) |
68 , m_hasSelectionToDelete(false) | 69 , m_hasSelectionToDelete(false) |
69 , m_smartDelete(smartDelete) | 70 , m_smartDelete(smartDelete) |
70 , m_mergeBlocksAfterDelete(mergeBlocksAfterDelete) | 71 , m_mergeBlocksAfterDelete(mergeBlocksAfterDelete) |
71 , m_needPlaceholder(false) | 72 , m_needPlaceholder(false) |
72 , m_expandForSpecialElements(expandForSpecialElements) | 73 , m_expandForSpecialElements(expandForSpecialElements) |
73 , m_pruneStartBlockIfNecessary(false) | 74 , m_pruneStartBlockIfNecessary(false) |
74 , m_startsAtEmptyLine(false) | 75 , m_startsAtEmptyLine(false) |
75 , m_sanitizeMarkup(sanitizeMarkup) | 76 , m_sanitizeMarkup(sanitizeMarkup) |
76 , m_inputType(inputType) | 77 , m_inputType(inputType) |
78 , m_referenceMovePosition(referenceMovePosition) | |
77 , m_startBlock(nullptr) | 79 , m_startBlock(nullptr) |
78 , m_endBlock(nullptr) | 80 , m_endBlock(nullptr) |
79 , m_typingStyle(nullptr) | 81 , m_typingStyle(nullptr) |
80 , m_deleteIntoBlockquoteStyle(nullptr) | 82 , m_deleteIntoBlockquoteStyle(nullptr) |
81 { | 83 { |
82 } | 84 } |
83 | 85 |
84 DeleteSelectionCommand::DeleteSelectionCommand(const VisibleSelection& selection , bool smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool sanitizeMarkup, InputEvent::InputType inputType) | 86 DeleteSelectionCommand::DeleteSelectionCommand(const VisibleSelection& selection , bool smartDelete, bool mergeBlocksAfterDelete, bool expandForSpecialElements, bool sanitizeMarkup, InputEvent::InputType inputType) |
85 : CompositeEditCommand(*selection.start().document()) | 87 : CompositeEditCommand(*selection.start().document()) |
86 , m_hasSelectionToDelete(true) | 88 , m_hasSelectionToDelete(true) |
(...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
801 void DeleteSelectionCommand::clearTransientState() | 803 void DeleteSelectionCommand::clearTransientState() |
802 { | 804 { |
803 m_selectionToDelete = VisibleSelection(); | 805 m_selectionToDelete = VisibleSelection(); |
804 m_upstreamStart = Position(); | 806 m_upstreamStart = Position(); |
805 m_downstreamStart = Position(); | 807 m_downstreamStart = Position(); |
806 m_upstreamEnd = Position(); | 808 m_upstreamEnd = Position(); |
807 m_downstreamEnd = Position(); | 809 m_downstreamEnd = Position(); |
808 m_endingPosition = Position(); | 810 m_endingPosition = Position(); |
809 m_leadingWhitespace = Position(); | 811 m_leadingWhitespace = Position(); |
810 m_trailingWhitespace = Position(); | 812 m_trailingWhitespace = Position(); |
813 m_referenceMovePosition = Position(); | |
811 } | 814 } |
812 | 815 |
813 // This method removes div elements with no attributes that have only one child or no children at all. | 816 // This method removes div elements with no attributes that have only one child or no children at all. |
814 void DeleteSelectionCommand::removeRedundantBlocks(EditingState* editingState) | 817 void DeleteSelectionCommand::removeRedundantBlocks(EditingState* editingState) |
815 { | 818 { |
816 Node* node = m_endingPosition.computeContainerNode(); | 819 Node* node = m_endingPosition.computeContainerNode(); |
817 Element* rootElement = rootEditableElement(*node); | 820 Element* rootElement = rootEditableElement(*node); |
818 | 821 |
819 while (node != rootElement) { | 822 while (node != rootElement) { |
820 if (isRemovableBlock(node)) { | 823 if (isRemovableBlock(node)) { |
(...skipping 13 matching lines...) Expand all Loading... | |
834 void DeleteSelectionCommand::doApply(EditingState* editingState) | 837 void DeleteSelectionCommand::doApply(EditingState* editingState) |
835 { | 838 { |
836 // If selection has not been set to a custom selection when the command was created, | 839 // If selection has not been set to a custom selection when the command was created, |
837 // use the current ending selection. | 840 // use the current ending selection. |
838 if (!m_hasSelectionToDelete) | 841 if (!m_hasSelectionToDelete) |
839 m_selectionToDelete = endingSelection(); | 842 m_selectionToDelete = endingSelection(); |
840 | 843 |
841 if (!m_selectionToDelete.isNonOrphanedRange() || !m_selectionToDelete.isCont entEditable()) | 844 if (!m_selectionToDelete.isNonOrphanedRange() || !m_selectionToDelete.isCont entEditable()) |
842 return; | 845 return; |
843 | 846 |
847 RelocatablePosition relocatableReferencePosition(m_referenceMovePosition); | |
yosin_UTC9
2016/10/03 09:19:03
Good usage!
chongz
2016/10/04 02:18:39
Thanks!
| |
848 | |
844 // save this to later make the selection with | 849 // save this to later make the selection with |
845 TextAffinity affinity = m_selectionToDelete.affinity(); | 850 TextAffinity affinity = m_selectionToDelete.affinity(); |
846 | 851 |
847 Position downstreamEnd = mostForwardCaretPosition(m_selectionToDelete.end()) ; | 852 Position downstreamEnd = mostForwardCaretPosition(m_selectionToDelete.end()) ; |
848 bool rootWillStayOpenWithoutPlaceholder = downstreamEnd.computeContainerNode () == rootEditableElement(*downstreamEnd.computeContainerNode()) | 853 bool rootWillStayOpenWithoutPlaceholder = downstreamEnd.computeContainerNode () == rootEditableElement(*downstreamEnd.computeContainerNode()) |
849 || (downstreamEnd.computeContainerNode()->isTextNode() && downstreamEnd. computeContainerNode()->parentNode() == rootEditableElement(*downstreamEnd.compu teContainerNode())); | 854 || (downstreamEnd.computeContainerNode()->isTextNode() && downstreamEnd. computeContainerNode()->parentNode() == rootEditableElement(*downstreamEnd.compu teContainerNode())); |
850 bool lineBreakAtEndOfSelectionToDelete = lineBreakExistsAtVisiblePosition(m_ selectionToDelete.visibleEndDeprecated()); | 855 bool lineBreakAtEndOfSelectionToDelete = lineBreakExistsAtVisiblePosition(m_ selectionToDelete.visibleEndDeprecated()); |
851 m_needPlaceholder = !rootWillStayOpenWithoutPlaceholder | 856 m_needPlaceholder = !rootWillStayOpenWithoutPlaceholder |
852 && isStartOfParagraphDeprecated(m_selectionToDelete.visibleStartDeprecat ed(), CanCrossEditingBoundary) | 857 && isStartOfParagraphDeprecated(m_selectionToDelete.visibleStartDeprecat ed(), CanCrossEditingBoundary) |
853 && isEndOfParagraphDeprecated(m_selectionToDelete.visibleEndDeprecated() , CanCrossEditingBoundary) | 858 && isEndOfParagraphDeprecated(m_selectionToDelete.visibleEndDeprecated() , CanCrossEditingBoundary) |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
924 if (editingState->isAborted()) | 929 if (editingState->isAborted()) |
925 return; | 930 return; |
926 } | 931 } |
927 } | 932 } |
928 | 933 |
929 rebalanceWhitespaceAt(m_endingPosition); | 934 rebalanceWhitespaceAt(m_endingPosition); |
930 | 935 |
931 calculateTypingStyleAfterDelete(); | 936 calculateTypingStyleAfterDelete(); |
932 | 937 |
933 setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSelect ion().isDirectional())); | 938 setEndingSelection(VisibleSelection(m_endingPosition, affinity, endingSelect ion().isDirectional())); |
939 | |
940 // This deletion command is part or a move operation. | |
941 if (relocatableReferencePosition.position().isNotNull()) { | |
yosin_UTC9
2016/10/03 09:19:03
Could you use early-return style?
if (relocatable
chongz
2016/10/04 02:18:39
Done.
| |
942 m_referenceMovePosition = relocatableReferencePosition.position(); | |
943 // If the node for the destination has been removed as a result of the d eletion, | |
944 // set the destination to the ending point after the deletion. | |
945 // Fixes: <rdar://problem/3910425> REGRESSION (Mail): Crash in ReplaceSe lectionCommand; | |
946 // selection is empty, leading to null deref | |
947 if (!m_referenceMovePosition.isConnected()) | |
948 m_referenceMovePosition = endingSelection().start(); | |
949 | |
950 // Move selection shouldn't left empty <li> block. | |
951 cleanupAfterDeletion(editingState, createVisiblePositionDeprecated(m_ref erenceMovePosition)); | |
952 if (editingState->isAborted()) | |
953 return; | |
954 } | |
955 | |
934 clearTransientState(); | 956 clearTransientState(); |
935 } | 957 } |
936 | 958 |
937 InputEvent::InputType DeleteSelectionCommand::inputType() const | 959 InputEvent::InputType DeleteSelectionCommand::inputType() const |
938 { | 960 { |
939 // |DeleteSelectionCommand| could be used with Cut, Menu Bar deletion and |T ypingCommand|. | 961 // |DeleteSelectionCommand| could be used with Cut, Menu Bar deletion and |T ypingCommand|. |
940 // 1. Cut and Menu Bar deletion should rely on correct |m_inputType|. | 962 // 1. Cut and Menu Bar deletion should rely on correct |m_inputType|. |
941 // 2. |TypingCommand| will supply the |inputType()|, so |m_inputType| could default to |InputType::None|. | 963 // 2. |TypingCommand| will supply the |inputType()|, so |m_inputType| could default to |InputType::None|. |
942 return m_inputType; | 964 return m_inputType; |
943 } | 965 } |
944 | 966 |
945 // Normally deletion doesn't preserve the typing style that was present before i t. For example, | 967 // Normally deletion doesn't preserve the typing style that was present before i t. For example, |
946 // type a character, Bold, then delete the character and start typing. The Bold typing style shouldn't | 968 // type a character, Bold, then delete the character and start typing. The Bold typing style shouldn't |
947 // stick around. Deletion should preserve a typing style that *it* sets, howeve r. | 969 // stick around. Deletion should preserve a typing style that *it* sets, howeve r. |
948 bool DeleteSelectionCommand::preservesTypingStyle() const | 970 bool DeleteSelectionCommand::preservesTypingStyle() const |
949 { | 971 { |
950 return m_typingStyle; | 972 return m_typingStyle; |
951 } | 973 } |
952 | 974 |
953 DEFINE_TRACE(DeleteSelectionCommand) | 975 DEFINE_TRACE(DeleteSelectionCommand) |
954 { | 976 { |
955 visitor->trace(m_selectionToDelete); | 977 visitor->trace(m_selectionToDelete); |
956 visitor->trace(m_upstreamStart); | 978 visitor->trace(m_upstreamStart); |
957 visitor->trace(m_downstreamStart); | 979 visitor->trace(m_downstreamStart); |
958 visitor->trace(m_upstreamEnd); | 980 visitor->trace(m_upstreamEnd); |
959 visitor->trace(m_downstreamEnd); | 981 visitor->trace(m_downstreamEnd); |
960 visitor->trace(m_endingPosition); | 982 visitor->trace(m_endingPosition); |
961 visitor->trace(m_leadingWhitespace); | 983 visitor->trace(m_leadingWhitespace); |
962 visitor->trace(m_trailingWhitespace); | 984 visitor->trace(m_trailingWhitespace); |
985 visitor->trace(m_referenceMovePosition); | |
963 visitor->trace(m_startBlock); | 986 visitor->trace(m_startBlock); |
964 visitor->trace(m_endBlock); | 987 visitor->trace(m_endBlock); |
965 visitor->trace(m_typingStyle); | 988 visitor->trace(m_typingStyle); |
966 visitor->trace(m_deleteIntoBlockquoteStyle); | 989 visitor->trace(m_deleteIntoBlockquoteStyle); |
967 visitor->trace(m_startRoot); | 990 visitor->trace(m_startRoot); |
968 visitor->trace(m_endRoot); | 991 visitor->trace(m_endRoot); |
969 visitor->trace(m_startTableRow); | 992 visitor->trace(m_startTableRow); |
970 visitor->trace(m_endTableRow); | 993 visitor->trace(m_endTableRow); |
971 visitor->trace(m_temporaryPlaceholder); | 994 visitor->trace(m_temporaryPlaceholder); |
972 CompositeEditCommand::trace(visitor); | 995 CompositeEditCommand::trace(visitor); |
973 } | 996 } |
974 | 997 |
975 } // namespace blink | 998 } // namespace blink |
OLD | NEW |