OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2005 Apple Computer, Inc. All rights reserved. | 2 * Copyright (C) 2005 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 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 } | 330 } |
331 | 331 |
332 return false; | 332 return false; |
333 } | 333 } |
334 | 334 |
335 static Position firstEditablePositionInNode(Node* node) | 335 static Position firstEditablePositionInNode(Node* node) |
336 { | 336 { |
337 ASSERT(node); | 337 ASSERT(node); |
338 Node* next = node; | 338 Node* next = node; |
339 while (next && !next->rendererIsEditable()) | 339 while (next && !next->rendererIsEditable()) |
340 next = NodeTraversal::next(next, node); | 340 next = NodeTraversal::next(*next, node); |
341 return next ? firstPositionInOrBeforeNode(next) : Position(); | 341 return next ? firstPositionInOrBeforeNode(next) : Position(); |
342 } | 342 } |
343 | 343 |
344 void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node, ShouldAssumeConte
ntIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) | 344 void DeleteSelectionCommand::removeNode(PassRefPtr<Node> node, ShouldAssumeConte
ntIsAlwaysEditable shouldAssumeContentIsAlwaysEditable) |
345 { | 345 { |
346 if (!node) | 346 if (!node) |
347 return; | 347 return; |
348 | 348 |
349 if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) &&
node->isDescendantOf(m_endRoot.get()))) { | 349 if (m_startRoot != m_endRoot && !(node->isDescendantOf(m_startRoot.get()) &&
node->isDescendantOf(m_endRoot.get()))) { |
350 // If a node is not in both the start and end editable roots, remove it
only if its inside an editable region. | 350 // If a node is not in both the start and end editable roots, remove it
only if its inside an editable region. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd); | 422 updatePositionForTextRemoval(node.get(), offset, count, m_downstreamEnd); |
423 | 423 |
424 CompositeEditCommand::deleteTextFromNode(node, offset, count); | 424 CompositeEditCommand::deleteTextFromNode(node, offset, count); |
425 } | 425 } |
426 | 426 |
427 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr
eventStyleLoss() | 427 void DeleteSelectionCommand::makeStylingElementsDirectChildrenOfEditableRootToPr
eventStyleLoss() |
428 { | 428 { |
429 RefPtr<Range> range = m_selectionToDelete.toNormalizedRange(); | 429 RefPtr<Range> range = m_selectionToDelete.toNormalizedRange(); |
430 RefPtr<Node> node = range->firstNode(); | 430 RefPtr<Node> node = range->firstNode(); |
431 while (node && node != range->pastLastNode()) { | 431 while (node && node != range->pastLastNode()) { |
432 RefPtr<Node> nextNode = NodeTraversal::next(node.get()); | 432 RefPtr<Node> nextNode = NodeTraversal::next(*node); |
433 if ((node->hasTagName(styleTag) && !(toElement(node)->hasAttribute(scope
dAttr))) || node->hasTagName(linkTag)) { | 433 if ((node->hasTagName(styleTag) && !(toElement(node)->hasAttribute(scope
dAttr))) || node->hasTagName(linkTag)) { |
434 nextNode = NodeTraversal::nextSkippingChildren(node.get()); | 434 nextNode = NodeTraversal::nextSkippingChildren(node.get()); |
435 RefPtr<ContainerNode> rootEditableElement = node->rootEditableElemen
t(); | 435 RefPtr<ContainerNode> rootEditableElement = node->rootEditableElemen
t(); |
436 if (rootEditableElement.get()) { | 436 if (rootEditableElement.get()) { |
437 removeNode(node); | 437 removeNode(node); |
438 appendNode(node, rootEditableElement); | 438 appendNode(node, rootEditableElement); |
439 } | 439 } |
440 } | 440 } |
441 node = nextNode; | 441 node = nextNode; |
442 } | 442 } |
443 } | 443 } |
444 | 444 |
445 void DeleteSelectionCommand::handleGeneralDelete() | 445 void DeleteSelectionCommand::handleGeneralDelete() |
446 { | 446 { |
447 if (m_upstreamStart.isNull()) | 447 if (m_upstreamStart.isNull()) |
448 return; | 448 return; |
449 | 449 |
450 int startOffset = m_upstreamStart.deprecatedEditingOffset(); | 450 int startOffset = m_upstreamStart.deprecatedEditingOffset(); |
451 Node* startNode = m_upstreamStart.deprecatedNode(); | 451 Node* startNode = m_upstreamStart.deprecatedNode(); |
| 452 ASSERT(startNode); |
452 | 453 |
453 makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(); | 454 makeStylingElementsDirectChildrenOfEditableRootToPreventStyleLoss(); |
454 | 455 |
455 // Never remove the start block unless it's a table, in which case we won't
merge content in. | 456 // Never remove the start block unless it's a table, in which case we won't
merge content in. |
456 if (startNode->isSameNode(m_startBlock.get()) && !startOffset && canHaveChil
drenForEditing(startNode) && !isHTMLTableElement(startNode)) { | 457 if (startNode->isSameNode(m_startBlock.get()) && !startOffset && canHaveChil
drenForEditing(startNode) && !isHTMLTableElement(startNode)) { |
457 startOffset = 0; | 458 startOffset = 0; |
458 startNode = NodeTraversal::next(startNode); | 459 startNode = NodeTraversal::next(*startNode); |
459 if (!startNode) | 460 if (!startNode) |
460 return; | 461 return; |
461 } | 462 } |
462 | 463 |
463 if (startOffset >= caretMaxOffset(startNode) && startNode->isTextNode()) { | 464 if (startOffset >= caretMaxOffset(startNode) && startNode->isTextNode()) { |
464 Text* text = toText(startNode); | 465 Text* text = toText(startNode); |
465 if (text->length() > (unsigned)caretMaxOffset(startNode)) | 466 if (text->length() > (unsigned)caretMaxOffset(startNode)) |
466 deleteTextFromNode(text, caretMaxOffset(startNode), text->length() -
caretMaxOffset(startNode)); | 467 deleteTextFromNode(text, caretMaxOffset(startNode), text->length() -
caretMaxOffset(startNode)); |
467 } | 468 } |
468 | 469 |
(...skipping 25 matching lines...) Expand all Loading... |
494 else { | 495 else { |
495 bool startNodeWasDescendantOfEndNode = m_upstreamStart.deprecatedNode()-
>isDescendantOf(m_downstreamEnd.deprecatedNode()); | 496 bool startNodeWasDescendantOfEndNode = m_upstreamStart.deprecatedNode()-
>isDescendantOf(m_downstreamEnd.deprecatedNode()); |
496 // The selection to delete spans more than one node. | 497 // The selection to delete spans more than one node. |
497 RefPtr<Node> node(startNode); | 498 RefPtr<Node> node(startNode); |
498 | 499 |
499 if (startOffset > 0) { | 500 if (startOffset > 0) { |
500 if (startNode->isTextNode()) { | 501 if (startNode->isTextNode()) { |
501 // in a text node that needs to be trimmed | 502 // in a text node that needs to be trimmed |
502 Text* text = toText(node); | 503 Text* text = toText(node); |
503 deleteTextFromNode(text, startOffset, text->length() - startOffs
et); | 504 deleteTextFromNode(text, startOffset, text->length() - startOffs
et); |
504 node = NodeTraversal::next(node.get()); | 505 node = NodeTraversal::next(*node); |
505 } else { | 506 } else { |
506 node = startNode->childNode(startOffset); | 507 node = startNode->childNode(startOffset); |
507 } | 508 } |
508 } else if (startNode == m_upstreamEnd.deprecatedNode() && startNode->isT
extNode()) { | 509 } else if (startNode == m_upstreamEnd.deprecatedNode() && startNode->isT
extNode()) { |
509 Text* text = toText(m_upstreamEnd.deprecatedNode()); | 510 Text* text = toText(m_upstreamEnd.deprecatedNode()); |
510 deleteTextFromNode(text, 0, m_upstreamEnd.deprecatedEditingOffset())
; | 511 deleteTextFromNode(text, 0, m_upstreamEnd.deprecatedEditingOffset())
; |
511 } | 512 } |
512 | 513 |
513 // handle deleting all nodes that are completely selected | 514 // handle deleting all nodes that are completely selected |
514 while (node && node != m_downstreamEnd.deprecatedNode()) { | 515 while (node && node != m_downstreamEnd.deprecatedNode()) { |
515 if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_down
streamEnd) >= 0) { | 516 if (comparePositions(firstPositionInOrBeforeNode(node.get()), m_down
streamEnd) >= 0) { |
516 // NodeTraversal::nextSkippingChildren just blew past the end po
sition, so stop deleting | 517 // NodeTraversal::nextSkippingChildren just blew past the end po
sition, so stop deleting |
517 node = 0; | 518 node = 0; |
518 } else if (!m_downstreamEnd.deprecatedNode()->isDescendantOf(node.ge
t())) { | 519 } else if (!m_downstreamEnd.deprecatedNode()->isDescendantOf(node.ge
t())) { |
519 RefPtr<Node> nextNode = NodeTraversal::nextSkippingChildren(node
.get()); | 520 RefPtr<Node> nextNode = NodeTraversal::nextSkippingChildren(node
.get()); |
520 // if we just removed a node from the end container, update end
position so the | 521 // if we just removed a node from the end container, update end
position so the |
521 // check above will work | 522 // check above will work |
522 updatePositionForNodeRemoval(m_downstreamEnd, node.get()); | 523 updatePositionForNodeRemoval(m_downstreamEnd, node.get()); |
523 removeNode(node.get()); | 524 removeNode(node.get()); |
524 node = nextNode.get(); | 525 node = nextNode.get(); |
525 } else { | 526 } else { |
526 Node& n = node->lastDescendant(); | 527 Node& n = node->lastDescendant(); |
527 if (m_downstreamEnd.deprecatedNode() == n && m_downstreamEnd.dep
recatedEditingOffset() >= caretMaxOffset(&n)) { | 528 if (m_downstreamEnd.deprecatedNode() == n && m_downstreamEnd.dep
recatedEditingOffset() >= caretMaxOffset(&n)) { |
528 removeNode(node.get()); | 529 removeNode(node.get()); |
529 node = 0; | 530 node = 0; |
530 } else | 531 } else { |
531 node = NodeTraversal::next(node.get()); | 532 node = NodeTraversal::next(*node); |
| 533 } |
532 } | 534 } |
533 } | 535 } |
534 | 536 |
535 if (m_downstreamEnd.deprecatedNode() != startNode && !m_upstreamStart.de
precatedNode()->isDescendantOf(m_downstreamEnd.deprecatedNode()) && m_downstream
End.inDocument() && m_downstreamEnd.deprecatedEditingOffset() >= caretMinOffset(
m_downstreamEnd.deprecatedNode())) { | 537 if (m_downstreamEnd.deprecatedNode() != startNode && !m_upstreamStart.de
precatedNode()->isDescendantOf(m_downstreamEnd.deprecatedNode()) && m_downstream
End.inDocument() && m_downstreamEnd.deprecatedEditingOffset() >= caretMinOffset(
m_downstreamEnd.deprecatedNode())) { |
536 if (m_downstreamEnd.atLastEditingPositionForNode() && !canHaveChildr
enForEditing(m_downstreamEnd.deprecatedNode())) { | 538 if (m_downstreamEnd.atLastEditingPositionForNode() && !canHaveChildr
enForEditing(m_downstreamEnd.deprecatedNode())) { |
537 // The node itself is fully selected, not just its contents. De
lete it. | 539 // The node itself is fully selected, not just its contents. De
lete it. |
538 removeNode(m_downstreamEnd.deprecatedNode()); | 540 removeNode(m_downstreamEnd.deprecatedNode()); |
539 } else { | 541 } else { |
540 if (m_downstreamEnd.deprecatedNode()->isTextNode()) { | 542 if (m_downstreamEnd.deprecatedNode()->isTextNode()) { |
541 // in a text node that needs to be trimmed | 543 // in a text node that needs to be trimmed |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 | 855 |
854 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, | 856 // Normally deletion doesn't preserve the typing style that was present before i
t. For example, |
855 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't | 857 // type a character, Bold, then delete the character and start typing. The Bold
typing style shouldn't |
856 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. | 858 // stick around. Deletion should preserve a typing style that *it* sets, howeve
r. |
857 bool DeleteSelectionCommand::preservesTypingStyle() const | 859 bool DeleteSelectionCommand::preservesTypingStyle() const |
858 { | 860 { |
859 return m_typingStyle; | 861 return m_typingStyle; |
860 } | 862 } |
861 | 863 |
862 } // namespace WebCore | 864 } // namespace WebCore |
OLD | NEW |