| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 // parent's layoutObject. | 59 // parent's layoutObject. |
| 60 Position p(insertionPos.parentAnchoredEquivalent()); | 60 Position p(insertionPos.parentAnchoredEquivalent()); |
| 61 return isRichlyEditablePosition(p) && p.anchorNode()->layoutObject() && | 61 return isRichlyEditablePosition(p) && p.anchorNode()->layoutObject() && |
| 62 !p.anchorNode()->layoutObject()->style()->preserveNewline(); | 62 !p.anchorNode()->layoutObject()->style()->preserveNewline(); |
| 63 } | 63 } |
| 64 | 64 |
| 65 void InsertLineBreakCommand::doApply(EditingState* editingState) { | 65 void InsertLineBreakCommand::doApply(EditingState* editingState) { |
| 66 deleteSelection(editingState); | 66 deleteSelection(editingState); |
| 67 if (editingState->isAborted()) | 67 if (editingState->isAborted()) |
| 68 return; | 68 return; |
| 69 |
| 70 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 71 |
| 69 VisibleSelection selection = endingSelection(); | 72 VisibleSelection selection = endingSelection(); |
| 70 if (!selection.isNonOrphanedCaretOrRange()) | 73 if (!selection.isNonOrphanedCaretOrRange()) |
| 71 return; | 74 return; |
| 72 | 75 |
| 73 VisiblePosition caret(selection.visibleStartDeprecated()); | 76 // TODO(xiaochengh): Stop storing VisiblePositions through mutations. |
| 77 VisiblePosition caret(selection.visibleStart()); |
| 74 // FIXME: If the node is hidden, we should still be able to insert text. For | 78 // FIXME: If the node is hidden, we should still be able to insert text. For |
| 75 // now, we return to avoid a crash. | 79 // now, we return to avoid a crash. |
| 76 // https://bugs.webkit.org/show_bug.cgi?id=40342 | 80 // https://bugs.webkit.org/show_bug.cgi?id=40342 |
| 77 if (caret.isNull()) | 81 if (caret.isNull()) |
| 78 return; | 82 return; |
| 79 | 83 |
| 80 Position pos(caret.deepEquivalent()); | 84 Position pos(caret.deepEquivalent()); |
| 81 | 85 |
| 82 pos = positionAvoidingSpecialElementBoundary(pos, editingState); | 86 pos = positionAvoidingSpecialElementBoundary(pos, editingState); |
| 83 if (editingState->isAborted()) | 87 if (editingState->isAborted()) |
| 84 return; | 88 return; |
| 85 | 89 |
| 86 pos = positionOutsideTabSpan(pos); | 90 pos = positionOutsideTabSpan(pos); |
| 87 | 91 |
| 88 Node* nodeToInsert = nullptr; | 92 Node* nodeToInsert = nullptr; |
| 89 if (shouldUseBreakElement(pos)) | 93 if (shouldUseBreakElement(pos)) |
| 90 nodeToInsert = HTMLBRElement::create(document()); | 94 nodeToInsert = HTMLBRElement::create(document()); |
| 91 else | 95 else |
| 92 nodeToInsert = document().createTextNode("\n"); | 96 nodeToInsert = document().createTextNode("\n"); |
| 93 | 97 |
| 98 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 99 |
| 94 // FIXME: Need to merge text nodes when inserting just after or before text. | 100 // FIXME: Need to merge text nodes when inserting just after or before text. |
| 95 | 101 |
| 96 if (isEndOfParagraphDeprecated(caret) && | 102 if (isEndOfParagraph(createVisiblePosition(caret.toPositionWithAffinity())) && |
| 97 !lineBreakExistsAtVisiblePosition(caret)) { | 103 !lineBreakExistsAtVisiblePosition(caret)) { |
| 98 bool needExtraLineBreak = !isHTMLHRElement(*pos.anchorNode()) && | 104 bool needExtraLineBreak = !isHTMLHRElement(*pos.anchorNode()) && |
| 99 !isHTMLTableElement(*pos.anchorNode()); | 105 !isHTMLTableElement(*pos.anchorNode()); |
| 100 | 106 |
| 101 insertNodeAt(nodeToInsert, pos, editingState); | 107 insertNodeAt(nodeToInsert, pos, editingState); |
| 102 if (editingState->isAborted()) | 108 if (editingState->isAborted()) |
| 103 return; | 109 return; |
| 104 | 110 |
| 105 if (needExtraLineBreak) { | 111 if (needExtraLineBreak) { |
| 106 Node* extraNode; | 112 Node* extraNode; |
| 107 // TODO(tkent): Can we remove HTMLTextFormControlElement dependency? | 113 // TODO(tkent): Can we remove HTMLTextFormControlElement dependency? |
| 108 if (HTMLTextFormControlElement* textControl = | 114 if (HTMLTextFormControlElement* textControl = |
| 109 enclosingTextFormControl(nodeToInsert)) { | 115 enclosingTextFormControl(nodeToInsert)) { |
| 110 extraNode = textControl->createPlaceholderBreakElement(); | 116 extraNode = textControl->createPlaceholderBreakElement(); |
| 111 // The placeholder BR should be the last child. There might be | 117 // The placeholder BR should be the last child. There might be |
| 112 // empty Text nodes at |pos|. | 118 // empty Text nodes at |pos|. |
| 113 appendNode(extraNode, nodeToInsert->parentNode(), editingState); | 119 appendNode(extraNode, nodeToInsert->parentNode(), editingState); |
| 114 } else { | 120 } else { |
| 115 extraNode = nodeToInsert->cloneNode(false); | 121 extraNode = nodeToInsert->cloneNode(false); |
| 116 insertNodeAfter(extraNode, nodeToInsert, editingState); | 122 insertNodeAfter(extraNode, nodeToInsert, editingState); |
| 117 } | 123 } |
| 118 if (editingState->isAborted()) | 124 if (editingState->isAborted()) |
| 119 return; | 125 return; |
| 120 nodeToInsert = extraNode; | 126 nodeToInsert = extraNode; |
| 121 } | 127 } |
| 122 | 128 |
| 129 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 123 VisiblePosition endingPosition = VisiblePosition::beforeNode(nodeToInsert); | 130 VisiblePosition endingPosition = VisiblePosition::beforeNode(nodeToInsert); |
| 124 setEndingSelection(createVisibleSelectionDeprecated( | 131 setEndingSelection(createVisibleSelection( |
| 125 endingPosition, endingSelection().isDirectional())); | 132 endingPosition, endingSelection().isDirectional())); |
| 126 } else if (pos.computeEditingOffset() <= caretMinOffset(pos.anchorNode())) { | 133 } else if (pos.computeEditingOffset() <= caretMinOffset(pos.anchorNode())) { |
| 127 insertNodeAt(nodeToInsert, pos, editingState); | 134 insertNodeAt(nodeToInsert, pos, editingState); |
| 128 if (editingState->isAborted()) | 135 if (editingState->isAborted()) |
| 129 return; | 136 return; |
| 137 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 130 | 138 |
| 131 // Insert an extra br or '\n' if the just inserted one collapsed. | 139 // Insert an extra br or '\n' if the just inserted one collapsed. |
| 132 if (!isStartOfParagraphDeprecated( | 140 if (!isStartOfParagraph(VisiblePosition::beforeNode(nodeToInsert))) { |
| 133 VisiblePosition::beforeNode(nodeToInsert))) { | |
| 134 insertNodeBefore(nodeToInsert->cloneNode(false), nodeToInsert, | 141 insertNodeBefore(nodeToInsert->cloneNode(false), nodeToInsert, |
| 135 editingState); | 142 editingState); |
| 136 if (editingState->isAborted()) | 143 if (editingState->isAborted()) |
| 137 return; | 144 return; |
| 145 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 138 } | 146 } |
| 139 | 147 |
| 140 setEndingSelection(createVisibleSelectionDeprecated( | 148 setEndingSelection(createVisibleSelection( |
| 141 Position::inParentAfterNode(*nodeToInsert), TextAffinity::Downstream, | 149 Position::inParentAfterNode(*nodeToInsert), TextAffinity::Downstream, |
| 142 endingSelection().isDirectional())); | 150 endingSelection().isDirectional())); |
| 143 // If we're inserting after all of the rendered text in a text node, or into | 151 // If we're inserting after all of the rendered text in a text node, or into |
| 144 // a non-text node, a simple insertion is sufficient. | 152 // a non-text node, a simple insertion is sufficient. |
| 145 } else if (!pos.anchorNode()->isTextNode() || | 153 } else if (!pos.anchorNode()->isTextNode() || |
| 146 pos.computeOffsetInContainerNode() >= | 154 pos.computeOffsetInContainerNode() >= |
| 147 caretMaxOffset(pos.anchorNode())) { | 155 caretMaxOffset(pos.anchorNode())) { |
| 148 insertNodeAt(nodeToInsert, pos, editingState); | 156 insertNodeAt(nodeToInsert, pos, editingState); |
| 149 if (editingState->isAborted()) | 157 if (editingState->isAborted()) |
| 150 return; | 158 return; |
| 151 setEndingSelection(createVisibleSelectionDeprecated( | 159 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 160 setEndingSelection(createVisibleSelection( |
| 152 Position::inParentAfterNode(*nodeToInsert), TextAffinity::Downstream, | 161 Position::inParentAfterNode(*nodeToInsert), TextAffinity::Downstream, |
| 153 endingSelection().isDirectional())); | 162 endingSelection().isDirectional())); |
| 154 } else if (pos.anchorNode()->isTextNode()) { | 163 } else if (pos.anchorNode()->isTextNode()) { |
| 155 // Split a text node | 164 // Split a text node |
| 156 Text* textNode = toText(pos.anchorNode()); | 165 Text* textNode = toText(pos.anchorNode()); |
| 157 splitTextNode(textNode, pos.computeOffsetInContainerNode()); | 166 splitTextNode(textNode, pos.computeOffsetInContainerNode()); |
| 158 insertNodeBefore(nodeToInsert, textNode, editingState); | 167 insertNodeBefore(nodeToInsert, textNode, editingState); |
| 159 if (editingState->isAborted()) | 168 if (editingState->isAborted()) |
| 160 return; | 169 return; |
| 161 Position endingPosition = Position::firstPositionInNode(textNode); | 170 Position endingPosition = Position::firstPositionInNode(textNode); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 176 insertTextIntoNode(textNode, 0, nonBreakingSpaceString()); | 185 insertTextIntoNode(textNode, 0, nonBreakingSpaceString()); |
| 177 } else { | 186 } else { |
| 178 Text* nbspNode = document().createTextNode(nonBreakingSpaceString()); | 187 Text* nbspNode = document().createTextNode(nonBreakingSpaceString()); |
| 179 insertNodeAt(nbspNode, positionBeforeTextNode, editingState); | 188 insertNodeAt(nbspNode, positionBeforeTextNode, editingState); |
| 180 if (editingState->isAborted()) | 189 if (editingState->isAborted()) |
| 181 return; | 190 return; |
| 182 endingPosition = Position::firstPositionInNode(nbspNode); | 191 endingPosition = Position::firstPositionInNode(nbspNode); |
| 183 } | 192 } |
| 184 } | 193 } |
| 185 | 194 |
| 186 setEndingSelection(createVisibleSelectionDeprecated( | 195 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 187 endingPosition, TextAffinity::Downstream, | 196 setEndingSelection( |
| 188 endingSelection().isDirectional())); | 197 createVisibleSelection(endingPosition, TextAffinity::Downstream, |
| 198 endingSelection().isDirectional())); |
| 189 } | 199 } |
| 190 | 200 |
| 191 // Handle the case where there is a typing style. | 201 // Handle the case where there is a typing style. |
| 192 | 202 |
| 193 EditingStyle* typingStyle = document().frame()->selection().typingStyle(); | 203 EditingStyle* typingStyle = document().frame()->selection().typingStyle(); |
| 194 | 204 |
| 195 if (typingStyle && !typingStyle->isEmpty()) { | 205 if (typingStyle && !typingStyle->isEmpty()) { |
| 196 // Apply the typing style to the inserted line break, so that if the | 206 // Apply the typing style to the inserted line break, so that if the |
| 197 // selection leaves and then comes back, new input will have the right | 207 // selection leaves and then comes back, new input will have the right |
| 198 // style. | 208 // style. |
| 199 // FIXME: We shouldn't always apply the typing style to the line break here, | 209 // FIXME: We shouldn't always apply the typing style to the line break here, |
| 200 // see <rdar://problem/5794462>. | 210 // see <rdar://problem/5794462>. |
| 201 applyStyle(typingStyle, firstPositionInOrBeforeNode(nodeToInsert), | 211 applyStyle(typingStyle, firstPositionInOrBeforeNode(nodeToInsert), |
| 202 lastPositionInOrAfterNode(nodeToInsert), editingState); | 212 lastPositionInOrAfterNode(nodeToInsert), editingState); |
| 203 if (editingState->isAborted()) | 213 if (editingState->isAborted()) |
| 204 return; | 214 return; |
| 205 // Even though this applyStyle operates on a Range, it still sets an | 215 // Even though this applyStyle operates on a Range, it still sets an |
| 206 // endingSelection(). It tries to set a VisibleSelection around the content | 216 // endingSelection(). It tries to set a VisibleSelection around the content |
| 207 // it operated on. So, that VisibleSelection will either | 217 // it operated on. So, that VisibleSelection will either |
| 208 // (a) select the line break we inserted, or it will | 218 // (a) select the line break we inserted, or it will |
| 209 // (b) be a caret just before the line break (if the line break is at the | 219 // (b) be a caret just before the line break (if the line break is at the |
| 210 // end of a block it isn't selectable). | 220 // end of a block it isn't selectable). |
| 211 // So, this next call sets the endingSelection() to a caret just after the | 221 // So, this next call sets the endingSelection() to a caret just after the |
| 212 // line break that we inserted, or just before it if it's at the end of a | 222 // line break that we inserted, or just before it if it's at the end of a |
| 213 // block. | 223 // block. |
| 214 setEndingSelection(endingSelection().visibleEndDeprecated()); | 224 document().updateStyleAndLayoutIgnorePendingStylesheets(); |
| 225 setEndingSelection(endingSelection().visibleEnd()); |
| 215 } | 226 } |
| 216 | 227 |
| 217 rebalanceWhitespace(); | 228 rebalanceWhitespace(); |
| 218 } | 229 } |
| 219 | 230 |
| 220 } // namespace blink | 231 } // namespace blink |
| OLD | NEW |