| 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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 return Position::firstPositionInNode(textNode); | 70 return Position::firstPositionInNode(textNode); |
| 71 } | 71 } |
| 72 | 72 |
| 73 return pos; | 73 return pos; |
| 74 } | 74 } |
| 75 | 75 |
| 76 void InsertTextCommand::setEndingSelectionWithoutValidation( | 76 void InsertTextCommand::setEndingSelectionWithoutValidation( |
| 77 const Position& startPosition, | 77 const Position& startPosition, |
| 78 const Position& endPosition) { | 78 const Position& endPosition) { |
| 79 // We could have inserted a part of composed character sequence, | 79 // We could have inserted a part of composed character sequence, |
| 80 // so we are basically treating ending selection as a range to avoid validatio
n. | 80 // so we are basically treating ending selection as a range to avoid |
| 81 // <http://bugs.webkit.org/show_bug.cgi?id=15781> | 81 // validation. <http://bugs.webkit.org/show_bug.cgi?id=15781> |
| 82 VisibleSelection forcedEndingSelection; | 82 VisibleSelection forcedEndingSelection; |
| 83 forcedEndingSelection.setWithoutValidation(startPosition, endPosition); | 83 forcedEndingSelection.setWithoutValidation(startPosition, endPosition); |
| 84 forcedEndingSelection.setIsDirectional(endingSelection().isDirectional()); | 84 forcedEndingSelection.setIsDirectional(endingSelection().isDirectional()); |
| 85 setEndingSelection(forcedEndingSelection); | 85 setEndingSelection(forcedEndingSelection); |
| 86 } | 86 } |
| 87 | 87 |
| 88 // This avoids the expense of a full fledged delete operation, and avoids a layo
ut that typically results | 88 // This avoids the expense of a full fledged delete operation, and avoids a |
| 89 // from text removal. | 89 // layout that typically results from text removal. |
| 90 bool InsertTextCommand::performTrivialReplace(const String& text, | 90 bool InsertTextCommand::performTrivialReplace(const String& text, |
| 91 bool selectInsertedText) { | 91 bool selectInsertedText) { |
| 92 if (!endingSelection().isRange()) | 92 if (!endingSelection().isRange()) |
| 93 return false; | 93 return false; |
| 94 | 94 |
| 95 if (text.contains('\t') || text.contains(' ') || text.contains('\n')) | 95 if (text.contains('\t') || text.contains(' ') || text.contains('\n')) |
| 96 return false; | 96 return false; |
| 97 | 97 |
| 98 Position start = endingSelection().start(); | 98 Position start = endingSelection().start(); |
| 99 Position endPosition = replaceSelectedTextInNode(text); | 99 Position endPosition = replaceSelectedTextInNode(text); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 // Delete the current selection. | 146 // Delete the current selection. |
| 147 // FIXME: This delete operation blows away the typing style. | 147 // FIXME: This delete operation blows away the typing style. |
| 148 if (endingSelection().isRange()) { | 148 if (endingSelection().isRange()) { |
| 149 if (performTrivialReplace(m_text, m_selectInsertedText)) | 149 if (performTrivialReplace(m_text, m_selectInsertedText)) |
| 150 return; | 150 return; |
| 151 bool endOfSelectionWasAtStartOfBlock = | 151 bool endOfSelectionWasAtStartOfBlock = |
| 152 isStartOfBlock(endingSelection().visibleEndDeprecated()); | 152 isStartOfBlock(endingSelection().visibleEndDeprecated()); |
| 153 deleteSelection(editingState, false, true, false, false); | 153 deleteSelection(editingState, false, true, false, false); |
| 154 if (editingState->isAborted()) | 154 if (editingState->isAborted()) |
| 155 return; | 155 return; |
| 156 // deleteSelection eventually makes a new endingSelection out of a Position.
If that Position doesn't have | 156 // deleteSelection eventually makes a new endingSelection out of a Position. |
| 157 // a layoutObject (e.g. it is on a <frameset> in the DOM), the VisibleSelect
ion cannot be canonicalized to | 157 // If that Position doesn't have a layoutObject (e.g. it is on a <frameset> |
| 158 // anything other than NoSelection. The rest of this function requires a rea
l endingSelection, so bail out. | 158 // in the DOM), the VisibleSelection cannot be canonicalized to anything |
| 159 // other than NoSelection. The rest of this function requires a real |
| 160 // endingSelection, so bail out. |
| 159 if (endingSelection().isNone()) | 161 if (endingSelection().isNone()) |
| 160 return; | 162 return; |
| 161 if (endOfSelectionWasAtStartOfBlock) { | 163 if (endOfSelectionWasAtStartOfBlock) { |
| 162 if (EditingStyle* typingStyle = | 164 if (EditingStyle* typingStyle = |
| 163 document().frame()->selection().typingStyle()) | 165 document().frame()->selection().typingStyle()) |
| 164 typingStyle->removeBlockProperties(); | 166 typingStyle->removeBlockProperties(); |
| 165 } | 167 } |
| 166 } else if (document().frame()->editor().isOverwriteModeEnabled()) { | 168 } else if (document().frame()->editor().isOverwriteModeEnabled()) { |
| 167 if (performOverwrite(m_text, m_selectInsertedText)) | 169 if (performOverwrite(m_text, m_selectInsertedText)) |
| 168 return; | 170 return; |
| 169 } | 171 } |
| 170 | 172 |
| 171 Position startPosition(endingSelection().start()); | 173 Position startPosition(endingSelection().start()); |
| 172 | 174 |
| 173 Position placeholder; | 175 Position placeholder; |
| 174 // We want to remove preserved newlines and brs that will collapse (and thus b
ecome unnecessary) when content | 176 // We want to remove preserved newlines and brs that will collapse (and thus |
| 175 // is inserted just before them. | 177 // become unnecessary) when content is inserted just before them. |
| 176 // FIXME: We shouldn't really have to do this, but removing placeholders is a
workaround for 9661. | 178 // FIXME: We shouldn't really have to do this, but removing placeholders is a |
| 177 // If the caret is just before a placeholder, downstream will normalize the ca
ret to it. | 179 // workaround for 9661. |
| 180 // If the caret is just before a placeholder, downstream will normalize the |
| 181 // caret to it. |
| 178 Position downstream(mostForwardCaretPosition(startPosition)); | 182 Position downstream(mostForwardCaretPosition(startPosition)); |
| 179 if (lineBreakExistsAtPosition(downstream)) { | 183 if (lineBreakExistsAtPosition(downstream)) { |
| 180 // FIXME: This doesn't handle placeholders at the end of anonymous blocks. | 184 // FIXME: This doesn't handle placeholders at the end of anonymous blocks. |
| 181 VisiblePosition caret = createVisiblePositionDeprecated(startPosition); | 185 VisiblePosition caret = createVisiblePositionDeprecated(startPosition); |
| 182 if (isEndOfBlock(caret) && isStartOfParagraphDeprecated(caret)) | 186 if (isEndOfBlock(caret) && isStartOfParagraphDeprecated(caret)) |
| 183 placeholder = downstream; | 187 placeholder = downstream; |
| 184 // Don't remove the placeholder yet, otherwise the block we're inserting int
o would collapse before | 188 // Don't remove the placeholder yet, otherwise the block we're inserting |
| 185 // we get a chance to insert into it. We check for a placeholder now, thoug
h, because doing so requires | 189 // into would collapse before we get a chance to insert into it. We check |
| 186 // the creation of a VisiblePosition, and if we did that post-insertion it w
ould force a layout. | 190 // for a placeholder now, though, because doing so requires the creation of |
| 191 // a VisiblePosition, and if we did that post-insertion it would force a |
| 192 // layout. |
| 187 } | 193 } |
| 188 | 194 |
| 189 // Insert the character at the leftmost candidate. | 195 // Insert the character at the leftmost candidate. |
| 190 startPosition = mostBackwardCaretPosition(startPosition); | 196 startPosition = mostBackwardCaretPosition(startPosition); |
| 191 | 197 |
| 192 // It is possible for the node that contains startPosition to contain only unr
endered whitespace, | 198 // It is possible for the node that contains startPosition to contain only |
| 193 // and so deleteInsignificantText could remove it. Save the position before t
he node in case that happens. | 199 // unrendered whitespace, and so deleteInsignificantText could remove it. |
| 200 // Save the position before the node in case that happens. |
| 194 DCHECK(startPosition.computeContainerNode()) << startPosition; | 201 DCHECK(startPosition.computeContainerNode()) << startPosition; |
| 195 Position positionBeforeStartNode( | 202 Position positionBeforeStartNode( |
| 196 Position::inParentBeforeNode(*startPosition.computeContainerNode())); | 203 Position::inParentBeforeNode(*startPosition.computeContainerNode())); |
| 197 deleteInsignificantText(startPosition, | 204 deleteInsignificantText(startPosition, |
| 198 mostForwardCaretPosition(startPosition)); | 205 mostForwardCaretPosition(startPosition)); |
| 199 if (!startPosition.isConnected()) | 206 if (!startPosition.isConnected()) |
| 200 startPosition = positionBeforeStartNode; | 207 startPosition = positionBeforeStartNode; |
| 201 if (!isVisuallyEquivalentCandidate(startPosition)) | 208 if (!isVisuallyEquivalentCandidate(startPosition)) |
| 202 startPosition = mostForwardCaretPosition(startPosition); | 209 startPosition = mostForwardCaretPosition(startPosition); |
| 203 | 210 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 226 DCHECK(startPosition.computeContainerNode()->isTextNode()) << startPosition; | 233 DCHECK(startPosition.computeContainerNode()->isTextNode()) << startPosition; |
| 227 if (placeholder.isNotNull()) | 234 if (placeholder.isNotNull()) |
| 228 removePlaceholderAt(placeholder); | 235 removePlaceholderAt(placeholder); |
| 229 Text* textNode = toText(startPosition.computeContainerNode()); | 236 Text* textNode = toText(startPosition.computeContainerNode()); |
| 230 const unsigned offset = startPosition.offsetInContainerNode(); | 237 const unsigned offset = startPosition.offsetInContainerNode(); |
| 231 | 238 |
| 232 insertTextIntoNode(textNode, offset, m_text); | 239 insertTextIntoNode(textNode, offset, m_text); |
| 233 endPosition = Position(textNode, offset + m_text.length()); | 240 endPosition = Position(textNode, offset + m_text.length()); |
| 234 | 241 |
| 235 if (m_rebalanceType == RebalanceLeadingAndTrailingWhitespaces) { | 242 if (m_rebalanceType == RebalanceLeadingAndTrailingWhitespaces) { |
| 236 // The insertion may require adjusting adjacent whitespace, if it is prese
nt. | 243 // The insertion may require adjusting adjacent whitespace, if it is |
| 244 // present. |
| 237 rebalanceWhitespaceAt(endPosition); | 245 rebalanceWhitespaceAt(endPosition); |
| 238 // Rebalancing on both sides isn't necessary if we've inserted only spaces
. | 246 // Rebalancing on both sides isn't necessary if we've inserted only |
| 247 // spaces. |
| 239 if (!shouldRebalanceLeadingWhitespaceFor(m_text)) | 248 if (!shouldRebalanceLeadingWhitespaceFor(m_text)) |
| 240 rebalanceWhitespaceAt(startPosition); | 249 rebalanceWhitespaceAt(startPosition); |
| 241 } else { | 250 } else { |
| 242 DCHECK_EQ(m_rebalanceType, RebalanceAllWhitespaces); | 251 DCHECK_EQ(m_rebalanceType, RebalanceAllWhitespaces); |
| 243 if (canRebalance(startPosition) && canRebalance(endPosition)) | 252 if (canRebalance(startPosition) && canRebalance(endPosition)) |
| 244 rebalanceWhitespaceOnTextSubstring( | 253 rebalanceWhitespaceOnTextSubstring( |
| 245 textNode, startPosition.offsetInContainerNode(), | 254 textNode, startPosition.offsetInContainerNode(), |
| 246 endPosition.offsetInContainerNode()); | 255 endPosition.offsetInContainerNode()); |
| 247 } | 256 } |
| 248 } | 257 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 } | 313 } |
| 305 } | 314 } |
| 306 if (editingState->isAborted()) | 315 if (editingState->isAborted()) |
| 307 return Position(); | 316 return Position(); |
| 308 | 317 |
| 309 // return the position following the new tab | 318 // return the position following the new tab |
| 310 return Position::lastPositionInNode(spanElement); | 319 return Position::lastPositionInNode(spanElement); |
| 311 } | 320 } |
| 312 | 321 |
| 313 } // namespace blink | 322 } // namespace blink |
| OLD | NEW |