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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 bool InsertParagraphSeparatorCommand::preservesTypingStyle() const | 71 bool InsertParagraphSeparatorCommand::preservesTypingStyle() const |
72 { | 72 { |
73 return true; | 73 return true; |
74 } | 74 } |
75 | 75 |
76 void InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion(const Positi
on &pos) | 76 void InsertParagraphSeparatorCommand::calculateStyleBeforeInsertion(const Positi
on &pos) |
77 { | 77 { |
78 // It is only important to set a style to apply later if we're at the bounda
ries of | 78 // It is only important to set a style to apply later if we're at the bounda
ries of |
79 // a paragraph. Otherwise, content that is moved as part of the work of the
command | 79 // a paragraph. Otherwise, content that is moved as part of the work of the
command |
80 // will lend their styles to the new paragraph without any extra work needed
. | 80 // will lend their styles to the new paragraph without any extra work needed
. |
81 VisiblePosition visiblePos(pos, VP_DEFAULT_AFFINITY); | 81 VisiblePosition visiblePos = createVisiblePosition(pos, VP_DEFAULT_AFFINITY)
; |
82 if (!isStartOfParagraph(visiblePos) && !isEndOfParagraph(visiblePos)) | 82 if (!isStartOfParagraph(visiblePos) && !isEndOfParagraph(visiblePos)) |
83 return; | 83 return; |
84 | 84 |
85 ASSERT(pos.isNotNull()); | 85 ASSERT(pos.isNotNull()); |
86 m_style = EditingStyle::create(pos); | 86 m_style = EditingStyle::create(pos); |
87 m_style->mergeTypingStyle(pos.document()); | 87 m_style->mergeTypingStyle(pos.document()); |
88 } | 88 } |
89 | 89 |
90 void InsertParagraphSeparatorCommand::applyStyleAfterInsertion(Element* original
EnclosingBlock) | 90 void InsertParagraphSeparatorCommand::applyStyleAfterInsertion(Element* original
EnclosingBlock) |
91 { | 91 { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 calculateStyleBeforeInsertion(insertionPosition); | 163 calculateStyleBeforeInsertion(insertionPosition); |
164 deleteSelection(false, true); | 164 deleteSelection(false, true); |
165 insertionPosition = endingSelection().start(); | 165 insertionPosition = endingSelection().start(); |
166 affinity = endingSelection().affinity(); | 166 affinity = endingSelection().affinity(); |
167 } | 167 } |
168 | 168 |
169 // FIXME: The parentAnchoredEquivalent conversion needs to be moved into enc
losingBlock. | 169 // FIXME: The parentAnchoredEquivalent conversion needs to be moved into enc
losingBlock. |
170 RefPtrWillBeRawPtr<Element> startBlock = enclosingBlock(insertionPosition.pa
rentAnchoredEquivalent().computeContainerNode()); | 170 RefPtrWillBeRawPtr<Element> startBlock = enclosingBlock(insertionPosition.pa
rentAnchoredEquivalent().computeContainerNode()); |
171 Node* listChildNode = enclosingListChild(insertionPosition.parentAnchoredEqu
ivalent().computeContainerNode()); | 171 Node* listChildNode = enclosingListChild(insertionPosition.parentAnchoredEqu
ivalent().computeContainerNode()); |
172 RefPtrWillBeRawPtr<HTMLElement> listChild = listChildNode && listChildNode->
isHTMLElement() ? toHTMLElement(listChildNode) : 0; | 172 RefPtrWillBeRawPtr<HTMLElement> listChild = listChildNode && listChildNode->
isHTMLElement() ? toHTMLElement(listChildNode) : 0; |
173 Position canonicalPos = VisiblePosition(insertionPosition).deepEquivalent(); | 173 Position canonicalPos = createVisiblePosition(insertionPosition).deepEquival
ent(); |
174 if (!startBlock | 174 if (!startBlock |
175 || !startBlock->nonShadowBoundaryParentNode() | 175 || !startBlock->nonShadowBoundaryParentNode() |
176 || isTableCell(startBlock.get()) | 176 || isTableCell(startBlock.get()) |
177 || isHTMLFormElement(*startBlock) | 177 || isHTMLFormElement(*startBlock) |
178 // FIXME: If the node is hidden, we don't have a canonical position so w
e will do the wrong thing for tables and <hr>. https://bugs.webkit.org/show_bug.
cgi?id=40342 | 178 // FIXME: If the node is hidden, we don't have a canonical position so w
e will do the wrong thing for tables and <hr>. https://bugs.webkit.org/show_bug.
cgi?id=40342 |
179 || (!canonicalPos.isNull() && isRenderedTableElement(canonicalPos.anchor
Node())) | 179 || (!canonicalPos.isNull() && isRenderedTableElement(canonicalPos.anchor
Node())) |
180 || (!canonicalPos.isNull() && isHTMLHRElement(*canonicalPos.anchorNode()
))) { | 180 || (!canonicalPos.isNull() && isHTMLHRElement(*canonicalPos.anchorNode()
))) { |
181 applyCommandToComposite(InsertLineBreakCommand::create(document())); | 181 applyCommandToComposite(InsertLineBreakCommand::create(document())); |
182 return; | 182 return; |
183 } | 183 } |
184 | 184 |
185 // Use the leftmost candidate. | 185 // Use the leftmost candidate. |
186 insertionPosition = mostBackwardCaretPosition(insertionPosition); | 186 insertionPosition = mostBackwardCaretPosition(insertionPosition); |
187 if (!isVisuallyEquivalentCandidate(insertionPosition)) | 187 if (!isVisuallyEquivalentCandidate(insertionPosition)) |
188 insertionPosition = mostForwardCaretPosition(insertionPosition); | 188 insertionPosition = mostForwardCaretPosition(insertionPosition); |
189 | 189 |
190 // Adjust the insertion position after the delete | 190 // Adjust the insertion position after the delete |
191 insertionPosition = positionAvoidingSpecialElementBoundary(insertionPosition
); | 191 insertionPosition = positionAvoidingSpecialElementBoundary(insertionPosition
); |
192 VisiblePosition visiblePos(insertionPosition, affinity); | 192 VisiblePosition visiblePos = createVisiblePosition(insertionPosition, affini
ty); |
193 calculateStyleBeforeInsertion(insertionPosition); | 193 calculateStyleBeforeInsertion(insertionPosition); |
194 | 194 |
195 //--------------------------------------------------------------------- | 195 //--------------------------------------------------------------------- |
196 // Handle special case of typing return on an empty list item | 196 // Handle special case of typing return on an empty list item |
197 if (breakOutOfEmptyListItem()) | 197 if (breakOutOfEmptyListItem()) |
198 return; | 198 return; |
199 | 199 |
200 //--------------------------------------------------------------------- | 200 //--------------------------------------------------------------------- |
201 // Prepare for more general cases. | 201 // Prepare for more general cases. |
202 | 202 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 } | 326 } |
327 } | 327 } |
328 | 328 |
329 // Move downstream. Typing style code will take care of carrying along the | 329 // Move downstream. Typing style code will take care of carrying along the |
330 // style of the upstream position. | 330 // style of the upstream position. |
331 insertionPosition = mostForwardCaretPosition(insertionPosition); | 331 insertionPosition = mostForwardCaretPosition(insertionPosition); |
332 | 332 |
333 // At this point, the insertionPosition's node could be a container, and we
want to make sure we include | 333 // At this point, the insertionPosition's node could be a container, and we
want to make sure we include |
334 // all of the correct nodes when building the ancestor list. So this needs
to be the deepest representation of the position | 334 // all of the correct nodes when building the ancestor list. So this needs
to be the deepest representation of the position |
335 // before we walk the DOM tree. | 335 // before we walk the DOM tree. |
336 insertionPosition = positionOutsideTabSpan(VisiblePosition(insertionPosition
).deepEquivalent()); | 336 insertionPosition = positionOutsideTabSpan(createVisiblePosition(insertionPo
sition).deepEquivalent()); |
337 | 337 |
338 // If the returned position lies either at the end or at the start of an ele
ment that is ignored by editing | 338 // If the returned position lies either at the end or at the start of an ele
ment that is ignored by editing |
339 // we should move to its upstream or downstream position. | 339 // we should move to its upstream or downstream position. |
340 if (editingIgnoresContent(insertionPosition.anchorNode())) { | 340 if (editingIgnoresContent(insertionPosition.anchorNode())) { |
341 if (insertionPosition.atLastEditingPositionForNode()) | 341 if (insertionPosition.atLastEditingPositionForNode()) |
342 insertionPosition = mostForwardCaretPosition(insertionPosition); | 342 insertionPosition = mostForwardCaretPosition(insertionPosition); |
343 else if (insertionPosition.atFirstEditingPositionForNode()) | 343 else if (insertionPosition.atFirstEditingPositionForNode()) |
344 insertionPosition = mostBackwardCaretPosition(insertionPosition); | 344 insertionPosition = mostBackwardCaretPosition(insertionPosition); |
345 } | 345 } |
346 | 346 |
(...skipping 11 matching lines...) Expand all Loading... |
358 // Split at pos if in the middle of a text node. | 358 // Split at pos if in the middle of a text node. |
359 Position positionAfterSplit; | 359 Position positionAfterSplit; |
360 if (insertionPosition.isOffsetInAnchor() && insertionPosition.computeContain
erNode()->isTextNode()) { | 360 if (insertionPosition.isOffsetInAnchor() && insertionPosition.computeContain
erNode()->isTextNode()) { |
361 RefPtrWillBeRawPtr<Text> textNode = toText(insertionPosition.computeCont
ainerNode()); | 361 RefPtrWillBeRawPtr<Text> textNode = toText(insertionPosition.computeCont
ainerNode()); |
362 int textOffset = insertionPosition.offsetInContainerNode(); | 362 int textOffset = insertionPosition.offsetInContainerNode(); |
363 bool atEnd = static_cast<unsigned>(textOffset) >= textNode->length(); | 363 bool atEnd = static_cast<unsigned>(textOffset) >= textNode->length(); |
364 if (textOffset > 0 && !atEnd) { | 364 if (textOffset > 0 && !atEnd) { |
365 splitTextNode(textNode, textOffset); | 365 splitTextNode(textNode, textOffset); |
366 positionAfterSplit = firstPositionInNode(textNode.get()); | 366 positionAfterSplit = firstPositionInNode(textNode.get()); |
367 insertionPosition = Position(textNode->previousSibling(), textOffset
); | 367 insertionPosition = Position(textNode->previousSibling(), textOffset
); |
368 visiblePos = VisiblePosition(insertionPosition); | 368 visiblePos = createVisiblePosition(insertionPosition); |
369 } | 369 } |
370 } | 370 } |
371 | 371 |
372 // If we got detached due to mutation events, just bail out. | 372 // If we got detached due to mutation events, just bail out. |
373 if (!startBlock->parentNode()) | 373 if (!startBlock->parentNode()) |
374 return; | 374 return; |
375 | 375 |
376 // Put the added block in the tree. | 376 // Put the added block in the tree. |
377 if (nestNewBlock) { | 377 if (nestNewBlock) { |
378 appendNode(blockToInsert.get(), startBlock); | 378 appendNode(blockToInsert.get(), startBlock); |
379 } else if (listChild && listChild != startBlock) { | 379 } else if (listChild && listChild != startBlock) { |
380 RefPtrWillBeRawPtr<Element> listChildToInsert = listChild->cloneElementW
ithoutChildren(); | 380 RefPtrWillBeRawPtr<Element> listChildToInsert = listChild->cloneElementW
ithoutChildren(); |
381 appendNode(blockToInsert.get(), listChildToInsert.get()); | 381 appendNode(blockToInsert.get(), listChildToInsert.get()); |
382 insertNodeAfter(listChildToInsert.get(), listChild); | 382 insertNodeAfter(listChildToInsert.get(), listChild); |
383 } else { | 383 } else { |
384 insertNodeAfter(blockToInsert.get(), startBlock); | 384 insertNodeAfter(blockToInsert.get(), startBlock); |
385 } | 385 } |
386 | 386 |
387 document().updateLayoutIgnorePendingStylesheets(); | 387 document().updateLayoutIgnorePendingStylesheets(); |
388 | 388 |
389 // If the paragraph separator was inserted at the end of a paragraph, an emp
ty line must be | 389 // If the paragraph separator was inserted at the end of a paragraph, an emp
ty line must be |
390 // created. All of the nodes, starting at visiblePos, are about to be added
to the new paragraph | 390 // created. All of the nodes, starting at visiblePos, are about to be added
to the new paragraph |
391 // element. If the first node to be inserted won't be one that will hold an
empty line open, add a br. | 391 // element. If the first node to be inserted won't be one that will hold an
empty line open, add a br. |
392 if (isEndOfParagraph(visiblePos) && !lineBreakExistsAtVisiblePosition(visibl
ePos)) | 392 if (isEndOfParagraph(visiblePos) && !lineBreakExistsAtVisiblePosition(visibl
ePos)) |
393 appendNode(createBreakElement(document()).get(), blockToInsert.get()); | 393 appendNode(createBreakElement(document()).get(), blockToInsert.get()); |
394 | 394 |
395 // Move the start node and the siblings of the start node. | 395 // Move the start node and the siblings of the start node. |
396 if (VisiblePosition(insertionPosition).deepEquivalent() != VisiblePosition(p
ositionBeforeNode(blockToInsert.get())).deepEquivalent()) { | 396 if (createVisiblePosition(insertionPosition).deepEquivalent() != createVisib
lePosition(positionBeforeNode(blockToInsert.get())).deepEquivalent()) { |
397 Node* n; | 397 Node* n; |
398 if (insertionPosition.computeContainerNode() == startBlock) { | 398 if (insertionPosition.computeContainerNode() == startBlock) { |
399 n = insertionPosition.computeNodeAfterPosition(); | 399 n = insertionPosition.computeNodeAfterPosition(); |
400 } else { | 400 } else { |
401 Node* splitTo = insertionPosition.computeContainerNode(); | 401 Node* splitTo = insertionPosition.computeContainerNode(); |
402 if (splitTo->isTextNode() && insertionPosition.offsetInContainerNode
() >= caretMaxOffset(splitTo)) | 402 if (splitTo->isTextNode() && insertionPosition.offsetInContainerNode
() >= caretMaxOffset(splitTo)) |
403 splitTo = NodeTraversal::next(*splitTo, startBlock.get()); | 403 splitTo = NodeTraversal::next(*splitTo, startBlock.get()); |
404 ASSERT(splitTo); | 404 ASSERT(splitTo); |
405 splitTreeToNode(splitTo, startBlock.get()); | 405 splitTreeToNode(splitTo, startBlock.get()); |
406 | 406 |
407 for (n = startBlock->firstChild(); n; n = n->nextSibling()) { | 407 for (n = startBlock->firstChild(); n; n = n->nextSibling()) { |
408 VisiblePosition beforeNodePosition(positionBeforeNode(n)); | 408 VisiblePosition beforeNodePosition = createVisiblePosition(posit
ionBeforeNode(n)); |
409 if (!beforeNodePosition.isNull() && comparePositions(VisiblePosi
tion(insertionPosition), beforeNodePosition) <= 0) | 409 if (!beforeNodePosition.isNull() && comparePositions(createVisib
lePosition(insertionPosition), beforeNodePosition) <= 0) |
410 break; | 410 break; |
411 } | 411 } |
412 } | 412 } |
413 | 413 |
414 moveRemainingSiblingsToNewParent(n, blockToInsert.get(), blockToInsert); | 414 moveRemainingSiblingsToNewParent(n, blockToInsert.get(), blockToInsert); |
415 } | 415 } |
416 | 416 |
417 // Handle whitespace that occurs after the split | 417 // Handle whitespace that occurs after the split |
418 if (positionAfterSplit.isNotNull()) { | 418 if (positionAfterSplit.isNotNull()) { |
419 document().updateLayoutIgnorePendingStylesheets(); | 419 document().updateLayoutIgnorePendingStylesheets(); |
(...skipping 13 matching lines...) Expand all Loading... |
433 } | 433 } |
434 | 434 |
435 DEFINE_TRACE(InsertParagraphSeparatorCommand) | 435 DEFINE_TRACE(InsertParagraphSeparatorCommand) |
436 { | 436 { |
437 visitor->trace(m_style); | 437 visitor->trace(m_style); |
438 CompositeEditCommand::trace(visitor); | 438 CompositeEditCommand::trace(visitor); |
439 } | 439 } |
440 | 440 |
441 | 441 |
442 } // namespace blink | 442 } // namespace blink |
OLD | NEW |