| 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 18 matching lines...) Expand all Loading... |
| 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/Text.h" | 31 #include "core/dom/Text.h" |
| 32 #include "core/editing/Editor.h" | 32 #include "core/editing/Editor.h" |
| 33 #include "core/editing/VisibleUnits.h" | 33 #include "core/editing/VisibleUnits.h" |
| 34 #include "core/editing/htmlediting.h" | 34 #include "core/editing/htmlediting.h" |
| 35 #include "core/page/Frame.h" | 35 #include "core/page/Frame.h" |
| 36 | 36 |
| 37 namespace WebCore { | 37 namespace WebCore { |
| 38 | 38 |
| 39 InsertTextCommand::InsertTextCommand(Document* document, const String& text, boo
l selectInsertedText, RebalanceType rebalanceType) | 39 InsertTextCommand::InsertTextCommand(Document& document, const String& text, boo
l selectInsertedText, RebalanceType rebalanceType) |
| 40 : CompositeEditCommand(document) | 40 : CompositeEditCommand(document) |
| 41 , m_text(text) | 41 , m_text(text) |
| 42 , m_selectInsertedText(selectInsertedText) | 42 , m_selectInsertedText(selectInsertedText) |
| 43 , m_rebalanceType(rebalanceType) | 43 , m_rebalanceType(rebalanceType) |
| 44 { | 44 { |
| 45 } | 45 } |
| 46 | 46 |
| 47 InsertTextCommand::InsertTextCommand(Document* document, const String& text, Pas
sRefPtr<TextInsertionMarkerSupplier> markerSupplier) | 47 InsertTextCommand::InsertTextCommand(Document& document, const String& text, Pas
sRefPtr<TextInsertionMarkerSupplier> markerSupplier) |
| 48 : CompositeEditCommand(document) | 48 : CompositeEditCommand(document) |
| 49 , m_text(text) | 49 , m_text(text) |
| 50 , m_selectInsertedText(false) | 50 , m_selectInsertedText(false) |
| 51 , m_rebalanceType(RebalanceLeadingAndTrailingWhitespaces) | 51 , m_rebalanceType(RebalanceLeadingAndTrailingWhitespaces) |
| 52 , m_markerSupplier(markerSupplier) | 52 , m_markerSupplier(markerSupplier) |
| 53 { | 53 { |
| 54 } | 54 } |
| 55 | 55 |
| 56 Position InsertTextCommand::positionInsideTextNode(const Position& p) | 56 Position InsertTextCommand::positionInsideTextNode(const Position& p) |
| 57 { | 57 { |
| 58 Position pos = p; | 58 Position pos = p; |
| 59 if (isTabSpanTextNode(pos.anchorNode())) { | 59 if (isTabSpanTextNode(pos.anchorNode())) { |
| 60 RefPtr<Node> textNode = document()->createEditingTextNode(""); | 60 RefPtr<Node> textNode = document().createEditingTextNode(""); |
| 61 insertNodeAtTabSpanPosition(textNode.get(), pos); | 61 insertNodeAtTabSpanPosition(textNode.get(), pos); |
| 62 return firstPositionInNode(textNode.get()); | 62 return firstPositionInNode(textNode.get()); |
| 63 } | 63 } |
| 64 | 64 |
| 65 // Prepare for text input by looking at the specified position. | 65 // Prepare for text input by looking at the specified position. |
| 66 // It may be necessary to insert a text node to receive characters. | 66 // It may be necessary to insert a text node to receive characters. |
| 67 if (!pos.containerNode()->isTextNode()) { | 67 if (!pos.containerNode()->isTextNode()) { |
| 68 RefPtr<Node> textNode = document()->createEditingTextNode(""); | 68 RefPtr<Node> textNode = document().createEditingTextNode(""); |
| 69 insertNodeAt(textNode.get(), pos); | 69 insertNodeAt(textNode.get(), pos); |
| 70 return firstPositionInNode(textNode.get()); | 70 return firstPositionInNode(textNode.get()); |
| 71 } | 71 } |
| 72 | 72 |
| 73 return pos; | 73 return pos; |
| 74 } | 74 } |
| 75 | 75 |
| 76 void InsertTextCommand::setEndingSelectionWithoutValidation(const Position& star
tPosition, const Position& endPosition) | 76 void InsertTextCommand::setEndingSelectionWithoutValidation(const Position& star
tPosition, const Position& endPosition) |
| 77 { | 77 { |
| 78 // We could have inserted a part of composed character sequence, | 78 // We could have inserted a part of composed character sequence, |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 // FIXME: This delete operation blows away the typing style. | 138 // FIXME: This delete operation blows away the typing style. |
| 139 if (endingSelection().isRange()) { | 139 if (endingSelection().isRange()) { |
| 140 if (performTrivialReplace(m_text, m_selectInsertedText)) | 140 if (performTrivialReplace(m_text, m_selectInsertedText)) |
| 141 return; | 141 return; |
| 142 deleteSelection(false, true, true, false, false); | 142 deleteSelection(false, true, true, false, false); |
| 143 // deleteSelection eventually makes a new endingSelection out of a Posit
ion. If that Position doesn't have | 143 // deleteSelection eventually makes a new endingSelection out of a Posit
ion. If that Position doesn't have |
| 144 // a renderer (e.g. it is on a <frameset> in the DOM), the VisibleSelect
ion cannot be canonicalized to | 144 // a renderer (e.g. it is on a <frameset> in the DOM), the VisibleSelect
ion cannot be canonicalized to |
| 145 // anything other than NoSelection. The rest of this function requires a
real endingSelection, so bail out. | 145 // anything other than NoSelection. The rest of this function requires a
real endingSelection, so bail out. |
| 146 if (endingSelection().isNone()) | 146 if (endingSelection().isNone()) |
| 147 return; | 147 return; |
| 148 } else if (document()->frame()->editor().isOverwriteModeEnabled()) { | 148 } else if (document().frame()->editor().isOverwriteModeEnabled()) { |
| 149 if (performOverwrite(m_text, m_selectInsertedText)) | 149 if (performOverwrite(m_text, m_selectInsertedText)) |
| 150 return; | 150 return; |
| 151 } | 151 } |
| 152 | 152 |
| 153 Position startPosition(endingSelection().start()); | 153 Position startPosition(endingSelection().start()); |
| 154 | 154 |
| 155 Position placeholder; | 155 Position placeholder; |
| 156 // We want to remove preserved newlines and brs that will collapse (and thus
become unnecessary) when content | 156 // We want to remove preserved newlines and brs that will collapse (and thus
become unnecessary) when content |
| 157 // is inserted just before them. | 157 // is inserted just before them. |
| 158 // FIXME: We shouldn't really have to do this, but removing placeholders is
a workaround for 9661. | 158 // FIXME: We shouldn't really have to do this, but removing placeholders is
a workaround for 9661. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 } else { | 214 } else { |
| 215 ASSERT(m_rebalanceType == RebalanceAllWhitespaces); | 215 ASSERT(m_rebalanceType == RebalanceAllWhitespaces); |
| 216 if (canRebalance(startPosition) && canRebalance(endPosition)) | 216 if (canRebalance(startPosition) && canRebalance(endPosition)) |
| 217 rebalanceWhitespaceOnTextSubstring(textNode, startPosition.offse
tInContainerNode(), endPosition.offsetInContainerNode()); | 217 rebalanceWhitespaceOnTextSubstring(textNode, startPosition.offse
tInContainerNode(), endPosition.offsetInContainerNode()); |
| 218 } | 218 } |
| 219 } | 219 } |
| 220 | 220 |
| 221 setEndingSelectionWithoutValidation(startPosition, endPosition); | 221 setEndingSelectionWithoutValidation(startPosition, endPosition); |
| 222 | 222 |
| 223 // Handle the case where there is a typing style. | 223 // Handle the case where there is a typing style. |
| 224 if (RefPtr<EditingStyle> typingStyle = document()->frame()->selection()->typ
ingStyle()) { | 224 if (RefPtr<EditingStyle> typingStyle = document().frame()->selection()->typi
ngStyle()) { |
| 225 typingStyle->prepareToApplyAt(endPosition, EditingStyle::PreserveWriting
Direction); | 225 typingStyle->prepareToApplyAt(endPosition, EditingStyle::PreserveWriting
Direction); |
| 226 if (!typingStyle->isEmpty()) | 226 if (!typingStyle->isEmpty()) |
| 227 applyStyle(typingStyle.get()); | 227 applyStyle(typingStyle.get()); |
| 228 } | 228 } |
| 229 | 229 |
| 230 if (!m_selectInsertedText) | 230 if (!m_selectInsertedText) |
| 231 setEndingSelection(VisibleSelection(endingSelection().end(), endingSelec
tion().affinity(), endingSelection().isDirectional())); | 231 setEndingSelection(VisibleSelection(endingSelection().end(), endingSelec
tion().affinity(), endingSelection().isDirectional())); |
| 232 } | 232 } |
| 233 | 233 |
| 234 Position InsertTextCommand::insertTab(const Position& pos) | 234 Position InsertTextCommand::insertTab(const Position& pos) |
| 235 { | 235 { |
| 236 Position insertPos = VisiblePosition(pos, DOWNSTREAM).deepEquivalent(); | 236 Position insertPos = VisiblePosition(pos, DOWNSTREAM).deepEquivalent(); |
| 237 | 237 |
| 238 Node* node = insertPos.containerNode(); | 238 Node* node = insertPos.containerNode(); |
| 239 unsigned int offset = node->isTextNode() ? insertPos.offsetInContainerNode()
: 0; | 239 unsigned int offset = node->isTextNode() ? insertPos.offsetInContainerNode()
: 0; |
| 240 | 240 |
| 241 // keep tabs coalesced in tab span | 241 // keep tabs coalesced in tab span |
| 242 if (isTabSpanTextNode(node)) { | 242 if (isTabSpanTextNode(node)) { |
| 243 RefPtr<Text> textNode = toText(node); | 243 RefPtr<Text> textNode = toText(node); |
| 244 insertTextIntoNode(textNode, offset, "\t"); | 244 insertTextIntoNode(textNode, offset, "\t"); |
| 245 return Position(textNode.release(), offset + 1); | 245 return Position(textNode.release(), offset + 1); |
| 246 } | 246 } |
| 247 | 247 |
| 248 // create new tab span | 248 // create new tab span |
| 249 RefPtr<Element> spanNode = createTabSpanElement(document()); | 249 RefPtr<Element> spanNode = createTabSpanElement(&document()); |
| 250 | 250 |
| 251 // place it | 251 // place it |
| 252 if (!node->isTextNode()) { | 252 if (!node->isTextNode()) { |
| 253 insertNodeAt(spanNode.get(), insertPos); | 253 insertNodeAt(spanNode.get(), insertPos); |
| 254 } else { | 254 } else { |
| 255 RefPtr<Text> textNode = toText(node); | 255 RefPtr<Text> textNode = toText(node); |
| 256 if (offset >= textNode->length()) | 256 if (offset >= textNode->length()) |
| 257 insertNodeAfter(spanNode, textNode.release()); | 257 insertNodeAfter(spanNode, textNode.release()); |
| 258 else { | 258 else { |
| 259 // split node to make room for the span | 259 // split node to make room for the span |
| 260 // NOTE: splitTextNode uses textNode for the | 260 // NOTE: splitTextNode uses textNode for the |
| 261 // second node in the split, so we need to | 261 // second node in the split, so we need to |
| 262 // insert the span before it. | 262 // insert the span before it. |
| 263 if (offset > 0) | 263 if (offset > 0) |
| 264 splitTextNode(textNode, offset); | 264 splitTextNode(textNode, offset); |
| 265 insertNodeBefore(spanNode, textNode.release()); | 265 insertNodeBefore(spanNode, textNode.release()); |
| 266 } | 266 } |
| 267 } | 267 } |
| 268 | 268 |
| 269 // return the position following the new tab | 269 // return the position following the new tab |
| 270 return lastPositionInNode(spanNode.get()); | 270 return lastPositionInNode(spanNode.get()); |
| 271 } | 271 } |
| 272 | 272 |
| 273 } | 273 } |
| OLD | NEW |