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 "SVGNames.h"
     33 #include "XLinkNames.h"
     34 #include "bindings/v8/ExceptionStatePlaceholder.h"
     35 #include "core/accessibility/AXObjectCache.h"
     36 #include "core/css/CSSComputedStyleDeclaration.h"
     37 #include "core/css/StylePropertySet.h"
     38 #include "core/dom/Clipboard.h"
     39 #include "core/dom/DocumentFragment.h"
     40 #include "core/dom/DocumentMarkerController.h"
     41 #include "core/dom/NodeList.h"
     42 #include "core/dom/NodeTraversal.h"
     43 #include "core/dom/ParserContentPolicy.h"
     44 #include "core/dom/Text.h"
     45 #include "core/editing/ApplyStyleCommand.h"
     46 #include "core/editing/DeleteSelectionCommand.h"
     47 #include "core/editing/IndentOutdentCommand.h"
     48 #include "core/editing/InputMethodController.h"
     49 #include "core/editing/InsertListCommand.h"
     50 #include "core/editing/ModifySelectionListLevel.h"
     51 #include "core/editing/RemoveFormatCommand.h"
     52 #include "core/editing/RenderedPosition.h"
     53 #include "core/editing/ReplaceSelectionCommand.h"
     54 #include "core/editing/SimplifyMarkupCommand.h"
     55 #include "core/editing/SpellChecker.h"
     56 #include "core/editing/TypingCommand.h"
     57 #include "core/editing/UndoStack.h"
     58 #include "core/editing/VisibleUnits.h"
     59 #include "core/editing/htmlediting.h"
     60 #include "core/editing/markup.h"
     61 #include "core/events/ClipboardEvent.h"
     62 #include "core/events/KeyboardEvent.h"
     63 #include "core/events/ScopedEventQueue.h"
     64 #include "core/events/TextEvent.h"
     65 #include "core/events/ThreadLocalEventNames.h"
     66 #include "core/fetch/ImageResource.h"
     67 #include "core/fetch/ResourceFetcher.h"
     68 #include "core/html/HTMLImageElement.h"
     69 #include "core/html/HTMLInputElement.h"
     70 #include "core/html/HTMLTextAreaElement.h"
     71 #include "core/html/parser/HTMLParserIdioms.h"
     72 #include "core/loader/EmptyClients.h"
     73 #include "core/page/EditorClient.h"
     74 #include "core/page/EventHandler.h"
     75 #include "core/page/FocusController.h"
     76 #include "core/frame/Frame.h"
     77 #include "core/frame/FrameView.h"
     78 #include "core/page/Page.h"
     79 #include "core/frame/Settings.h"
     80 #include "core/platform/Pasteboard.h"
     81 #include "core/platform/chromium/ChromiumDataObject.h"
     82 #include "core/rendering/HitTestResult.h"
     83 #include "core/rendering/RenderImage.h"
     84 #include "platform/KillRing.h"
     85 #include "platform/weborigin/KURL.h"
     86 #include "wtf/unicode/CharacterNames.h"
     87 
     88 namespace WebCore {
     89 
     90 using namespace std;
     91 using namespace HTMLNames;
     92 using namespace WTF;
     93 using namespace Unicode;
     94 
     95 Editor::RevealSelectionScope::RevealSelectionScope(Editor* editor)
     96     : m_editor(editor)
     97 {
     98     ++m_editor->m_preventRevealSelection;
     99 }
    100 
    101 Editor::RevealSelectionScope::~RevealSelectionScope()
    102 {
    103     ASSERT(m_editor->m_preventRevealSelection);
    104     --m_editor->m_preventRevealSelection;
    105     if (!m_editor->m_preventRevealSelection)
    106         m_editor->m_frame.selection().revealSelection(ScrollAlignment::alignToEdgeIfNeeded, RevealExtent);
    107 }
    108 
    109 // When an event handler has moved the selection outside of a text control
    110 // we should use the target control's selection for this editing operation.
    111 VisibleSelection Editor::selectionForCommand(Event* event)
    112 {
    113     VisibleSelection selection = m_frame.selection().selection();
    114     if (!event)
    115         return selection;
    116     // If the target is a text control, and the current selection is outside of its shadow tree,
    117     // then use the saved selection for that text control.
    118     HTMLTextFormControlElement* textFormControlOfSelectionStart = enclosingTextFormControl(selection.start());
    119     HTMLTextFormControlElement* textFromControlOfTarget = isHTMLTextFormControlElement(event->target()->toNode()) ? toHTMLTextFormControlElement(event->target()->toNode()) : 0;
    120     if (textFromControlOfTarget && (selection.start().isNull() || textFromControlOfTarget != textFormControlOfSelectionStart)) {
    121         if (RefPtr<Range> range = textFromControlOfTarget->selection())
    122             return VisibleSelection(range.get(), DOWNSTREAM, selection.isDirectional());
    123     }
    124     return selection;
    125 }
    126 
    127 // Function considers Mac editing behavior a fallback when Page or Settings is not available.
    128 EditingBehavior Editor::behavior() const
    129 {
    130     if (!m_frame.settings())
    131         return EditingBehavior(EditingMacBehavior);
    132 
    133     return EditingBehavior(m_frame.settings()->editingBehaviorType());
    134 }
    135 
    136 static EditorClient& emptyEditorClient()
    137 {
    138     DEFINE_STATIC_LOCAL(EmptyEditorClient, client, ());
    139     return client;
    140 }
    141 
    142 EditorClient& Editor::client() const
    143 {
    144     if (Page* page = m_frame.page())
    145         return page->editorClient();
    146     return emptyEditorClient();
    147 }
    148 
    149 UndoStack* Editor::undoStack() const
    150 {
    151     if (Page* page = m_frame.page())
    152         return &page->undoStack();
    153     return 0;
    154 }
    155 
    156 bool Editor::handleTextEvent(TextEvent* event)
    157 {
    158     // Default event handling for Drag and Drop will be handled by DragController
    159     // so we leave the event for it.
    160     if (event->isDrop())
    161         return false;
    162 
    163     if (event->isPaste()) {
    164         if (event->pastingFragment())
    165             replaceSelectionWithFragment(event->pastingFragment(), false, event->shouldSmartReplace(), event->shouldMatchStyle());
    166         else
    167             replaceSelectionWithText(event->data(), false, event->shouldSmartReplace());
    168         return true;
    169     }
    170 
    171     String data = event->data();
    172     if (data == "\n") {
    173         if (event->isLineBreak())
    174             return insertLineBreak();
    175         return insertParagraphSeparator();
    176     }
    177 
    178     return insertTextWithoutSendingTextEvent(data, false, event);
    179 }
    180 
    181 bool Editor::canEdit() const
    182 {
    183     return m_frame.selection().rootEditableElement();
    184 }
    185 
    186 bool Editor::canEditRichly() const
    187 {
    188     return m_frame.selection().isContentRichlyEditable();
    189 }
    190 
    191 // WinIE uses onbeforecut and onbeforepaste to enables the cut and paste menu items. They
    192 // also send onbeforecopy, apparently for symmetry, but it doesn't affect the menu items.
    193 // We need to use onbeforecopy as a real menu enabler because we allow elements that are not
    194 // normally selectable to implement copy/paste (like divs, or a document body).
    195 
    196 bool Editor::canDHTMLCut()
    197 {
    198     return !m_frame.selection().isInPasswordField() && !dispatchCPPEvent(EventTypeNames::beforecut, ClipboardNumb);
    199 }
    200 
    201 bool Editor::canDHTMLCopy()
    202 {
    203     return !m_frame.selection().isInPasswordField() && !dispatchCPPEvent(EventTypeNames::beforecopy, ClipboardNumb);
    204 }
    205 
    206 bool Editor::canDHTMLPaste()
    207 {
    208     return !dispatchCPPEvent(EventTypeNames::beforepaste, ClipboardNumb);
    209 }
    210 
    211 bool Editor::canCut() const
    212 {
    213     return canCopy() && canDelete();
    214 }
    215 
    216 static HTMLImageElement* imageElementFromImageDocument(Document* document)
    217 {
    218     if (!document)
    219         return 0;
    220     if (!document->isImageDocument())
    221         return 0;
    222 
    223     HTMLElement* body = document->body();
    224     if (!body)
    225         return 0;
    226 
    227     Node* node = body->firstChild();
    228     if (!node)
    229         return 0;
    230     if (!node->hasTagName(imgTag))
    231         return 0;
    232     return toHTMLImageElement(node);
    233 }
    234 
    235 bool Editor::canCopy() const
    236 {
    237     if (imageElementFromImageDocument(m_frame.document()))
    238         return true;
    239     FrameSelection& selection = m_frame.selection();
    240     return selection.isRange() && !selection.isInPasswordField();
    241 }
    242 
    243 bool Editor::canPaste() const
    244 {
    245     return canEdit();
    246 }
    247 
    248 bool Editor::canDelete() const
    249 {
    250     FrameSelection& selection = m_frame.selection();
    251     return selection.isRange() && selection.rootEditableElement();
    252 }
    253 
    254 bool Editor::canDeleteRange(Range* range) const
    255 {
    256     Node* startContainer = range->startContainer();
    257     Node* endContainer = range->endContainer();
    258     if (!startContainer || !endContainer)
    259         return false;
    260 
    261     if (!startContainer->rendererIsEditable() || !endContainer->rendererIsEditable())
    262         return false;
    263 
    264     if (range->collapsed(IGNORE_EXCEPTION)) {
    265         VisiblePosition start(range->startPosition(), DOWNSTREAM);
    266         VisiblePosition previous = start.previous();
    267         // FIXME: We sometimes allow deletions at the start of editable roots, like when the caret is in an empty list item.
    268         if (previous.isNull() || previous.deepEquivalent().deprecatedNode()->rootEditableElement() != startContainer->rootEditableElement())
    269             return false;
    270     }
    271     return true;
    272 }
    273 
    274 bool Editor::smartInsertDeleteEnabled() const
    275 {
    276     if (Settings* settings = m_frame.settings())
    277         return settings->smartInsertDeleteEnabled();
    278     return false;
    279 }
    280 
    281 bool Editor::canSmartCopyOrDelete() const
    282 {
    283     return smartInsertDeleteEnabled() && m_frame.selection().granularity() == WordGranularity;
    284 }
    285 
    286 bool Editor::isSelectTrailingWhitespaceEnabled() const
    287 {
    288     if (Settings* settings = m_frame.settings())
    289         return settings->selectTrailingWhitespaceEnabled();
    290     return false;
    291 }
    292 
    293 bool Editor::deleteWithDirection(SelectionDirection direction, TextGranularity granularity, bool killRing, bool isTypingAction)
    294 {
    295     if (!canEdit())
    296         return false;
    297 
    298     if (m_frame.selection().isRange()) {
    299         if (isTypingAction) {
    300             ASSERT(m_frame.document());
    301             TypingCommand::deleteKeyPressed(*m_frame.document(), canSmartCopyOrDelete() ? TypingCommand::SmartDelete : 0, granularity);
    302             revealSelectionAfterEditingOperation();
    303         } else {
    304             if (killRing)
    305                 addToKillRing(selectedRange().get(), false);
    306             deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
    307             // Implicitly calls revealSelectionAfterEditingOperation().
    308         }
    309     } else {
    310         TypingCommand::Options options = 0;
    311         if (canSmartCopyOrDelete())
    312             options |= TypingCommand::SmartDelete;
    313         if (killRing)
    314             options |= TypingCommand::KillRing;
    315         switch (direction) {
    316         case DirectionForward:
    317         case DirectionRight:
    318             ASSERT(m_frame.document());
    319             TypingCommand::forwardDeleteKeyPressed(*m_frame.document(), options, granularity);
    320             break;
    321         case DirectionBackward:
    322         case DirectionLeft:
    323             ASSERT(m_frame.document());
    324             TypingCommand::deleteKeyPressed(*m_frame.document(), options, granularity);
    325             break;
    326         }
    327         revealSelectionAfterEditingOperation();
    328     }
    329 
    330     // FIXME: We should to move this down into deleteKeyPressed.
    331     // clear the "start new kill ring sequence" setting, because it was set to true
    332     // when the selection was updated by deleting the range
    333     if (killRing)
    334         setStartNewKillRingSequence(false);
    335 
    336     return true;
    337 }
    338 
    339 void Editor::deleteSelectionWithSmartDelete(bool smartDelete)
    340 {
    341     if (m_frame.selection().isNone())
    342         return;
    343 
    344     ASSERT(m_frame.document());
    345     DeleteSelectionCommand::create(*m_frame.document(), smartDelete)->apply();
    346 }
    347 
    348 void Editor::pasteAsPlainText(const String& pastingText, bool smartReplace)
    349 {
    350     Node* target = findEventTargetFromSelection();
    351     if (!target)
    352         return;
    353     target->dispatchEvent(TextEvent::createForPlainTextPaste(m_frame.domWindow(), pastingText, smartReplace), IGNORE_EXCEPTION);
    354 }
    355 
    356 void Editor::pasteAsFragment(PassRefPtr<DocumentFragment> pastingFragment, bool smartReplace, bool matchStyle)
    357 {
    358     Node* target = findEventTargetFromSelection();
    359     if (!target)
    360         return;
    361     target->dispatchEvent(TextEvent::createForFragmentPaste(m_frame.domWindow(), pastingFragment, smartReplace, matchStyle), IGNORE_EXCEPTION);
    362 }
    363 
    364 bool Editor::tryDHTMLCopy()
    365 {
    366     if (m_frame.selection().isInPasswordField())
    367         return false;
    368 
    369     return !dispatchCPPEvent(EventTypeNames::copy, ClipboardWritable);
    370 }
    371 
    372 bool Editor::tryDHTMLCut()
    373 {
    374     if (m_frame.selection().isInPasswordField())
    375         return false;
    376 
    377     return !dispatchCPPEvent(EventTypeNames::cut, ClipboardWritable);
    378 }
    379 
    380 bool Editor::tryDHTMLPaste(PasteMode pasteMode)
    381 {
    382     return !dispatchCPPEvent(EventTypeNames::paste, ClipboardReadable, pasteMode);
    383 }
    384 
    385 void Editor::pasteAsPlainTextWithPasteboard(Pasteboard* pasteboard)
    386 {
    387     String text = pasteboard->plainText();
    388     pasteAsPlainText(text, canSmartReplaceWithPasteboard(pasteboard));
    389 }
    390 
    391 void Editor::pasteWithPasteboard(Pasteboard* pasteboard)
    392 {
    393     RefPtr<Range> range = selectedRange();
    394     RefPtr<DocumentFragment> fragment;
    395     bool chosePlainText = false;
    396 
    397     if (pasteboard->isHTMLAvailable()) {
    398         unsigned fragmentStart = 0;
    399         unsigned fragmentEnd = 0;
    400         KURL url;
    401         String markup = pasteboard->readHTML(url, fragmentStart, fragmentEnd);
    402         if (!markup.isEmpty()) {
    403             ASSERT(m_frame.document());
    404             fragment = createFragmentFromMarkupWithContext(*m_frame.document(), markup, fragmentStart, fragmentEnd, url, DisallowScriptingAndPluginContent);
    405         }
    406     }
    407 
    408     if (!fragment) {
    409         String text = pasteboard->plainText();
    410         if (!text.isEmpty()) {
    411             chosePlainText = true;
    412             fragment = createFragmentFromText(range.get(), text);
    413         }
    414     }
    415 
    416     if (fragment)
    417         pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), chosePlainText);
    418 }
    419 
    420 void Editor::writeSelectionToPasteboard(Pasteboard* pasteboard, Range* selectedRange, const String& plainText)
    421 {
    422     String html = createMarkup(selectedRange, 0, AnnotateForInterchange, false, ResolveNonLocalURLs);
    423     KURL url = selectedRange->startContainer()->document().url();
    424     pasteboard->writeHTML(html, url, plainText, canSmartCopyOrDelete());
    425 }
    426 
    427 static void writeImageNodeToPasteboard(Pasteboard* pasteboard, Node* node, const String& title)
    428 {
    429     ASSERT(pasteboard);
    430     ASSERT(node);
    431 
    432     if (!(node->renderer() && node->renderer()->isImage()))
    433         return;
    434 
    435     RenderImage* renderer = toRenderImage(node->renderer());
    436     ImageResource* cachedImage = renderer->cachedImage();
    437     if (!cachedImage || cachedImage->errorOccurred())
    438         return;
    439     Image* image = cachedImage->imageForRenderer(renderer);
    440     ASSERT(image);
    441 
    442     // FIXME: This should probably be reconciled with HitTestResult::absoluteImageURL.
    443     AtomicString urlString;
    444     if (node->hasTagName(imgTag) || node->hasTagName(inputTag))
    445         urlString = toElement(node)->getAttribute(srcAttr);
    446     else if (node->hasTagName(SVGNames::imageTag))
    447         urlString = toElement(node)->getAttribute(XLinkNames::hrefAttr);
    448     else if (node->hasTagName(embedTag) || node->hasTagName(objectTag))
    449         urlString = toElement(node)->imageSourceURL();
    450     KURL url = urlString.isEmpty() ? KURL() : node->document().completeURL(stripLeadingAndTrailingHTMLSpaces(urlString));
    451 
    452     pasteboard->writeImage(image, url, title);
    453 }
    454 
    455 // Returns whether caller should continue with "the default processing", which is the same as
    456 // the event handler NOT setting the return value to false
    457 bool Editor::dispatchCPPEvent(const AtomicString &eventType, ClipboardAccessPolicy policy, PasteMode pasteMode)
    458 {
    459     Node* target = findEventTargetFromSelection();
    460     if (!target)
    461         return true;
    462 
    463     RefPtr<Clipboard> clipboard = Clipboard::create(
    464         Clipboard::CopyAndPaste,
    465         policy,
    466         policy == ClipboardWritable
    467             ? ChromiumDataObject::create()
    468             : ChromiumDataObject::createFromPasteboard(pasteMode));
    469 
    470     RefPtr<Event> evt = ClipboardEvent::create(eventType, true, true, clipboard);
    471     target->dispatchEvent(evt, IGNORE_EXCEPTION);
    472     bool noDefaultProcessing = evt->defaultPrevented();
    473     if (noDefaultProcessing && policy == ClipboardWritable) {
    474         RefPtr<ChromiumDataObject> dataObject = clipboard->dataObject();
    475         Pasteboard::generalPasteboard()->writeDataObject(dataObject.release());
    476     }
    477 
    478     // invalidate clipboard here for security
    479     clipboard->setAccessPolicy(ClipboardNumb);
    480 
    481     return !noDefaultProcessing;
    482 }
    483 
    484 bool Editor::canSmartReplaceWithPasteboard(Pasteboard* pasteboard)
    485 {
    486     return smartInsertDeleteEnabled() && pasteboard->canSmartReplace();
    487 }
    488 
    489 void Editor::replaceSelectionWithFragment(PassRefPtr<DocumentFragment> fragment, bool selectReplacement, bool smartReplace, bool matchStyle)
    490 {
    491     if (m_frame.selection().isNone() || !m_frame.selection().isContentEditable() || !fragment)
    492         return;
    493 
    494     ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::PreventNesting | ReplaceSelectionCommand::SanitizeFragment;
    495     if (selectReplacement)
    496         options |= ReplaceSelectionCommand::SelectReplacement;
    497     if (smartReplace)
    498         options |= ReplaceSelectionCommand::SmartReplace;
    499     if (matchStyle)
    500         options |= ReplaceSelectionCommand::MatchStyle;
    501     ASSERT(m_frame.document());
    502     ReplaceSelectionCommand::create(*m_frame.document(), fragment, options, EditActionPaste)->apply();
    503     revealSelectionAfterEditingOperation();
    504 
    505     if (m_frame.selection().isInPasswordField() || !spellChecker().isContinuousSpellCheckingEnabled())
    506         return;
    507     spellChecker().chunkAndMarkAllMisspellingsAndBadGrammar(m_frame.selection().rootEditableElement());
    508 }
    509 
    510 void Editor::replaceSelectionWithText(const String& text, bool selectReplacement, bool smartReplace)
    511 {
    512     replaceSelectionWithFragment(createFragmentFromText(selectedRange().get(), text), selectReplacement, smartReplace, true);
    513 }
    514 
    515 PassRefPtr<Range> Editor::selectedRange()
    516 {
    517     return m_frame.selection().toNormalizedRange();
    518 }
    519 
    520 bool Editor::shouldDeleteRange(Range* range) const
    521 {
    522     if (!range || range->collapsed(IGNORE_EXCEPTION))
    523         return false;
    524 
    525     return canDeleteRange(range);
    526 }
    527 
    528 void Editor::notifyComponentsOnChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
    529 {
    530     client().respondToChangedSelection(m_frame.selection().selectionType());
    531     setStartNewKillRingSequence(true);
    532 }
    533 
    534 void Editor::respondToChangedContents(const VisibleSelection& endingSelection)
    535 {
    536     if (AXObjectCache::accessibilityEnabled()) {
    537         Node* node = endingSelection.start().deprecatedNode();
    538         if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache())
    539             cache->postNotification(node, AXObjectCache::AXValueChanged, false);
    540     }
    541 
    542     spellChecker().updateMarkersForWordsAffectedByEditing(true);
    543     client().respondToChangedContents();
    544 }
    545 
    546 TriState Editor::selectionUnorderedListState() const
    547 {
    548     if (m_frame.selection().isCaret()) {
    549         if (enclosingNodeWithTag(m_frame.selection().selection().start(), ulTag))
    550             return TrueTriState;
    551     } else if (m_frame.selection().isRange()) {
    552         Node* startNode = enclosingNodeWithTag(m_frame.selection().selection().start(), ulTag);
    553         Node* endNode = enclosingNodeWithTag(m_frame.selection().selection().end(), ulTag);
    554         if (startNode && endNode && startNode == endNode)
    555             return TrueTriState;
    556     }
    557 
    558     return FalseTriState;
    559 }
    560 
    561 TriState Editor::selectionOrderedListState() const
    562 {
    563     if (m_frame.selection().isCaret()) {
    564         if (enclosingNodeWithTag(m_frame.selection().selection().start(), olTag))
    565             return TrueTriState;
    566     } else if (m_frame.selection().isRange()) {
    567         Node* startNode = enclosingNodeWithTag(m_frame.selection().selection().start(), olTag);
    568         Node* endNode = enclosingNodeWithTag(m_frame.selection().selection().end(), olTag);
    569         if (startNode && endNode && startNode == endNode)
    570             return TrueTriState;
    571     }
    572 
    573     return FalseTriState;
    574 }
    575 
    576 PassRefPtr<Node> Editor::insertOrderedList()
    577 {
    578     if (!canEditRichly())
    579         return 0;
    580 
    581     ASSERT(m_frame.document());
    582     RefPtr<Node> newList = InsertListCommand::insertList(*m_frame.document(), InsertListCommand::OrderedList);
    583     revealSelectionAfterEditingOperation();
    584     return newList;
    585 }
    586 
    587 PassRefPtr<Node> Editor::insertUnorderedList()
    588 {
    589     if (!canEditRichly())
    590         return 0;
    591 
    592     ASSERT(m_frame.document());
    593     RefPtr<Node> newList = InsertListCommand::insertList(*m_frame.document(), InsertListCommand::UnorderedList);
    594     revealSelectionAfterEditingOperation();
    595     return newList;
    596 }
    597 
    598 bool Editor::canIncreaseSelectionListLevel()
    599 {
    600     ASSERT(m_frame.document());
    601     return canEditRichly() && IncreaseSelectionListLevelCommand::canIncreaseSelectionListLevel(*m_frame.document());
    602 }
    603 
    604 bool Editor::canDecreaseSelectionListLevel()
    605 {
    606     ASSERT(m_frame.document());
    607     return canEditRichly() && DecreaseSelectionListLevelCommand::canDecreaseSelectionListLevel(*m_frame.document());
    608 }
    609 
    610 PassRefPtr<Node> Editor::increaseSelectionListLevel()
    611 {
    612     if (!canEditRichly() || m_frame.selection().isNone())
    613         return 0;
    614 
    615     ASSERT(m_frame.document());
    616     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevel(*m_frame.document());
    617     revealSelectionAfterEditingOperation();
    618     return newList;
    619 }
    620 
    621 PassRefPtr<Node> Editor::increaseSelectionListLevelOrdered()
    622 {
    623     if (!canEditRichly() || m_frame.selection().isNone())
    624         return 0;
    625 
    626     ASSERT(m_frame.document());
    627     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(*m_frame.document());
    628     revealSelectionAfterEditingOperation();
    629     return newList.release();
    630 }
    631 
    632 PassRefPtr<Node> Editor::increaseSelectionListLevelUnordered()
    633 {
    634     if (!canEditRichly() || m_frame.selection().isNone())
    635         return 0;
    636 
    637     ASSERT(m_frame.document());
    638     RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(*m_frame.document());
    639     revealSelectionAfterEditingOperation();
    640     return newList.release();
    641 }
    642 
    643 void Editor::decreaseSelectionListLevel()
    644 {
    645     if (!canEditRichly() || m_frame.selection().isNone())
    646         return;
    647 
    648     ASSERT(m_frame.document());
    649     DecreaseSelectionListLevelCommand::decreaseSelectionListLevel(*m_frame.document());
    650     revealSelectionAfterEditingOperation();
    651 }
    652 
    653 void Editor::removeFormattingAndStyle()
    654 {
    655     ASSERT(m_frame.document());
    656     RemoveFormatCommand::create(*m_frame.document())->apply();
    657 }
    658 
    659 void Editor::clearLastEditCommand()
    660 {
    661     m_lastEditCommand.clear();
    662 }
    663 
    664 Node* Editor::findEventTargetFrom(const VisibleSelection& selection) const
    665 {
    666     Node* target = selection.start().element();
    667     if (!target)
    668         target = m_frame.document()->body();
    669 
    670     return target;
    671 }
    672 
    673 Node* Editor::findEventTargetFromSelection() const
    674 {
    675     return findEventTargetFrom(m_frame.selection().selection());
    676 }
    677 
    678 void Editor::applyStyle(StylePropertySet* style, EditAction editingAction)
    679 {
    680     switch (m_frame.selection().selectionType()) {
    681     case NoSelection:
    682         // do nothing
    683         break;
    684     case CaretSelection:
    685         computeAndSetTypingStyle(style, editingAction);
    686         break;
    687     case RangeSelection:
    688         if (style) {
    689             ASSERT(m_frame.document());
    690             ApplyStyleCommand::create(*m_frame.document(), EditingStyle::create(style).get(), editingAction)->apply();
    691         }
    692         break;
    693     }
    694 }
    695 
    696 void Editor::applyParagraphStyle(StylePropertySet* style, EditAction editingAction)
    697 {
    698     if (m_frame.selection().isNone() || !style)
    699         return;
    700     ASSERT(m_frame.document());
    701     ApplyStyleCommand::create(*m_frame.document(), EditingStyle::create(style).get(), editingAction, ApplyStyleCommand::ForceBlockProperties)->apply();
    702 }
    703 
    704 void Editor::applyStyleToSelection(StylePropertySet* style, EditAction editingAction)
    705 {
    706     if (!style || style->isEmpty() || !canEditRichly())
    707         return;
    708 
    709     applyStyle(style, editingAction);
    710 }
    711 
    712 void Editor::applyParagraphStyleToSelection(StylePropertySet* style, EditAction editingAction)
    713 {
    714     if (!style || style->isEmpty() || !canEditRichly())
    715         return;
    716 
    717     applyParagraphStyle(style, editingAction);
    718 }
    719 
    720 bool Editor::selectionStartHasStyle(CSSPropertyID propertyID, const String& value) const
    721 {
    722     return EditingStyle::create(propertyID, value)->triStateOfStyle(
    723         EditingStyle::styleAtSelectionStart(m_frame.selection().selection(), propertyID == CSSPropertyBackgroundColor).get());
    724 }
    725 
    726 TriState Editor::selectionHasStyle(CSSPropertyID propertyID, const String& value) const
    727 {
    728     return EditingStyle::create(propertyID, value)->triStateOfStyle(m_frame.selection().selection());
    729 }
    730 
    731 String Editor::selectionStartCSSPropertyValue(CSSPropertyID propertyID)
    732 {
    733     RefPtr<EditingStyle> selectionStyle = EditingStyle::styleAtSelectionStart(m_frame.selection().selection(),
    734         propertyID == CSSPropertyBackgroundColor);
    735     if (!selectionStyle || !selectionStyle->style())
    736         return String();
    737 
    738     if (propertyID == CSSPropertyFontSize)
    739         return String::number(selectionStyle->legacyFontSize(m_frame.document()));
    740     return selectionStyle->style()->getPropertyValue(propertyID);
    741 }
    742 
    743 void Editor::indent()
    744 {
    745     ASSERT(m_frame.document());
    746     IndentOutdentCommand::create(*m_frame.document(), IndentOutdentCommand::Indent)->apply();
    747 }
    748 
    749 void Editor::outdent()
    750 {
    751     ASSERT(m_frame.document());
    752     IndentOutdentCommand::create(*m_frame.document(), IndentOutdentCommand::Outdent)->apply();
    753 }
    754 
    755 static void dispatchEditableContentChangedEvents(PassRefPtr<Element> startRoot, PassRefPtr<Element> endRoot)
    756 {
    757     if (startRoot)
    758         startRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableContentChanged), IGNORE_EXCEPTION);
    759     if (endRoot && endRoot != startRoot)
    760         endRoot->dispatchEvent(Event::create(EventTypeNames::webkitEditableContentChanged), IGNORE_EXCEPTION);
    761 }
    762 
    763 void Editor::appliedEditing(PassRefPtr<CompositeEditCommand> cmd)
    764 {
    765     EventQueueScope scope;
    766     m_frame.document()->updateLayout();
    767 
    768     EditCommandComposition* composition = cmd->composition();
    769     ASSERT(composition);
    770     dispatchEditableContentChangedEvents(composition->startingRootEditableElement(), composition->endingRootEditableElement());
    771     VisibleSelection newSelection(cmd->endingSelection());
    772 
    773     // Don't clear the typing style with this selection change. We do those things elsewhere if necessary.
    774     changeSelectionAfterCommand(newSelection, 0);
    775 
    776     if (!cmd->preservesTypingStyle())
    777         m_frame.selection().clearTypingStyle();
    778 
    779     // Command will be equal to last edit command only in the case of typing
    780     if (m_lastEditCommand.get() == cmd) {
    781         ASSERT(cmd->isTypingCommand());
    782     } else {
    783         // Only register a new undo command if the command passed in is
    784         // different from the last command
    785         m_lastEditCommand = cmd;
    786         if (UndoStack* undoStack = this->undoStack())
    787             undoStack->registerUndoStep(m_lastEditCommand->ensureComposition());
    788     }
    789 
    790     respondToChangedContents(newSelection);
    791 }
    792 
    793 void Editor::unappliedEditing(PassRefPtr<EditCommandComposition> cmd)
    794 {
    795     EventQueueScope scope;
    796     m_frame.document()->updateLayout();
    797 
    798     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
    799 
    800     VisibleSelection newSelection(cmd->startingSelection());
    801     changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
    802 
    803     m_lastEditCommand = 0;
    804     if (UndoStack* undoStack = this->undoStack())
    805         undoStack->registerRedoStep(cmd);
    806     respondToChangedContents(newSelection);
    807 }
    808 
    809 void Editor::reappliedEditing(PassRefPtr<EditCommandComposition> cmd)
    810 {
    811     EventQueueScope scope;
    812     m_frame.document()->updateLayout();
    813 
    814     dispatchEditableContentChangedEvents(cmd->startingRootEditableElement(), cmd->endingRootEditableElement());
    815 
    816     VisibleSelection newSelection(cmd->endingSelection());
    817     changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
    818 
    819     m_lastEditCommand = 0;
    820     if (UndoStack* undoStack = this->undoStack())
    821         undoStack->registerUndoStep(cmd);
    822     respondToChangedContents(newSelection);
    823 }
    824 
    825 PassOwnPtr<Editor> Editor::create(Frame& frame)
    826 {
    827     return adoptPtr(new Editor(frame));
    828 }
    829 
    830 Editor::Editor(Frame& frame)
    831     : m_frame(frame)
    832     , m_preventRevealSelection(0)
    833     , m_shouldStartNewKillRingSequence(false)
    834     // This is off by default, since most editors want this behavior (this matches IE but not FF).
    835     , m_shouldStyleWithCSS(false)
    836     , m_killRing(adoptPtr(new KillRing))
    837     , m_areMarkedTextMatchesHighlighted(false)
    838     , m_defaultParagraphSeparator(EditorParagraphSeparatorIsDiv)
    839     , m_overwriteModeEnabled(false)
    840 {
    841 }
    842 
    843 Editor::~Editor()
    844 {
    845 }
    846 
    847 void Editor::clear()
    848 {
    849     m_frame.inputMethodController().clear();
    850     m_shouldStyleWithCSS = false;
    851     m_defaultParagraphSeparator = EditorParagraphSeparatorIsDiv;
    852 }
    853 
    854 bool Editor::insertText(const String& text, Event* triggeringEvent)
    855 {
    856     return m_frame.eventHandler().handleTextInputEvent(text, triggeringEvent);
    857 }
    858 
    859 bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectInsertedText, TextEvent* triggeringEvent)
    860 {
    861     if (text.isEmpty())
    862         return false;
    863 
    864     VisibleSelection selection = selectionForCommand(triggeringEvent);
    865     if (!selection.isContentEditable())
    866         return false;
    867     RefPtr<Range> range = selection.toNormalizedRange();
    868 
    869     spellChecker().updateMarkersForWordsAffectedByEditing(isSpaceOrNewline(text[0]));
    870 
    871     // Get the selection to use for the event that triggered this insertText.
    872     // If the event handler changed the selection, we may want to use a different selection
    873     // that is contained in the event target.
    874     selection = selectionForCommand(triggeringEvent);
    875     if (selection.isContentEditable()) {
    876         if (Node* selectionStart = selection.start().deprecatedNode()) {
    877             RefPtr<Document> document(selectionStart->document());
    878 
    879             // Insert the text
    880             TypingCommand::Options options = 0;
    881             if (selectInsertedText)
    882                 options |= TypingCommand::SelectInsertedText;
    883             TypingCommand::insertText(*document.get(), text, selection, options, triggeringEvent && triggeringEvent->isComposition() ? TypingCommand::TextCompositionConfirm : TypingCommand::TextCompositionNone);
    884 
    885             // Reveal the current selection
    886             if (Frame* editedFrame = document->frame()) {
    887                 if (Page* page = editedFrame->page())
    888                     page->focusController().focusedOrMainFrame()->selection().revealSelection(ScrollAlignment::alignCenterIfNeeded);
    889             }
    890         }
    891     }
    892 
    893     return true;
    894 }
    895 
    896 bool Editor::insertLineBreak()
    897 {
    898     if (!canEdit())
    899         return false;
    900 
    901     VisiblePosition caret = m_frame.selection().selection().visibleStart();
    902     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
    903     ASSERT(m_frame.document());
    904     TypingCommand::insertLineBreak(*m_frame.document(), 0);
    905     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
    906 
    907     return true;
    908 }
    909 
    910 bool Editor::insertParagraphSeparator()
    911 {
    912     if (!canEdit())
    913         return false;
    914 
    915     if (!canEditRichly())
    916         return insertLineBreak();
    917 
    918     VisiblePosition caret = m_frame.selection().selection().visibleStart();
    919     bool alignToEdge = isEndOfEditableOrNonEditableContent(caret);
    920     ASSERT(m_frame.document());
    921     TypingCommand::insertParagraphSeparator(*m_frame.document(), 0);
    922     revealSelectionAfterEditingOperation(alignToEdge ? ScrollAlignment::alignToEdgeIfNeeded : ScrollAlignment::alignCenterIfNeeded);
    923 
    924     return true;
    925 }
    926 
    927 void Editor::cut()
    928 {
    929     if (tryDHTMLCut())
    930         return; // DHTML did the whole operation
    931     if (!canCut())
    932         return;
    933     RefPtr<Range> selection = selectedRange();
    934     if (shouldDeleteRange(selection.get())) {
    935         spellChecker().updateMarkersForWordsAffectedByEditing(true);
    936         String plainText = m_frame.selectedTextForClipboard();
    937         if (enclosingTextFormControl(m_frame.selection().start())) {
    938             Pasteboard::generalPasteboard()->writePlainText(plainText,
    939                 canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
    940         } else {
    941             writeSelectionToPasteboard(Pasteboard::generalPasteboard(), selection.get(), plainText);
    942         }
    943         deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
    944     }
    945 }
    946 
    947 void Editor::copy()
    948 {
    949     if (tryDHTMLCopy())
    950         return; // DHTML did the whole operation
    951     if (!canCopy())
    952         return;
    953     if (enclosingTextFormControl(m_frame.selection().start())) {
    954         Pasteboard::generalPasteboard()->writePlainText(m_frame.selectedTextForClipboard(),
    955             canSmartCopyOrDelete() ? Pasteboard::CanSmartReplace : Pasteboard::CannotSmartReplace);
    956     } else {
    957         Document* document = m_frame.document();
    958         if (HTMLImageElement* imageElement = imageElementFromImageDocument(document))
    959             writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), imageElement, document->title());
    960         else
    961             writeSelectionToPasteboard(Pasteboard::generalPasteboard(), selectedRange().get(), m_frame.selectedTextForClipboard());
    962     }
    963 }
    964 
    965 void Editor::paste()
    966 {
    967     ASSERT(m_frame.document());
    968     if (tryDHTMLPaste(AllMimeTypes))
    969         return; // DHTML did the whole operation
    970     if (!canPaste())
    971         return;
    972     spellChecker().updateMarkersForWordsAffectedByEditing(false);
    973     ResourceFetcher* loader = m_frame.document()->fetcher();
    974     ResourceCacheValidationSuppressor validationSuppressor(loader);
    975     if (m_frame.selection().isContentRichlyEditable())
    976         pasteWithPasteboard(Pasteboard::generalPasteboard());
    977     else
    978         pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
    979 }
    980 
    981 void Editor::pasteAsPlainText()
    982 {
    983     if (tryDHTMLPaste(PlainTextOnly))
    984         return;
    985     if (!canPaste())
    986         return;
    987     spellChecker().updateMarkersForWordsAffectedByEditing(false);
    988     pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
    989 }
    990 
    991 void Editor::performDelete()
    992 {
    993     if (!canDelete())
    994         return;
    995     addToKillRing(selectedRange().get(), false);
    996     deleteSelectionWithSmartDelete(canSmartCopyOrDelete());
    997 
    998     // clear the "start new kill ring sequence" setting, because it was set to true
    999     // when the selection was updated by deleting the range
   1000     setStartNewKillRingSequence(false);
   1001 }
   1002 
   1003 void Editor::copyImage(const HitTestResult& result)
   1004 {
   1005     writeImageNodeToPasteboard(Pasteboard::generalPasteboard(), result.innerNonSharedNode(), result.altDisplayString());
   1006 }
   1007 
   1008 bool Editor::canUndo()
   1009 {
   1010     if (UndoStack* undoStack = this->undoStack())
   1011         return undoStack->canUndo();
   1012     return false;
   1013 }
   1014 
   1015 void Editor::undo()
   1016 {
   1017     if (UndoStack* undoStack = this->undoStack())
   1018         undoStack->undo();
   1019 }
   1020 
   1021 bool Editor::canRedo()
   1022 {
   1023     if (UndoStack* undoStack = this->undoStack())
   1024         return undoStack->canRedo();
   1025     return false;
   1026 }
   1027 
   1028 void Editor::redo()
   1029 {
   1030     if (UndoStack* undoStack = this->undoStack())
   1031         undoStack->redo();
   1032 }
   1033 
   1034 void Editor::setBaseWritingDirection(WritingDirection direction)
   1035 {
   1036     Node* focusedElement = frame().document()->focusedElement();
   1037     if (focusedElement && isHTMLTextFormControlElement(focusedElement)) {
   1038         if (direction == NaturalWritingDirection)
   1039             return;
   1040         toHTMLElement(focusedElement)->setAttribute(dirAttr, direction == LeftToRightWritingDirection ? "ltr" : "rtl");
   1041         focusedElement->dispatchInputEvent();
   1042         frame().document()->updateStyleIfNeeded();
   1043         return;
   1044     }
   1045 
   1046     RefPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
   1047     style->setProperty(CSSPropertyDirection, direction == LeftToRightWritingDirection ? "ltr" : direction == RightToLeftWritingDirection ? "rtl" : "inherit", false);
   1048     applyParagraphStyleToSelection(style.get(), EditActionSetWritingDirection);
   1049 }
   1050 
   1051 void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
   1052 {
   1053     if (m_preventRevealSelection)
   1054         return;
   1055 
   1056     m_frame.selection().revealSelection(alignment, revealExtentOption);
   1057 }
   1058 
   1059 void Editor::transpose()
   1060 {
   1061     if (!canEdit())
   1062         return;
   1063 
   1064     VisibleSelection selection = m_frame.selection().selection();
   1065     if (!selection.isCaret())
   1066         return;
   1067 
   1068     // Make a selection that goes back one character and forward two characters.
   1069     VisiblePosition caret = selection.visibleStart();
   1070     VisiblePosition next = isEndOfParagraph(caret) ? caret : caret.next();
   1071     VisiblePosition previous = next.previous();
   1072     if (next == previous)
   1073         return;
   1074     previous = previous.previous();
   1075     if (!inSameParagraph(next, previous))
   1076         return;
   1077     RefPtr<Range> range = makeRange(previous, next);
   1078     if (!range)
   1079         return;
   1080     VisibleSelection newSelection(range.get(), DOWNSTREAM);
   1081 
   1082     // Transpose the two characters.
   1083     String text = plainText(range.get());
   1084     if (text.length() != 2)
   1085         return;
   1086     String transposed = text.right(1) + text.left(1);
   1087 
   1088     // Select the two characters.
   1089     if (newSelection != m_frame.selection().selection())
   1090         m_frame.selection().setSelection(newSelection);
   1091 
   1092     // Insert the transposed characters.
   1093     replaceSelectionWithText(transposed, false, false);
   1094 }
   1095 
   1096 void Editor::addToKillRing(Range* range, bool prepend)
   1097 {
   1098     if (m_shouldStartNewKillRingSequence)
   1099         killRing().startNewSequence();
   1100 
   1101     String text = plainText(range);
   1102     if (prepend)
   1103         killRing().prepend(text);
   1104     else
   1105         killRing().append(text);
   1106     m_shouldStartNewKillRingSequence = false;
   1107 }
   1108 
   1109 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection,  FrameSelection::SetSelectionOptions options)
   1110 {
   1111     // If the new selection is orphaned, then don't update the selection.
   1112     if (newSelection.start().isOrphan() || newSelection.end().isOrphan())
   1113         return;
   1114 
   1115     // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
   1116     bool selectionDidNotChangeDOMPosition = newSelection == m_frame.selection().selection();
   1117     m_frame.selection().setSelection(newSelection, options);
   1118 
   1119     // Some editing operations change the selection visually without affecting its position within the DOM.
   1120     // For example when you press return in the following (the caret is marked by ^):
   1121     // <div contentEditable="true"><div>^Hello</div></div>
   1122     // WebCore inserts <div><br></div> *before* the current block, which correctly moves the paragraph down but which doesn't
   1123     // change the caret's DOM position (["hello", 0]). In these situations the above FrameSelection::setSelection call
   1124     // does not call EditorClient::respondToChangedSelection(), which, on the Mac, sends selection change notifications and
   1125     // starts a new kill ring sequence, but we want to do these things (matches AppKit).
   1126     if (selectionDidNotChangeDOMPosition)
   1127         client().respondToChangedSelection(m_frame.selection().selectionType());
   1128 }
   1129 
   1130 IntRect Editor::firstRectForRange(Range* range) const
   1131 {
   1132     LayoutUnit extraWidthToEndOfLine = 0;
   1133     ASSERT(range->startContainer());
   1134     ASSERT(range->endContainer());
   1135 
   1136     IntRect startCaretRect = RenderedPosition(VisiblePosition(range->startPosition()).deepEquivalent(), DOWNSTREAM).absoluteRect(&extraWidthToEndOfLine);
   1137     if (startCaretRect == LayoutRect())
   1138         return IntRect();
   1139 
   1140     IntRect endCaretRect = RenderedPosition(VisiblePosition(range->endPosition()).deepEquivalent(), UPSTREAM).absoluteRect();
   1141     if (endCaretRect == LayoutRect())
   1142         return IntRect();
   1143 
   1144     if (startCaretRect.y() == endCaretRect.y()) {
   1145         // start and end are on the same line
   1146         return IntRect(min(startCaretRect.x(), endCaretRect.x()),
   1147             startCaretRect.y(),
   1148             abs(endCaretRect.x() - startCaretRect.x()),
   1149             max(startCaretRect.height(), endCaretRect.height()));
   1150     }
   1151 
   1152     // start and end aren't on the same line, so go from start to the end of its line
   1153     return IntRect(startCaretRect.x(),
   1154         startCaretRect.y(),
   1155         startCaretRect.width() + extraWidthToEndOfLine,
   1156         startCaretRect.height());
   1157 }
   1158 
   1159 void Editor::computeAndSetTypingStyle(StylePropertySet* style, EditAction editingAction)
   1160 {
   1161     if (!style || style->isEmpty()) {
   1162         m_frame.selection().clearTypingStyle();
   1163         return;
   1164     }
   1165 
   1166     // Calculate the current typing style.
   1167     RefPtr<EditingStyle> typingStyle;
   1168     if (m_frame.selection().typingStyle()) {
   1169         typingStyle = m_frame.selection().typingStyle()->copy();
   1170         typingStyle->overrideWithStyle(style);
   1171     } else {
   1172         typingStyle = EditingStyle::create(style);
   1173     }
   1174 
   1175     typingStyle->prepareToApplyAt(m_frame.selection().selection().visibleStart().deepEquivalent(), EditingStyle::PreserveWritingDirection);
   1176 
   1177     // Handle block styles, substracting these from the typing style.
   1178     RefPtr<EditingStyle> blockStyle = typingStyle->extractAndRemoveBlockProperties();
   1179     if (!blockStyle->isEmpty()) {
   1180         ASSERT(m_frame.document());
   1181         ApplyStyleCommand::create(*m_frame.document(), blockStyle.get(), editingAction)->apply();
   1182     }
   1183 
   1184     // Set the remaining style as the typing style.
   1185     m_frame.selection().setTypingStyle(typingStyle);
   1186 }
   1187 
   1188 bool Editor::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection)
   1189 {
   1190     FindOptions options = (forward ? 0 : Backwards) | (caseFlag ? 0 : CaseInsensitive) | (wrapFlag ? WrapAround : 0) | (startInSelection ? StartInSelection : 0);
   1191     return findString(target, options);
   1192 }
   1193 
   1194 bool Editor::findString(const String& target, FindOptions options)
   1195 {
   1196     VisibleSelection selection = m_frame.selection().selection();
   1197 
   1198     RefPtr<Range> resultRange = rangeOfString(target, selection.firstRange().get(), options);
   1199 
   1200     if (!resultRange)
   1201         return false;
   1202 
   1203     m_frame.selection().setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM));
   1204     m_frame.selection().revealSelection();
   1205     return true;
   1206 }
   1207 
   1208 PassRefPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* previousMatch, FindOptions options)
   1209 {
   1210     RefPtr<Range> nextMatch = rangeOfString(target, previousMatch, options);
   1211     if (!nextMatch)
   1212         return 0;
   1213 
   1214     nextMatch->firstNode()->renderer()->scrollRectToVisible(nextMatch->boundingBox(),
   1215         ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
   1216 
   1217     return nextMatch.release();
   1218 }
   1219 
   1220 PassRefPtr<Range> Editor::rangeOfString(const String& target, Range* referenceRange, FindOptions options)
   1221 {
   1222     if (target.isEmpty())
   1223         return 0;
   1224 
   1225     // Start from an edge of the reference range, if there's a reference range that's not in shadow content. Which edge
   1226     // is used depends on whether we're searching forward or backward, and whether startInSelection is set.
   1227     RefPtr<Range> searchRange(rangeOfContents(m_frame.document()));
   1228 
   1229     bool forward = !(options & Backwards);
   1230     bool startInReferenceRange = referenceRange && (options & StartInSelection);
   1231     if (referenceRange) {
   1232         if (forward)
   1233             searchRange->setStart(startInReferenceRange ? referenceRange->startPosition() : referenceRange->endPosition());
   1234         else
   1235             searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
   1236     }
   1237 
   1238     RefPtr<Node> shadowTreeRoot = referenceRange && referenceRange->startContainer() ? referenceRange->startContainer()->nonBoundaryShadowTreeRootNode() : 0;
   1239     if (shadowTreeRoot) {
   1240         if (forward)
   1241             searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->childNodeCount());
   1242         else
   1243             searchRange->setStart(shadowTreeRoot.get(), 0);
   1244     }
   1245 
   1246     RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, options));
   1247     // If we started in the reference range and the found range exactly matches the reference range, find again.
   1248     // Build a selection with the found range to remove collapsed whitespace.
   1249     // Compare ranges instead of selection objects to ignore the way that the current selection was made.
   1250     if (startInReferenceRange && areRangesEqual(VisibleSelection(resultRange.get()).toNormalizedRange().get(), referenceRange)) {
   1251         searchRange = rangeOfContents(m_frame.document());
   1252         if (forward)
   1253             searchRange->setStart(referenceRange->endPosition());
   1254         else
   1255             searchRange->setEnd(referenceRange->startPosition());
   1256 
   1257         if (shadowTreeRoot) {
   1258             if (forward)
   1259                 searchRange->setEnd(shadowTreeRoot.get(), shadowTreeRoot->childNodeCount());
   1260             else
   1261                 searchRange->setStart(shadowTreeRoot.get(), 0);
   1262         }
   1263 
   1264         resultRange = findPlainText(searchRange.get(), target, options);
   1265     }
   1266 
   1267     // If nothing was found in the shadow tree, search in main content following the shadow tree.
   1268     if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && shadowTreeRoot) {
   1269         searchRange = rangeOfContents(m_frame.document());
   1270         if (forward)
   1271             searchRange->setStartAfter(shadowTreeRoot->shadowHost());
   1272         else
   1273             searchRange->setEndBefore(shadowTreeRoot->shadowHost());
   1274 
   1275         resultRange = findPlainText(searchRange.get(), target, options);
   1276     }
   1277 
   1278     // If we didn't find anything and we're wrapping, search again in the entire document (this will
   1279     // redundantly re-search the area already searched in some cases).
   1280     if (resultRange->collapsed(ASSERT_NO_EXCEPTION) && options & WrapAround) {
   1281         searchRange = rangeOfContents(m_frame.document());
   1282         resultRange = findPlainText(searchRange.get(), target, options);
   1283         // We used to return false here if we ended up with the same range that we started with
   1284         // (e.g., the reference range was already the only instance of this text). But we decided that
   1285         // this should be a success case instead, so we'll just fall through in that case.
   1286     }
   1287 
   1288     return resultRange->collapsed(ASSERT_NO_EXCEPTION) ? 0 : resultRange.release();
   1289 }
   1290 
   1291 void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
   1292 {
   1293     if (flag == m_areMarkedTextMatchesHighlighted)
   1294         return;
   1295 
   1296     m_areMarkedTextMatchesHighlighted = flag;
   1297     m_frame.document()->markers()->repaintMarkers(DocumentMarker::TextMatch);
   1298 }
   1299 
   1300 void Editor::respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
   1301 {
   1302     spellChecker().respondToChangedSelection(oldSelection, options);
   1303     m_frame.inputMethodController().cancelCompositionIfSelectionIsInvalid();
   1304     notifyComponentsOnChangedSelection(oldSelection, options);
   1305 }
   1306 
   1307 SpellChecker& Editor::spellChecker() const
   1308 {
   1309     return m_frame.spellChecker();
   1310 }
   1311 
   1312 void Editor::toggleOverwriteModeEnabled()
   1313 {
   1314     m_overwriteModeEnabled = !m_overwriteModeEnabled;
   1315     frame().selection().setShouldShowBlockCursor(m_overwriteModeEnabled);
   1316 }
   1317 
   1318 } // namespace WebCore
   1319