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 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 if (!node || !node->nonShadowBoundaryParentNode()) | 386 if (!node || !node->nonShadowBoundaryParentNode()) |
387 return; | 387 return; |
388 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); | 388 applyCommandToComposite(RemoveNodeCommand::create(node, shouldAssumeContentI
sAlwaysEditable)); |
389 } | 389 } |
390 | 390 |
391 void CompositeEditCommand::removeNodePreservingChildren(PassRefPtr<Node> node, S
houldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 391 void CompositeEditCommand::removeNodePreservingChildren(PassRefPtr<Node> node, S
houldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) |
392 { | 392 { |
393 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable)); | 393 applyCommandToComposite(RemoveNodePreservingChildrenCommand::create(node, sh
ouldAssumeContentIsAlwaysEditable)); |
394 } | 394 } |
395 | 395 |
396 void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtr<Node> node) | 396 void CompositeEditCommand::removeNodeAndPruneAncestors(PassRefPtr<Node> node, No
de* excludeNode) |
397 { | 397 { |
| 398 ASSERT(node.get() != excludeNode); |
398 RefPtr<ContainerNode> parent = node->parentNode(); | 399 RefPtr<ContainerNode> parent = node->parentNode(); |
399 removeNode(node); | 400 removeNode(node); |
400 prune(parent.release()); | 401 prune(parent.release(), excludeNode); |
401 } | 402 } |
402 | 403 |
403 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, PassRefPtr<Element> prpNewParent) | 404 void CompositeEditCommand::moveRemainingSiblingsToNewParent(Node* node, Node* pa
stLastNodeToMove, PassRefPtr<Element> prpNewParent) |
404 { | 405 { |
405 NodeVector nodesToRemove; | 406 NodeVector nodesToRemove; |
406 RefPtr<Element> newParent = prpNewParent; | 407 RefPtr<Element> newParent = prpNewParent; |
407 | 408 |
408 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) | 409 for (; node && node != pastLastNodeToMove; node = node->nextSibling()) |
409 nodesToRemove.append(node); | 410 nodesToRemove.append(node); |
410 | 411 |
(...skipping 18 matching lines...) Expand all Loading... |
429 // reduce the number of edit commands could do so here. | 430 // reduce the number of edit commands could do so here. |
430 RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); | 431 RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre
ate(node); |
431 applyCommandToComposite(command); | 432 applyCommandToComposite(command); |
432 // Returning a raw pointer here is OK because the command is retained by | 433 // Returning a raw pointer here is OK because the command is retained by |
433 // applyCommandToComposite (thus retaining the span), and the span is also | 434 // applyCommandToComposite (thus retaining the span), and the span is also |
434 // in the DOM tree, and thus alive whie it has a parent. | 435 // in the DOM tree, and thus alive whie it has a parent. |
435 ASSERT(command->spanElement()->inDocument()); | 436 ASSERT(command->spanElement()->inDocument()); |
436 return command->spanElement(); | 437 return command->spanElement(); |
437 } | 438 } |
438 | 439 |
439 void CompositeEditCommand::prune(PassRefPtr<Node> node) | 440 void CompositeEditCommand::prune(PassRefPtr<Node> node, Node* excludeNode) |
440 { | 441 { |
441 if (RefPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get
())) | 442 if (RefPtr<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node.get
(), excludeNode)) |
442 removeNode(highestNodeToRemove.release()); | 443 removeNode(highestNodeToRemove.release()); |
443 } | 444 } |
444 | 445 |
445 void CompositeEditCommand::splitTextNode(PassRefPtr<Text> node, unsigned offset) | 446 void CompositeEditCommand::splitTextNode(PassRefPtr<Text> node, unsigned offset) |
446 { | 447 { |
447 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); | 448 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); |
448 } | 449 } |
449 | 450 |
450 void CompositeEditCommand::splitElement(PassRefPtr<Element> element, PassRefPtr<
Node> atChild) | 451 void CompositeEditCommand::splitElement(PassRefPtr<Element> element, PassRefPtr<
Node> atChild) |
451 { | 452 { |
(...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1037 | 1038 |
1038 // There are bugs in deletion when it removes a fully selected table/list. | 1039 // There are bugs in deletion when it removes a fully selected table/list. |
1039 // It expands and removes the entire table/list, but will let content | 1040 // It expands and removes the entire table/list, but will let content |
1040 // before and after the table/list collapse onto one line. | 1041 // before and after the table/list collapse onto one line. |
1041 // Deleting a paragraph will leave a placeholder. Remove it (and prune | 1042 // Deleting a paragraph will leave a placeholder. Remove it (and prune |
1042 // empty or unrendered parents). | 1043 // empty or unrendered parents). |
1043 | 1044 |
1044 void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination) | 1045 void CompositeEditCommand::cleanupAfterDeletion(VisiblePosition destination) |
1045 { | 1046 { |
1046 VisiblePosition caretAfterDelete = endingSelection().visibleStart(); | 1047 VisiblePosition caretAfterDelete = endingSelection().visibleStart(); |
| 1048 Node* destinationNode = destination.deepEquivalent().anchorNode(); |
1047 if (caretAfterDelete != destination && isStartOfParagraph(caretAfterDelete)
&& isEndOfParagraph(caretAfterDelete)) { | 1049 if (caretAfterDelete != destination && isStartOfParagraph(caretAfterDelete)
&& isEndOfParagraph(caretAfterDelete)) { |
1048 // Note: We want the rightmost candidate. | 1050 // Note: We want the rightmost candidate. |
1049 Position position = caretAfterDelete.deepEquivalent().downstream(); | 1051 Position position = caretAfterDelete.deepEquivalent().downstream(); |
1050 Node* node = position.deprecatedNode(); | 1052 Node* node = position.deprecatedNode(); |
1051 // Normally deletion will leave a br as a placeholder. | 1053 // Normally deletion will leave a br as a placeholder. |
1052 if (node->hasTagName(brTag)) | 1054 if (node->hasTagName(brTag)) |
1053 removeNodeAndPruneAncestors(node); | 1055 removeNodeAndPruneAncestors(node, destinationNode); |
1054 // If the selection to move was empty and in an empty block that | 1056 // If the selection to move was empty and in an empty block that |
1055 // doesn't require a placeholder to prop itself open (like a bordered | 1057 // doesn't require a placeholder to prop itself open (like a bordered |
1056 // div or an li), remove it during the move (the list removal code | 1058 // div or an li), remove it during the move (the list removal code |
1057 // expects this behavior). | 1059 // expects this behavior). |
1058 else if (isBlock(node)) { | 1060 else if (isBlock(node)) { |
1059 // If caret position after deletion and destination position coincid
es, | 1061 // If caret position after deletion and destination position coincid
es, |
1060 // node should not be removed. | 1062 // node should not be removed. |
1061 if (!position.rendersInDifferentPosition(destination.deepEquivalent(
))) { | 1063 if (!position.rendersInDifferentPosition(destination.deepEquivalent(
))) { |
1062 prune(node); | 1064 prune(node, destinationNode); |
1063 return; | 1065 return; |
1064 } | 1066 } |
1065 removeNodeAndPruneAncestors(node); | 1067 removeNodeAndPruneAncestors(node, destinationNode); |
1066 } | 1068 } |
1067 else if (lineBreakExistsAtPosition(position)) { | 1069 else if (lineBreakExistsAtPosition(position)) { |
1068 // There is a preserved '\n' at caretAfterDelete. | 1070 // There is a preserved '\n' at caretAfterDelete. |
1069 // We can safely assume this is a text node. | 1071 // We can safely assume this is a text node. |
1070 Text* textNode = toText(node); | 1072 Text* textNode = toText(node); |
1071 if (textNode->length() == 1) | 1073 if (textNode->length() == 1) |
1072 removeNodeAndPruneAncestors(node); | 1074 removeNodeAndPruneAncestors(node, destinationNode); |
1073 else | 1075 else |
1074 deleteTextFromNode(textNode, position.deprecatedEditingOffset(),
1); | 1076 deleteTextFromNode(textNode, position.deprecatedEditingOffset(),
1); |
1075 } | 1077 } |
1076 } | 1078 } |
1077 } | 1079 } |
1078 | 1080 |
1079 // This is a version of moveParagraph that preserves style by keeping the origin
al markup | 1081 // This is a version of moveParagraph that preserves style by keeping the origin
al markup |
1080 // It is currently used only by IndentOutdentCommand but it is meant to be used
in the | 1082 // It is currently used only by IndentOutdentCommand but it is meant to be used
in the |
1081 // future by several other commands such as InsertList and the align commands. | 1083 // future by several other commands such as InsertList and the align commands. |
1082 // The blockElement parameter is the element to move the paragraph to, | 1084 // The blockElement parameter is the element to move the paragraph to, |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1456 return node.release(); | 1458 return node.release(); |
1457 } | 1459 } |
1458 | 1460 |
1459 PassRefPtr<Element> createBlockPlaceholderElement(Document* document) | 1461 PassRefPtr<Element> createBlockPlaceholderElement(Document* document) |
1460 { | 1462 { |
1461 RefPtr<Element> breakNode = document->createElement(brTag, false); | 1463 RefPtr<Element> breakNode = document->createElement(brTag, false); |
1462 return breakNode.release(); | 1464 return breakNode.release(); |
1463 } | 1465 } |
1464 | 1466 |
1465 } // namespace WebCore | 1467 } // namespace WebCore |
OLD | NEW |