Chromium Code Reviews| 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 |