Home | History | Annotate | Download | only in editing
      1 /*
      2  * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "core/editing/Editor.h"
     29 
     30 #include "CSSPropertyNames.h"
     31 #include "HTMLNames.h"
     32 #include "bindings/v8/ExceptionStatePlaceholder.h"
     33 #include "core/accessibility/AXObjectCache.h"
     34 #include "core/css/CSSComputedStyleDeclaration.h"
     35 #include "core/css/StylePropertySet.h"
     36 #include "core/dom/Clipboard.h"
     37 #include "core/dom/ClipboardEvent.h"
     38 #include "core/dom/DocumentFragment.h"
     39 #include "core/dom/DocumentMarkerController.h"
     40 #include "core/dom/EventNames.h"
     41 #include "core/dom/KeyboardEvent.h"
     42 #include "core/dom/NodeList.h"
     43 #include "core/dom/NodeTraversal.h"
     44 #include "core/dom/Text.h"
     45 #include "core/dom/TextEvent.h"
     46 #include "core/editing/ApplyStyleCommand.h"
     47 #include "core/editing/DeleteSelectionCommand.h"
     48 #include "core/editing/IndentOutdentCommand.h"
     49 #include "core/editing/InputMethodController.h"
     50 #include "core/editing/InsertListCommand.h"
     51 #include "core/editing/ModifySelectionListLevel.h"
     52 #include "core/editing/RemoveFormatCommand.h"
     53 #include "core/editing/RenderedPosition.h"
     54 #include "core/editing/ReplaceSelectionCommand.h"
     55 #include "core/editing/SimplifyMarkupCommand.h"
     56 #include "core/editing/SpellChecker.h"
     57 #include "core/editing/TextCheckingHelper.h"
     58 #include "core/editing/TextIterator.h"
     59 #include "core/editing/TypingCommand.h"
     60 #include "core/editing/VisibleUnits.h"
     61 #include "core/editing/htmlediting.h"
     62 #include "core/editing/markup.h"
     63 #include "core/html/HTMLImageElement.h"
     64 #include "core/html/HTMLInputElement.h"
     65 #include "core/html/HTMLTextAreaElement.h"
     66 #include "core/loader/cache/ResourceFetcher.h"
     67 #include "core/page/EditorClient.h"
     68 #include "core/page/EventHandler.h"
     69 #include "core/page/FocusController.h"
     70 #include "core/page/Frame.h"
     71 #include "core/page/FrameView.h"
     72 #include "core/page/Page.h"
     73 #include "core/page/Settings.h"
     74 #include "core/platform/KillRing.h"
     75 #include "core/platform/Pasteboard.h"
     76 #include "core/platform/Sound.h"
     77 #include "core/platform/text/TextCheckerClient.h"
     78 #include "core/rendering/HitTestResult.h"
     79 #include "core/rendering/RenderBlock.h"
     80 #include "core/rendering/RenderTextControl.h"
     81 #include "wtf/unicode/CharacterNames.h"
     82 
     83 namespace WebCore {
     84 
     85 using namespace std;
     86 using namespace HTMLNames;
     87 using namespace WTF;
     88 using namespace Unicode;
     89 
     90 Editor::RevealSelectionScope::RevealSelectionScope(Editor* editor)
     91     : m_editor(editor)
     92 {
     93     ++m_editor->m_preventRevealSelection;
     94 }
     95 
     96 Editor::RevealSelectionScope::~RevealSelectionScope()
     97 {
     98     ASSERT(m_editor->m_preventRevealSelection);
     99     --m_editor->m_preventRevealSelection;
    100     if (!m_editor->m_preventRevealSelection)
    101         m_editor->m_frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
    102 }
    103 
    104 namespace {
    105 
    106 bool isSelectionInTextField(const VisibleSelection& selection)
    107 {
    108     HTMLTextFormControlElement* textControl = enclosingTextFormControl(selection.start());
    109     return textControl && textControl->hasTagName(inputTag) && toHTMLInputElement(textControl)->isTextField();
    110 }
    111 
    112 } // namespace
    113 
    114 // When an event handler has moved the selection outside of a text control
    115 // we should use the target control's selection for this editing operation.
    116 VisibleSelection Editor::selectionForCommand(Event* event)
    117 {
    118     VisibleSelection selection = m_frame->selection()->selection();
    119     if (!event)
    120         return selection;
    121     // If the target is a text control, and the current selection is outside of its shadow tree,
    122     // then use the saved selection for that text control.
    123     HTMLTextFormControlElement* textFormControlOfSelectionStart = enclosingTextFormControl(selection.start());
    124     HTMLTextFormControlElement* textFromControlOfTarget = isHTMLTextFormControlElement(event->target()->toNode()) ? toHTMLTextFormControlElement(event->target()->toNode()) : 0;
    125     if (textFromControlOfTarget && (selection.start().isNull() || textFromControlOfTarget != textFormControlOfSelectionStart)) {
    126         if (RefPtr<Range> range = textFromControlOfTarget->selection())
    127             return VisibleSelection(range.get(), DOWNSTREAM, selection.isDirectional());
    128     }
    129     return selection;
    130 }
    131 
    132 // Function considers Mac editing behavior a fallback when Page or Settings is not available.
    133 EditingBehavior Editor::behavior() const
    134 {
    135     if (!m_frame || !m_frame->settings())
    136         return EditingBehavior(EditingMacBehavior);
    137 
    138     return EditingBehavior(m_frame->settings()->editingBehaviorType());
    139 }
    140 
    141 EditorClient* Editor::client() const
    142 {
    143     if (Page* page = m_frame->page())
    144         return page->editorClient();
    145     return 0;
    146 }
    147 
    148 
    149 TextCheckerClient* Editor::textChecker() const
    150 {
    151     if (EditorClient* owner = client())
    152         return owner->textChecker();
    153     return 0;
    154 }
    155 
    156 void Editor::handleKeyboardEvent(KeyboardEvent* event)
    157 {
    158     if (EditorClient* c = client())
    159         c->handleKeyboardEvent(event);
    160 }
    161 
    162 bool Editor::handleTextEvent(TextEvent* event)
    163 {
    164     // Default event handling for Drag and Drop will be handled by DragController
    165     // so we leave the event for it.
    166     if (event->isDrop())
    167         return false;
    168 
    169     if (event->isPaste()) {
    170         if (event->pastingFragment())
    171             replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle());
    172         else
    173             replaceSelectionWithText(event->data(), false, event->shouldSmartReplace());
    174         return true;
    175     }
    176 
    177     String data = event->data();
    178     if (data == "\n") {
    179         if (event->isLineBreak())
    180             return insertLineBreak();
    181         return insertParagraphSeparator();
    182     }
    183 
    184     return insertTextWithoutSendingTextEvent(data, false, event);
    185 }
    186 
    187 bool Editor::canEdit() const
    188 {
    189     return m_frame->selection()->rootEditableElement();
    190 }
    191 
    192 bool Editor::canEditRichly() const
    193 {
    194     return m_frame->selection()->isContentRichlyEditable();
    195 }
    196 
    197 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items.  They
    198 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
    199 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
    200 // normally selectable to implement copy/paste (like divs, or a document body).
    201 
    202 bool Editor::canDHTMLCut()
    203 {
    204     return !m_frame->selection()->isInPasswordField() && !dispatchCPPEvent(eventNames().beforecutEvent, ClipboardNumb);
    205 }
    206 
    207 bool Editor::canDHTMLCopy()
    208 {
    209     return !m_frame->selection()->isInPasswordField() && !dispatchCPPEvent(eventNames().beforecopyEvent, ClipboardNumb);
    210 }
    211 
    212 bool Editor::canDHTMLPaste()
    213 {
    214     return !dispatchCPPEvent(eventNames().beforepasteEvent, ClipboardNumb);
    215 }
    216 
    217 bool Editor::canCut() const
    218 {
    219     return canCopy() && canDelete();
    220 }
    221 
    222 static HTMLImageElement* imageElementFromImageDocument(Document* document)
    223 {
    224     if (!document)
    225         return 0;
    226     if (!document->isImageDocument())
    227         return 0;
    228 
    229     HTMLElement* body = document->body();
    230     if (!body)
    231         return 0;
    232 
    233     Node* node = body->firstChild();
    234     if (!node)
    235         return 0;
    236     if (!node->hasTagName(imgTag))
    237         return 0;
    238     return toHTMLImageElement(node);
    239 }
    240 
    241 bool Editor::canCopy() const
    242 {
    243     if (imageElementFromImageDocument(m_frame->document()))
    244         return true;
    245     FrameSelection* selection = m_frame->selection();
    246     return selection->isRange() && !selection->isInPasswordField();
    247 }
    248 
    249 bool Editor::canPaste() const
    250 {
    251     return canEdit();
    252 }
    253 
    254 bool Editor::canDelete() const
    255 {
    256     FrameSelection* selection = m_frame->selection();
    257     return selection->isRange() && selection->rootEditableElement();
    258 }
    259 
    260 bool Editor::canDeleteRange(Range* range) const
    261 {
    262     Node* startContainer = range->startContainer();
    263     Node* endContainer = range->endContainer();
    264     if (!startContainer || !endContainer)
    265         return false;
    266 
    267     if (!startContainer->rendererIsEditable() || !endContainer->rendererIsEditable())
    268         return false;
    269 
    270     if (range->collapsed(IGNORE_EXCEPTION)) {
    271         VisiblePosition start(range->startPosition(), DOWNSTREAM);
    272         VisiblePosition previous = start.previous();
    273         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
    274         if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer->rootEditableElement())
    275             return false;
    276     }
    277     return true;
    278 }
    279 
    280 bool Editor::smartInsertDeleteEnabled()
    281 {
    282     return client() && client()->smartInsertDeleteEnabled();
    283 }
    284 
    285 bool Editor::canSmartCopyOrDelete()
    286 {
    287     return client() && client()->smartInsertDeleteEnabled() && m_frame->selection()->granularity() == WordGranularity;
    288 }
    289 
    290 bool Editor::isSelectTrailingWhitespaceEnabled()
    291 {
    292     return client() && client()->isSelectTrailingWhitespaceEnabled();
    293 }
    294 
    295 bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool killRing, bool isTypingAction)
    296 {
    297     if (!canEdit())
    298         return false;
    299 
    300     if (m_frame->selection()->isRange()) {
    301         if (isTypingAction) {
    302             TypingCommand::deleteKeyPressed(m_frame->document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
    303             revealSelectionAfterEditingOperation();
    304         } else {
    305             if (killRing)
    306                 addToKillRing(selectedRange().get(), false);
    307             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
    308             // Implicitly calls revealSelectionAfterEditingOperation().
    309         }
    310     } else {
    311         TypingCommand::Options options = 0;
    312         if (canSmartCopyOrDelete())
    313             options |= TypingCommand::SmartDelete;
    314         if (killRing)
    315             options |= TypingCommand::KillRing;
    316         switch (direction) {
    317         case DirectionForward:
    318         case DirectionRight:
    319             TypingCommand::forwardDeleteKeyPressed(m_frame->document(), options, granularity);
    320             break;
    321         case DirectionBackward:
    322         case DirectionLeft:
    323             TypingCommand::deleteKeyPressed(m_frame->document(), options, granularity);
    324             break;
    325         }
    326         revealSelectionAfterEditingOperation();
    327     }
    328 
    329     // FIXME: We should to move this down into deleteKeyPressed.
    330     // clear the "start new kill ring sequence" setting, because it was set to true
    331     // when the selection was updated by deleting the range
    332     if (killRing)
    333         setStartNewKillRingSequence(false);
    334 
    335     return true;
    336 }
    337 
    338 void Editor::deleteSelectionWithSmartDelete(bool smartDelete)
    339 {
    340     if (m_frame->selection()->isNone())
    341         return;
    342 
    343     applyCommand(DeleteSelectionCommand::create(m_frame->document(), smartDelete));
    344 }
    345 
    346 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
    347 {
    348     Node* target = findEventTargetFromSelection();
    349     if (!target)
    350         return;
    351     target->dispatchEvent(TextEvent::createForPlainTextPaste(m_frame->domWindow(), pastingText, smartReplace), IGNORE_EXCEPTION);
    352 }
    353 
    354 void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle)
    355 {
    356     Node* target = findEventTargetFromSelection();
    357     if (!target)
    358         return;
    359     target->dispatchEvent(TextEvent::createForFragmentPaste(m_frame->domWindow(), pastingFragment, smartReplace, matchStyle), IGNORE_EXCEPTION);
    360 }
    361 
    362 void Editor::pasteAsPlainTextBypassingDHTML()
    363 {
    364     pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
    365 }
    366 
    367 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard* pasteboard)
    368 {
    369     String text = pasteboard->plainText(m_frame);
    370     if (client() && client()->shouldInsertText(text, selectedRange().get(), EditorInsertActionPasted))
    371         pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
    372 }
    373 
    374 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
    375 {
    376     RefPtr<Range> range = selectedRange();
    377     bool chosePlainText;
    378     RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, range, allowPlainText, chosePlainText);
    379     if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
    380         pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), chosePlainText);
    381 }
    382 
    383 bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard)
    384 {
    385     return client() && client()->smartInsertDeleteEnabled() && pasteboard->canSmartReplace();
    386 }
    387 
    388 bool Editor::shouldInsertFragment(PassRefPtr<DocumentFragment> fragment, PassRefPtr<Range> replacingDOMRange, EditorInsertAction givenAction)
    389 {
    390     if (!client())
    391         return false;
    392 
    393     if (fragment) {
    394         Node* child = fragment->firstChild();
    395         if (child && fragment->lastChild() == child && child->isCharacterDataNode())
    396             return client()->shouldInsertText(static_cast<CharacterData*>(child)->data(), replacingDOMRange.get(), givenAction);
    397     }
    398 
    399     return client()->shouldInsertNode(fragment.get(), replacingDOMRange.get(), givenAction);
    400 }
    401 
    402 void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle)
    403 {
    404     if (m_frame->selection()->isNone() || !m_frame->selection()->isContentEditable() || !fragment)
    405         return;
    406 
    407     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting | ReplaceSelectionCommand::SanitizeFragment;
    408     if (selectReplacement)
    409         options |= ReplaceSelectionCommand::SelectReplacement;
    410     if (smartReplace)
    411         options |= ReplaceSelectionCommand::SmartReplace;
    412     if (matchStyle)
    413         options |= ReplaceSelectionCommand::MatchStyle;
    414     applyCommand(ReplaceSelectionCommand::create(m_frame->document(), fragment, options, EditActionPaste));
    415     revealSelectionAfterEditingOperation();
    416 
    417     if (m_frame->selection()->isInPasswordField() || !isContinuousSpellCheckingEnabled())
    418         return;
    419     Node* nodeToCheck = m_frame->selection()->rootEditableElement();
    420     if (!nodeToCheck)
    421         return;
    422 
    423     RefPtr<Range> rangeToCheck = Range::create(m_frame->document(), firstPositionInNode(nodeToCheck), lastPositionInNode(nodeToCheck));
    424     m_spellChecker->requestCheckingFor(SpellCheckRequest::create(resolveTextCheckingTypeMask(TextCheckingTypeSpelling | TextCheckingTypeGrammar), TextCheckingProcessBatch, rangeToCheck, rangeToCheck));
    425 }
    426 
    427 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace)
    428 {
    429     replaceSelectionWithFragment(createFragmentFromText(selectedRange().get(), text), selectReplacement, smartReplace, true);
    430 }
    431 
    432 PassRefPtr<Range> Editor::selectedRange()
    433 {
    434     if (!m_frame)
    435         return 0;
    436     return m_frame->selection()->toNormalizedRange();
    437 }
    438 
    439 bool Editor::shouldDeleteRange(Range* range) const
    440 {
    441     if (!range || range->collapsed(IGNORE_EXCEPTION))
    442         return false;
    443 
    444     if (!canDeleteRange(range))
    445         return false;
    446 
    447     return client() && client()->shouldDeleteRange(range);
    448 }
    449 
    450 bool Editor::tryDHTMLCopy()
    451 {
    452     if (m_frame->selection()->isInPasswordField())
    453         return false;
    454 
    455     return !dispatchCPPEvent(eventNames().copyEvent, ClipboardWritable);
    456 }
    457 
    458 bool Editor::tryDHTMLCut()
    459 {
    460     if (m_frame->selection()->isInPasswordField())
    461         return false;
    462 
    463     return !dispatchCPPEvent(eventNames().cutEvent, ClipboardWritable);
    464 }
    465 
    466 bool Editor::tryDHTMLPaste()
    467 {
    468     return !dispatchCPPEvent(eventNames().pasteEvent, ClipboardReadable);
    469 }
    470 
    471 bool Editor::shouldInsertText(const String& text, Range* range, EditorInsertAction action) const
    472 {
    473     return client() && client()->shouldInsertText(text, range, action);
    474 }
    475 
    476 void Editor::notifyComponentsOnChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
    477 {
    478     if (client())
    479         client()->respondToChangedSelection(m_frame);
    480     setStartNewKillRingSequence(true);
    481 }
    482 
    483 void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
    484 {
    485     if (AXObjectCache::accessibilityEnabled()) {
    486         Node* node = endingSelection.start().deprecatedNode();
    487         if (AXObjectCache* cache = m_frame->document()->existingAXObjectCache())
    488             cache->postNotification(node, AXObjectCache::AXValueChanged, false);
    489     }
    490 
    491     updateMarkersForWordsAffectedByEditing(true);
    492 
    493     if (client())
    494         client()->respondToChangedContents();
    495 }
    496 
    497 TriState Editor::selectionUnorderedListState() const
    498 {
    499     if (m_frame->selection()->isCaret()) {
    500         if (enclosingNodeWithTag(m_frame->selection()->selection().start(), ulTag))
    501             return TrueTriState;
    502     } else if (m_frame->selection()->isRange()) {
    503         Node* startNode = enclosingNodeWithTag(m_frame->selection()->selection().start(), ulTag);
    504         Node* endNode = enclosingNodeWithTag(m_frame->selection()->selection().end(), ulTag);
    505         if (startNode && endNode && startNode == endNode)
    506             return TrueTriState;
    507     }
    508 
    509     return FalseTriState;
    510 }
    511 
    512 TriState Editor::selectionOrderedListState() const
    513 {
    514     if (m_frame->selection()->isCaret()) {
    515         if (enclosingNodeWithTag(m_frame->selection()->selection().start(), olTag))
    516             return TrueTriState;
    517     } else if (m_frame->selection()->isRange()) {
    518         Node* startNode = enclosingNodeWithTag(m_frame->selection()->selection().start(), olTag);
    519         Node* endNode = enclosingNodeWithTag(m_frame->selection()->selection().end(), olTag);
    520         if (startNode && endNode && startNode == endNode)
    521             return TrueTriState;
    522     }
    523 
    524     return FalseTriState;
    525 }
    526 
    527 PassRefPtr<Node> Editor::insertOrderedList()
    528 {
    529     if (!canEditRichly())
    530         return 0;
    531 
    532     RefPtr<Node> newList = InsertListCommand::insertList(m_frame->document(), InsertListCommand::OrderedList);
    533     revealSelectionAfterEditingOperation();
    534     return newList;
    535 }
    536 
    537 PassRefPtr<Node> Editor::insertUnorderedList()
    538 {
    539     if (!canEditRichly())
    540         return 0;
    541 
    542     RefPtr<Node> newList = InsertListCommand::insertList(m_frame->document(), InsertListCommand::UnorderedList);
    543     revealSelectionAfterEditingOperation();
    544     return newList;
    545 }
    546 
    547 bool Editor::canIncreaseSelectionListLevel()
    548 {
    549     return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(m_frame->document());
    550 }
    551 
    552 bool Editor::canDecreaseSelectionListLevel()
    553 {
    554     return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(m_frame->document());
    555 }
    556 
    557 PassRefPtr<Node> Editor::increaseSelectionListLevel()
    558 {
    559     if (!canEditRichly() || m_frame->selection()->isNone())
    560         return 0;
    561 
    562     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(m_frame->document());
    563     revealSelectionAfterEditingOperation();
    564     return newList;
    565 }
    566 
    567 PassRefPtr<Node> Editor::increaseSelectionListLevelOrdered()
    568 {
    569     if (!canEditRichly() || m_frame->selection()->isNone())
    570         return 0;
    571 
    572     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(m_frame->document());
    573     revealSelectionAfterEditingOperation();
    574     return newList.release();
    575 }
    576 
    577 PassRefPtr<Node> Editor::increaseSelectionListLevelUnordered()
    578 {
    579     if (!canEditRichly() || m_frame->selection()->isNone())
    580         return 0;
    581 
    582     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(m_frame->document());
    583     revealSelectionAfterEditingOperation();
    584     return newList.release();
    585 }
    586 
    587 void Editor::decreaseSelectionListLevel()
    588 {
    589     if (!canEditRichly() || m_frame->selection()->isNone())
    590         return;
    591 
    592     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(m_frame->document());
    593     revealSelectionAfterEditingOperation();
    594 }
    595 
    596 void Editor::removeFormattingAndStyle()
    597 {
    598     applyCommand(RemoveFormatCommand::create(m_frame->document()));
    599 }
    600 
    601 void Editor::clearLastEditCommand()
    602 {
    603     m_lastEditCommand.clear();
    604 }
    605 
    606 // Returns whether caller should continue with "the default processing", which is the same as
    607 // the event handler NOT setting the return value to false
    608 bool Editor::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPolicy policy)
    609 {
    610     Node* target = findEventTargetFromSelection();
    611     if (!target)
    612         return true;
    613 
    614     RefPtr<Clipboard> clipboard = newGeneralClipboard(policy, m_frame);
    615 
    616     RefPtr<Event> evt = ClipboardEvent::create(eventType, true, true, clipboard);
    617     target->dispatchEvent(evt, IGNORE_EXCEPTION);
    618     bool noDefaultProcessing = evt->defaultPrevented();
    619     if (noDefaultProcessing && policy == ClipboardWritable) {
    620         Pasteboard* pasteboard = Pasteboard::generalPasteboard();
    621         pasteboard->clear();
    622         pasteboard->writeClipboard(clipboard.get());
    623     }
    624 
    625     // invalidate clipboard here for security
    626     clipboard->setAccessPolicy(ClipboardNumb);
    627 
    628     return !noDefaultProcessing;
    629 }
    630 
    631 Node* Editor::findEventTargetFrom(const VisibleSelection& selection) const
    632 {
    633     Node* target = selection.start().element();
    634     if (!target)
    635         target = m_frame->document()->body();
    636     if (!target)
    637         return 0;
    638 
    639     return target;
    640 }
    641 
    642 Node* Editor::findEventTargetFromSelection() const
    643 {
    644     return findEventTargetFrom(m_frame->selection()->selection());
    645 }
    646 
    647 void Editor::applyStyle(StylePropertySet* style, EditAction editingAction)
    648 {
    649     switch (m_frame->selection()->selectionType()) {
    650     case VisibleSelection::NoSelection:
    651         // do nothing
    652         break;
    653     case VisibleSelection::CaretSelection:
    654         computeAndSetTypingStyle(style, editingAction);
    655         break;
    656     case VisibleSelection::RangeSelection:
    657         if (style)
    658             applyCommand(ApplyStyleCommand::create(m_frame->document(), EditingStyle::create(style).get(), editingAction));
    659         break;
    660     }
    661 }
    662 
    663 bool Editor::shouldApplyStyle(StylePropertySet* style, Range* range)
    664 {
    665     return client()->shouldApplyStyle(style, range);
    666 }
    667 
    668 void Editor::applyParagraphStyle(StylePropertySet* style, EditAction editingAction)
    669 {
    670     switch (m_frame->selection()->selectionType()) {
    671     case VisibleSelection::NoSelection:
    672         // do nothing
    673         break;
    674     case VisibleSelection::CaretSelection:
    675     case VisibleSelection::RangeSelection:
    676         if (style)
    677             applyCommand(ApplyStyleCommand::create(m_frame->document(), EditingStyle::create(style).get(), editingAction, ApplyStyleCommand::ForceBlockProperties));
    678         break;
    679     }
    680 }
    681 
    682 void Editor::applyStyleToSelection(StylePropertySet* style, EditAction editingAction)
    683 {
    684     if (!style || style->isEmpty() || !canEditRichly())
    685         return;
    686 
    687     if (client() && client()->shouldApplyStyle(style, m_frame->selection()->toNormalizedRange().get()))
    688         applyStyle(style, editingAction);
    689 }
    690 
    691 void Editor::applyParagraphStyleToSelection(StylePropertySet* style, EditAction editingAction)
    692 {
    693     if (!style || style->isEmpty() || !canEditRichly())
    694         return;
    695 
    696     if (client() && client()->shouldApplyStyle(style, m_frame->selection()->toNormalizedRange().get()))
    697         applyParagraphStyle(style, editingAction);
    698 }
    699 
    700 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
    701 {
    702     return EditingStyle::create(propertyID, value)->triStateOfStyle(
    703         EditingStyle::styleAtSelectionStart(m_frame->selection()->selection(), propertyID == CSSPropertyBackgroundColor).get());
    704 }
    705 
    706 TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
    707 {
    708     return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame->selection()->selection());
    709 }
    710 
    711 String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
    712 {
    713     RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame->selection()->selection(),
    714         propertyID == CSSPropertyBackgroundColor);
    715     if (!selectionStyle || !selectionStyle->style())
    716         return String();
    717 
    718     if (propertyID == CSSPropertyFontSize)
    719         return String::number(selectionStyle->legacyFontSize(m_frame->document()));
    720     return selectionStyle->style()->getPropertyValue(propertyID);
    721 }
    722 
    723 void Editor::indent()
    724 {
    725     applyCommand(IndentOutdentCommand::create(m_frame->document(), IndentOutdentCommand::Indent));
    726 }
    727 
    728 void Editor::outdent()
    729 {
    730     applyCommand(IndentOutdentCommand::create(m_frame->document(), IndentOutdentCommand::Outdent));
    731 }
    732 
    733 static void dispatchEditableContentChangedEvents(PassRefPtr<Element> startRoot, PassRefPtr<Element> endRoot)
    734 {
    735     if (startRoot)
    736         startRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentChangedEvent, false, false), IGNORE_EXCEPTION);
    737     if (endRoot && endRoot != startRoot)
    738         endRoot->dispatchEvent(Event::create(eventNames().webkitEditableContentChangedEvent, false, false), IGNORE_EXCEPTION);
    739 }
    740 
    741 void Editor::appliedEditing(PassRefPtr<CompositeEditCommand> cmd)
    742 {
    743     m_frame->document()->updateLayout();
    744 
    745     EditCommandComposition* composition = cmd->composition();
    746     ASSERT(composition);
    747     VisibleSelection newSelection(cmd->endingSelection());
    748 
    749     // Don't clear the typing style with this selection change.  We do those things elsewhere if necessary.
    750     changeSelectionAfterCommand(newSelection, 0);
    751     dispatchEditableContentChangedEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement());
    752 
    753     if (!cmd->preservesTypingStyle())
    754         m_frame->selection()->clearTypingStyle();
    755 
    756     // Command will be equal to last edit command only in the case of typing
    757     if (m_lastEditCommand.get() == cmd)
    758         ASSERT(cmd->isTypingCommand());
    759     else {
    760         // Only register a new undo command if the command passed in is
    761         // different from the last command
    762         m_lastEditCommand = cmd;
    763         if (client())
    764             client()->registerUndoStep(m_lastEditCommand->ensureComposition());
    765     }
    766 
    767     respondToChangedContents(newSelection);
    768 }
    769 
    770 void Editor::unappliedEditing(PassRefPtr<EditCommandComposition> cmd)
    771 {
    772     m_frame->document()->updateLayout();
    773 
    774     VisibleSelection newSelection(cmd->startingSelection());
    775     changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
    776     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
    777 
    778     m_lastEditCommand = 0;
    779     if (client())
    780         client()->registerRedoStep(cmd);
    781     respondToChangedContents(newSelection);
    782 }
    783 
    784 void Editor::reappliedEditing(PassRefPtr<EditCommandComposition> cmd)
    785 {
    786     m_frame->document()->updateLayout();
    787 
    788     VisibleSelection newSelection(cmd->endingSelection());
    789     changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
    790     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
    791 
    792     m_lastEditCommand = 0;
    793     if (client())
    794         client()->registerUndoStep(cmd);
    795     respondToChangedContents(newSelection);
    796 }
    797 
    798 Editor::Editor(Frame* frame)
    799     : FrameDestructionObserver(frame)
    800     , m_preventRevealSelection(0)
    801     , m_shouldStartNewKillRingSequence(false)
    802     // This is off by default, since most editors want this behavior (this matches IE but not FF).
    803     , m_shouldStyleWithCSS(false)
    804     , m_killRing(adoptPtr(new KillRing))
    805     , m_spellChecker(adoptPtr(new SpellChecker(frame)))
    806     , m_areMarkedTextMatchesHighlighted(false)
    807     , m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv)
    808     , m_overwriteModeEnabled(false)
    809 {
    810 }
    811 
    812 Editor::~Editor()
    813 {
    814 }
    815 
    816 void Editor::clear()
    817 {
    818     m_frame->inputMethodController().clear();
    819     m_shouldStyleWithCSS = false;
    820     m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
    821 }
    822 
    823 bool Editor::insertText(const String& text, Event* triggeringEvent)
    824 {
    825     return m_frame->eventHandler()->handleTextInputEvent(text, triggeringEvent);
    826 }
    827 
    828 bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
    829 {
    830     if (text.isEmpty())
    831         return false;
    832 
    833     VisibleSelection selection = selectionForCommand(triggeringEvent);
    834     if (!selection.isContentEditable())
    835         return false;
    836     RefPtr<Range> range = selection.toNormalizedRange();
    837 
    838     if (!shouldInsertText(text, range.get(), EditorInsertActionTyped))
    839         return true;
    840 
    841     if (!text.isEmpty())
    842         updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
    843 
    844     // Get the selection to use for the event that triggered this insertText.
    845     // If the event handler changed the selection, we may want to use a different selection
    846     // that is contained in the event target.
    847     selection = selectionForCommand(triggeringEvent);
    848     if (selection.isContentEditable()) {
    849         if (Node* selectionStart = selection.start().deprecatedNode()) {
    850             RefPtr<Document> document = selectionStart->document();
    851 
    852             // Insert the text
    853             TypingCommand::Options options = 0;
    854             if (selectInsertedText)
    855                 options |= TypingCommand::SelectInsertedText;
    856             TypingCommand::insertText(document.get(), text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionConfirm : TypingCommand::TextCompositionNone);
    857 
    858             // Reveal the current selection
    859             if (Frame* editedFrame = document->frame()) {
    860                 if (Page* page = editedFrame->page())
    861                     page->focusController().focusedOrMainFrame()->selection()->revealSelection(ScrollAlignment::alignCenterIfNeeded);
    862             }
    863         }
    864     }
    865 
    866     return true;
    867 }
    868 
    869 bool Editor::insertLineBreak()
    870 {
    871     if (!canEdit())
    872         return false;
    873 
    874     if (!shouldInsertText("\n", m_frame->selection()->toNormalizedRange().get(), EditorInsertActionTyped))
    875         return true;
    876 
    877     VisiblePosition caret = m_frame->selection()->selection().visibleStart();
    878     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
    879     TypingCommand::insertLineBreak(m_frame->document(), 0);
    880     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
    881 
    882     return true;
    883 }
    884 
    885 bool Editor::insertParagraphSeparator()
    886 {
    887     if (!canEdit())
    888         return false;
    889 
    890     if (!canEditRichly())
    891         return insertLineBreak();
    892 
    893     if (!shouldInsertText("\n", m_frame->selection()->toNormalizedRange().get(), EditorInsertActionTyped))
    894         return true;
    895 
    896     VisiblePosition caret = m_frame->selection()->selection().visibleStart();
    897     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
    898     TypingCommand::insertParagraphSeparator(m_frame->document(), 0);
    899     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
    900 
    901     return true;
    902 }
    903 
    904 void Editor::cut()
    905 {
    906     if (tryDHTMLCut())
    907         return; // DHTML did the whole operation
    908     if (!canCut()) {
    909         systemBeep();
    910         return;
    911     }
    912     RefPtr<Range> selection = selectedRange();
    913     if (shouldDeleteRange(selection.get())) {
    914         updateMarkersForWordsAffectedByEditing(true);
    915         if (enclosingTextFormControl(m_frame->selection()->start())) {
    916             Pasteboard::generalPasteboard()->writePlainText(m_frame->selectedTextForClipboard(),
    917                 canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
    918         } else
    919             Pasteboard::generalPasteboard()->writeSelection(selection.get(), canSmartCopyOrDelete(), m_frame, IncludeImageAltTextForClipboard);
    920         deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
    921     }
    922 }
    923 
    924 void Editor::copy()
    925 {
    926     if (tryDHTMLCopy())
    927         return; // DHTML did the whole operation
    928     if (!canCopy()) {
    929         systemBeep();
    930         return;
    931     }
    932 
    933     if (enclosingTextFormControl(m_frame->selection()->start())) {
    934         Pasteboard::generalPasteboard()->writePlainText(m_frame->selectedTextForClipboard(),
    935             canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
    936     } else {
    937         Document* document = m_frame->document();
    938         if (HTMLImageElement* imageElement = imageElementFromImageDocument(document))
    939             Pasteboard::generalPasteboard()->writeImage(imageElement, document->url(), document->title());
    940         else
    941             Pasteboard::generalPasteboard()->writeSelection(selectedRange().get(), canSmartCopyOrDelete(), m_frame, IncludeImageAltTextForClipboard);
    942     }
    943 }
    944 
    945 void Editor::paste()
    946 {
    947     ASSERT(m_frame->document());
    948     if (tryDHTMLPaste())
    949         return; // DHTML did the whole operation
    950     if (!canPaste())
    951         return;
    952     updateMarkersForWordsAffectedByEditing(false);
    953     ResourceFetcher* loader = m_frame->document()->fetcher();
    954     ResourceCacheValidationSuppressor validationSuppressor(loader);
    955     if (m_frame->selection()->isContentRichlyEditable())
    956         pasteWithPasteboard(Pasteboard::generalPasteboard(), true);
    957     else
    958         pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
    959 }
    960 
    961 void Editor::pasteAsPlainText()
    962 {
    963     if (tryDHTMLPaste())
    964         return;
    965     if (!canPaste())
    966         return;
    967     updateMarkersForWordsAffectedByEditing(false);
    968     pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
    969 }
    970 
    971 void Editor::performDelete()
    972 {
    973     if (!canDelete()) {
    974         systemBeep();
    975         return;
    976     }
    977 
    978     addToKillRing(selectedRange().get(), false);
    979     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
    980 
    981     // clear the "start new kill ring sequence" setting, because it was set to true
    982     // when the selection was updated by deleting the range
    983     setStartNewKillRingSequence(false);
    984 }
    985 
    986 void Editor::simplifyMarkup(Node* startNode, Node* endNode)
    987 {
    988     if (!startNode)
    989         return;
    990     if (endNode) {
    991         if (startNode->document() != endNode->document())
    992             return;
    993         // check if start node is before endNode
    994         Node* node = startNode;
    995         while (node && node != endNode)
    996             node = NodeTraversal::next(node);
    997         if (!node)
    998             return;
    999     }
   1000 
   1001     applyCommand(SimplifyMarkupCommand::create(m_frame->document(), startNode, (endNode) ? NodeTraversal::next(endNode) : 0));
   1002 }
   1003 
   1004 void Editor::copyURL(const KURL& url, const String& title)
   1005 {
   1006     Pasteboard::generalPasteboard()->writeURL(url, title, m_frame);
   1007 }
   1008 
   1009 void Editor::copyImage(const HitTestResult& result)
   1010 {
   1011     KURL url = result.absoluteLinkURL();
   1012     if (url.isEmpty())
   1013         url = result.absoluteImageURL();
   1014 
   1015     Pasteboard::generalPasteboard()->writeImage(result.innerNonSharedNode(), url, result.altDisplayString());
   1016 }
   1017 
   1018 bool Editor::isContinuousSpellCheckingEnabled() const
   1019 {
   1020     return client() && client()->isContinuousSpellCheckingEnabled();
   1021 }
   1022 
   1023 void Editor::toggleContinuousSpellChecking()
   1024 {
   1025     if (client())
   1026         client()->toggleContinuousSpellChecking();
   1027 }
   1028 
   1029 bool Editor::isGrammarCheckingEnabled()
   1030 {
   1031     return client() && client()->isGrammarCheckingEnabled();
   1032 }
   1033 
   1034 bool Editor::shouldEndEditing(Range* range)
   1035 {
   1036     return client() && client()->shouldEndEditing(range);
   1037 }
   1038 
   1039 bool Editor::shouldBeginEditing(Range* range)
   1040 {
   1041     return client() && client()->shouldBeginEditing(range);
   1042 }
   1043 
   1044 void Editor::clearUndoRedoOperations()
   1045 {
   1046     if (client())
   1047         client()->clearUndoRedoOperations();
   1048 }
   1049 
   1050 bool Editor::canUndo()
   1051 {
   1052     return client() && client()->canUndo();
   1053 }
   1054 
   1055 void Editor::undo()
   1056 {
   1057     if (client())
   1058         client()->undo();
   1059 }
   1060 
   1061 bool Editor::canRedo()
   1062 {
   1063     return client() && client()->canRedo();
   1064 }
   1065 
   1066 void Editor::redo()
   1067 {
   1068     if (client())
   1069         client()->redo();
   1070 }
   1071 
   1072 void Editor::didBeginEditing()
   1073 {
   1074     if (client())
   1075         client()->didBeginEditing();
   1076 }
   1077 
   1078 void Editor::didEndEditing()
   1079 {
   1080     if (client())
   1081         client()->didEndEditing();
   1082 }
   1083 
   1084 void Editor::setBaseWritingDirection(WritingDirection direction)
   1085 {
   1086     Node* focusedElement = frame()->document()->focusedElement();
   1087     if (focusedElement && isHTMLTextFormControlElement(focusedElement)) {
   1088         if (direction == NaturalWritingDirection)
   1089             return;
   1090         toHTMLElement(focusedElement)->setAttribute(dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl");
   1091         focusedElement->dispatchInputEvent();
   1092         frame()->document()->updateStyleIfNeeded();
   1093         return;
   1094     }
   1095 
   1096     RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
   1097     style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false);
   1098     applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);
   1099 }
   1100 
   1101 WritingDirection Editor::baseWritingDirectionForSelectionStart() const
   1102 {
   1103     WritingDirection result = LeftToRightWritingDirection;
   1104 
   1105     Position pos = m_frame->selection()->selection().visibleStart().deepEquivalent();
   1106     Node* node = pos.deprecatedNode();
   1107     if (!node)
   1108         return result;
   1109 
   1110     RenderObject* renderer = node->renderer();
   1111     if (!renderer)
   1112         return result;
   1113 
   1114     if (!renderer->isBlockFlow()) {
   1115         renderer = renderer->containingBlock();
   1116         if (!renderer)
   1117             return result;
   1118     }
   1119 
   1120     RenderStyle* style = renderer->style();
   1121     if (!style)
   1122         return result;
   1123 
   1124     switch (style->direction()) {
   1125     case LTR:
   1126         return LeftToRightWritingDirection;
   1127     case RTL:
   1128         return RightToLeftWritingDirection;
   1129     }
   1130 
   1131     return result;
   1132 }
   1133 
   1134 void Editor::ignoreSpelling()
   1135 {
   1136     if (!client())
   1137         return;
   1138 
   1139     RefPtr<Range> selectedRange = frame()->selection()->toNormalizedRange();
   1140     if (selectedRange)
   1141         frame()->document()->markers()->removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
   1142 }
   1143 
   1144 void Editor::advanceToNextMisspelling(bool startBeforeSelection)
   1145 {
   1146     // The basic approach is to search in two phases - from the selection end to the end of the doc, and
   1147     // then we wrap and search from the doc start to (approximately) where we started.
   1148 
   1149     // Start at the end of the selection, search to edge of document.  Starting at the selection end makes
   1150     // repeated "check spelling" commands work.
   1151     VisibleSelection selection(frame()->selection()->selection());
   1152     RefPtr<Range> spellingSearchRange(rangeOfContents(frame()->document()));
   1153 
   1154     bool startedWithSelection = false;
   1155     if (selection.start().deprecatedNode()) {
   1156         startedWithSelection = true;
   1157         if (startBeforeSelection) {
   1158             VisiblePosition start(selection.visibleStart());
   1159             // We match AppKit's rule: Start 1 character before the selection.
   1160             VisiblePosition oneBeforeStart = start.previous();
   1161             setStart(spellingSearchRange.get(), oneBeforeStart.isNotNull() ? oneBeforeStart : start);
   1162         } else
   1163             setStart(spellingSearchRange.get(), selection.visibleEnd());
   1164     }
   1165 
   1166     Position position = spellingSearchRange->startPosition();
   1167     if (!isEditablePosition(position)) {
   1168         // This shouldn't happen in very often because the Spelling menu items aren't enabled unless the
   1169         // selection is editable.
   1170         // This can happen in Mail for a mix of non-editable and editable content (like Stationary),
   1171         // when spell checking the whole document before sending the message.
   1172         // In that case the document might not be editable, but there are editable pockets that need to be spell checked.
   1173 
   1174         position = firstEditablePositionAfterPositionInRoot(position, frame()->document()->documentElement()).deepEquivalent();
   1175         if (position.isNull())
   1176             return;
   1177 
   1178         Position rangeCompliantPosition = position.parentAnchoredEquivalent();
   1179         spellingSearchRange->setStart(rangeCompliantPosition.deprecatedNode(), rangeCompliantPosition.deprecatedEditingOffset(), IGNORE_EXCEPTION);
   1180         startedWithSelection = false; // won't need to wrap
   1181     }
   1182 
   1183     // topNode defines the whole range we want to operate on
   1184     Node* topNode = highestEditableRoot(position);
   1185     // FIXME: lastOffsetForEditing() is wrong here if editingIgnoresContent(highestEditableRoot()) returns true (e.g. a <table>)
   1186     spellingSearchRange->setEnd(topNode, lastOffsetForEditing(topNode), IGNORE_EXCEPTION);
   1187 
   1188     // If spellingSearchRange starts in the middle of a word, advance to the next word so we start checking
   1189     // at a word boundary. Going back by one char and then forward by a word does the trick.
   1190     if (startedWithSelection) {
   1191         VisiblePosition oneBeforeStart = startVisiblePosition(spellingSearchRange.get(), DOWNSTREAM).previous();
   1192         if (oneBeforeStart.isNotNull())
   1193             setStart(spellingSearchRange.get(), endOfWord(oneBeforeStart));
   1194         // else we were already at the start of the editable node
   1195     }
   1196 
   1197     if (spellingSearchRange->collapsed(IGNORE_EXCEPTION))
   1198         return; // nothing to search in
   1199 
   1200     // Get the spell checker if it is available
   1201     if (!client())
   1202         return;
   1203 
   1204     // We go to the end of our first range instead of the start of it, just to be sure
   1205     // we don't get foiled by any word boundary problems at the start.  It means we might
   1206     // do a tiny bit more searching.
   1207     Node* searchEndNodeAfterWrap = spellingSearchRange->endContainer();
   1208     int searchEndOffsetAfterWrap = spellingSearchRange->endOffset();
   1209 
   1210     int misspellingOffset = 0;
   1211     GrammarDetail grammarDetail;
   1212     int grammarPhraseOffset = 0;
   1213     RefPtr<Range> grammarSearchRange;
   1214     String badGrammarPhrase;
   1215     String misspelledWord;
   1216 
   1217     bool isSpelling = true;
   1218     int foundOffset = 0;
   1219     String foundItem;
   1220     RefPtr<Range> firstMisspellingRange;
   1221     if (unifiedTextCheckerEnabled()) {
   1222         grammarSearchRange = spellingSearchRange->cloneRange(IGNORE_EXCEPTION);
   1223         foundItem = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
   1224         if (isSpelling) {
   1225             misspelledWord = foundItem;
   1226             misspellingOffset = foundOffset;
   1227         } else {
   1228             badGrammarPhrase = foundItem;
   1229             grammarPhraseOffset = foundOffset;
   1230         }
   1231     } else {
   1232         misspelledWord = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
   1233         grammarSearchRange = spellingSearchRange->cloneRange(IGNORE_EXCEPTION);
   1234         if (!misspelledWord.isEmpty()) {
   1235             // Stop looking at start of next misspelled word
   1236             CharacterIterator chars(grammarSearchRange.get());
   1237             chars.advance(misspellingOffset);
   1238             grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset(), IGNORE_EXCEPTION);
   1239         }
   1240 
   1241         if (isGrammarCheckingEnabled())
   1242             badGrammarPhrase = TextCheckingHelper(client(), grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
   1243     }
   1244 
   1245     // If we found neither bad grammar nor a misspelled word, wrap and try again (but don't bother if we started at the beginning of the
   1246     // block rather than at a selection).
   1247     if (startedWithSelection && !misspelledWord && !badGrammarPhrase) {
   1248         spellingSearchRange->setStart(topNode, 0, IGNORE_EXCEPTION);
   1249         // going until the end of the very first chunk we tested is far enough
   1250         spellingSearchRange->setEnd(searchEndNodeAfterWrap, searchEndOffsetAfterWrap, IGNORE_EXCEPTION);
   1251 
   1252         if (unifiedTextCheckerEnabled()) {
   1253             grammarSearchRange = spellingSearchRange->cloneRange(IGNORE_EXCEPTION);
   1254             foundItem = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspellingOrBadGrammar(isGrammarCheckingEnabled(), isSpelling, foundOffset, grammarDetail);
   1255             if (isSpelling) {
   1256                 misspelledWord = foundItem;
   1257                 misspellingOffset = foundOffset;
   1258             } else {
   1259                 badGrammarPhrase = foundItem;
   1260                 grammarPhraseOffset = foundOffset;
   1261             }
   1262         } else {
   1263             misspelledWord = TextCheckingHelper(client(), spellingSearchRange).findFirstMisspelling(misspellingOffset, false, firstMisspellingRange);
   1264             grammarSearchRange = spellingSearchRange->cloneRange(IGNORE_EXCEPTION);
   1265             if (!misspelledWord.isEmpty()) {
   1266                 // Stop looking at start of next misspelled word
   1267                 CharacterIterator chars(grammarSearchRange.get());
   1268                 chars.advance(misspellingOffset);
   1269                 grammarSearchRange->setEnd(chars.range()->startContainer(), chars.range()->startOffset(), IGNORE_EXCEPTION);
   1270             }
   1271 
   1272             if (isGrammarCheckingEnabled())
   1273                 badGrammarPhrase = TextCheckingHelper(client(), grammarSearchRange).findFirstBadGrammar(grammarDetail, grammarPhraseOffset, false);
   1274         }
   1275     }
   1276 
   1277     if (!badGrammarPhrase.isEmpty()) {
   1278         // We found bad grammar. Since we only searched for bad grammar up to the first misspelled word, the bad grammar
   1279         // takes precedence and we ignore any potential misspelled word. Select the grammar detail, update the spelling
   1280         // panel, and store a marker so we draw the green squiggle later.
   1281 
   1282         ASSERT(badGrammarPhrase.length() > 0);
   1283         ASSERT(grammarDetail.location != -1 && grammarDetail.length > 0);
   1284 
   1285         // FIXME 4859190: This gets confused with doubled punctuation at the end of a paragraph
   1286         RefPtr<Range> badGrammarRange = TextIterator::subrange(grammarSearchRange.get(), grammarPhraseOffset + grammarDetail.location, grammarDetail.length);
   1287         frame()->selection()->setSelection(VisibleSelection(badGrammarRange.get(), SEL_DEFAULT_AFFINITY));
   1288         frame()->selection()->revealSelection();
   1289 
   1290         frame()->document()->markers()->addMarker(badGrammarRange.get(), DocumentMarker::Grammar, grammarDetail.userDescription);
   1291     } else if (!misspelledWord.isEmpty()) {
   1292         // We found a misspelling, but not any earlier bad grammar. Select the misspelling, update the spelling panel, and store
   1293         // a marker so we draw the red squiggle later.
   1294 
   1295         RefPtr<Range> misspellingRange = TextIterator::subrange(spellingSearchRange.get(), misspellingOffset, misspelledWord.length());
   1296         frame()->selection()->setSelection(VisibleSelection(misspellingRange.get(), DOWNSTREAM));
   1297         frame()->selection()->revealSelection();
   1298 
   1299         client()->updateSpellingUIWithMisspelledWord(misspelledWord);
   1300         frame()->document()->markers()->addMarker(misspellingRange.get(), DocumentMarker::Spelling);
   1301     }
   1302 }
   1303 
   1304 String Editor::misspelledWordAtCaretOrRange(Node* clickedNode) const
   1305 {
   1306     if (!isContinuousSpellCheckingEnabled() || !clickedNode || !isSpellCheckingEnabledFor(clickedNode))
   1307         return String();
   1308 
   1309     VisibleSelection selection = m_frame->selection()->selection();
   1310     if (!selection.isContentEditable() || selection.isNone())
   1311         return String();
   1312 
   1313     VisibleSelection wordSelection(selection.base());
   1314     wordSelection.expandUsingGranularity(WordGranularity);
   1315     RefPtr<Range> wordRange = wordSelection.toNormalizedRange();
   1316 
   1317     // In compliance with GTK+ applications, additionally allow to provide suggestions when the current
   1318     // selection exactly match the word selection.
   1319     if (selection.isRange() && !areRangesEqual(wordRange.get(), selection.toNormalizedRange().get()))
   1320         return String();
   1321 
   1322     String word = wordRange->text();
   1323     if (word.isEmpty() || !client())
   1324         return String();
   1325 
   1326     int wordLength = word.length();
   1327     int misspellingLocation = -1;
   1328     int misspellingLength = 0;
   1329     textChecker()->checkSpellingOfString(word, &misspellingLocation, &misspellingLength);
   1330 
   1331     return misspellingLength == wordLength ? word : String();
   1332 }
   1333 
   1334 void Editor::showSpellingGuessPanel()
   1335 {
   1336     if (!client()) {
   1337         LOG_ERROR("No NSSpellChecker");
   1338         return;
   1339     }
   1340 
   1341     if (client()->spellingUIIsShowing()) {
   1342         client()->showSpellingUI(false);
   1343         return;
   1344     }
   1345 
   1346     advanceToNextMisspelling(true);
   1347     client()->showSpellingUI(true);
   1348 }
   1349 
   1350 void Editor::clearMisspellingsAndBadGrammar(const VisibleSelection &movingSelection)
   1351 {
   1352     RefPtr<Range> selectedRange = movingSelection.toNormalizedRange();
   1353     if (selectedRange) {
   1354         frame()->document()->markers()->removeMarkers(selectedRange.get(), DocumentMarker::Spelling);
   1355         frame()->document()->markers()->removeMarkers(selectedRange.get(), DocumentMarker::Grammar);
   1356     }
   1357 }
   1358 
   1359 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection &movingSelection)
   1360 {
   1361     markMisspellingsAndBadGrammar(movingSelection, isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled(), movingSelection);
   1362 }
   1363 
   1364 void Editor::markMisspellingsAfterTypingToWord(const VisiblePosition &wordStart, const VisibleSelection& selectionAfterTyping)
   1365 {
   1366     if (unifiedTextCheckerEnabled()) {
   1367         TextCheckingTypeMask textCheckingOptions = 0;
   1368 
   1369         if (isContinuousSpellCheckingEnabled())
   1370             textCheckingOptions |= TextCheckingTypeSpelling;
   1371 
   1372         if (!(textCheckingOptions & TextCheckingTypeSpelling))
   1373             return;
   1374 
   1375         if (isGrammarCheckingEnabled())
   1376             textCheckingOptions |= TextCheckingTypeGrammar;
   1377 
   1378         VisibleSelection adjacentWords = VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary));
   1379         if (textCheckingOptions & TextCheckingTypeGrammar) {
   1380             VisibleSelection selectedSentence = VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart));
   1381             markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), selectedSentence.toNormalizedRange().get());
   1382         } else
   1383             markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, adjacentWords.toNormalizedRange().get(), adjacentWords.toNormalizedRange().get());
   1384         return;
   1385     }
   1386 
   1387     if (!isContinuousSpellCheckingEnabled())
   1388         return;
   1389 
   1390     // Check spelling of one word
   1391     RefPtr<Range> misspellingRange;
   1392     markMisspellings(VisibleSelection(startOfWord(wordStart, LeftWordIfOnBoundary), endOfWord(wordStart, RightWordIfOnBoundary)), misspellingRange);
   1393 
   1394     // Autocorrect the misspelled word.
   1395     if (!misspellingRange)
   1396         return;
   1397 
   1398     // Get the misspelled word.
   1399     const String misspelledWord = plainText(misspellingRange.get());
   1400     String autocorrectedString = textChecker()->getAutoCorrectSuggestionForMisspelledWord(misspelledWord);
   1401 
   1402     // If autocorrected word is non empty, replace the misspelled word by this word.
   1403     if (!autocorrectedString.isEmpty()) {
   1404         VisibleSelection newSelection(misspellingRange.get(), DOWNSTREAM);
   1405         if (newSelection != frame()->selection()->selection()) {
   1406             if (!frame()->selection()->shouldChangeSelection(newSelection))
   1407                 return;
   1408             frame()->selection()->setSelection(newSelection);
   1409         }
   1410 
   1411         if (!frame()->editor()->shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertActionTyped))
   1412             return;
   1413         frame()->editor()->replaceSelectionWithText(autocorrectedString, false, false);
   1414 
   1415         // Reset the charet one character further.
   1416         frame()->selection()->moveTo(frame()->selection()->end());
   1417         frame()->selection()->modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
   1418     }
   1419 
   1420     if (!isGrammarCheckingEnabled())
   1421         return;
   1422 
   1423     // Check grammar of entire sentence
   1424     markBadGrammar(VisibleSelection(startOfSentence(wordStart), endOfSentence(wordStart)));
   1425 }
   1426 
   1427 void Editor::markMisspellingsOrBadGrammar(const VisibleSelection& selection, bool checkSpelling, RefPtr<Range>& firstMisspellingRange)
   1428 {
   1429     // This function is called with a selection already expanded to word boundaries.
   1430     // Might be nice to assert that here.
   1431 
   1432     // This function is used only for as-you-type checking, so if that's off we do nothing. Note that
   1433     // grammar checking can only be on if spell checking is also on.
   1434     if (!isContinuousSpellCheckingEnabled())
   1435         return;
   1436 
   1437     RefPtr<Range> searchRange(selection.toNormalizedRange());
   1438     if (!searchRange)
   1439         return;
   1440 
   1441     // If we're not in an editable node, bail.
   1442     Node* editableNode = searchRange->startContainer();
   1443     if (!editableNode || !editableNode->rendererIsEditable())
   1444         return;
   1445 
   1446     if (!isSpellCheckingEnabledFor(editableNode))
   1447         return;
   1448 
   1449     // Get the spell checker if it is available
   1450     if (!client())
   1451         return;
   1452 
   1453     TextCheckingHelper checker(client(), searchRange);
   1454     if (checkSpelling)
   1455         checker.markAllMisspellings(firstMisspellingRange);
   1456     else if (isGrammarCheckingEnabled())
   1457         checker.markAllBadGrammar();
   1458 }
   1459 
   1460 bool Editor::isSpellCheckingEnabledFor(Node* node) const
   1461 {
   1462     if (!node)
   1463         return false;
   1464     const Element* focusedElement = node->isElementNode() ? toElement(node) : node->parentElement();
   1465     if (!focusedElement)
   1466         return false;
   1467     return focusedElement->isSpellCheckingEnabled();
   1468 }
   1469 
   1470 bool Editor::isSpellCheckingEnabledInFocusedNode() const
   1471 {
   1472     return isSpellCheckingEnabledFor(m_frame->selection()->start().deprecatedNode());
   1473 }
   1474 
   1475 void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
   1476 {
   1477     markMisspellingsOrBadGrammar(selection, true, firstMisspellingRange);
   1478 }
   1479 
   1480 void Editor::markBadGrammar(const VisibleSelection& selection)
   1481 {
   1482     RefPtr<Range> firstMisspellingRange;
   1483     markMisspellingsOrBadGrammar(selection, false, firstMisspellingRange);
   1484 }
   1485 
   1486 void Editor::markAllMisspellingsAndBadGrammarInRanges(TextCheckingTypeMask textCheckingOptions, Range* spellingRange, Range* grammarRange)
   1487 {
   1488     ASSERT(m_frame);
   1489     ASSERT(unifiedTextCheckerEnabled());
   1490 
   1491     bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
   1492 
   1493     // This function is called with selections already expanded to word boundaries.
   1494     if (!client() || !spellingRange || (shouldMarkGrammar && !grammarRange))
   1495         return;
   1496 
   1497     // If we're not in an editable node, bail.
   1498     Node* editableNode = spellingRange->startContainer();
   1499     if (!editableNode || !editableNode->rendererIsEditable())
   1500         return;
   1501 
   1502     if (!isSpellCheckingEnabledFor(editableNode))
   1503         return;
   1504 
   1505     Range* rangeToCheck = shouldMarkGrammar ? grammarRange : spellingRange;
   1506     TextCheckingParagraph paragraphToCheck(rangeToCheck);
   1507     if (paragraphToCheck.isRangeEmpty() || paragraphToCheck.isEmpty())
   1508         return;
   1509     RefPtr<Range> paragraphRange = paragraphToCheck.paragraphRange();
   1510 
   1511     bool asynchronous = m_frame && m_frame->settings() && m_frame->settings()->asynchronousSpellCheckingEnabled();
   1512 
   1513     // In asynchronous mode, we intentionally check paragraph-wide sentence.
   1514     RefPtr<SpellCheckRequest> request = SpellCheckRequest::create(resolveTextCheckingTypeMask(textCheckingOptions), TextCheckingProcessIncremental, asynchronous ? paragraphRange : rangeToCheck, paragraphRange);
   1515 
   1516     if (asynchronous) {
   1517         m_spellChecker->requestCheckingFor(request);
   1518         return;
   1519     }
   1520 
   1521     Vector<TextCheckingResult> results;
   1522     checkTextOfParagraph(textChecker(), paragraphToCheck.text(), resolveTextCheckingTypeMask(textCheckingOptions), results);
   1523     markAndReplaceFor(request, results);
   1524 }
   1525 
   1526 void Editor::markAndReplaceFor(PassRefPtr<SpellCheckRequest> request, const Vector<TextCheckingResult>& results)
   1527 {
   1528     ASSERT(request);
   1529 
   1530     TextCheckingTypeMask textCheckingOptions = request->data().mask();
   1531     TextCheckingParagraph paragraph(request->checkingRange(), request->paragraphRange());
   1532 
   1533     bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
   1534     bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
   1535 
   1536     // Expand the range to encompass entire paragraphs, since text checking needs that much context.
   1537     int selectionOffset = 0;
   1538     int ambiguousBoundaryOffset = -1;
   1539     bool selectionChanged = false;
   1540     bool restoreSelectionAfterChange = false;
   1541     bool adjustSelectionForParagraphBoundaries = false;
   1542 
   1543     if (shouldMarkSpelling) {
   1544         if (m_frame->selection()->selectionType() == VisibleSelection::CaretSelection) {
   1545             // Attempt to save the caret position so we can restore it later if needed
   1546             Position caretPosition = m_frame->selection()->end();
   1547             selectionOffset = paragraph.offsetTo(caretPosition, ASSERT_NO_EXCEPTION);
   1548             restoreSelectionAfterChange = true;
   1549             if (selectionOffset > 0 && (static_cast<unsigned>(selectionOffset) > paragraph.text().length() || paragraph.textCharAt(selectionOffset - 1) == newlineCharacter))
   1550                 adjustSelectionForParagraphBoundaries = true;
   1551             if (selectionOffset > 0 && static_cast<unsigned>(selectionOffset) <= paragraph.text().length() && isAmbiguousBoundaryCharacter(paragraph.textCharAt(selectionOffset - 1)))
   1552                 ambiguousBoundaryOffset = selectionOffset - 1;
   1553         }
   1554     }
   1555 
   1556     for (unsigned i = 0; i < results.size(); i++) {
   1557         int spellingRangeEndOffset = paragraph.checkingEnd();
   1558         const TextCheckingResult* result = &results[i];
   1559         int resultLocation = result->location;
   1560         int resultLength = result->length;
   1561         bool resultEndsAtAmbiguousBoundary = ambiguousBoundaryOffset >= 0 && resultLocation + resultLength == ambiguousBoundaryOffset;
   1562 
   1563         // Only mark misspelling if:
   1564         // 1. Current text checking isn't done for autocorrection, in which case shouldMarkSpelling is false.
   1565         // 2. Result falls within spellingRange.
   1566         // 3. The word in question doesn't end at an ambiguous boundary. For instance, we would not mark
   1567         //    "wouldn'" as misspelled right after apostrophe is typed.
   1568         if (shouldMarkSpelling && result->type == TextCheckingTypeSpelling && resultLocation >= paragraph.checkingStart() && resultLocation + resultLength <= spellingRangeEndOffset && !resultEndsAtAmbiguousBoundary) {
   1569             ASSERT(resultLength > 0 && resultLocation >= 0);
   1570             RefPtr<Range> misspellingRange = paragraph.subrange(resultLocation, resultLength);
   1571             misspellingRange->startContainer()->document()->markers()->addMarker(misspellingRange.get(), DocumentMarker::Spelling, result->replacement, result->hash);
   1572         } else if (shouldMarkGrammar && result->type == TextCheckingTypeGrammar && paragraph.checkingRangeCovers(resultLocation, resultLength)) {
   1573             ASSERT(resultLength > 0 && resultLocation >= 0);
   1574             for (unsigned j = 0; j < result->details.size(); j++) {
   1575                 const GrammarDetail* detail = &result->details[j];
   1576                 ASSERT(detail->length > 0 && detail->location >= 0);
   1577                 if (paragraph.checkingRangeCovers(resultLocation + detail->location, detail->length)) {
   1578                     RefPtr<Range> badGrammarRange = paragraph.subrange(resultLocation + detail->location, detail->length);
   1579                     badGrammarRange->startContainer()->document()->markers()->addMarker(badGrammarRange.get(), DocumentMarker::Grammar, detail->userDescription, result->hash);
   1580                 }
   1581             }
   1582         }
   1583     }
   1584 
   1585     if (selectionChanged) {
   1586         TextCheckingParagraph extendedParagraph(paragraph);
   1587         // Restore the caret position if we have made any replacements
   1588         extendedParagraph.expandRangeToNextEnd();
   1589         if (restoreSelectionAfterChange && selectionOffset >= 0 && selectionOffset <= extendedParagraph.rangeLength()) {
   1590             RefPtr<Range> selectionRange = extendedParagraph.subrange(0, selectionOffset);
   1591             m_frame->selection()->moveTo(selectionRange->endPosition(), DOWNSTREAM);
   1592             if (adjustSelectionForParagraphBoundaries)
   1593                 m_frame->selection()->modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
   1594         } else {
   1595             // If this fails for any reason, the fallback is to go one position beyond the last replacement
   1596             m_frame->selection()->moveTo(m_frame->selection()->end());
   1597             m_frame->selection()->modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity);
   1598         }
   1599     }
   1600 }
   1601 
   1602 void Editor::markMisspellingsAndBadGrammar(const VisibleSelection& spellingSelection, bool markGrammar, const VisibleSelection& grammarSelection)
   1603 {
   1604     if (unifiedTextCheckerEnabled()) {
   1605         if (!isContinuousSpellCheckingEnabled())
   1606             return;
   1607 
   1608         // markMisspellingsAndBadGrammar() is triggered by selection change, in which case we check spelling and grammar, but don't autocorrect misspellings.
   1609         TextCheckingTypeMask textCheckingOptions = TextCheckingTypeSpelling;
   1610         if (markGrammar && isGrammarCheckingEnabled())
   1611             textCheckingOptions |= TextCheckingTypeGrammar;
   1612         markAllMisspellingsAndBadGrammarInRanges(textCheckingOptions, spellingSelection.toNormalizedRange().get(), grammarSelection.toNormalizedRange().get());
   1613         return;
   1614     }
   1615 
   1616     RefPtr<Range> firstMisspellingRange;
   1617     markMisspellings(spellingSelection, firstMisspellingRange);
   1618     if (markGrammar)
   1619         markBadGrammar(grammarSelection);
   1620 }
   1621 
   1622 void Editor::updateMarkersForWordsAffectedByEditing(bool doNotRemoveIfSelectionAtWordBoundary)
   1623 {
   1624     if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling))
   1625         return;
   1626 
   1627     // We want to remove the markers from a word if an editing command will change the word. This can happen in one of
   1628     // several scenarios:
   1629     // 1. Insert in the middle of a word.
   1630     // 2. Appending non whitespace at the beginning of word.
   1631     // 3. Appending non whitespace at the end of word.
   1632     // Note that, appending only whitespaces at the beginning or end of word won't change the word, so we don't need to
   1633     // remove the markers on that word.
   1634     // Of course, if current selection is a range, we potentially will edit two words that fall on the boundaries of
   1635     // selection, and remove words between the selection boundaries.
   1636     //
   1637     VisiblePosition startOfSelection = frame()->selection()->selection().start();
   1638     VisiblePosition endOfSelection = frame()->selection()->selection().end();
   1639     if (startOfSelection.isNull())
   1640         return;
   1641     // First word is the word that ends after or on the start of selection.
   1642     VisiblePosition startOfFirstWord = startOfWord(startOfSelection, LeftWordIfOnBoundary);
   1643     VisiblePosition endOfFirstWord = endOfWord(startOfSelection, LeftWordIfOnBoundary);
   1644     // Last word is the word that begins before or on the end of selection
   1645     VisiblePosition startOfLastWord = startOfWord(endOfSelection, RightWordIfOnBoundary);
   1646     VisiblePosition endOfLastWord = endOfWord(endOfSelection, RightWordIfOnBoundary);
   1647 
   1648     if (startOfFirstWord.isNull()) {
   1649         startOfFirstWord = startOfWord(startOfSelection, RightWordIfOnBoundary);
   1650         endOfFirstWord = endOfWord(startOfSelection, RightWordIfOnBoundary);
   1651     }
   1652 
   1653     if (endOfLastWord.isNull()) {
   1654         startOfLastWord = startOfWord(endOfSelection, LeftWordIfOnBoundary);
   1655         endOfLastWord = endOfWord(endOfSelection, LeftWordIfOnBoundary);
   1656     }
   1657 
   1658     // If doNotRemoveIfSelectionAtWordBoundary is true, and first word ends at the start of selection,
   1659     // we choose next word as the first word.
   1660     if (doNotRemoveIfSelectionAtWordBoundary && endOfFirstWord == startOfSelection) {
   1661         startOfFirstWord = nextWordPosition(startOfFirstWord);
   1662         endOfFirstWord = endOfWord(startOfFirstWord, RightWordIfOnBoundary);
   1663         if (startOfFirstWord == endOfSelection)
   1664             return;
   1665     }
   1666 
   1667     // If doNotRemoveIfSelectionAtWordBoundary is true, and last word begins at the end of selection,
   1668     // we choose previous word as the last word.
   1669     if (doNotRemoveIfSelectionAtWordBoundary && startOfLastWord == endOfSelection) {
   1670         startOfLastWord = previousWordPosition(startOfLastWord);
   1671         endOfLastWord = endOfWord(startOfLastWord, RightWordIfOnBoundary);
   1672         if (endOfLastWord == startOfSelection)
   1673             return;
   1674     }
   1675 
   1676     if (startOfFirstWord.isNull() || endOfFirstWord.isNull() || startOfLastWord.isNull() || endOfLastWord.isNull())
   1677         return;
   1678 
   1679     // Now we remove markers on everything between startOfFirstWord and endOfLastWord.
   1680     // However, if an autocorrection change a single word to multiple words, we want to remove correction mark from all the
   1681     // resulted words even we only edit one of them. For example, assuming autocorrection changes "avantgarde" to "avant
   1682     // garde", we will have CorrectionIndicator marker on both words and on the whitespace between them. If we then edit garde,
   1683     // we would like to remove the marker from word "avant" and whitespace as well. So we need to get the continous range of
   1684     // of marker that contains the word in question, and remove marker on that whole range.
   1685     Document* document = m_frame->document();
   1686     RefPtr<Range> wordRange = Range::create(document, startOfFirstWord.deepEquivalent(), endOfLastWord.deepEquivalent());
   1687 
   1688     document->markers()->removeMarkers(wordRange.get(), DocumentMarker::Spelling | DocumentMarker::Grammar, DocumentMarkerController::RemovePartiallyOverlappingMarker);
   1689 }
   1690 
   1691 PassRefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
   1692 {
   1693     Document* document = m_frame->documentAtPoint(windowPoint);
   1694     if (!document)
   1695         return 0;
   1696 
   1697     Frame* frame = document->frame();
   1698     ASSERT(frame);
   1699     FrameView* frameView = frame->view();
   1700     if (!frameView)
   1701         return 0;
   1702     IntPoint framePoint = frameView->windowToContents(windowPoint);
   1703     VisibleSelection selection(frame->visiblePositionForPoint(framePoint));
   1704 
   1705     return selection.toNormalizedRange().get();
   1706 }
   1707 
   1708 void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
   1709 {
   1710     if (m_preventRevealSelection)
   1711         return;
   1712 
   1713     m_frame->selection()->revealSelection(alignment, revealExtentOption);
   1714 }
   1715 
   1716 bool Editor::setSelectionOffsets(int selectionStart, int selectionEnd)
   1717 {
   1718     Element* rootEditableElement = m_frame->selection()->rootEditableElement();
   1719     if (!rootEditableElement)
   1720         return false;
   1721 
   1722     RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(rootEditableElement, selectionStart, selectionEnd - selectionStart);
   1723     if (!range)
   1724         return false;
   1725 
   1726     return m_frame->selection()->setSelectedRange(range.get(), VP_DEFAULT_AFFINITY, true);
   1727 }
   1728 
   1729 void Editor::transpose()
   1730 {
   1731     if (!canEdit())
   1732         return;
   1733 
   1734      VisibleSelection selection = m_frame->selection()->selection();
   1735      if (!selection.isCaret())
   1736          return;
   1737 
   1738     // Make a selection that goes back one character and forward two characters.
   1739     VisiblePosition caret = selection.visibleStart();
   1740     VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
   1741     VisiblePosition previous = next.previous();
   1742     if (next == previous)
   1743         return;
   1744     previous = previous.previous();
   1745     if (!inSameParagraph(next, previous))
   1746         return;
   1747     RefPtr<Range> range = makeRange(previous, next);
   1748     if (!range)
   1749         return;
   1750     VisibleSelection newSelection(range.get(), DOWNSTREAM);
   1751 
   1752     // Transpose the two characters.
   1753     String text = plainText(range.get());
   1754     if (text.length() != 2)
   1755         return;
   1756     String transposed = text.right(1) + text.left(1);
   1757 
   1758     // Select the two characters.
   1759     if (newSelection != m_frame->selection()->selection()) {
   1760         if (!m_frame->selection()->shouldChangeSelection(newSelection))
   1761             return;
   1762         m_frame->selection()->setSelection(newSelection);
   1763     }
   1764 
   1765     // Insert the transposed characters.
   1766     if (!shouldInsertText(transposed, range.get(), EditorInsertActionTyped))
   1767         return;
   1768     replaceSelectionWithText(transposed, false, false);
   1769 }
   1770 
   1771 void Editor::addToKillRing(Range* range, bool prepend)
   1772 {
   1773     if (m_shouldStartNewKillRingSequence)
   1774         killRing()->startNewSequence();
   1775 
   1776     String text = plainText(range);
   1777     if (prepend)
   1778         killRing()->prepend(text);
   1779     else
   1780         killRing()->append(text);
   1781     m_shouldStartNewKillRingSequence = false;
   1782 }
   1783 
   1784 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection,  FrameSelection::SetSelectionOptions options)
   1785 {
   1786     // If the new selection is orphaned, then don't update the selection.
   1787     if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
   1788         return;
   1789 
   1790     // If there is no selection change, don't bother sending shouldChangeSelection, but still call setSelection,
   1791     // because there is work that it must do in this situation.
   1792     // The old selection can be invalid here and calling shouldChangeSelection can produce some strange calls.
   1793     // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
   1794     bool selectionDidNotChangeDOMPosition = newSelection == m_frame->selection()->selection();
   1795     if (selectionDidNotChangeDOMPosition || m_frame->selection()->shouldChangeSelection(newSelection))
   1796         m_frame->selection()->setSelection(newSelection, options);
   1797 
   1798     // Some editing operations change the selection visually without affecting its position within the DOM.
   1799     // For example when you press return in the following (the caret is marked by ^):
   1800     // <div contentEditable="true"><div>^Hello</div></div>
   1801     // WebCore inserts <div><br></div> *before* the current block, which correctly moves the paragraph down but which doesn't
   1802     // change the caret's DOM position (["hello", 0]). In these situations the above FrameSelection::setSelection call
   1803     // does not call EditorClient::respondToChangedSelection(), which, on the Mac, sends selection change notifications and
   1804     // starts a new kill ring sequence, but we want to do these things (matches AppKit).
   1805     if (selectionDidNotChangeDOMPosition && client())
   1806         client()->respondToChangedSelection(m_frame);
   1807 }
   1808 
   1809 IntRect Editor::firstRectForRange(Range* range) const
   1810 {
   1811     LayoutUnit extraWidthToEndOfLine = 0;
   1812     ASSERT(range->startContainer());
   1813     ASSERT(range->endContainer());
   1814 
   1815     IntRect startCaretRect = RenderedPosition(VisiblePosition(range->startPosition()).deepEquivalent(), DOWNSTREAM).absoluteRect(&extraWidthToEndOfLine);
   1816     if (startCaretRect == LayoutRect())
   1817         return IntRect();
   1818 
   1819     IntRect endCaretRect = RenderedPosition(VisiblePosition(range->endPosition()).deepEquivalent(), UPSTREAM).absoluteRect();
   1820     if (endCaretRect == LayoutRect())
   1821         return IntRect();
   1822 
   1823     if (startCaretRect.y() == endCaretRect.y()) {
   1824         // start and end are on the same line
   1825         return IntRect(min(startCaretRect.x(), endCaretRect.x()),
   1826             startCaretRect.y(),
   1827             abs(endCaretRect.x() - startCaretRect.x()),
   1828             max(startCaretRect.height(), endCaretRect.height()));
   1829     }
   1830 
   1831     // start and end aren't on the same line, so go from start to the end of its line
   1832     return IntRect(startCaretRect.x(),
   1833         startCaretRect.y(),
   1834         startCaretRect.width() + extraWidthToEndOfLine,
   1835         startCaretRect.height());
   1836 }
   1837 
   1838 bool Editor::shouldChangeSelection(const VisibleSelection& oldSelection, const VisibleSelection& newSelection, EAffinity affinity, bool stillSelecting) const
   1839 {
   1840     return client() && client()->shouldChangeSelectedRange(oldSelection.toNormalizedRange().get(), newSelection.toNormalizedRange().get(), affinity, stillSelecting);
   1841 }
   1842 
   1843 void Editor::computeAndSetTypingStyle(StylePropertySet* style, EditAction editingAction)
   1844 {
   1845     if (!style || style->isEmpty()) {
   1846         m_frame->selection()->clearTypingStyle();
   1847         return;
   1848     }
   1849 
   1850     // Calculate the current typing style.
   1851     RefPtr<EditingStyle> typingStyle;
   1852     if (m_frame->selection()->typingStyle()) {
   1853         typingStyle = m_frame->selection()->typingStyle()->copy();
   1854         typingStyle->overrideWithStyle(style);
   1855     } else
   1856         typingStyle = EditingStyle::create(style);
   1857 
   1858     typingStyle->prepareToApplyAt(m_frame->selection()->selection().visibleStart().deepEquivalent(), EditingStyle::PreserveWritingDirection);
   1859 
   1860     // Handle block styles, substracting these from the typing style.
   1861     RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
   1862     if (!blockStyle->isEmpty())
   1863         applyCommand(ApplyStyleCommand::create(m_frame->document(), blockStyle.get(), editingAction));
   1864 
   1865     // Set the remaining style as the typing style.
   1866     m_frame->selection()->setTypingStyle(typingStyle);
   1867 }
   1868 
   1869 
   1870 void Editor::textFieldDidBeginEditing(Element* e)
   1871 {
   1872     if (isContinuousSpellCheckingEnabled()) {
   1873         Element* element = toHTMLTextFormControlElement(e)->innerTextElement();
   1874         VisibleSelection selection = VisibleSelection::selectionFromContentsOfNode(element);
   1875         markMisspellingsAndBadGrammar(selection);
   1876     }
   1877 }
   1878 
   1879 void Editor::textFieldDidEndEditing(Element* e)
   1880 {
   1881     // Remove markers when deactivating a selection in an <input type="text"/>.
   1882     // Prevent new ones from appearing too.
   1883     m_spellChecker->cancelCheck();
   1884     HTMLTextFormControlElement* textFormControlElement = toHTMLTextFormControlElement(e);
   1885     HTMLElement* innerText = textFormControlElement->innerTextElement();
   1886     DocumentMarker::MarkerTypes markerTypes(DocumentMarker::Spelling);
   1887     if (isGrammarCheckingEnabled() || unifiedTextCheckerEnabled())
   1888         markerTypes.add(DocumentMarker::Grammar);
   1889     for (Node* node = innerText; node; node = NodeTraversal::next(node, innerText)) {
   1890         m_frame->document()->markers()->removeMarkers(node, markerTypes);
   1891     }
   1892 
   1893     if (client())
   1894         client()->textFieldDidEndEditing(e);
   1895 }
   1896 
   1897 void Editor::textDidChangeInTextField(Element* e)
   1898 {
   1899     if (client())
   1900         client()->textDidChangeInTextField(e);
   1901 }
   1902 
   1903 bool Editor::doTextFieldCommandFromEvent(Element* e, KeyboardEvent* ke)
   1904 {
   1905     if (client())
   1906         return client()->doTextFieldCommandFromEvent(e, ke);
   1907 
   1908     return false;
   1909 }
   1910 
   1911 void Editor::applyEditingStyleToBodyElement() const
   1912 {
   1913     RefPtr<NodeList> list = m_frame->document()->getElementsByTagName("body");
   1914     unsigned len = list->length();
   1915     for (unsigned i = 0; i < len; i++)
   1916         applyEditingStyleToElement(toElement(list->item(i)));
   1917 }
   1918 
   1919 void Editor::applyEditingStyleToElement(Element* element) const
   1920 {
   1921     if (!element)
   1922         return;
   1923     ASSERT(element->isStyledElement());
   1924     if (!element->isStyledElement())
   1925         return;
   1926 
   1927     // Mutate using the CSSOM wrapper so we get the same event behavior as a script.
   1928     CSSStyleDeclaration* style = element->style();
   1929     style->setPropertyInternal(CSSPropertyWordWrap, "break-word", false, IGNORE_EXCEPTION);
   1930     style->setPropertyInternal(CSSPropertyWebkitLineBreak, "after-white-space", false, IGNORE_EXCEPTION);
   1931 }
   1932 
   1933 // Searches from the beginning of the document if nothing is selected.
   1934 bool Editor::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
   1935 {
   1936     FindOptions options = (forward ? 0 : Backwards) | (caseFlag ? 0 : CaseInsensitive) | (wrapFlag ? WrapAround : 0) | (startInSelection ? StartInSelection : 0);
   1937     return findString(target, options);
   1938 }
   1939 
   1940 bool Editor::findString(const String& target, FindOptions options)
   1941 {
   1942     VisibleSelection selection = m_frame->selection()->selection();
   1943 
   1944     RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
   1945 
   1946     if (!resultRange)
   1947         return false;
   1948 
   1949     m_frame->selection()->setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM));
   1950     m_frame->selection()->revealSelection();
   1951     return true;
   1952 }
   1953 
   1954 PassRefPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* previousMatch, FindOptions options)
   1955 {
   1956     RefPtr<Range> nextMatch = rangeOfString(target, previousMatch, options);
   1957     if (!nextMatch)
   1958         return 0;
   1959 
   1960     nextMatch->firstNode()->renderer()->scrollRectToVisible(nextMatch->boundingBox(),
   1961         ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
   1962 
   1963     return nextMatch.release();
   1964 }
   1965 
   1966 PassRefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
   1967 {
   1968     if (target.isEmpty())
   1969         return 0;
   1970 
   1971     // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
   1972     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
   1973     RefPtr<Range> searchRange(rangeOfContents(m_frame->document()));
   1974 
   1975     bool forward = !(options & Backwards);
   1976     bool startInReferenceRange = referenceRange && (options & StartInSelection);
   1977     if (referenceRange) {
   1978         if (forward)
   1979             searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
   1980         else
   1981             searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
   1982     }
   1983 
   1984     RefPtr<Node> shadowTreeRoot = referenceRange && referenceRange->startContainer() ? referenceRange->startContainer()->nonBoundaryShadowTreeRootNode() : 0;
   1985     if (shadowTreeRoot) {
   1986         if (forward)
   1987             searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->childNodeCount());
   1988         else
   1989             searchRange->setStart(shadowTreeRoot.get(), 0);
   1990     }
   1991 
   1992     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, options));
   1993     // If we started in the reference range and the found range exactly matches the reference range, find again.
   1994     // Build a selection with the found range to remove collapsed whitespace.
   1995     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
   1996     if (startInReferenceRange && areRangesEqual(VisibleSelection(resultRange.get()).toNormalizedRange().get(), referenceRange)) {
   1997         searchRange = rangeOfContents(m_frame->document());
   1998         if (forward)
   1999             searchRange->setStart(referenceRange->endPosition());
   2000         else
   2001             searchRange->setEnd(referenceRange->startPosition());
   2002 
   2003         if (shadowTreeRoot) {
   2004             if (forward)
   2005                 searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->childNodeCount());
   2006             else
   2007                 searchRange->setStart(shadowTreeRoot.get(), 0);
   2008         }
   2009 
   2010         resultRange = findPlainText(searchRange.get(), target, options);
   2011     }
   2012 
   2013     // If nothing was found in the shadow tree, search in main content following the shadow tree.
   2014     if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && shadowTreeRoot) {
   2015         searchRange = rangeOfContents(m_frame->document());
   2016         if (forward)
   2017             searchRange->setStartAfter(shadowTreeRoot->shadowHost());
   2018         else
   2019             searchRange->setEndBefore(shadowTreeRoot->shadowHost());
   2020 
   2021         resultRange = findPlainText(searchRange.get(), target, options);
   2022     }
   2023 
   2024     // If we didn't find anything and we're wrapping, search again in the entire document (this will
   2025     // redundantly re-search the area already searched in some cases).
   2026     if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && options & WrapAround) {
   2027         searchRange = rangeOfContents(m_frame->document());
   2028         resultRange = findPlainText(searchRange.get(), target, options);
   2029         // We used to return false here if we ended up with the same range that we started with
   2030         // (e.g., the reference range was already the only instance of this text). But we decided that
   2031         // this should be a success case instead, so we'll just fall through in that case.
   2032     }
   2033 
   2034     return resultRange->collapsed(ASSERT_NO_EXCEPTION) ? 0 : resultRange.release();
   2035 }
   2036 
   2037 void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
   2038 {
   2039     if (flag == m_areMarkedTextMatchesHighlighted)
   2040         return;
   2041 
   2042     m_areMarkedTextMatchesHighlighted = flag;
   2043     m_frame->document()->markers()->repaintMarkers(DocumentMarker::TextMatch);
   2044 }
   2045 
   2046 void Editor::respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
   2047 {
   2048     bool closeTyping = options & FrameSelection::CloseTyping;
   2049     bool isContinuousSpellCheckingEnabled = this->isContinuousSpellCheckingEnabled();
   2050     bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && isGrammarCheckingEnabled();
   2051     if (isContinuousSpellCheckingEnabled) {
   2052         VisibleSelection newAdjacentWords;
   2053         VisibleSelection newSelectedSentence;
   2054         bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
   2055         if (m_frame->selection()->selection().isContentEditable() || caretBrowsing) {
   2056             VisiblePosition newStart(m_frame->selection()->selection().visibleStart());
   2057             newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary));
   2058             if (isContinuousGrammarCheckingEnabled)
   2059                 newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart));
   2060         }
   2061 
   2062         // Don't check spelling and grammar if the change of selection is triggered by spelling correction itself.
   2063         bool shouldCheckSpellingAndGrammar = !(options & FrameSelection::SpellCorrectionTriggered);
   2064 
   2065         // When typing we check spelling elsewhere, so don't redo it here.
   2066         // If this is a change in selection resulting from a delete operation,
   2067         // oldSelection may no longer be in the document.
   2068         if (shouldCheckSpellingAndGrammar
   2069             && closeTyping
   2070             && oldSelection.isContentEditable()
   2071             && oldSelection.start().deprecatedNode()
   2072             && oldSelection.start().anchorNode()->inDocument()
   2073             && !isSelectionInTextField(oldSelection)) {
   2074             spellCheckOldSelection(oldSelection, newAdjacentWords, newSelectedSentence);
   2075         }
   2076 
   2077         if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeSpelling)) {
   2078             if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange())
   2079                 m_frame->document()->markers()->removeMarkers(wordRange.get(), DocumentMarker::Spelling);
   2080         }
   2081         if (!textChecker() || textChecker()->shouldEraseMarkersAfterChangeSelection(TextCheckingTypeGrammar)) {
   2082             if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange())
   2083                 m_frame->document()->markers()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar);
   2084         }
   2085     }
   2086 
   2087     // When continuous spell checking is off, existing markers disappear after the selection changes.
   2088     if (!isContinuousSpellCheckingEnabled)
   2089         m_frame->document()->markers()->removeMarkers(DocumentMarker::Spelling);
   2090     if (!isContinuousGrammarCheckingEnabled)
   2091         m_frame->document()->markers()->removeMarkers(DocumentMarker::Grammar);
   2092 
   2093     m_frame->inputMethodController().cancelCompositionIfSelectionIsInvalid();
   2094 
   2095     notifyComponentsOnChangedSelection(oldSelection, options);
   2096 }
   2097 
   2098 void Editor::spellCheckAfterBlur()
   2099 {
   2100     if (!m_frame->selection()->selection().isContentEditable())
   2101         return;
   2102 
   2103     if (isSelectionInTextField(m_frame->selection()->selection())) {
   2104         // textFieldDidEndEditing() and textFieldDidBeginEditing() handle this.
   2105         return;
   2106     }
   2107 
   2108     VisibleSelection empty;
   2109     spellCheckOldSelection(m_frame->selection()->selection(), empty, empty);
   2110 }
   2111 
   2112 void Editor::spellCheckOldSelection(const VisibleSelection& oldSelection, const VisibleSelection& newAdjacentWords, const VisibleSelection& newSelectedSentence)
   2113 {
   2114     VisiblePosition oldStart(oldSelection.visibleStart());
   2115     VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary));
   2116     if (oldAdjacentWords  != newAdjacentWords) {
   2117         if (isContinuousSpellCheckingEnabled() && isGrammarCheckingEnabled()) {
   2118             VisibleSelection selectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart));
   2119             markMisspellingsAndBadGrammar(oldAdjacentWords, selectedSentence != newSelectedSentence, selectedSentence);
   2120         } else {
   2121             markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords);
   2122         }
   2123     }
   2124 }
   2125 
   2126 static Node* findFirstMarkable(Node* node)
   2127 {
   2128     while (node) {
   2129         if (!node->renderer())
   2130             return 0;
   2131         if (node->renderer()->isText())
   2132             return node;
   2133         if (node->renderer()->isTextControl())
   2134             node = toRenderTextControl(node->renderer())->textFormControlElement()->visiblePositionForIndex(1).deepEquivalent().deprecatedNode();
   2135         else if (node->firstChild())
   2136             node = node->firstChild();
   2137         else
   2138             node = node->nextSibling();
   2139     }
   2140 
   2141     return 0;
   2142 }
   2143 
   2144 bool Editor::selectionStartHasMarkerFor(DocumentMarker::MarkerType markerType, int from, int length) const
   2145 {
   2146     Node* node = findFirstMarkable(m_frame->selection()->start().deprecatedNode());
   2147     if (!node)
   2148         return false;
   2149 
   2150     unsigned int startOffset = static_cast<unsigned int>(from);
   2151     unsigned int endOffset = static_cast<unsigned int>(from + length);
   2152     Vector<DocumentMarker*> markers = m_frame->document()->markers()->markersFor(node);
   2153     for (size_t i = 0; i < markers.size(); ++i) {
   2154         DocumentMarker* marker = markers[i];
   2155         if (marker->startOffset() <= startOffset && endOffset <= marker->endOffset() && marker->type() == markerType)
   2156             return true;
   2157     }
   2158 
   2159     return false;
   2160 }
   2161 
   2162 TextCheckingTypeMask Editor::resolveTextCheckingTypeMask(TextCheckingTypeMask textCheckingOptions)
   2163 {
   2164     bool shouldMarkSpelling = textCheckingOptions & TextCheckingTypeSpelling;
   2165     bool shouldMarkGrammar = textCheckingOptions & TextCheckingTypeGrammar;
   2166 
   2167     TextCheckingTypeMask checkingTypes = 0;
   2168     if (shouldMarkSpelling)
   2169         checkingTypes |= TextCheckingTypeSpelling;
   2170     if (shouldMarkGrammar)
   2171         checkingTypes |= TextCheckingTypeGrammar;
   2172 
   2173     return checkingTypes;
   2174 }
   2175 
   2176 bool Editor::unifiedTextCheckerEnabled() const
   2177 {
   2178     return WebCore::unifiedTextCheckerEnabled(m_frame);
   2179 }
   2180 
   2181 void Editor::toggleOverwriteModeEnabled()
   2182 {
   2183     m_overwriteModeEnabled = !m_overwriteModeEnabled;
   2184     frame()->selection()->setShouldShowBlockCursor(m_overwriteModeEnabled);
   2185 };
   2186 
   2187 } // namespace WebCore
   2188