OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
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 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 return; | 482 return; |
483 if (before == 0) | 483 if (before == 0) |
484 break; | 484 break; |
485 ++before; | 485 ++before; |
486 } while (frame().selection().start() == frame().selection().end() && before
<= static_cast<int>(selectionOffsets.start())); | 486 } while (frame().selection().start() == frame().selection().end() && before
<= static_cast<int>(selectionOffsets.start())); |
487 // TODO(chongz): According to spec |data| should be "forward" or "backward". | 487 // TODO(chongz): According to spec |data| should be "forward" or "backward". |
488 dispatchBeforeInputEditorCommand(frame().document()->focusedElement(), Input
Event::InputType::DeleteContent); | 488 dispatchBeforeInputEditorCommand(frame().document()->focusedElement(), Input
Event::InputType::DeleteContent); |
489 TypingCommand::deleteSelection(*frame().document()); | 489 TypingCommand::deleteSelection(*frame().document()); |
490 } | 490 } |
491 | 491 |
| 492 void InputMethodController::deleteSurroundingText(size_t before, size_t after) |
| 493 { |
| 494 if (!editor().canEdit()) |
| 495 return; |
| 496 PlainTextRange selectionOffsets(getSelectionOffsets()); |
| 497 if (selectionOffsets.isNull()) |
| 498 return; |
| 499 size_t selectionStart = selectionOffsets.start(); |
| 500 size_t selectionEnd = selectionOffsets.end(); |
| 501 Element* rootEditableElement = frame().selection().rootEditableElement(); |
| 502 if (!rootEditableElement) |
| 503 return; |
| 504 |
| 505 bool deleteBeforeText = before > 0u && selectionStart > 0u; |
| 506 bool deleteAftertext = after > 0u; |
| 507 |
| 508 if (deleteBeforeText) { |
| 509 // In case of exceeding the left boundary. |
| 510 int deletionStart = selectionStart - std::min(selectionStart, before); |
| 511 |
| 512 // Delete the text before selectionStart. |
| 513 // For multi-code text, we can't delete it successfully if we only |
| 514 // delete the right half of it. So we need to adjust the start of |
| 515 // deletion. |
| 516 const EphemeralRange& startRange = PlainTextRange(0, deletionStart).crea
teRange(*rootEditableElement); |
| 517 const Position& startPosition = startRange.endPosition(); |
| 518 Node* anchorNode = startPosition.anchorNode(); |
| 519 int deletionStartInContainerNode = startPosition.computeOffsetInContaine
rNode(); |
| 520 |
| 521 const Position position(anchorNode, deletionStartInContainerNode + 1); |
| 522 const Position& adjustedPosition = previousPositionOf(position, Position
MoveType::GraphemeCluster); |
| 523 int adjustedDeletionStart = adjustedPosition.computeOffsetInContainerNod
e(); |
| 524 |
| 525 Range* deletedRange = Range::create(*frame().document(), adjustedPositio
n, frame().selection().start()); |
| 526 deletedRange->deleteContents(ASSERT_NO_EXCEPTION); |
| 527 |
| 528 size_t deletedLength = selectionStart - static_cast<size_t>(deletionStar
t + deletionStartInContainerNode - adjustedDeletionStart); |
| 529 selectionEnd = selectionEnd - deletedLength; |
| 530 } |
| 531 |
| 532 if (deleteAftertext) { |
| 533 // In case of exceeding the right boundary. |
| 534 PlainTextRange range(static_cast<int>(selectionEnd), static_cast<int>(se
lectionEnd + after)); |
| 535 if (range.isNull()) |
| 536 return; |
| 537 const EphemeralRange adjustedRange = range.createRange(*rootEditableElem
ent); |
| 538 if (adjustedRange.isNull()) |
| 539 return; |
| 540 |
| 541 const Position& endPosition = adjustedRange.endPosition(); |
| 542 Node* anchorNode = endPosition.anchorNode(); |
| 543 int deletionEndInContainerNode = endPosition.computeOffsetInContainerNod
e(); |
| 544 |
| 545 // Delete the text after selectionEnd. |
| 546 // We also need to adjust the end of deletion for multi-code text. |
| 547 Position position(anchorNode, deletionEndInContainerNode - 1); |
| 548 Position adjustedPosition = nextPositionOf(position, PositionMoveType::G
raphemeCluster); |
| 549 |
| 550 Range* deletedRange = Range::create(*frame().document(), frame().selecti
on().end(), adjustedPosition); |
| 551 deletedRange->deleteContents(ASSERT_NO_EXCEPTION); |
| 552 } |
| 553 |
| 554 if (deleteBeforeText || deleteAftertext) { |
| 555 rootEditableElement->dispatchEvent(Event::create(EventTypeNames::webkitE
ditableContentChanged)); |
| 556 } |
| 557 |
| 558 if (deleteBeforeText) { |
| 559 rootEditableElement->dispatchEvent(Event::create(EventTypeNames::selecti
onchange)); |
| 560 } |
| 561 } |
| 562 |
492 DEFINE_TRACE(InputMethodController) | 563 DEFINE_TRACE(InputMethodController) |
493 { | 564 { |
494 visitor->trace(m_frame); | 565 visitor->trace(m_frame); |
495 visitor->trace(m_compositionRange); | 566 visitor->trace(m_compositionRange); |
496 } | 567 } |
497 | 568 |
498 } // namespace blink | 569 } // namespace blink |
OLD | NEW |