OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple 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 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 } | 313 } |
314 | 314 |
315 void CompositeEditCommand::insertNodeAfter(PassRefPtrWillBeRawPtr<Node> insertCh
ild, PassRefPtrWillBeRawPtr<Node> refChild) | 315 void CompositeEditCommand::insertNodeAfter(PassRefPtrWillBeRawPtr<Node> insertCh
ild, PassRefPtrWillBeRawPtr<Node> refChild) |
316 { | 316 { |
317 ASSERT(insertChild); | 317 ASSERT(insertChild); |
318 ASSERT(refChild); | 318 ASSERT(refChild); |
319 ASSERT(!isHTMLBodyElement(*refChild)); | 319 ASSERT(!isHTMLBodyElement(*refChild)); |
320 ContainerNode* parent = refChild->parentNode(); | 320 ContainerNode* parent = refChild->parentNode(); |
321 ASSERT(parent); | 321 ASSERT(parent); |
322 ASSERT(!parent->isShadowRoot()); | 322 ASSERT(!parent->isShadowRoot()); |
323 if (parent->lastChild() == refChild) | 323 if (parent->lastChild() == refChild) { |
324 appendNode(insertChild, parent); | 324 appendNode(insertChild, parent); |
325 else { | 325 } else { |
326 ASSERT(refChild->nextSibling()); | 326 ASSERT(refChild->nextSibling()); |
327 insertNodeBefore(insertChild, refChild->nextSibling()); | 327 insertNodeBefore(insertChild, refChild->nextSibling()); |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<Node> insertChild
, const Position& editingPosition) | 331 void CompositeEditCommand::insertNodeAt(PassRefPtrWillBeRawPtr<Node> insertChild
, const Position& editingPosition) |
332 { | 332 { |
333 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); | 333 ASSERT(isEditablePosition(editingPosition, ContentIsEditable, DoNotUpdateSty
le)); |
334 // For editing positions like [table, 0], insert before the table, | 334 // For editing positions like [table, 0], insert before the table, |
335 // likewise for replaced elements, brs, etc. | 335 // likewise for replaced elements, brs, etc. |
336 Position p = editingPosition.parentAnchoredEquivalent(); | 336 Position p = editingPosition.parentAnchoredEquivalent(); |
337 Node* refChild = p.anchorNode(); | 337 Node* refChild = p.anchorNode(); |
338 int offset = p.offsetInContainerNode(); | 338 int offset = p.offsetInContainerNode(); |
339 | 339 |
340 if (canHaveChildrenForEditing(refChild)) { | 340 if (canHaveChildrenForEditing(refChild)) { |
341 Node* child = refChild->firstChild(); | 341 Node* child = refChild->firstChild(); |
342 for (int i = 0; child && i < offset; i++) | 342 for (int i = 0; child && i < offset; i++) |
343 child = child->nextSibling(); | 343 child = child->nextSibling(); |
344 if (child) | 344 if (child) |
345 insertNodeBefore(insertChild, child); | 345 insertNodeBefore(insertChild, child); |
346 else | 346 else |
347 appendNode(insertChild, toContainerNode(refChild)); | 347 appendNode(insertChild, toContainerNode(refChild)); |
348 } else if (caretMinOffset(refChild) >= offset) | 348 } else if (caretMinOffset(refChild) >= offset) { |
349 insertNodeBefore(insertChild, refChild); | 349 insertNodeBefore(insertChild, refChild); |
350 else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { | 350 } else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) { |
351 splitTextNode(toText(refChild), offset); | 351 splitTextNode(toText(refChild), offset); |
352 | 352 |
353 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild | 353 // Mutation events (bug 22634) from the text node insertion may have rem
oved the refChild |
354 if (!refChild->inDocument()) | 354 if (!refChild->inDocument()) |
355 return; | 355 return; |
356 insertNodeBefore(insertChild, refChild); | 356 insertNodeBefore(insertChild, refChild); |
357 } else | 357 } else { |
358 insertNodeAfter(insertChild, refChild); | 358 insertNodeAfter(insertChild, refChild); |
| 359 } |
359 } | 360 } |
360 | 361 |
361 void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRef
PtrWillBeRawPtr<ContainerNode> parent) | 362 void CompositeEditCommand::appendNode(PassRefPtrWillBeRawPtr<Node> node, PassRef
PtrWillBeRawPtr<ContainerNode> parent) |
362 { | 363 { |
363 // When cloneParagraphUnderNewElement() clones the fallback content | 364 // When cloneParagraphUnderNewElement() clones the fallback content |
364 // of an OBJECT element, the ASSERT below may fire since the return | 365 // of an OBJECT element, the ASSERT below may fire since the return |
365 // value of canHaveChildrenForEditing is not reliable until the layout | 366 // value of canHaveChildrenForEditing is not reliable until the layout |
366 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. | 367 // object of the OBJECT is created. Hence we ignore this check for OBJECTs. |
367 ASSERT(canHaveChildrenForEditing(parent.get()) | 368 ASSERT(canHaveChildrenForEditing(parent.get()) |
368 || (parent->isElementNode() && toElement(parent.get())->tagQName() == ob
jectTag)); | 369 || (parent->isElementNode() && toElement(parent.get())->tagQName() == ob
jectTag)); |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 | 668 |
668 int length = downstream - upstream; | 669 int length = downstream - upstream; |
669 if (!length) | 670 if (!length) |
670 return; | 671 return; |
671 | 672 |
672 VisiblePosition visibleUpstreamPos(Position(textNode, upstream)); | 673 VisiblePosition visibleUpstreamPos(Position(textNode, upstream)); |
673 VisiblePosition visibleDownstreamPos(Position(textNode, downstream)); | 674 VisiblePosition visibleDownstreamPos(Position(textNode, downstream)); |
674 | 675 |
675 String string = text.substring(upstream, length); | 676 String string = text.substring(upstream, length); |
676 String rebalancedString = stringWithRebalancedWhitespace(string, | 677 String rebalancedString = stringWithRebalancedWhitespace(string, |
677 // FIXME: Because of the problem mentioned at the top of this function, we m
ust also use nbsps at the start/end of the string because | 678 // FIXME: Because of the problem mentioned at the top of this function, we |
678 // this function doesn't get all surrounding whitespace, just the whitespace
in the current text node. | 679 // must also use nbsps at the start/end of the string because this function |
679 isStartOfParagraph(
visibleUpstreamPos) || upstream == 0, | 680 // doesn't get all surrounding whitespace, just the whitespace in the |
680 isEndOfParagraph(vi
sibleDownstreamPos) || (unsigned)downstream == text.length()); | 681 // current text node. |
| 682 isStartOfParagraph(visibleUpstreamPos) || upstream == 0, |
| 683 isEndOfParagraph(visibleDownstreamPos) || (unsigned)downstream == text.l
ength()); |
681 | 684 |
682 if (string != rebalancedString) | 685 if (string != rebalancedString) |
683 replaceTextInNodePreservingMarkers(textNode.release(), upstream, length,
rebalancedString); | 686 replaceTextInNodePreservingMarkers(textNode.release(), upstream, length,
rebalancedString); |
684 } | 687 } |
685 | 688 |
686 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& positio
n) | 689 void CompositeEditCommand::prepareWhitespaceAtPositionForSplit(Position& positio
n) |
687 { | 690 { |
688 Node* node = position.anchorNode(); | 691 Node* node = position.anchorNode(); |
689 if (!node || !node->isTextNode()) | 692 if (!node || !node->isTextNode()) |
690 return; | 693 return; |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
762 return; | 765 return; |
763 | 766 |
764 unsigned removed = 0; | 767 unsigned removed = 0; |
765 InlineTextBox* prevBox = nullptr; | 768 InlineTextBox* prevBox = nullptr; |
766 String str; | 769 String str; |
767 | 770 |
768 // This loop structure works to process all gaps preceding a box, | 771 // This loop structure works to process all gaps preceding a box, |
769 // and also will look at the gap after the last box. | 772 // and also will look at the gap after the last box. |
770 while (prevBox || box) { | 773 while (prevBox || box) { |
771 unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0; | 774 unsigned gapStart = prevBox ? prevBox->start() + prevBox->len() : 0; |
772 if (end < gapStart) | 775 if (end < gapStart) { |
773 // No more chance for any intersections | 776 // No more chance for any intersections |
774 break; | 777 break; |
| 778 } |
775 | 779 |
776 unsigned gapEnd = box ? box->start() : length; | 780 unsigned gapEnd = box ? box->start() : length; |
777 bool indicesIntersect = start <= gapEnd && end >= gapStart; | 781 bool indicesIntersect = start <= gapEnd && end >= gapStart; |
778 int gapLen = gapEnd - gapStart; | 782 int gapLen = gapEnd - gapStart; |
779 if (indicesIntersect && gapLen > 0) { | 783 if (indicesIntersect && gapLen > 0) { |
780 gapStart = std::max(gapStart, start); | 784 gapStart = std::max(gapStart, start); |
781 if (str.isNull()) | 785 if (str.isNull()) |
782 str = textNode->data().substring(start, end - start); | 786 str = textNode->data().substring(start, end - start); |
783 // remove text in the gap | 787 // remove text in the gap |
784 str.remove(gapStart - start - removed, gapLen); | 788 str.remove(gapStart - start - removed, gapLen); |
785 removed += gapLen; | 789 removed += gapLen; |
786 } | 790 } |
787 | 791 |
788 prevBox = box; | 792 prevBox = box; |
789 if (box) { | 793 if (box) { |
790 if (++sortedTextBoxesPosition < sortedTextBoxes.size()) | 794 if (++sortedTextBoxesPosition < sortedTextBoxes.size()) |
791 box = sortedTextBoxes[sortedTextBoxesPosition]; | 795 box = sortedTextBoxes[sortedTextBoxesPosition]; |
792 else | 796 else |
793 box = 0; | 797 box = 0; |
794 } | 798 } |
795 } | 799 } |
796 | 800 |
797 if (!str.isNull()) { | 801 if (!str.isNull()) { |
798 // Replace the text between start and end with our pruned version. | 802 // Replace the text between start and end with our pruned version. |
799 if (!str.isEmpty()) | 803 if (!str.isEmpty()) { |
800 replaceTextInNode(textNode, start, end - start, str); | 804 replaceTextInNode(textNode, start, end - start, str); |
801 else { | 805 } else { |
802 // Assert that we are not going to delete all of the text in the nod
e. | 806 // Assert that we are not going to delete all of the text in the nod
e. |
803 // If we were, that should have been done above with the call to | 807 // If we were, that should have been done above with the call to |
804 // removeNode and return. | 808 // removeNode and return. |
805 ASSERT(start > 0 || end - start < textNode->length()); | 809 ASSERT(start > 0 || end - start < textNode->length()); |
806 deleteTextFromNode(textNode, start, end - start); | 810 deleteTextFromNode(textNode, start, end - start); |
807 } | 811 } |
808 } | 812 } |
809 } | 813 } |
810 | 814 |
811 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) | 815 void CompositeEditCommand::deleteInsignificantText(const Position& start, const
Position& end) |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1096 // div or an li), remove it during the move (the list removal code | 1100 // div or an li), remove it during the move (the list removal code |
1097 // expects this behavior). | 1101 // expects this behavior). |
1098 } else if (isBlock(node)) { | 1102 } else if (isBlock(node)) { |
1099 // If caret position after deletion and destination position coincid
es, | 1103 // If caret position after deletion and destination position coincid
es, |
1100 // node should not be removed. | 1104 // node should not be removed. |
1101 if (!rendersInDifferentPosition(position, destination.deepEquivalent
())) { | 1105 if (!rendersInDifferentPosition(position, destination.deepEquivalent
())) { |
1102 prune(node, destinationNode); | 1106 prune(node, destinationNode); |
1103 return; | 1107 return; |
1104 } | 1108 } |
1105 removeNodeAndPruneAncestors(node, destinationNode); | 1109 removeNodeAndPruneAncestors(node, destinationNode); |
1106 } | 1110 } else if (lineBreakExistsAtPosition(position)) { |
1107 else if (lineBreakExistsAtPosition(position)) { | |
1108 // There is a preserved '\n' at caretAfterDelete. | 1111 // There is a preserved '\n' at caretAfterDelete. |
1109 // We can safely assume this is a text node. | 1112 // We can safely assume this is a text node. |
1110 Text* textNode = toText(node); | 1113 Text* textNode = toText(node); |
1111 if (textNode->length() == 1) | 1114 if (textNode->length() == 1) |
1112 removeNodeAndPruneAncestors(node, destinationNode); | 1115 removeNodeAndPruneAncestors(node, destinationNode); |
1113 else | 1116 else |
1114 deleteTextFromNode(textNode, position.computeOffsetInContainerNo
de(), 1); | 1117 deleteTextFromNode(textNode, position.computeOffsetInContainerNo
de(), 1); |
1115 } | 1118 } |
1116 } | 1119 } |
1117 } | 1120 } |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1499 } | 1502 } |
1500 | 1503 |
1501 DEFINE_TRACE(CompositeEditCommand) | 1504 DEFINE_TRACE(CompositeEditCommand) |
1502 { | 1505 { |
1503 visitor->trace(m_commands); | 1506 visitor->trace(m_commands); |
1504 visitor->trace(m_composition); | 1507 visitor->trace(m_composition); |
1505 EditCommand::trace(visitor); | 1508 EditCommand::trace(visitor); |
1506 } | 1509 } |
1507 | 1510 |
1508 } // namespace blink | 1511 } // namespace blink |
OLD | NEW |