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 |