Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: third_party/WebKit/Source/core/editing/commands/ApplyBlockElementCommand.cpp

Issue 2393133002: Prune deprecated editing functions from ApplyBlockElementCommand and its subclasses (Closed)
Patch Set: Add a missing layout update call Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
50 m_inlineStyle(inlineStyle) {} 50 m_inlineStyle(inlineStyle) {}
51 51
52 ApplyBlockElementCommand::ApplyBlockElementCommand(Document& document, 52 ApplyBlockElementCommand::ApplyBlockElementCommand(Document& document,
53 const QualifiedName& tagName) 53 const QualifiedName& tagName)
54 : CompositeEditCommand(document), m_tagName(tagName) {} 54 : CompositeEditCommand(document), m_tagName(tagName) {}
55 55
56 void ApplyBlockElementCommand::doApply(EditingState* editingState) { 56 void ApplyBlockElementCommand::doApply(EditingState* editingState) {
57 if (!endingSelection().rootEditableElement()) 57 if (!endingSelection().rootEditableElement())
58 return; 58 return;
59 59
60 VisiblePosition visibleEnd = endingSelection().visibleEndDeprecated(); 60 // ApplyBlockElementCommands are only created directly by editor commands'
61 VisiblePosition visibleStart = endingSelection().visibleStartDeprecated(); 61 // execution, which updates layout before entering doApply().
62 DCHECK(!document().needsLayoutTreeUpdate());
63
64 VisiblePosition visibleEnd = endingSelection().visibleEnd();
65 VisiblePosition visibleStart = endingSelection().visibleStart();
62 if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull() || 66 if (visibleStart.isNull() || visibleStart.isOrphan() || visibleEnd.isNull() ||
63 visibleEnd.isOrphan()) 67 visibleEnd.isOrphan())
64 return; 68 return;
65 69
66 // When a selection ends at the start of a paragraph, we rarely paint 70 // When a selection ends at the start of a paragraph, we rarely paint
67 // the selection gap before that paragraph, because there often is no gap. 71 // the selection gap before that paragraph, because there often is no gap.
68 // In a case like this, it's not obvious to the user that the selection 72 // In a case like this, it's not obvious to the user that the selection
69 // ends "inside" that paragraph, so it would be confusing if Indent/Outdent 73 // ends "inside" that paragraph, so it would be confusing if Indent/Outdent
70 // operated on that paragraph. 74 // operated on that paragraph.
71 // FIXME: We paint the gap before some paragraphs that are indented with left 75 // FIXME: We paint the gap before some paragraphs that are indented with left
72 // margin/padding, but not others. We should make the gap painting more 76 // margin/padding, but not others. We should make the gap painting more
73 // consistent and then use a left margin/padding rule here. 77 // consistent and then use a left margin/padding rule here.
74 if (visibleEnd.deepEquivalent() != visibleStart.deepEquivalent() && 78 if (visibleEnd.deepEquivalent() != visibleStart.deepEquivalent() &&
75 isStartOfParagraphDeprecated(visibleEnd)) { 79 isStartOfParagraph(visibleEnd)) {
76 VisibleSelection newSelection = createVisibleSelectionDeprecated( 80 VisibleSelection newSelection = createVisibleSelection(
77 visibleStart, 81 visibleStart,
78 previousPositionOf(visibleEnd, CannotCrossEditingBoundary), 82 previousPositionOf(visibleEnd, CannotCrossEditingBoundary),
79 endingSelection().isDirectional()); 83 endingSelection().isDirectional());
80 if (newSelection.isNone()) 84 if (newSelection.isNone())
81 return; 85 return;
82 setEndingSelection(newSelection); 86 setEndingSelection(newSelection);
83 } 87 }
84 88
85 VisibleSelection selection = 89 VisibleSelection selection =
86 selectionForParagraphIteration(endingSelection()); 90 selectionForParagraphIteration(endingSelection());
87 VisiblePosition startOfSelection = selection.visibleStartDeprecated(); 91 VisiblePosition startOfSelection = selection.visibleStart();
88 VisiblePosition endOfSelection = selection.visibleEndDeprecated(); 92 VisiblePosition endOfSelection = selection.visibleEnd();
89 DCHECK(!startOfSelection.isNull()); 93 DCHECK(!startOfSelection.isNull());
90 DCHECK(!endOfSelection.isNull()); 94 DCHECK(!endOfSelection.isNull());
91 ContainerNode* startScope = nullptr; 95 ContainerNode* startScope = nullptr;
92 int startIndex = indexForVisiblePosition(startOfSelection, startScope); 96 int startIndex = indexForVisiblePosition(startOfSelection, startScope);
93 ContainerNode* endScope = nullptr; 97 ContainerNode* endScope = nullptr;
94 int endIndex = indexForVisiblePosition(endOfSelection, endScope); 98 int endIndex = indexForVisiblePosition(endOfSelection, endScope);
95 99
96 formatSelection(startOfSelection, endOfSelection, editingState); 100 formatSelection(startOfSelection, endOfSelection, editingState);
97 if (editingState->isAborted()) 101 if (editingState->isAborted())
98 return; 102 return;
99 103
100 document().updateStyleAndLayoutIgnorePendingStylesheets(); 104 document().updateStyleAndLayoutIgnorePendingStylesheets();
101 105
102 DCHECK_EQ(startScope, endScope); 106 DCHECK_EQ(startScope, endScope);
103 DCHECK_GE(startIndex, 0); 107 DCHECK_GE(startIndex, 0);
104 DCHECK_LE(startIndex, endIndex); 108 DCHECK_LE(startIndex, endIndex);
105 if (startScope == endScope && startIndex >= 0 && startIndex <= endIndex) { 109 if (startScope == endScope && startIndex >= 0 && startIndex <= endIndex) {
106 VisiblePosition start(visiblePositionForIndex(startIndex, startScope)); 110 VisiblePosition start(visiblePositionForIndex(startIndex, startScope));
107 VisiblePosition end(visiblePositionForIndex(endIndex, endScope)); 111 VisiblePosition end(visiblePositionForIndex(endIndex, endScope));
108 if (start.isNotNull() && end.isNotNull()) 112 if (start.isNotNull() && end.isNotNull())
109 setEndingSelection(createVisibleSelectionDeprecated( 113 setEndingSelection(createVisibleSelection(
110 start, end, endingSelection().isDirectional())); 114 start, end, endingSelection().isDirectional()));
111 } 115 }
112 } 116 }
113 117
114 static bool isAtUnsplittableElement(const Position& pos) { 118 static bool isAtUnsplittableElement(const Position& pos) {
115 Node* node = pos.anchorNode(); 119 Node* node = pos.anchorNode();
116 return node == rootEditableElementOf(pos) || 120 return node == rootEditableElementOf(pos) ||
117 node == enclosingNodeOfType(pos, &isTableCell); 121 node == enclosingNodeOfType(pos, &isTableCell);
118 } 122 }
119 123
120 void ApplyBlockElementCommand::formatSelection( 124 void ApplyBlockElementCommand::formatSelection(
121 const VisiblePosition& startOfSelection, 125 const VisiblePosition& startOfSelection,
122 const VisiblePosition& endOfSelection, 126 const VisiblePosition& endOfSelection,
123 EditingState* editingState) { 127 EditingState* editingState) {
124 // Special case empty unsplittable elements because there's nothing to split 128 // Special case empty unsplittable elements because there's nothing to split
125 // and there's nothing to move. 129 // and there's nothing to move.
126 Position start = mostForwardCaretPosition(startOfSelection.deepEquivalent()); 130 Position start = mostForwardCaretPosition(startOfSelection.deepEquivalent());
127 if (isAtUnsplittableElement(start)) { 131 if (isAtUnsplittableElement(start)) {
128 HTMLElement* blockquote = createBlockElement(); 132 HTMLElement* blockquote = createBlockElement();
129 insertNodeAt(blockquote, start, editingState); 133 insertNodeAt(blockquote, start, editingState);
130 if (editingState->isAborted()) 134 if (editingState->isAborted())
131 return; 135 return;
132 HTMLBRElement* placeholder = HTMLBRElement::create(document()); 136 HTMLBRElement* placeholder = HTMLBRElement::create(document());
133 appendNode(placeholder, blockquote, editingState); 137 appendNode(placeholder, blockquote, editingState);
134 if (editingState->isAborted()) 138 if (editingState->isAborted())
135 return; 139 return;
136 setEndingSelection(createVisibleSelectionDeprecated( 140 document().updateStyleAndLayoutIgnorePendingStylesheets();
141 setEndingSelection(createVisibleSelection(
137 Position::beforeNode(placeholder), TextAffinity::Downstream, 142 Position::beforeNode(placeholder), TextAffinity::Downstream,
138 endingSelection().isDirectional())); 143 endingSelection().isDirectional()));
139 return; 144 return;
140 } 145 }
141 146
142 HTMLElement* blockquoteForNextIndent = nullptr; 147 HTMLElement* blockquoteForNextIndent = nullptr;
143 VisiblePosition endOfCurrentParagraph = 148 VisiblePosition endOfCurrentParagraph = endOfParagraph(startOfSelection);
144 endOfParagraphDeprecated(startOfSelection); 149 VisiblePosition endOfLastParagraph = endOfParagraph(endOfSelection);
145 VisiblePosition endOfLastParagraph = endOfParagraphDeprecated(endOfSelection); 150 Position endAfterSelection =
146 VisiblePosition endAfterSelection = 151 endOfParagraph(nextPositionOf(endOfLastParagraph)).deepEquivalent();
147 endOfParagraphDeprecated(nextPositionOf(endOfLastParagraph));
148 m_endOfLastParagraph = endOfLastParagraph.deepEquivalent(); 152 m_endOfLastParagraph = endOfLastParagraph.deepEquivalent();
149 153
150 bool atEnd = false; 154 bool atEnd = false;
151 Position end; 155 Position end;
152 while (endOfCurrentParagraph.deepEquivalent() != 156 while (endOfCurrentParagraph.deepEquivalent() != endAfterSelection &&
153 endAfterSelection.deepEquivalent() &&
154 !atEnd) { 157 !atEnd) {
155 if (endOfCurrentParagraph.deepEquivalent() == m_endOfLastParagraph) 158 if (endOfCurrentParagraph.deepEquivalent() == m_endOfLastParagraph)
156 atEnd = true; 159 atEnd = true;
157 160
158 rangeForParagraphSplittingTextNodesIfNeeded(endOfCurrentParagraph, start, 161 rangeForParagraphSplittingTextNodesIfNeeded(endOfCurrentParagraph, start,
159 end); 162 end);
160 endOfCurrentParagraph = createVisiblePositionDeprecated(end); 163 endOfCurrentParagraph = createVisiblePosition(end);
161 164
162 Node* enclosingCell = enclosingNodeOfType(start, &isTableCell); 165 Node* enclosingCell = enclosingNodeOfType(start, &isTableCell);
163 VisiblePosition endOfNextParagraph = 166 PositionWithAffinity endOfNextParagraph =
164 endOfNextParagrahSplittingTextNodesIfNeeded(endOfCurrentParagraph, 167 endOfNextParagrahSplittingTextNodesIfNeeded(endOfCurrentParagraph,
165 start, end); 168 start, end)
169 .toPositionWithAffinity();
166 170
167 formatRange(start, end, m_endOfLastParagraph, blockquoteForNextIndent, 171 formatRange(start, end, m_endOfLastParagraph, blockquoteForNextIndent,
168 editingState); 172 editingState);
169 if (editingState->isAborted()) 173 if (editingState->isAborted())
170 return; 174 return;
171 175
172 // Don't put the next paragraph in the blockquote we just created for this p aragraph unless 176 // Don't put the next paragraph in the blockquote we just created for this p aragraph unless
173 // the next paragraph is in the same cell. 177 // the next paragraph is in the same cell.
174 if (enclosingCell && 178 if (enclosingCell &&
175 enclosingCell != enclosingNodeOfType( 179 enclosingCell !=
176 endOfNextParagraph.deepEquivalent(), &isTableCell)) 180 enclosingNodeOfType(endOfNextParagraph.position(), &isTableCell))
177 blockquoteForNextIndent = nullptr; 181 blockquoteForNextIndent = nullptr;
178 182
179 // indentIntoBlockquote could move more than one paragraph if the paragraph 183 // indentIntoBlockquote could move more than one paragraph if the paragraph
180 // is in a list item or a table. As a result, endAfterSelection could refer to a position 184 // is in a list item or a table. As a result, endAfterSelection could refer to a position
181 // no longer in the document. 185 // no longer in the document.
182 if (endAfterSelection.isNotNull() && 186 if (endAfterSelection.isNotNull() && !endAfterSelection.isConnected())
183 !endAfterSelection.deepEquivalent().isConnected())
184 break; 187 break;
185 // Sanity check: Make sure our moveParagraph calls didn't remove endOfNextPa ragraph.deepEquivalent().anchorNode() 188 // Sanity check: Make sure our moveParagraph calls didn't remove endOfNextPa ragraph.position().anchorNode()
186 // If somehow, e.g. mutation event handler, we did, return to prevent crashe s. 189 // If somehow, e.g. mutation event handler, we did, return to prevent crashe s.
187 if (endOfNextParagraph.isNotNull() && 190 if (endOfNextParagraph.isNotNull() &&
188 !endOfNextParagraph.deepEquivalent().isConnected()) 191 !endOfNextParagraph.position().isConnected())
189 return; 192 return;
190 endOfCurrentParagraph = endOfNextParagraph; 193
194 document().updateStyleAndLayoutIgnorePendingStylesheets();
195 endOfCurrentParagraph = createVisiblePosition(endOfNextParagraph);
191 } 196 }
192 } 197 }
193 198
194 static bool isNewLineAtPosition(const Position& position) { 199 static bool isNewLineAtPosition(const Position& position) {
195 Node* textNode = position.computeContainerNode(); 200 Node* textNode = position.computeContainerNode();
196 int offset = position.offsetInContainerNode(); 201 int offset = position.offsetInContainerNode();
197 if (!textNode || !textNode->isTextNode() || offset < 0 || 202 if (!textNode || !textNode->isTextNode() || offset < 0 ||
198 offset >= textNode->maxCharacterOffset()) 203 offset >= textNode->maxCharacterOffset())
199 return false; 204 return false;
200 205
(...skipping 11 matching lines...) Expand all
212 if (!position.isOffsetInAnchor() || !position.computeContainerNode() || 217 if (!position.isOffsetInAnchor() || !position.computeContainerNode() ||
213 !position.computeContainerNode()->isTextNode()) 218 !position.computeContainerNode()->isTextNode())
214 return 0; 219 return 0;
215 return position.computeContainerNode()->computedStyle(); 220 return position.computeContainerNode()->computedStyle();
216 } 221 }
217 222
218 void ApplyBlockElementCommand::rangeForParagraphSplittingTextNodesIfNeeded( 223 void ApplyBlockElementCommand::rangeForParagraphSplittingTextNodesIfNeeded(
219 const VisiblePosition& endOfCurrentParagraph, 224 const VisiblePosition& endOfCurrentParagraph,
220 Position& start, 225 Position& start,
221 Position& end) { 226 Position& end) {
222 start = startOfParagraphDeprecated(endOfCurrentParagraph).deepEquivalent(); 227 start = startOfParagraph(endOfCurrentParagraph).deepEquivalent();
223 end = endOfCurrentParagraph.deepEquivalent(); 228 end = endOfCurrentParagraph.deepEquivalent();
224 229
225 document().updateStyleAndLayoutTree();
226
227 bool isStartAndEndOnSameNode = false; 230 bool isStartAndEndOnSameNode = false;
228 if (const ComputedStyle* startStyle = 231 if (const ComputedStyle* startStyle =
229 computedStyleOfEnclosingTextNode(start)) { 232 computedStyleOfEnclosingTextNode(start)) {
230 isStartAndEndOnSameNode = 233 isStartAndEndOnSameNode =
231 computedStyleOfEnclosingTextNode(end) && 234 computedStyleOfEnclosingTextNode(end) &&
232 start.computeContainerNode() == end.computeContainerNode(); 235 start.computeContainerNode() == end.computeContainerNode();
233 bool isStartAndEndOfLastParagraphOnSameNode = 236 bool isStartAndEndOfLastParagraphOnSameNode =
234 computedStyleOfEnclosingTextNode(m_endOfLastParagraph) && 237 computedStyleOfEnclosingTextNode(m_endOfLastParagraph) &&
235 start.computeContainerNode() == 238 start.computeContainerNode() ==
236 m_endOfLastParagraph.computeContainerNode(); 239 m_endOfLastParagraph.computeContainerNode();
237 240
238 // Avoid obtanining the start of next paragraph for start 241 // Avoid obtanining the start of next paragraph for start
239 // TODO(yosin) We should use |PositionMoveType::CodePoint| for 242 // TODO(yosin) We should use |PositionMoveType::CodePoint| for
240 // |previousPositionOf()|. 243 // |previousPositionOf()|.
241 if (startStyle->preserveNewline() && isNewLineAtPosition(start) && 244 if (startStyle->preserveNewline() && isNewLineAtPosition(start) &&
242 !isNewLineAtPosition( 245 !isNewLineAtPosition(
243 previousPositionOf(start, PositionMoveType::CodeUnit)) && 246 previousPositionOf(start, PositionMoveType::CodeUnit)) &&
244 start.offsetInContainerNode() > 0) 247 start.offsetInContainerNode() > 0)
245 start = startOfParagraphDeprecated( 248 start = startOfParagraph(createVisiblePosition(previousPositionOf(
246 createVisiblePositionDeprecated( 249 end, PositionMoveType::CodeUnit)))
247 previousPositionOf(end, PositionMoveType::CodeUnit)))
248 .deepEquivalent(); 250 .deepEquivalent();
249 251
250 // If start is in the middle of a text node, split. 252 // If start is in the middle of a text node, split.
251 if (!startStyle->collapseWhiteSpace() && 253 if (!startStyle->collapseWhiteSpace() &&
252 start.offsetInContainerNode() > 0) { 254 start.offsetInContainerNode() > 0) {
253 int startOffset = start.offsetInContainerNode(); 255 int startOffset = start.offsetInContainerNode();
254 Text* startText = toText(start.computeContainerNode()); 256 Text* startText = toText(start.computeContainerNode());
255 splitTextNode(startText, startOffset); 257 splitTextNode(startText, startOffset);
258 document().updateStyleAndLayoutTree();
259
256 start = Position::firstPositionInNode(startText); 260 start = Position::firstPositionInNode(startText);
257 if (isStartAndEndOnSameNode) { 261 if (isStartAndEndOnSameNode) {
258 DCHECK_GE(end.offsetInContainerNode(), startOffset); 262 DCHECK_GE(end.offsetInContainerNode(), startOffset);
259 end = Position(startText, end.offsetInContainerNode() - startOffset); 263 end = Position(startText, end.offsetInContainerNode() - startOffset);
260 } 264 }
261 if (isStartAndEndOfLastParagraphOnSameNode) { 265 if (isStartAndEndOfLastParagraphOnSameNode) {
262 DCHECK_GE(m_endOfLastParagraph.offsetInContainerNode(), startOffset); 266 DCHECK_GE(m_endOfLastParagraph.offsetInContainerNode(), startOffset);
263 m_endOfLastParagraph = 267 m_endOfLastParagraph =
264 Position(startText, m_endOfLastParagraph.offsetInContainerNode() - 268 Position(startText, m_endOfLastParagraph.offsetInContainerNode() -
265 startOffset); 269 startOffset);
266 } 270 }
267 } 271 }
268 } 272 }
269 273
270 document().updateStyleAndLayoutTree();
271
272 if (const ComputedStyle* endStyle = computedStyleOfEnclosingTextNode(end)) { 274 if (const ComputedStyle* endStyle = computedStyleOfEnclosingTextNode(end)) {
273 bool isEndAndEndOfLastParagraphOnSameNode = 275 bool isEndAndEndOfLastParagraphOnSameNode =
274 computedStyleOfEnclosingTextNode(m_endOfLastParagraph) && 276 computedStyleOfEnclosingTextNode(m_endOfLastParagraph) &&
275 end.anchorNode() == m_endOfLastParagraph.anchorNode(); 277 end.anchorNode() == m_endOfLastParagraph.anchorNode();
276 // Include \n at the end of line if we're at an empty paragraph 278 // Include \n at the end of line if we're at an empty paragraph
277 if (endStyle->preserveNewline() && start == end && 279 if (endStyle->preserveNewline() && start == end &&
278 end.offsetInContainerNode() < 280 end.offsetInContainerNode() <
279 end.computeContainerNode()->maxCharacterOffset()) { 281 end.computeContainerNode()->maxCharacterOffset()) {
280 int endOffset = end.offsetInContainerNode(); 282 int endOffset = end.offsetInContainerNode();
281 // TODO(yosin) We should use |PositionMoveType::CodePoint| for 283 // TODO(yosin) We should use |PositionMoveType::CodePoint| for
282 // |previousPositionOf()|. 284 // |previousPositionOf()|.
283 if (!isNewLineAtPosition( 285 if (!isNewLineAtPosition(
284 previousPositionOf(end, PositionMoveType::CodeUnit)) && 286 previousPositionOf(end, PositionMoveType::CodeUnit)) &&
285 isNewLineAtPosition(end)) 287 isNewLineAtPosition(end))
286 end = Position(end.computeContainerNode(), endOffset + 1); 288 end = Position(end.computeContainerNode(), endOffset + 1);
287 if (isEndAndEndOfLastParagraphOnSameNode && 289 if (isEndAndEndOfLastParagraphOnSameNode &&
288 end.offsetInContainerNode() >= 290 end.offsetInContainerNode() >=
289 m_endOfLastParagraph.offsetInContainerNode()) 291 m_endOfLastParagraph.offsetInContainerNode())
290 m_endOfLastParagraph = end; 292 m_endOfLastParagraph = end;
291 } 293 }
292 294
293 // If end is in the middle of a text node, split. 295 // If end is in the middle of a text node, split.
294 if (endStyle->userModify() != READ_ONLY && 296 if (endStyle->userModify() != READ_ONLY &&
295 !endStyle->collapseWhiteSpace() && end.offsetInContainerNode() && 297 !endStyle->collapseWhiteSpace() && end.offsetInContainerNode() &&
296 end.offsetInContainerNode() < 298 end.offsetInContainerNode() <
297 end.computeContainerNode()->maxCharacterOffset()) { 299 end.computeContainerNode()->maxCharacterOffset()) {
298 Text* endContainer = toText(end.computeContainerNode()); 300 Text* endContainer = toText(end.computeContainerNode());
299 splitTextNode(endContainer, end.offsetInContainerNode()); 301 splitTextNode(endContainer, end.offsetInContainerNode());
302 document().updateStyleAndLayoutTree();
303
300 if (isStartAndEndOnSameNode) 304 if (isStartAndEndOnSameNode)
301 start = firstPositionInOrBeforeNode(endContainer->previousSibling()); 305 start = firstPositionInOrBeforeNode(endContainer->previousSibling());
302 if (isEndAndEndOfLastParagraphOnSameNode) { 306 if (isEndAndEndOfLastParagraphOnSameNode) {
303 if (m_endOfLastParagraph.offsetInContainerNode() == 307 if (m_endOfLastParagraph.offsetInContainerNode() ==
304 end.offsetInContainerNode()) 308 end.offsetInContainerNode())
305 m_endOfLastParagraph = 309 m_endOfLastParagraph =
306 lastPositionInOrAfterNode(endContainer->previousSibling()); 310 lastPositionInOrAfterNode(endContainer->previousSibling());
307 else 311 else
308 m_endOfLastParagraph = Position( 312 m_endOfLastParagraph = Position(
309 endContainer, m_endOfLastParagraph.offsetInContainerNode() - 313 endContainer, m_endOfLastParagraph.offsetInContainerNode() -
310 end.offsetInContainerNode()); 314 end.offsetInContainerNode());
311 } 315 }
312 end = Position::lastPositionInNode(endContainer->previousSibling()); 316 end = Position::lastPositionInNode(endContainer->previousSibling());
313 } 317 }
314 } 318 }
315 } 319 }
316 320
317 VisiblePosition 321 VisiblePosition
318 ApplyBlockElementCommand::endOfNextParagrahSplittingTextNodesIfNeeded( 322 ApplyBlockElementCommand::endOfNextParagrahSplittingTextNodesIfNeeded(
319 VisiblePosition& endOfCurrentParagraph, 323 VisiblePosition& endOfCurrentParagraph,
320 Position& start, 324 Position& start,
321 Position& end) { 325 Position& end) {
322 VisiblePosition endOfNextParagraph = 326 VisiblePosition endOfNextParagraph =
323 endOfParagraphDeprecated(nextPositionOf(endOfCurrentParagraph)); 327 endOfParagraph(nextPositionOf(endOfCurrentParagraph));
324 Position position = endOfNextParagraph.deepEquivalent(); 328 Position position = endOfNextParagraph.deepEquivalent();
325 const ComputedStyle* style = computedStyleOfEnclosingTextNode(position); 329 const ComputedStyle* style = computedStyleOfEnclosingTextNode(position);
326 if (!style) 330 if (!style)
327 return endOfNextParagraph; 331 return endOfNextParagraph;
328 332
329 Text* text = toText(position.computeContainerNode()); 333 Text* text = toText(position.computeContainerNode());
330 if (!style->preserveNewline() || !position.offsetInContainerNode() || 334 if (!style->preserveNewline() || !position.offsetInContainerNode() ||
331 !isNewLineAtPosition(Position::firstPositionInNode(text))) 335 !isNewLineAtPosition(Position::firstPositionInNode(text)))
332 return endOfNextParagraph; 336 return endOfNextParagraph;
333 337
334 // \n at the beginning of the text node immediately following the current para graph is trimmed by moveParagraphWithClones. 338 // \n at the beginning of the text node immediately following the current para graph is trimmed by moveParagraphWithClones.
335 // If endOfNextParagraph was pointing at this same text node, endOfNextParagra ph will be shifted by one paragraph. 339 // If endOfNextParagraph was pointing at this same text node, endOfNextParagra ph will be shifted by one paragraph.
336 // Avoid this by splitting "\n" 340 // Avoid this by splitting "\n"
337 splitTextNode(text, 1); 341 splitTextNode(text, 1);
342 document().updateStyleAndLayoutIgnorePendingStylesheets();
338 343
339 if (text == start.computeContainerNode() && text->previousSibling() && 344 if (text == start.computeContainerNode() && text->previousSibling() &&
340 text->previousSibling()->isTextNode()) { 345 text->previousSibling()->isTextNode()) {
341 DCHECK_LT(start.offsetInContainerNode(), position.offsetInContainerNode()); 346 DCHECK_LT(start.offsetInContainerNode(), position.offsetInContainerNode());
342 start = Position(toText(text->previousSibling()), 347 start = Position(toText(text->previousSibling()),
343 start.offsetInContainerNode()); 348 start.offsetInContainerNode());
344 } 349 }
345 if (text == end.computeContainerNode() && text->previousSibling() && 350 if (text == end.computeContainerNode() && text->previousSibling() &&
346 text->previousSibling()->isTextNode()) { 351 text->previousSibling()->isTextNode()) {
347 DCHECK_LT(end.offsetInContainerNode(), position.offsetInContainerNode()); 352 DCHECK_LT(end.offsetInContainerNode(), position.offsetInContainerNode());
348 end = 353 end =
349 Position(toText(text->previousSibling()), end.offsetInContainerNode()); 354 Position(toText(text->previousSibling()), end.offsetInContainerNode());
350 } 355 }
351 if (text == m_endOfLastParagraph.computeContainerNode()) { 356 if (text == m_endOfLastParagraph.computeContainerNode()) {
352 if (m_endOfLastParagraph.offsetInContainerNode() < 357 if (m_endOfLastParagraph.offsetInContainerNode() <
353 position.offsetInContainerNode()) { 358 position.offsetInContainerNode()) {
354 // We can only fix endOfLastParagraph if the previous node was still text and hasn't been modified by script. 359 // We can only fix endOfLastParagraph if the previous node was still text and hasn't been modified by script.
355 if (text->previousSibling()->isTextNode() && 360 if (text->previousSibling()->isTextNode() &&
356 static_cast<unsigned>(m_endOfLastParagraph.offsetInContainerNode()) <= 361 static_cast<unsigned>(m_endOfLastParagraph.offsetInContainerNode()) <=
357 toText(text->previousSibling())->length()) 362 toText(text->previousSibling())->length())
358 m_endOfLastParagraph = 363 m_endOfLastParagraph =
359 Position(toText(text->previousSibling()), 364 Position(toText(text->previousSibling()),
360 m_endOfLastParagraph.offsetInContainerNode()); 365 m_endOfLastParagraph.offsetInContainerNode());
361 } else { 366 } else {
362 m_endOfLastParagraph = 367 m_endOfLastParagraph =
363 Position(text, m_endOfLastParagraph.offsetInContainerNode() - 1); 368 Position(text, m_endOfLastParagraph.offsetInContainerNode() - 1);
364 } 369 }
365 } 370 }
366 371
367 return createVisiblePositionDeprecated( 372 return createVisiblePosition(
368 Position(text, position.offsetInContainerNode() - 1)); 373 Position(text, position.offsetInContainerNode() - 1));
369 } 374 }
370 375
371 HTMLElement* ApplyBlockElementCommand::createBlockElement() const { 376 HTMLElement* ApplyBlockElementCommand::createBlockElement() const {
372 HTMLElement* element = createHTMLElement(document(), m_tagName); 377 HTMLElement* element = createHTMLElement(document(), m_tagName);
373 if (m_inlineStyle.length()) 378 if (m_inlineStyle.length())
374 element->setAttribute(styleAttr, m_inlineStyle); 379 element->setAttribute(styleAttr, m_inlineStyle);
375 return element; 380 return element;
376 } 381 }
377 382
378 DEFINE_TRACE(ApplyBlockElementCommand) { 383 DEFINE_TRACE(ApplyBlockElementCommand) {
379 visitor->trace(m_endOfLastParagraph); 384 visitor->trace(m_endOfLastParagraph);
380 CompositeEditCommand::trace(visitor); 385 CompositeEditCommand::trace(visitor);
381 } 386 }
382 387
383 } // namespace blink 388 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/editing/commands/FormatBlockCommand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698