| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2005, 2006, 2008 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2009, 2010, 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2009, 2010, 2011 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 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 | 399 |
| 400 inline void | 400 inline void |
| 401 ReplaceSelectionCommand::InsertedNodes::willRemoveNodePreservingChildren( | 401 ReplaceSelectionCommand::InsertedNodes::willRemoveNodePreservingChildren( |
| 402 Node& node) { | 402 Node& node) { |
| 403 if (m_firstNodeInserted.get() == node) | 403 if (m_firstNodeInserted.get() == node) |
| 404 m_firstNodeInserted = NodeTraversal::next(node); | 404 m_firstNodeInserted = NodeTraversal::next(node); |
| 405 if (m_lastNodeInserted.get() == node) | 405 if (m_lastNodeInserted.get() == node) |
| 406 m_lastNodeInserted = node.lastChild() | 406 m_lastNodeInserted = node.lastChild() |
| 407 ? node.lastChild() | 407 ? node.lastChild() |
| 408 : NodeTraversal::nextSkippingChildren(node); | 408 : NodeTraversal::nextSkippingChildren(node); |
| 409 if (m_refNode.get() == node) |
| 410 m_refNode = NodeTraversal::next(node); |
| 409 } | 411 } |
| 410 | 412 |
| 411 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNode(Node& node) { | 413 inline void ReplaceSelectionCommand::InsertedNodes::willRemoveNode(Node& node) { |
| 412 if (m_firstNodeInserted.get() == node && m_lastNodeInserted.get() == node) { | 414 if (m_firstNodeInserted.get() == node && m_lastNodeInserted.get() == node) { |
| 413 m_firstNodeInserted = nullptr; | 415 m_firstNodeInserted = nullptr; |
| 414 m_lastNodeInserted = nullptr; | 416 m_lastNodeInserted = nullptr; |
| 415 } else if (m_firstNodeInserted.get() == node) { | 417 } else if (m_firstNodeInserted.get() == node) { |
| 416 m_firstNodeInserted = | 418 m_firstNodeInserted = |
| 417 NodeTraversal::nextSkippingChildren(*m_firstNodeInserted); | 419 NodeTraversal::nextSkippingChildren(*m_firstNodeInserted); |
| 418 } else if (m_lastNodeInserted.get() == node) { | 420 } else if (m_lastNodeInserted.get() == node) { |
| 419 m_lastNodeInserted = | 421 m_lastNodeInserted = |
| 420 NodeTraversal::previousSkippingChildren(*m_lastNodeInserted); | 422 NodeTraversal::previousSkippingChildren(*m_lastNodeInserted); |
| 421 } | 423 } |
| 424 if (node.contains(m_refNode)) |
| 425 m_refNode = NodeTraversal::nextSkippingChildren(node); |
| 422 } | 426 } |
| 423 | 427 |
| 424 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode( | 428 inline void ReplaceSelectionCommand::InsertedNodes::didReplaceNode( |
| 425 Node& node, | 429 Node& node, |
| 426 Node& newNode) { | 430 Node& newNode) { |
| 427 if (m_firstNodeInserted.get() == node) | 431 if (m_firstNodeInserted.get() == node) |
| 428 m_firstNodeInserted = &newNode; | 432 m_firstNodeInserted = &newNode; |
| 429 if (m_lastNodeInserted.get() == node) | 433 if (m_lastNodeInserted.get() == node) |
| 430 m_lastNodeInserted = &newNode; | 434 m_lastNodeInserted = &newNode; |
| 435 if (m_refNode.get() == node) |
| 436 m_refNode = &newNode; |
| 431 } | 437 } |
| 432 | 438 |
| 433 ReplaceSelectionCommand::ReplaceSelectionCommand( | 439 ReplaceSelectionCommand::ReplaceSelectionCommand( |
| 434 Document& document, | 440 Document& document, |
| 435 DocumentFragment* fragment, | 441 DocumentFragment* fragment, |
| 436 CommandOptions options, | 442 CommandOptions options, |
| 437 InputEvent::InputType inputType) | 443 InputEvent::InputType inputType) |
| 438 : CompositeEditCommand(document), | 444 : CompositeEditCommand(document), |
| 439 m_selectReplacement(options & SelectReplacement), | 445 m_selectReplacement(options & SelectReplacement), |
| 440 m_smartReplace(options & SmartReplace), | 446 m_smartReplace(options & SmartReplace), |
| (...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1405 // position being pasted into. | 1411 // position being pasted into. |
| 1406 // 4) Do one of the following: | 1412 // 4) Do one of the following: |
| 1407 // a) expand the last br if the fragment ends with one and it collapsed, | 1413 // a) expand the last br if the fragment ends with one and it collapsed, |
| 1408 // b) merge the last paragraph of the incoming fragment with the paragraph | 1414 // b) merge the last paragraph of the incoming fragment with the paragraph |
| 1409 // that contained the end of the selection that was pasted into, or | 1415 // that contained the end of the selection that was pasted into, or |
| 1410 // c) handle an interchange newline at the end of the incoming fragment. | 1416 // c) handle an interchange newline at the end of the incoming fragment. |
| 1411 // 5) Add spaces for smart replace. | 1417 // 5) Add spaces for smart replace. |
| 1412 // 6) Select the replacement if requested, and match style if requested. | 1418 // 6) Select the replacement if requested, and match style if requested. |
| 1413 | 1419 |
| 1414 InsertedNodes insertedNodes; | 1420 InsertedNodes insertedNodes; |
| 1415 Node* refNode = fragment.firstChild(); | 1421 insertedNodes.setRefNode(fragment.firstChild()); |
| 1416 DCHECK(refNode); | 1422 DCHECK(insertedNodes.refNode()); |
| 1417 Node* node = refNode->nextSibling(); | 1423 Node* node = insertedNodes.refNode()->nextSibling(); |
| 1418 | 1424 |
| 1419 fragment.removeNode(refNode); | 1425 fragment.removeNode(insertedNodes.refNode()); |
| 1420 | 1426 |
| 1421 Element* blockStart = enclosingBlock(insertionPos.anchorNode()); | 1427 Element* blockStart = enclosingBlock(insertionPos.anchorNode()); |
| 1422 if ((isHTMLListElement(refNode) || | 1428 if ((isHTMLListElement(insertedNodes.refNode()) || |
| 1423 (isLegacyAppleHTMLSpanElement(refNode) && | 1429 (isLegacyAppleHTMLSpanElement(insertedNodes.refNode()) && |
| 1424 isHTMLListElement(refNode->firstChild()))) && | 1430 isHTMLListElement(insertedNodes.refNode()->firstChild()))) && |
| 1425 blockStart && blockStart->layoutObject()->isListItem() && | 1431 blockStart && blockStart->layoutObject()->isListItem() && |
| 1426 hasEditableStyle(*blockStart->parentNode())) { | 1432 hasEditableStyle(*blockStart->parentNode())) { |
| 1427 refNode = insertAsListItems(toHTMLElement(refNode), blockStart, | 1433 insertedNodes.setRefNode( |
| 1428 insertionPos, insertedNodes, editingState); | 1434 insertAsListItems(toHTMLElement(insertedNodes.refNode()), blockStart, |
| 1435 insertionPos, insertedNodes, editingState)); |
| 1429 if (editingState->isAborted()) | 1436 if (editingState->isAborted()) |
| 1430 return; | 1437 return; |
| 1431 } else { | 1438 } else { |
| 1432 insertNodeAt(refNode, insertionPos, editingState); | 1439 insertNodeAt(insertedNodes.refNode(), insertionPos, editingState); |
| 1433 if (editingState->isAborted()) | 1440 if (editingState->isAborted()) |
| 1434 return; | 1441 return; |
| 1435 insertedNodes.respondToNodeInsertion(*refNode); | 1442 insertedNodes.respondToNodeInsertion(*insertedNodes.refNode()); |
| 1436 } | 1443 } |
| 1437 | 1444 |
| 1438 // Mutation events (bug 22634) may have already removed the inserted content | 1445 // Mutation events (bug 22634) may have already removed the inserted content |
| 1439 if (!refNode->isConnected()) | 1446 if (!insertedNodes.refNode()->isConnected()) |
| 1440 return; | 1447 return; |
| 1441 | 1448 |
| 1442 bool plainTextFragment = isPlainTextMarkup(refNode); | 1449 bool plainTextFragment = isPlainTextMarkup(insertedNodes.refNode()); |
| 1443 | 1450 |
| 1444 while (node) { | 1451 while (node) { |
| 1445 Node* next = node->nextSibling(); | 1452 Node* next = node->nextSibling(); |
| 1446 fragment.removeNode(node); | 1453 fragment.removeNode(node); |
| 1447 insertNodeAfter(node, refNode, editingState); | 1454 insertNodeAfter(node, insertedNodes.refNode(), editingState); |
| 1448 if (editingState->isAborted()) | 1455 if (editingState->isAborted()) |
| 1449 return; | 1456 return; |
| 1450 insertedNodes.respondToNodeInsertion(*node); | 1457 insertedNodes.respondToNodeInsertion(*node); |
| 1451 | 1458 |
| 1452 // Mutation events (bug 22634) may have already removed the inserted content | 1459 // Mutation events (bug 22634) may have already removed the inserted content |
| 1453 if (!node->isConnected()) | 1460 if (!node->isConnected()) |
| 1454 return; | 1461 return; |
| 1455 | 1462 |
| 1456 refNode = node; | 1463 insertedNodes.setRefNode(node); |
| 1457 if (node && plainTextFragment) | 1464 if (node && plainTextFragment) |
| 1458 plainTextFragment = isPlainTextMarkup(node); | 1465 plainTextFragment = isPlainTextMarkup(node); |
| 1459 node = next; | 1466 node = next; |
| 1460 } | 1467 } |
| 1461 | 1468 |
| 1462 if (isRichlyEditablePosition(insertionPos)) | 1469 if (isRichlyEditablePosition(insertionPos)) |
| 1463 removeUnrenderedTextNodesAtEnds(insertedNodes); | 1470 removeUnrenderedTextNodesAtEnds(insertedNodes); |
| 1464 | 1471 |
| 1465 if (!handledStyleSpans) { | 1472 if (!handledStyleSpans) { |
| 1466 handleStyleSpans(insertedNodes, editingState); | 1473 handleStyleSpans(insertedNodes, editingState); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 if (editingState->isAborted()) | 1523 if (editingState->isAborted()) |
| 1517 return; | 1524 return; |
| 1518 } | 1525 } |
| 1519 } | 1526 } |
| 1520 | 1527 |
| 1521 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes, | 1528 makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes, |
| 1522 editingState); | 1529 editingState); |
| 1523 if (editingState->isAborted()) | 1530 if (editingState->isAborted()) |
| 1524 return; | 1531 return; |
| 1525 | 1532 |
| 1526 removeRedundantStylesAndKeepStyleSpanInline(insertedNodes, editingState); | 1533 { |
| 1527 if (editingState->isAborted()) | 1534 // TODO(dominicc): refNode may not be connected, for example in |
| 1528 return; | 1535 // LayoutTests/editing/inserting/insert-table-in-paragraph-crash.html . |
| 1536 // Refactor this so there's a relationship between the conditions |
| 1537 // where refNode is dereferenced and refNode is connected. |
| 1538 bool refNodeWasConnected = insertedNodes.refNode()->isConnected(); |
| 1539 removeRedundantStylesAndKeepStyleSpanInline(insertedNodes, editingState); |
| 1540 if (editingState->isAborted()) |
| 1541 return; |
| 1542 DCHECK_EQ(insertedNodes.refNode()->isConnected(), refNodeWasConnected) |
| 1543 << insertedNodes.refNode(); |
| 1544 } |
| 1529 | 1545 |
| 1530 if (m_sanitizeFragment && insertedNodes.firstNodeInserted()) { | 1546 if (m_sanitizeFragment && insertedNodes.firstNodeInserted()) { |
| 1531 applyCommandToComposite(SimplifyMarkupCommand::create( | 1547 applyCommandToComposite(SimplifyMarkupCommand::create( |
| 1532 document(), insertedNodes.firstNodeInserted(), | 1548 document(), insertedNodes.firstNodeInserted(), |
| 1533 insertedNodes.pastLastLeaf()), | 1549 insertedNodes.pastLastLeaf()), |
| 1534 editingState); | 1550 editingState); |
| 1535 if (editingState->isAborted()) | 1551 if (editingState->isAborted()) |
| 1536 return; | 1552 return; |
| 1537 } | 1553 } |
| 1538 | 1554 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1562 | 1578 |
| 1563 // We need to handle the case where we need to merge the end | 1579 // We need to handle the case where we need to merge the end |
| 1564 // but our destination node is inside an inline that is the last in the | 1580 // but our destination node is inside an inline that is the last in the |
| 1565 // block. | 1581 // block. |
| 1566 // We insert a placeholder before the newly inserted content to avoid being | 1582 // We insert a placeholder before the newly inserted content to avoid being |
| 1567 // merged into the inline. | 1583 // merged into the inline. |
| 1568 Node* destinationNode = destination.deepEquivalent().anchorNode(); | 1584 Node* destinationNode = destination.deepEquivalent().anchorNode(); |
| 1569 if (m_shouldMergeEnd && | 1585 if (m_shouldMergeEnd && |
| 1570 destinationNode != enclosingInline(destinationNode) && | 1586 destinationNode != enclosingInline(destinationNode) && |
| 1571 enclosingInline(destinationNode)->nextSibling()) { | 1587 enclosingInline(destinationNode)->nextSibling()) { |
| 1572 insertNodeBefore(HTMLBRElement::create(document()), refNode, | 1588 insertNodeBefore(HTMLBRElement::create(document()), |
| 1573 editingState); | 1589 insertedNodes.refNode(), editingState); |
| 1574 if (editingState->isAborted()) | 1590 if (editingState->isAborted()) |
| 1575 return; | 1591 return; |
| 1576 } | 1592 } |
| 1577 | 1593 |
| 1578 // Merging the the first paragraph of inserted content with the content that | 1594 // Merging the the first paragraph of inserted content with the content that |
| 1579 // came before the selection that was pasted into would also move content | 1595 // came before the selection that was pasted into would also move content |
| 1580 // after the selection that was pasted into if: only one paragraph was being | 1596 // after the selection that was pasted into if: only one paragraph was being |
| 1581 // pasted, and it was not wrapped in a block, the selection that was pasted | 1597 // pasted, and it was not wrapped in a block, the selection that was pasted |
| 1582 // into ended at the end of a block and the next paragraph didn't start at | 1598 // into ended at the end of a block and the next paragraph didn't start at |
| 1583 // the start of a block. | 1599 // the start of a block. |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2114 visitor->trace(m_startOfInsertedContent); | 2130 visitor->trace(m_startOfInsertedContent); |
| 2115 visitor->trace(m_endOfInsertedContent); | 2131 visitor->trace(m_endOfInsertedContent); |
| 2116 visitor->trace(m_insertionStyle); | 2132 visitor->trace(m_insertionStyle); |
| 2117 visitor->trace(m_documentFragment); | 2133 visitor->trace(m_documentFragment); |
| 2118 visitor->trace(m_startOfInsertedRange); | 2134 visitor->trace(m_startOfInsertedRange); |
| 2119 visitor->trace(m_endOfInsertedRange); | 2135 visitor->trace(m_endOfInsertedRange); |
| 2120 CompositeEditCommand::trace(visitor); | 2136 CompositeEditCommand::trace(visitor); |
| 2121 } | 2137 } |
| 2122 | 2138 |
| 2123 } // namespace blink | 2139 } // namespace blink |
| OLD | NEW |