1/*
2 * Copyright (C) 2004, 2008, 2009, 2010 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "FrameSelection.h"
28
29#include "CharacterData.h"
30#include "DeleteSelectionCommand.h"
31#include "Document.h"
32#include "Editor.h"
33#include "EditorClient.h"
34#include "Element.h"
35#include "EventHandler.h"
36#include "ExceptionCode.h"
37#include "FloatQuad.h"
38#include "FocusController.h"
39#include "Frame.h"
40#include "FrameTree.h"
41#include "FrameView.h"
42#include "GraphicsContext.h"
43#include "HTMLFormElement.h"
44#include "HTMLFrameElementBase.h"
45#include "HTMLInputElement.h"
46#include "HTMLSelectElement.h"
47#include "HTMLNames.h"
48#include "HitTestRequest.h"
49#include "HitTestResult.h"
50#include "InlineTextBox.h"
51#include "NodeTraversal.h"
52#include "Page.h"
53#include "Range.h"
54#include "RenderText.h"
55#include "RenderTextControl.h"
56#include "RenderTheme.h"
57#include "RenderView.h"
58#include "RenderWidget.h"
59#include "RenderedPosition.h"
60#include "Settings.h"
61#include "SpatialNavigation.h"
62#include "StylePropertySet.h"
63#include "TextIterator.h"
64#include "TypingCommand.h"
65#include "VisibleUnits.h"
66#include "htmlediting.h"
67#include <limits.h>
68#include <stdio.h>
69#include <wtf/text/CString.h>
70
71#define EDIT_DEBUG 0
72
73namespace WebCore {
74
75using namespace HTMLNames;
76
77static inline LayoutUnit NoXPosForVerticalArrowNavigation()
78{
79    return LayoutUnit::min();
80}
81
82CaretBase::CaretBase(CaretVisibility visibility)
83    : m_caretRectNeedsUpdate(true)
84    , m_caretVisibility(visibility)
85{
86}
87
88DragCaretController::DragCaretController()
89    : CaretBase(Visible)
90{
91}
92
93PassOwnPtr<DragCaretController> DragCaretController::create()
94{
95    return adoptPtr(new DragCaretController);
96}
97
98bool DragCaretController::isContentRichlyEditable() const
99{
100    return isRichlyEditablePosition(m_position.deepEquivalent());
101}
102
103static inline bool shouldAlwaysUseDirectionalSelection(Frame* frame)
104{
105    return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirectional();
106}
107
108FrameSelection::FrameSelection(Frame* frame)
109    : m_frame(frame)
110    , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
111    , m_granularity(CharacterGranularity)
112    , m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired)
113    , m_absCaretBoundsDirty(true)
114    , m_caretPaint(true)
115    , m_isCaretBlinkingSuspended(false)
116    , m_focused(frame && frame->page() && frame->page()->focusController()->focusedFrame() == frame)
117    , m_shouldShowBlockCursor(false)
118{
119    if (shouldAlwaysUseDirectionalSelection(m_frame))
120        m_selection.setIsDirectional(true);
121}
122
123Element* FrameSelection::rootEditableElementOrDocumentElement() const
124{
125    Element* selectionRoot = m_selection.rootEditableElement();
126    return selectionRoot ? selectionRoot : m_frame->document()->documentElement();
127}
128
129Node* FrameSelection::rootEditableElementOrTreeScopeRootNode() const
130{
131    Element* selectionRoot = m_selection.rootEditableElement();
132    if (selectionRoot)
133        return selectionRoot;
134
135    Node* node = m_selection.base().containerNode();
136    return node ? node->treeScope()->rootNode() : 0;
137}
138
139Element* FrameSelection::rootEditableElementRespectingShadowTree() const
140{
141    Element* selectionRoot = m_selection.rootEditableElement();
142    if (selectionRoot && selectionRoot->isInShadowTree())
143        selectionRoot = selectionRoot->shadowHost();
144    return selectionRoot;
145}
146
147void FrameSelection::moveTo(const VisiblePosition &pos, EUserTriggered userTriggered, CursorAlignOnScroll align)
148{
149    SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
150    setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity(), m_selection.isDirectional()), options, align);
151}
152
153void FrameSelection::moveTo(const VisiblePosition &base, const VisiblePosition &extent, EUserTriggered userTriggered)
154{
155    const bool selectionHasDirection = true;
156    SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
157    setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity(), selectionHasDirection), options);
158}
159
160void FrameSelection::moveTo(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
161{
162    SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
163    setSelection(VisibleSelection(pos, affinity, m_selection.isDirectional()), options);
164}
165
166void FrameSelection::moveTo(const Range *r, EAffinity affinity, EUserTriggered userTriggered)
167{
168    SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
169    VisibleSelection selection = r ? VisibleSelection(r->startPosition(), r->endPosition(), affinity) : VisibleSelection(Position(), Position(), affinity);
170    setSelection(selection, options);
171}
172
173void FrameSelection::moveTo(const Position &base, const Position &extent, EAffinity affinity, EUserTriggered userTriggered)
174{
175    const bool selectionHasDirection = true;
176    SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
177    setSelection(VisibleSelection(base, extent, affinity, selectionHasDirection), options);
178}
179
180void DragCaretController::setCaretPosition(const VisiblePosition& position)
181{
182    if (Node* node = m_position.deepEquivalent().deprecatedNode())
183        invalidateCaretRect(node);
184    m_position = position;
185    setCaretRectNeedsUpdate();
186    Document* document = 0;
187    if (Node* node = m_position.deepEquivalent().deprecatedNode()) {
188        invalidateCaretRect(node);
189        document = node->document();
190    }
191    if (m_position.isNull() || m_position.isOrphan())
192        clearCaretRect();
193    else
194        updateCaretRect(document, m_position);
195}
196
197static void adjustEndpointsAtBidiBoundary(VisiblePosition& visibleBase, VisiblePosition& visibleExtent)
198{
199    RenderedPosition base(visibleBase);
200    RenderedPosition extent(visibleExtent);
201
202    if (base.isNull() || extent.isNull() || base.isEquivalent(extent))
203        return;
204
205    if (base.atLeftBoundaryOfBidiRun()) {
206        if (!extent.atRightBoundaryOfBidiRun(base.bidiLevelOnRight())
207            && base.isEquivalent(extent.leftBoundaryOfBidiRun(base.bidiLevelOnRight()))) {
208            visibleBase = base.positionAtLeftBoundaryOfBiDiRun();
209            return;
210        }
211        return;
212    }
213
214    if (base.atRightBoundaryOfBidiRun()) {
215        if (!extent.atLeftBoundaryOfBidiRun(base.bidiLevelOnLeft())
216            && base.isEquivalent(extent.rightBoundaryOfBidiRun(base.bidiLevelOnLeft()))) {
217            visibleBase = base.positionAtRightBoundaryOfBiDiRun();
218            return;
219        }
220        return;
221    }
222
223    if (extent.atLeftBoundaryOfBidiRun() && extent.isEquivalent(base.leftBoundaryOfBidiRun(extent.bidiLevelOnRight()))) {
224        visibleExtent = extent.positionAtLeftBoundaryOfBiDiRun();
225        return;
226    }
227
228    if (extent.atRightBoundaryOfBidiRun() && extent.isEquivalent(base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) {
229        visibleExtent = extent.positionAtRightBoundaryOfBiDiRun();
230        return;
231    }
232}
233
234void FrameSelection::setNonDirectionalSelectionIfNeeded(const VisibleSelection& passedNewSelection, TextGranularity granularity,
235    EndPointsAdjustmentMode endpointsAdjustmentMode)
236{
237    VisibleSelection newSelection = passedNewSelection;
238    bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || newSelection.isDirectional();
239
240    VisiblePosition base = m_originalBase.isNotNull() ? m_originalBase : newSelection.visibleBase();
241    VisiblePosition newBase = base;
242    VisiblePosition newExtent = newSelection.visibleExtent();
243    if (endpointsAdjustmentMode == AdjustEndpointsAtBidiBoundary)
244        adjustEndpointsAtBidiBoundary(newBase, newExtent);
245
246    if (newBase != base || newExtent != newSelection.visibleExtent()) {
247        m_originalBase = base;
248        newSelection.setBase(newBase);
249        newSelection.setExtent(newExtent);
250    } else if (m_originalBase.isNotNull()) {
251        if (m_selection.base() == newSelection.base())
252            newSelection.setBase(m_originalBase);
253        m_originalBase.clear();
254    }
255
256    newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
257    if (m_selection == newSelection || !shouldChangeSelection(newSelection))
258        return;
259
260    setSelection(newSelection, granularity);
261}
262
263void FrameSelection::setSelection(const VisibleSelection& newSelection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity)
264{
265    bool closeTyping = options & CloseTyping;
266    bool shouldClearTypingStyle = options & ClearTypingStyle;
267    EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
268
269    VisibleSelection s = newSelection;
270    if (shouldAlwaysUseDirectionalSelection(m_frame))
271        s.setIsDirectional(true);
272
273    if (!m_frame) {
274        m_selection = s;
275        return;
276    }
277
278    // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at FrameSelection::setSelection
279    // if document->frame() == m_frame we can get into an infinite loop
280    if (s.base().anchorNode()) {
281        Document* document = s.base().anchorNode()->document();
282        if (document && document->frame() && document->frame() != m_frame && document != m_frame->document()) {
283            RefPtr<Frame> guard = document->frame();
284            document->frame()->selection()->setSelection(s, options, align, granularity);
285            // It's possible that during the above set selection, this FrameSelection has been modified by
286            // selectFrameElementInParentIfFullySelected, but that the selection is no longer valid since
287            // the frame is about to be destroyed. If this is the case, clear our selection.
288            if (guard->hasOneRef() && !m_selection.isNonOrphanedCaretOrRange())
289                clear();
290            return;
291        }
292    }
293
294    m_granularity = granularity;
295
296    if (closeTyping)
297        TypingCommand::closeTyping(m_frame);
298
299    if (shouldClearTypingStyle)
300        clearTypingStyle();
301
302    if (m_selection == s) {
303        // Even if selection was not changed, selection offsets may have been changed.
304        notifyRendererOfSelectionChange(userTriggered);
305        return;
306    }
307
308    VisibleSelection oldSelection = m_selection;
309
310    m_selection = s;
311    setCaretRectNeedsUpdate();
312
313    if (!s.isNone() && !(options & DoNotSetFocus))
314        setFocusedElementIfNeeded();
315
316    if (!(options & DoNotUpdateAppearance)) {
317#if ENABLE(TEXT_CARET)
318        m_frame->document()->updateLayoutIgnorePendingStylesheets();
319#else
320        m_frame->document()->updateStyleIfNeeded();
321#endif
322        updateAppearance();
323    }
324
325    // Always clear the x position used for vertical arrow navigation.
326    // It will be restored by the vertical arrow navigation code if necessary.
327    m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
328    selectFrameElementInParentIfFullySelected();
329    notifyRendererOfSelectionChange(userTriggered);
330    m_frame->editor().respondToChangedSelection(oldSelection, options);
331    if (userTriggered == UserTriggered) {
332        ScrollAlignment alignment;
333
334        if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
335            alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignCenterAlways : ScrollAlignment::alignCenterIfNeeded;
336        else
337            alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
338
339        revealSelection(alignment, RevealExtent);
340    }
341#if HAVE(ACCESSIBILITY)
342    notifyAccessibilityForSelectionChange();
343#endif
344    m_frame->document()->enqueueDocumentEvent(Event::create(eventNames().selectionchangeEvent, false, false));
345}
346
347static bool removingNodeRemovesPosition(Node* node, const Position& position)
348{
349    if (!position.anchorNode())
350        return false;
351
352    if (position.anchorNode() == node)
353        return true;
354
355    if (!node->isElementNode())
356        return false;
357
358    Element* element = toElement(node);
359    return element->containsIncludingShadowDOM(position.anchorNode());
360}
361
362static void clearRenderViewSelection(const Position& position)
363{
364    RefPtr<Document> document = position.anchorNode()->document();
365    document->updateStyleIfNeeded();
366    if (RenderView* view = document->renderView())
367        view->clearSelection();
368}
369
370void DragCaretController::nodeWillBeRemoved(Node* node)
371{
372    if (!hasCaret() || (node && !node->inDocument()))
373        return;
374
375    if (!removingNodeRemovesPosition(node, m_position.deepEquivalent()))
376        return;
377
378    clearRenderViewSelection(m_position.deepEquivalent());
379    clear();
380}
381
382void FrameSelection::nodeWillBeRemoved(Node* node)
383{
384    // There can't be a selection inside a fragment, so if a fragment's node is being removed,
385    // the selection in the document that created the fragment needs no adjustment.
386    if (isNone() || (node && !node->inDocument()))
387        return;
388
389    respondToNodeModification(node, removingNodeRemovesPosition(node, m_selection.base()), removingNodeRemovesPosition(node, m_selection.extent()),
390        removingNodeRemovesPosition(node, m_selection.start()), removingNodeRemovesPosition(node, m_selection.end()));
391}
392
393void FrameSelection::respondToNodeModification(Node* node, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved)
394{
395    bool clearRenderTreeSelection = false;
396    bool clearDOMTreeSelection = false;
397
398    if (startRemoved || endRemoved) {
399        Position start = m_selection.start();
400        Position end = m_selection.end();
401        if (startRemoved)
402            updatePositionForNodeRemoval(start, node);
403        if (endRemoved)
404            updatePositionForNodeRemoval(end, node);
405
406        if (start.isNotNull() && end.isNotNull()) {
407            if (m_selection.isBaseFirst())
408                m_selection.setWithoutValidation(start, end);
409            else
410                m_selection.setWithoutValidation(end, start);
411        } else
412            clearDOMTreeSelection = true;
413
414        clearRenderTreeSelection = true;
415    } else if (baseRemoved || extentRemoved) {
416        // The base and/or extent are about to be removed, but the start and end aren't.
417        // Change the base and extent to the start and end, but don't re-validate the
418        // selection, since doing so could move the start and end into the node
419        // that is about to be removed.
420        if (m_selection.isBaseFirst())
421            m_selection.setWithoutValidation(m_selection.start(), m_selection.end());
422        else
423            m_selection.setWithoutValidation(m_selection.end(), m_selection.start());
424    } else if (RefPtr<Range> range = m_selection.firstRange()) {
425        ExceptionCode ec = 0;
426        Range::CompareResults compareResult = range->compareNode(node, ec);
427        if (!ec && (compareResult == Range::NODE_BEFORE_AND_AFTER || compareResult == Range::NODE_INSIDE)) {
428            // If we did nothing here, when this node's renderer was destroyed, the rect that it
429            // occupied would be invalidated, but, selection gaps that change as a result of
430            // the removal wouldn't be invalidated.
431            // FIXME: Don't do so much unnecessary invalidation.
432            clearRenderTreeSelection = true;
433        }
434    }
435
436    if (clearRenderTreeSelection)
437        clearRenderViewSelection(m_selection.start());
438
439    if (clearDOMTreeSelection)
440        setSelection(VisibleSelection(), DoNotSetFocus);
441}
442
443static void updatePositionAfterAdoptingTextReplacement(Position& position, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
444{
445    if (!position.anchorNode() || position.anchorNode() != node || position.anchorType() != Position::PositionIsOffsetInAnchor)
446        return;
447
448    // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation
449    ASSERT(position.offsetInContainerNode() >= 0);
450    unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
451    // Replacing text can be viewed as a deletion followed by insertion.
452    if (positionOffset >= offset && positionOffset <= offset + oldLength)
453        position.moveToOffset(offset);
454
455    // Adjust the offset if the position is after the end of the deleted contents
456    // (positionOffset > offset + oldLength) to avoid having a stale offset.
457    if (positionOffset > offset + oldLength)
458        position.moveToOffset(positionOffset - oldLength + newLength);
459
460    ASSERT(static_cast<unsigned>(position.offsetInContainerNode()) <= node->length());
461}
462
463static inline bool nodeIsDetachedFromDocument(Node* node)
464{
465    ASSERT(node);
466    Node* highest = highestAncestor(node);
467    return highest->nodeType() == Node::DOCUMENT_FRAGMENT_NODE && !highest->isShadowRoot();
468}
469
470void FrameSelection::textWasReplaced(CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
471{
472    // The fragment check is a performance optimization. See http://trac.webkit.org/changeset/30062.
473    if (isNone() || !node || nodeIsDetachedFromDocument(node))
474        return;
475
476    Position base = m_selection.base();
477    Position extent = m_selection.extent();
478    Position start = m_selection.start();
479    Position end = m_selection.end();
480    updatePositionAfterAdoptingTextReplacement(base, node, offset, oldLength, newLength);
481    updatePositionAfterAdoptingTextReplacement(extent, node, offset, oldLength, newLength);
482    updatePositionAfterAdoptingTextReplacement(start, node, offset, oldLength, newLength);
483    updatePositionAfterAdoptingTextReplacement(end, node, offset, oldLength, newLength);
484
485    if (base != m_selection.base() || extent != m_selection.extent() || start != m_selection.start() || end != m_selection.end()) {
486        VisibleSelection newSelection;
487        newSelection.setWithoutValidation(base, extent);
488        m_frame->document()->updateLayout();
489        setSelection(newSelection, DoNotSetFocus);
490    }
491}
492
493TextDirection FrameSelection::directionOfEnclosingBlock()
494{
495    return WebCore::directionOfEnclosingBlock(m_selection.extent());
496}
497
498TextDirection FrameSelection::directionOfSelection()
499{
500    InlineBox* startBox = 0;
501    InlineBox* endBox = 0;
502    int unusedOffset;
503    // Cache the VisiblePositions because visibleStart() and visibleEnd()
504    // can cause layout, which has the potential to invalidate lineboxes.
505    VisiblePosition startPosition = m_selection.visibleStart();
506    VisiblePosition endPosition = m_selection.visibleEnd();
507    if (startPosition.isNotNull())
508        startPosition.getInlineBoxAndOffset(startBox, unusedOffset);
509    if (endPosition.isNotNull())
510        endPosition.getInlineBoxAndOffset(endBox, unusedOffset);
511    if (startBox && endBox && startBox->direction() == endBox->direction())
512        return startBox->direction();
513
514    return directionOfEnclosingBlock();
515}
516
517void FrameSelection::willBeModified(EAlteration alter, SelectionDirection direction)
518{
519    if (alter != AlterationExtend)
520        return;
521
522    Position start = m_selection.start();
523    Position end = m_selection.end();
524
525    bool baseIsStart = true;
526
527    if (m_selection.isDirectional()) {
528        // Make base and extent match start and end so we extend the user-visible selection.
529        // This only matters for cases where base and extend point to different positions than
530        // start and end (e.g. after a double-click to select a word).
531        if (m_selection.isBaseFirst())
532            baseIsStart = true;
533        else
534            baseIsStart = false;
535    } else {
536        switch (direction) {
537        case DirectionRight:
538            if (directionOfSelection() == LTR)
539                baseIsStart = true;
540            else
541                baseIsStart = false;
542            break;
543        case DirectionForward:
544            baseIsStart = true;
545            break;
546        case DirectionLeft:
547            if (directionOfSelection() == LTR)
548                baseIsStart = false;
549            else
550                baseIsStart = true;
551            break;
552        case DirectionBackward:
553            baseIsStart = false;
554            break;
555        }
556    }
557    if (baseIsStart) {
558        m_selection.setBase(start);
559        m_selection.setExtent(end);
560    } else {
561        m_selection.setBase(end);
562        m_selection.setExtent(start);
563    }
564}
565
566VisiblePosition FrameSelection::positionForPlatform(bool isGetStart) const
567{
568    Settings* settings = m_frame ? m_frame->settings() : 0;
569    if (settings && settings->editingBehaviorType() == EditingMacBehavior)
570        return isGetStart ? m_selection.visibleStart() : m_selection.visibleEnd();
571    // Linux and Windows always extend selections from the extent endpoint.
572    // FIXME: VisibleSelection should be fixed to ensure as an invariant that
573    // base/extent always point to the same nodes as start/end, but which points
574    // to which depends on the value of isBaseFirst. Then this can be changed
575    // to just return m_sel.extent().
576    return m_selection.isBaseFirst() ? m_selection.visibleEnd() : m_selection.visibleStart();
577}
578
579VisiblePosition FrameSelection::startForPlatform() const
580{
581    return positionForPlatform(true);
582}
583
584VisiblePosition FrameSelection::endForPlatform() const
585{
586    return positionForPlatform(false);
587}
588
589VisiblePosition FrameSelection::nextWordPositionForPlatform(const VisiblePosition &originalPosition)
590{
591    VisiblePosition positionAfterCurrentWord = nextWordPosition(originalPosition);
592
593    if (m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight()) {
594        // In order to skip spaces when moving right, we advance one
595        // word further and then move one word back. Given the
596        // semantics of previousWordPosition() this will put us at the
597        // beginning of the word following.
598        VisiblePosition positionAfterSpacingAndFollowingWord = nextWordPosition(positionAfterCurrentWord);
599        if (positionAfterSpacingAndFollowingWord != positionAfterCurrentWord)
600            positionAfterCurrentWord = previousWordPosition(positionAfterSpacingAndFollowingWord);
601
602        bool movingBackwardsMovedPositionToStartOfCurrentWord = positionAfterCurrentWord == previousWordPosition(nextWordPosition(originalPosition));
603        if (movingBackwardsMovedPositionToStartOfCurrentWord)
604            positionAfterCurrentWord = positionAfterSpacingAndFollowingWord;
605    }
606    return positionAfterCurrentWord;
607}
608
609#if ENABLE(USERSELECT_ALL)
610static void adjustPositionForUserSelectAll(VisiblePosition& pos, bool isForward)
611{
612    if (Node* rootUserSelectAll = Position::rootUserSelectAllForNode(pos.deepEquivalent().anchorNode()))
613        pos = isForward ? positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary) : positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary);
614}
615#endif
616
617VisiblePosition FrameSelection::modifyExtendingRight(TextGranularity granularity)
618{
619    VisiblePosition pos(m_selection.extent(), m_selection.affinity());
620
621    // The difference between modifyExtendingRight and modifyExtendingForward is:
622    // modifyExtendingForward always extends forward logically.
623    // modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
624    // it extends forward logically if the enclosing block is LTR direction,
625    // but it extends backward logically if the enclosing block is RTL direction.
626    switch (granularity) {
627    case CharacterGranularity:
628        if (directionOfEnclosingBlock() == LTR)
629            pos = pos.next(CannotCrossEditingBoundary);
630        else
631            pos = pos.previous(CannotCrossEditingBoundary);
632        break;
633    case WordGranularity:
634        if (directionOfEnclosingBlock() == LTR)
635            pos = nextWordPositionForPlatform(pos);
636        else
637            pos = previousWordPosition(pos);
638        break;
639    case LineBoundary:
640        if (directionOfEnclosingBlock() == LTR)
641            pos = modifyExtendingForward(granularity);
642        else
643            pos = modifyExtendingBackward(granularity);
644        break;
645    case SentenceGranularity:
646    case LineGranularity:
647    case ParagraphGranularity:
648    case SentenceBoundary:
649    case ParagraphBoundary:
650    case DocumentBoundary:
651        // FIXME: implement all of the above?
652        pos = modifyExtendingForward(granularity);
653        break;
654    }
655#if ENABLE(USERSELECT_ALL)
656    adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
657#endif
658    return pos;
659}
660
661VisiblePosition FrameSelection::modifyExtendingForward(TextGranularity granularity)
662{
663    VisiblePosition pos(m_selection.extent(), m_selection.affinity());
664    switch (granularity) {
665    case CharacterGranularity:
666        pos = pos.next(CannotCrossEditingBoundary);
667        break;
668    case WordGranularity:
669        pos = nextWordPositionForPlatform(pos);
670        break;
671    case SentenceGranularity:
672        pos = nextSentencePosition(pos);
673        break;
674    case LineGranularity:
675        pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
676        break;
677    case ParagraphGranularity:
678        pos = nextParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
679        break;
680    case SentenceBoundary:
681        pos = endOfSentence(endForPlatform());
682        break;
683    case LineBoundary:
684        pos = logicalEndOfLine(endForPlatform());
685        break;
686    case ParagraphBoundary:
687        pos = endOfParagraph(endForPlatform());
688        break;
689    case DocumentBoundary:
690        pos = endForPlatform();
691        if (isEditablePosition(pos.deepEquivalent()))
692            pos = endOfEditableContent(pos);
693        else
694            pos = endOfDocument(pos);
695        break;
696    }
697#if ENABLE(USERSELECT_ALL)
698     adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
699#endif
700    return pos;
701}
702
703VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
704{
705    VisiblePosition pos;
706    switch (granularity) {
707    case CharacterGranularity:
708        if (isRange()) {
709            if (directionOfSelection() == LTR)
710                pos = VisiblePosition(m_selection.end(), m_selection.affinity());
711            else
712                pos = VisiblePosition(m_selection.start(), m_selection.affinity());
713        } else
714            pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
715        break;
716    case WordGranularity: {
717#if USE(ICU_UNICODE)
718        // Visual word movement relies on isWordTextBreak which is not implemented in WinCE and QT.
719        // https://bugs.webkit.org/show_bug.cgi?id=81136.
720        bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
721        pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
722        break;
723#endif
724    }
725    case SentenceGranularity:
726    case LineGranularity:
727    case ParagraphGranularity:
728    case SentenceBoundary:
729    case ParagraphBoundary:
730    case DocumentBoundary:
731        // FIXME: Implement all of the above.
732        pos = modifyMovingForward(granularity);
733        break;
734    case LineBoundary:
735        pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
736        break;
737    }
738    return pos;
739}
740
741VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity)
742{
743    VisiblePosition pos;
744    // FIXME: Stay in editable content for the less common granularities.
745    switch (granularity) {
746    case CharacterGranularity:
747        if (isRange())
748            pos = VisiblePosition(m_selection.end(), m_selection.affinity());
749        else
750            pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CannotCrossEditingBoundary);
751        break;
752    case WordGranularity:
753        pos = nextWordPositionForPlatform(VisiblePosition(m_selection.extent(), m_selection.affinity()));
754        break;
755    case SentenceGranularity:
756        pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
757        break;
758    case LineGranularity: {
759        // down-arrowing from a range selection that ends at the start of a line needs
760        // to leave the selection at that line start (no need to call nextLinePosition!)
761        pos = endForPlatform();
762        if (!isRange() || !isStartOfLine(pos))
763            pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(START));
764        break;
765    }
766    case ParagraphGranularity:
767        pos = nextParagraphPosition(endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
768        break;
769    case SentenceBoundary:
770        pos = endOfSentence(endForPlatform());
771        break;
772    case LineBoundary:
773        pos = logicalEndOfLine(endForPlatform());
774        break;
775    case ParagraphBoundary:
776        pos = endOfParagraph(endForPlatform());
777        break;
778    case DocumentBoundary:
779        pos = endForPlatform();
780        if (isEditablePosition(pos.deepEquivalent()))
781            pos = endOfEditableContent(pos);
782        else
783            pos = endOfDocument(pos);
784        break;
785    }
786    return pos;
787}
788
789VisiblePosition FrameSelection::modifyExtendingLeft(TextGranularity granularity)
790{
791    VisiblePosition pos(m_selection.extent(), m_selection.affinity());
792
793    // The difference between modifyExtendingLeft and modifyExtendingBackward is:
794    // modifyExtendingBackward always extends backward logically.
795    // modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
796    // it extends backward logically if the enclosing block is LTR direction,
797    // but it extends forward logically if the enclosing block is RTL direction.
798    switch (granularity) {
799    case CharacterGranularity:
800        if (directionOfEnclosingBlock() == LTR)
801            pos = pos.previous(CannotCrossEditingBoundary);
802        else
803            pos = pos.next(CannotCrossEditingBoundary);
804        break;
805    case WordGranularity:
806        if (directionOfEnclosingBlock() == LTR)
807            pos = previousWordPosition(pos);
808        else
809            pos = nextWordPositionForPlatform(pos);
810        break;
811    case LineBoundary:
812        if (directionOfEnclosingBlock() == LTR)
813            pos = modifyExtendingBackward(granularity);
814        else
815            pos = modifyExtendingForward(granularity);
816        break;
817    case SentenceGranularity:
818    case LineGranularity:
819    case ParagraphGranularity:
820    case SentenceBoundary:
821    case ParagraphBoundary:
822    case DocumentBoundary:
823        pos = modifyExtendingBackward(granularity);
824        break;
825    }
826#if ENABLE(USERSELECT_ALL)
827    adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
828#endif
829    return pos;
830}
831
832VisiblePosition FrameSelection::modifyExtendingBackward(TextGranularity granularity)
833{
834    VisiblePosition pos(m_selection.extent(), m_selection.affinity());
835
836    // Extending a selection backward by word or character from just after a table selects
837    // the table.  This "makes sense" from the user perspective, esp. when deleting.
838    // It was done here instead of in VisiblePosition because we want VPs to iterate
839    // over everything.
840    switch (granularity) {
841    case CharacterGranularity:
842        pos = pos.previous(CannotCrossEditingBoundary);
843        break;
844    case WordGranularity:
845        pos = previousWordPosition(pos);
846        break;
847    case SentenceGranularity:
848        pos = previousSentencePosition(pos);
849        break;
850    case LineGranularity:
851        pos = previousLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
852        break;
853    case ParagraphGranularity:
854        pos = previousParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
855        break;
856    case SentenceBoundary:
857        pos = startOfSentence(startForPlatform());
858        break;
859    case LineBoundary:
860        pos = logicalStartOfLine(startForPlatform());
861        break;
862    case ParagraphBoundary:
863        pos = startOfParagraph(startForPlatform());
864        break;
865    case DocumentBoundary:
866        pos = startForPlatform();
867        if (isEditablePosition(pos.deepEquivalent()))
868            pos = startOfEditableContent(pos);
869        else
870            pos = startOfDocument(pos);
871        break;
872    }
873#if ENABLE(USERSELECT_ALL)
874    adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
875#endif
876    return pos;
877}
878
879VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
880{
881    VisiblePosition pos;
882    switch (granularity) {
883    case CharacterGranularity:
884        if (isRange())
885            if (directionOfSelection() == LTR)
886                pos = VisiblePosition(m_selection.start(), m_selection.affinity());
887            else
888                pos = VisiblePosition(m_selection.end(), m_selection.affinity());
889        else
890            pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
891        break;
892    case WordGranularity: {
893#if USE(ICU_UNICODE)
894        bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
895        pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
896        break;
897#endif
898    }
899    case SentenceGranularity:
900    case LineGranularity:
901    case ParagraphGranularity:
902    case SentenceBoundary:
903    case ParagraphBoundary:
904    case DocumentBoundary:
905        // FIXME: Implement all of the above.
906        pos = modifyMovingBackward(granularity);
907        break;
908    case LineBoundary:
909        pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
910        break;
911    }
912    return pos;
913}
914
915VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity)
916{
917    VisiblePosition pos;
918    switch (granularity) {
919    case CharacterGranularity:
920        if (isRange())
921            pos = VisiblePosition(m_selection.start(), m_selection.affinity());
922        else
923            pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CannotCrossEditingBoundary);
924        break;
925    case WordGranularity:
926        pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
927        break;
928    case SentenceGranularity:
929        pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
930        break;
931    case LineGranularity:
932        pos = previousLinePosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
933        break;
934    case ParagraphGranularity:
935        pos = previousParagraphPosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
936        break;
937    case SentenceBoundary:
938        pos = startOfSentence(startForPlatform());
939        break;
940    case LineBoundary:
941        pos = logicalStartOfLine(startForPlatform());
942        break;
943    case ParagraphBoundary:
944        pos = startOfParagraph(startForPlatform());
945        break;
946    case DocumentBoundary:
947        pos = startForPlatform();
948        if (isEditablePosition(pos.deepEquivalent()))
949            pos = startOfEditableContent(pos);
950        else
951            pos = startOfDocument(pos);
952        break;
953    }
954    return pos;
955}
956
957static bool isBoundary(TextGranularity granularity)
958{
959    return granularity == LineBoundary || granularity == ParagraphBoundary || granularity == DocumentBoundary;
960}
961
962bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered userTriggered)
963{
964    if (userTriggered == UserTriggered) {
965        FrameSelection trialFrameSelection;
966        trialFrameSelection.setSelection(m_selection);
967        trialFrameSelection.modify(alter, direction, granularity, NotUserTriggered);
968
969        bool change = shouldChangeSelection(trialFrameSelection.selection());
970        if (!change)
971            return false;
972
973        if (trialFrameSelection.selection().isRange() && m_selection.isCaret() && !dispatchSelectStart())
974            return false;
975    }
976
977    willBeModified(alter, direction);
978
979    bool wasRange = m_selection.isRange();
980    Position originalStartPosition = m_selection.start();
981    VisiblePosition position;
982    switch (direction) {
983    case DirectionRight:
984        if (alter == AlterationMove)
985            position = modifyMovingRight(granularity);
986        else
987            position = modifyExtendingRight(granularity);
988        break;
989    case DirectionForward:
990        if (alter == AlterationExtend)
991            position = modifyExtendingForward(granularity);
992        else
993            position = modifyMovingForward(granularity);
994        break;
995    case DirectionLeft:
996        if (alter == AlterationMove)
997            position = modifyMovingLeft(granularity);
998        else
999            position = modifyExtendingLeft(granularity);
1000        break;
1001    case DirectionBackward:
1002        if (alter == AlterationExtend)
1003            position = modifyExtendingBackward(granularity);
1004        else
1005            position = modifyMovingBackward(granularity);
1006        break;
1007    }
1008
1009    if (position.isNull())
1010        return false;
1011
1012    if (isSpatialNavigationEnabled(m_frame))
1013        if (!wasRange && alter == AlterationMove && position == originalStartPosition)
1014            return false;
1015
1016    // Some of the above operations set an xPosForVerticalArrowNavigation.
1017    // Setting a selection will clear it, so save it to possibly restore later.
1018    // Note: the START position type is arbitrary because it is unused, it would be
1019    // the requested position type if there were no xPosForVerticalArrowNavigation set.
1020    LayoutUnit x = lineDirectionPointForBlockDirectionNavigation(START);
1021    m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1022
1023    switch (alter) {
1024    case AlterationMove:
1025        moveTo(position, userTriggered);
1026        break;
1027    case AlterationExtend:
1028
1029        if (!m_selection.isCaret()
1030            && (granularity == WordGranularity || granularity == ParagraphGranularity || granularity == LineGranularity)
1031            && m_frame && !m_frame->editor().behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
1032            // Don't let the selection go across the base position directly. Needed to match mac
1033            // behavior when, for instance, word-selecting backwards starting with the caret in
1034            // the middle of a word and then word-selecting forward, leaving the caret in the
1035            // same place where it was, instead of directly selecting to the end of the word.
1036            VisibleSelection newSelection = m_selection;
1037            newSelection.setExtent(position);
1038            if (m_selection.isBaseFirst() != newSelection.isBaseFirst())
1039                position = m_selection.base();
1040        }
1041
1042        // Standard Mac behavior when extending to a boundary is grow the selection rather than leaving the
1043        // base in place and moving the extent. Matches NSTextView.
1044        if (!m_frame || !m_frame->editor().behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
1045            setExtent(position, userTriggered);
1046        else {
1047            TextDirection textDirection = directionOfEnclosingBlock();
1048            if (direction == DirectionForward || (textDirection == LTR && direction == DirectionRight) || (textDirection == RTL && direction == DirectionLeft))
1049                setEnd(position, userTriggered);
1050            else
1051                setStart(position, userTriggered);
1052        }
1053        break;
1054    }
1055
1056    if (granularity == LineGranularity || granularity == ParagraphGranularity)
1057        m_xPosForVerticalArrowNavigation = x;
1058
1059    if (userTriggered == UserTriggered)
1060        m_granularity = CharacterGranularity;
1061
1062    setCaretRectNeedsUpdate();
1063
1064    return true;
1065}
1066
1067// FIXME: Maybe baseline would be better?
1068static bool absoluteCaretY(const VisiblePosition &c, int &y)
1069{
1070    IntRect rect = c.absoluteCaretBounds();
1071    if (rect.isEmpty())
1072        return false;
1073    y = rect.y() + rect.height() / 2;
1074    return true;
1075}
1076
1077bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, VerticalDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align)
1078{
1079    if (!verticalDistance)
1080        return false;
1081
1082    if (userTriggered == UserTriggered) {
1083        FrameSelection trialFrameSelection;
1084        trialFrameSelection.setSelection(m_selection);
1085        trialFrameSelection.modify(alter, verticalDistance, direction, NotUserTriggered);
1086
1087        bool change = shouldChangeSelection(trialFrameSelection.selection());
1088        if (!change)
1089            return false;
1090    }
1091
1092    willBeModified(alter, direction == DirectionUp ? DirectionBackward : DirectionForward);
1093
1094    VisiblePosition pos;
1095    LayoutUnit xPos = 0;
1096    switch (alter) {
1097    case AlterationMove:
1098        pos = VisiblePosition(direction == DirectionUp ? m_selection.start() : m_selection.end(), m_selection.affinity());
1099        xPos = lineDirectionPointForBlockDirectionNavigation(direction == DirectionUp ? START : END);
1100        m_selection.setAffinity(direction == DirectionUp ? UPSTREAM : DOWNSTREAM);
1101        break;
1102    case AlterationExtend:
1103        pos = VisiblePosition(m_selection.extent(), m_selection.affinity());
1104        xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
1105        m_selection.setAffinity(DOWNSTREAM);
1106        break;
1107    }
1108
1109    int startY;
1110    if (!absoluteCaretY(pos, startY))
1111        return false;
1112    if (direction == DirectionUp)
1113        startY = -startY;
1114    int lastY = startY;
1115
1116    VisiblePosition result;
1117    VisiblePosition next;
1118    for (VisiblePosition p = pos; ; p = next) {
1119        if (direction == DirectionUp)
1120            next = previousLinePosition(p, xPos);
1121        else
1122            next = nextLinePosition(p, xPos);
1123
1124        if (next.isNull() || next == p)
1125            break;
1126        int nextY;
1127        if (!absoluteCaretY(next, nextY))
1128            break;
1129        if (direction == DirectionUp)
1130            nextY = -nextY;
1131        if (nextY - startY > static_cast<int>(verticalDistance))
1132            break;
1133        if (nextY >= lastY) {
1134            lastY = nextY;
1135            result = next;
1136        }
1137    }
1138
1139    if (result.isNull())
1140        return false;
1141
1142    switch (alter) {
1143    case AlterationMove:
1144        moveTo(result, userTriggered, align);
1145        break;
1146    case AlterationExtend:
1147        setExtent(result, userTriggered);
1148        break;
1149    }
1150
1151    if (userTriggered == UserTriggered)
1152        m_granularity = CharacterGranularity;
1153
1154    m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1155
1156    return true;
1157}
1158
1159LayoutUnit FrameSelection::lineDirectionPointForBlockDirectionNavigation(EPositionType type)
1160{
1161    LayoutUnit x = 0;
1162
1163    if (isNone())
1164        return x;
1165
1166    Position pos;
1167    switch (type) {
1168    case START:
1169        pos = m_selection.start();
1170        break;
1171    case END:
1172        pos = m_selection.end();
1173        break;
1174    case BASE:
1175        pos = m_selection.base();
1176        break;
1177    case EXTENT:
1178        pos = m_selection.extent();
1179        break;
1180    }
1181
1182    Frame* frame = pos.anchorNode()->document()->frame();
1183    if (!frame)
1184        return x;
1185
1186    if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation()) {
1187        VisiblePosition visiblePosition(pos, m_selection.affinity());
1188        // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
1189        // after the selection is created and before this function is called.
1190        x = visiblePosition.isNotNull() ? visiblePosition.lineDirectionPointForBlockDirectionNavigation() : 0;
1191        m_xPosForVerticalArrowNavigation = x;
1192    } else
1193        x = m_xPosForVerticalArrowNavigation;
1194
1195    return x;
1196}
1197
1198void FrameSelection::clear()
1199{
1200    m_granularity = CharacterGranularity;
1201    setSelection(VisibleSelection());
1202}
1203
1204void FrameSelection::prepareForDestruction()
1205{
1206    m_granularity = CharacterGranularity;
1207
1208#if ENABLE(TEXT_CARET)
1209    m_caretBlinkTimer.stop();
1210#endif
1211
1212    RenderView* view = m_frame->contentRenderer();
1213    if (view)
1214        view->clearSelection();
1215
1216    setSelection(VisibleSelection(), CloseTyping | ClearTypingStyle | DoNotUpdateAppearance);
1217    m_previousCaretNode.clear();
1218}
1219
1220void FrameSelection::setStart(const VisiblePosition &pos, EUserTriggered trigger)
1221{
1222    if (m_selection.isBaseFirst())
1223        setBase(pos, trigger);
1224    else
1225        setExtent(pos, trigger);
1226}
1227
1228void FrameSelection::setEnd(const VisiblePosition &pos, EUserTriggered trigger)
1229{
1230    if (m_selection.isBaseFirst())
1231        setExtent(pos, trigger);
1232    else
1233        setBase(pos, trigger);
1234}
1235
1236void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTriggered)
1237{
1238    const bool selectionHasDirection = true;
1239    setSelection(VisibleSelection(pos.deepEquivalent(), m_selection.extent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1240}
1241
1242void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTriggered)
1243{
1244    const bool selectionHasDirection = true;
1245    setSelection(VisibleSelection(m_selection.base(), pos.deepEquivalent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1246}
1247
1248void FrameSelection::setBase(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1249{
1250    const bool selectionHasDirection = true;
1251    setSelection(VisibleSelection(pos, m_selection.extent(), affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1252}
1253
1254void FrameSelection::setExtent(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1255{
1256    const bool selectionHasDirection = true;
1257    setSelection(VisibleSelection(m_selection.base(), pos, affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1258}
1259
1260void CaretBase::clearCaretRect()
1261{
1262    m_caretLocalRect = LayoutRect();
1263}
1264
1265static inline bool caretRendersInsideNode(Node* node)
1266{
1267    return node && !isTableElement(node) && !editingIgnoresContent(node);
1268}
1269
1270static RenderObject* caretRenderer(Node* node)
1271{
1272    if (!node)
1273        return 0;
1274
1275    RenderObject* renderer = node->renderer();
1276    if (!renderer)
1277        return 0;
1278
1279    // if caretNode is a block and caret is inside it then caret should be painted by that block
1280    bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node);
1281    return paintedByBlock ? renderer : renderer->containingBlock();
1282}
1283
1284bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caretPosition)
1285{
1286    document->updateStyleIfNeeded();
1287    m_caretLocalRect = LayoutRect();
1288
1289    m_caretRectNeedsUpdate = false;
1290
1291    if (caretPosition.isNull())
1292        return false;
1293
1294    ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());
1295
1296    // First compute a rect local to the renderer at the selection start.
1297    RenderObject* renderer;
1298    LayoutRect localRect = caretPosition.localCaretRect(renderer);
1299
1300    // Get the renderer that will be responsible for painting the caret
1301    // (which is either the renderer we just found, or one of its containers).
1302    RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent().deprecatedNode());
1303
1304    // Compute an offset between the renderer and the caretPainter.
1305    bool unrooted = false;
1306    while (renderer != caretPainter) {
1307        RenderObject* containerObject = renderer->container();
1308        if (!containerObject) {
1309            unrooted = true;
1310            break;
1311        }
1312        localRect.move(renderer->offsetFromContainer(containerObject, localRect.location()));
1313        renderer = containerObject;
1314    }
1315
1316    if (!unrooted)
1317        m_caretLocalRect = localRect;
1318
1319    return true;
1320}
1321
1322RenderObject* FrameSelection::caretRenderer() const
1323{
1324    return WebCore::caretRenderer(m_selection.start().deprecatedNode());
1325}
1326
1327RenderObject* DragCaretController::caretRenderer() const
1328{
1329    return WebCore::caretRenderer(m_position.deepEquivalent().deprecatedNode());
1330}
1331
1332static bool isNonOrphanedCaret(const VisibleSelection& selection)
1333{
1334    return selection.isCaret() && !selection.start().isOrphan() && !selection.end().isOrphan();
1335}
1336
1337LayoutRect FrameSelection::localCaretRect()
1338{
1339    if (shouldUpdateCaretRect()) {
1340        if (!isNonOrphanedCaret(m_selection))
1341            clearCaretRect();
1342        else if (updateCaretRect(m_frame->document(), VisiblePosition(m_selection.start(), m_selection.affinity())))
1343            m_absCaretBoundsDirty = true;
1344    }
1345
1346    return localCaretRectWithoutUpdate();
1347}
1348
1349IntRect CaretBase::absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) const
1350{
1351    RenderObject* caretPainter = caretRenderer(node);
1352    if (!caretPainter)
1353        return IntRect();
1354
1355    LayoutRect localRect(rect);
1356    if (caretPainter->isBox())
1357        toRenderBox(caretPainter)->flipForWritingMode(localRect);
1358    return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
1359}
1360
1361IntRect FrameSelection::absoluteCaretBounds()
1362{
1363    recomputeCaretRect();
1364    return m_absCaretBounds;
1365}
1366
1367static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect)
1368{
1369    RenderObject* caretPainter = caretRenderer(node);
1370    if (!caretPainter)
1371        return;
1372
1373    caretPainter->repaintRectangle(rect);
1374}
1375
1376bool FrameSelection::recomputeCaretRect()
1377{
1378    if (!shouldUpdateCaretRect())
1379        return false;
1380
1381    if (!m_frame)
1382        return false;
1383
1384    FrameView* v = m_frame->document()->view();
1385    if (!v)
1386        return false;
1387
1388    LayoutRect oldRect = localCaretRectWithoutUpdate();
1389    LayoutRect newRect = localCaretRect();
1390    if (oldRect == newRect && !m_absCaretBoundsDirty)
1391        return false;
1392
1393    IntRect oldAbsCaretBounds = m_absCaretBounds;
1394    m_absCaretBounds = absoluteBoundsForLocalRect(m_selection.start().deprecatedNode(), localCaretRectWithoutUpdate());
1395    m_absCaretBoundsDirty = false;
1396
1397    if (oldAbsCaretBounds == m_absCaretBounds)
1398        return false;
1399
1400#if ENABLE(TEXT_CARET)
1401    if (RenderView* view = m_frame->document()->renderView()) {
1402        bool previousOrNewCaretNodeIsContentEditable = isContentEditable() || (m_previousCaretNode && m_previousCaretNode->isContentEditable());
1403        if (shouldRepaintCaret(view, previousOrNewCaretNodeIsContentEditable)) {
1404            Node* node = m_selection.start().deprecatedNode();
1405            if (m_previousCaretNode)
1406                repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect);
1407            m_previousCaretNode = node;
1408            repaintCaretForLocalRect(node, newRect);
1409        }
1410    }
1411#endif
1412    return true;
1413}
1414
1415bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditable) const
1416{
1417    ASSERT(view);
1418    Frame* frame = view->frameView() ? view->frameView()->frame() : 0; // The frame where the selection started.
1419    bool caretBrowsing = frame && frame->settings() && frame->settings()->caretBrowsingEnabled();
1420    return (caretBrowsing || isContentEditable);
1421}
1422
1423void FrameSelection::invalidateCaretRect()
1424{
1425    if (!isCaret())
1426        return;
1427
1428    CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect());
1429}
1430
1431void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
1432{
1433    // EDIT FIXME: This is an unfortunate hack.
1434    // Basically, we can't trust this layout position since we
1435    // can't guarantee that the check to see if we are in unrendered
1436    // content will work at this point. We may have to wait for
1437    // a layout and re-render of the document to happen. So, resetting this
1438    // flag will cause another caret layout to happen the first time
1439    // that we try to paint the caret after this call. That one will work since
1440    // it happens after the document has accounted for any editing
1441    // changes which may have been done.
1442    // And, we need to leave this layout here so the caret moves right
1443    // away after clicking.
1444    m_caretRectNeedsUpdate = true;
1445
1446    if (caretRectChanged)
1447        return;
1448
1449    if (RenderView* view = node->document()->renderView()) {
1450        if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)))
1451            repaintCaretForLocalRect(node, localCaretRectWithoutUpdate());
1452    }
1453}
1454
1455void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
1456{
1457    if (m_selection.isCaret() && m_caretPaint)
1458        CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
1459}
1460
1461void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1462{
1463#if ENABLE(TEXT_CARET)
1464    if (m_caretVisibility == Hidden)
1465        return;
1466
1467    LayoutRect drawingRect = localCaretRectWithoutUpdate();
1468    RenderObject* renderer = caretRenderer(node);
1469    if (renderer && renderer->isBox())
1470        toRenderBox(renderer)->flipForWritingMode(drawingRect);
1471    drawingRect.moveBy(roundedIntPoint(paintOffset));
1472    LayoutRect caret = intersection(drawingRect, clipRect);
1473    if (caret.isEmpty())
1474        return;
1475
1476    Color caretColor = Color::black;
1477    ColorSpace colorSpace = ColorSpaceDeviceRGB;
1478    Element* element = node->rootEditableElement();
1479    if (element && element->renderer()) {
1480        caretColor = element->renderer()->style()->visitedDependentColor(CSSPropertyColor);
1481        colorSpace = element->renderer()->style()->colorSpace();
1482    }
1483
1484    context->fillRect(caret, caretColor, colorSpace);
1485#else
1486    UNUSED_PARAM(node);
1487    UNUSED_PARAM(context);
1488    UNUSED_PARAM(paintOffset);
1489    UNUSED_PARAM(clipRect);
1490#endif
1491}
1492
1493void FrameSelection::debugRenderer(RenderObject *r, bool selected) const
1494{
1495    if (r->node()->isElementNode()) {
1496        Element* element = static_cast<Element *>(r->node());
1497        fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
1498    } else if (r->isText()) {
1499        RenderText* textRenderer = toRenderText(r);
1500        if (!textRenderer->textLength() || !textRenderer->firstTextBox()) {
1501            fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");
1502            return;
1503        }
1504
1505        static const int max = 36;
1506        String text = textRenderer->text();
1507        int textLength = text.length();
1508        if (selected) {
1509            int offset = 0;
1510            if (r->node() == m_selection.start().containerNode())
1511                offset = m_selection.start().computeOffsetInContainerNode();
1512            else if (r->node() == m_selection.end().containerNode())
1513                offset = m_selection.end().computeOffsetInContainerNode();
1514
1515            int pos;
1516            InlineTextBox* box = textRenderer->findNextInlineTextBox(offset, pos);
1517            text = text.substring(box->start(), box->len());
1518
1519            String show;
1520            int mid = max / 2;
1521            int caret = 0;
1522
1523            // text is shorter than max
1524            if (textLength < max) {
1525                show = text;
1526                caret = pos;
1527            } else if (pos - mid < 0) {
1528                // too few characters to left
1529                show = text.left(max - 3) + "...";
1530                caret = pos;
1531            } else if (pos - mid >= 0 && pos + mid <= textLength) {
1532                // enough characters on each side
1533                show = "..." + text.substring(pos - mid + 3, max - 6) + "...";
1534                caret = mid;
1535            } else {
1536                // too few characters on right
1537                show = "..." + text.right(max - 3);
1538                caret = pos - (textLength - show.length());
1539            }
1540
1541            show.replace('\n', ' ');
1542            show.replace('\r', ' ');
1543            fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);
1544            fprintf(stderr, "           ");
1545            for (int i = 0; i < caret; i++)
1546                fprintf(stderr, " ");
1547            fprintf(stderr, "^\n");
1548        } else {
1549            if ((int)text.length() > max)
1550                text = text.left(max - 3) + "...";
1551            else
1552                text = text.left(max);
1553            fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());
1554        }
1555    }
1556}
1557
1558bool FrameSelection::contains(const LayoutPoint& point)
1559{
1560    Document* document = m_frame->document();
1561
1562    // Treat a collapsed selection like no selection.
1563    if (!isRange())
1564        return false;
1565    if (!document->renderer())
1566        return false;
1567
1568    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1569    HitTestResult result(point);
1570    document->renderView()->hitTest(request, result);
1571    Node* innerNode = result.innerNode();
1572    if (!innerNode || !innerNode->renderer())
1573        return false;
1574
1575    VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));
1576    if (visiblePos.isNull())
1577        return false;
1578
1579    if (m_selection.visibleStart().isNull() || m_selection.visibleEnd().isNull())
1580        return false;
1581
1582    Position start(m_selection.visibleStart().deepEquivalent());
1583    Position end(m_selection.visibleEnd().deepEquivalent());
1584    Position p(visiblePos.deepEquivalent());
1585
1586    return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
1587}
1588
1589// Workaround for the fact that it's hard to delete a frame.
1590// Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
1591// Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
1592// for the focus to move to another frame. So instead we call it from places where we are selecting with the
1593// mouse or the keyboard after setting the selection.
1594void FrameSelection::selectFrameElementInParentIfFullySelected()
1595{
1596    // Find the parent frame; if there is none, then we have nothing to do.
1597    Frame* parent = m_frame->tree()->parent();
1598    if (!parent)
1599        return;
1600    Page* page = m_frame->page();
1601    if (!page)
1602        return;
1603
1604    // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
1605    if (!isRange())
1606        return;
1607    if (!isStartOfDocument(selection().visibleStart()))
1608        return;
1609    if (!isEndOfDocument(selection().visibleEnd()))
1610        return;
1611
1612    // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
1613    Element* ownerElement = m_frame->ownerElement();
1614    if (!ownerElement)
1615        return;
1616    ContainerNode* ownerElementParent = ownerElement->parentNode();
1617    if (!ownerElementParent)
1618        return;
1619
1620    // This method's purpose is it to make it easier to select iframes (in order to delete them).  Don't do anything if the iframe isn't deletable.
1621    if (!ownerElementParent->rendererIsEditable())
1622        return;
1623
1624    // Create compute positions before and after the element.
1625    unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
1626    VisiblePosition beforeOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex, Position::PositionIsOffsetInAnchor)));
1627    VisiblePosition afterOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex + 1, Position::PositionIsOffsetInAnchor), VP_UPSTREAM_IF_POSSIBLE));
1628
1629    // Focus on the parent frame, and then select from before this element to after.
1630    VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
1631    if (parent->selection()->shouldChangeSelection(newSelection)) {
1632        page->focusController()->setFocusedFrame(parent);
1633        parent->selection()->setSelection(newSelection);
1634    }
1635}
1636
1637void FrameSelection::selectAll()
1638{
1639    Document* document = m_frame->document();
1640
1641    if (document->focusedElement() && document->focusedElement()->hasTagName(selectTag)) {
1642        HTMLSelectElement* selectElement = toHTMLSelectElement(document->focusedElement());
1643        if (selectElement->canSelectAll()) {
1644            selectElement->selectAll();
1645            return;
1646        }
1647    }
1648
1649    RefPtr<Node> root = 0;
1650    Node* selectStartTarget = 0;
1651    if (isContentEditable()) {
1652        root = highestEditableRoot(m_selection.start());
1653        if (Node* shadowRoot = m_selection.nonBoundaryShadowTreeRootNode())
1654            selectStartTarget = shadowRoot->shadowHost();
1655        else
1656            selectStartTarget = root.get();
1657    } else {
1658        root = m_selection.nonBoundaryShadowTreeRootNode();
1659        if (root)
1660            selectStartTarget = root->shadowHost();
1661        else {
1662            root = document->documentElement();
1663            selectStartTarget = document->body();
1664        }
1665    }
1666    if (!root)
1667        return;
1668
1669    if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)))
1670        return;
1671
1672    VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root.get()));
1673
1674    if (shouldChangeSelection(newSelection))
1675        setSelection(newSelection);
1676
1677    selectFrameElementInParentIfFullySelected();
1678    notifyRendererOfSelectionChange(UserTriggered);
1679}
1680
1681bool FrameSelection::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping)
1682{
1683    if (!range || !range->startContainer() || !range->endContainer())
1684        return false;
1685    ASSERT(range->startContainer()->document() == range->endContainer()->document());
1686
1687    m_frame->document()->updateLayoutIgnorePendingStylesheets();
1688
1689    // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1690    // they start at the beginning of the next line instead
1691    ExceptionCode ec = 0;
1692    bool collapsed = range->collapsed(ec);
1693    if (ec)
1694        return false;
1695
1696    // FIXME: Can we provide extentAffinity?
1697    VisiblePosition visibleStart(range->startPosition(), collapsed ? affinity : DOWNSTREAM);
1698    VisiblePosition visibleEnd(range->endPosition(), SEL_DEFAULT_AFFINITY);
1699    setSelection(VisibleSelection(visibleStart, visibleEnd), ClearTypingStyle | (closeTyping ? CloseTyping : 0));
1700    return true;
1701}
1702
1703bool FrameSelection::isInPasswordField() const
1704{
1705    HTMLTextFormControlElement* textControl = enclosingTextFormControl(start());
1706    return textControl && textControl->hasTagName(inputTag) && static_cast<HTMLInputElement*>(textControl)->isPasswordField();
1707}
1708
1709void FrameSelection::focusedOrActiveStateChanged()
1710{
1711    bool activeAndFocused = isFocusedAndActive();
1712    RefPtr<Document> document = m_frame->document();
1713
1714    document->updateStyleIfNeeded();
1715
1716    // Because RenderObject::selectionBackgroundColor() and
1717    // RenderObject::selectionForegroundColor() check if the frame is active,
1718    // we have to update places those colors were painted.
1719    if (RenderView* view = document->renderView())
1720        view->repaintSelection();
1721
1722    // Caret appears in the active frame.
1723    if (activeAndFocused)
1724        setSelectionFromNone();
1725    setCaretVisibility(activeAndFocused ? Visible : Hidden);
1726
1727    // Update for caps lock state
1728    m_frame->eventHandler()->capsLockStateMayHaveChanged();
1729
1730    // Because StyleResolver::checkOneSelector() and
1731    // RenderTheme::isFocused() check if the frame is active, we have to
1732    // update style and theme state that depended on those.
1733    if (Element* element = document->focusedElement()) {
1734        element->setNeedsStyleRecalc();
1735        if (RenderObject* renderer = element->renderer())
1736            if (renderer && renderer->style()->hasAppearance())
1737                renderer->theme()->stateChanged(renderer, FocusState);
1738    }
1739}
1740
1741void FrameSelection::pageActivationChanged()
1742{
1743    focusedOrActiveStateChanged();
1744}
1745
1746void FrameSelection::setFocused(bool flag)
1747{
1748    if (m_focused == flag)
1749        return;
1750    m_focused = flag;
1751
1752    focusedOrActiveStateChanged();
1753}
1754
1755bool FrameSelection::isFocusedAndActive() const
1756{
1757    return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive();
1758}
1759
1760inline static bool shouldStopBlinkingDueToTypingCommand(Frame* frame)
1761{
1762    return frame->editor().lastEditCommand() && frame->editor().lastEditCommand()->shouldStopCaretBlinking();
1763}
1764
1765void FrameSelection::updateAppearance()
1766{
1767    // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case
1768    // the FrameSelection will paint a blinking caret as usual).
1769    VisiblePosition forwardPosition;
1770    if (m_shouldShowBlockCursor && m_selection.isCaret()) {
1771        forwardPosition = modifyExtendingForward(CharacterGranularity);
1772        m_caretPaint = forwardPosition.isNull();
1773    }
1774
1775#if ENABLE(TEXT_CARET)
1776    bool caretRectChangedOrCleared = recomputeCaretRect();
1777
1778    bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
1779    bool shouldBlink = caretIsVisible() && isCaret() && (isContentEditable() || caretBrowsing) && forwardPosition.isNull();
1780
1781    // If the caret moved, stop the blink timer so we can restart with a
1782    // black caret in the new location.
1783    if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame))
1784        m_caretBlinkTimer.stop();
1785
1786    // Start blinking with a black caret. Be sure not to restart if we're
1787    // already blinking in the right location.
1788    if (shouldBlink && !m_caretBlinkTimer.isActive()) {
1789        if (double blinkInterval = m_frame->page()->theme()->caretBlinkInterval())
1790            m_caretBlinkTimer.startRepeating(blinkInterval);
1791
1792        if (!m_caretPaint) {
1793            m_caretPaint = true;
1794            invalidateCaretRect();
1795        }
1796    }
1797#endif
1798
1799    RenderView* view = m_frame->contentRenderer();
1800    if (!view)
1801        return;
1802
1803    // Construct a new VisibleSolution, since m_selection is not necessarily valid, and the following steps
1804    // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69563> and <rdar://problem/10232866>.
1805    VisibleSelection selection(m_selection.visibleStart(), forwardPosition.isNotNull() ? forwardPosition : m_selection.visibleEnd());
1806
1807    if (!selection.isRange()) {
1808        view->clearSelection();
1809        return;
1810    }
1811
1812    // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
1813    // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
1814    // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
1815    // and will fill the gap before 'bar'.
1816    Position startPos = selection.start();
1817    Position candidate = startPos.downstream();
1818    if (candidate.isCandidate())
1819        startPos = candidate;
1820    Position endPos = selection.end();
1821    candidate = endPos.upstream();
1822    if (candidate.isCandidate())
1823        endPos = candidate;
1824
1825    // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
1826    // because we don't yet notify the FrameSelection of text removal.
1827    if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
1828        RenderObject* startRenderer = startPos.deprecatedNode()->renderer();
1829        RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
1830        view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset());
1831    }
1832}
1833
1834void FrameSelection::setCaretVisibility(CaretVisibility visibility)
1835{
1836    if (caretVisibility() == visibility)
1837        return;
1838
1839#if ENABLE(TEXT_CARET)
1840    m_frame->document()->updateLayoutIgnorePendingStylesheets();
1841    if (m_caretPaint) {
1842        m_caretPaint = false;
1843        invalidateCaretRect();
1844    }
1845    CaretBase::setCaretVisibility(visibility);
1846#else
1847    m_frame->document()->updateStyleIfNeeded();
1848#endif
1849
1850    updateAppearance();
1851}
1852
1853void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*)
1854{
1855#if ENABLE(TEXT_CARET)
1856    ASSERT(caretIsVisible());
1857    ASSERT(isCaret());
1858    bool caretPaint = m_caretPaint;
1859    if (isCaretBlinkingSuspended() && caretPaint)
1860        return;
1861    m_caretPaint = !caretPaint;
1862    invalidateCaretRect();
1863#endif
1864}
1865
1866void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggered)
1867{
1868    m_frame->document()->updateStyleIfNeeded();
1869
1870    if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start()))
1871        textControl->selectionChanged(userTriggered == UserTriggered);
1872}
1873
1874// Helper function that tells whether a particular node is an element that has an entire
1875// Frame and FrameView, a <frame>, <iframe>, or <object>.
1876static bool isFrameElement(const Node* n)
1877{
1878    if (!n)
1879        return false;
1880    RenderObject* renderer = n->renderer();
1881    if (!renderer || !renderer->isWidget())
1882        return false;
1883    Widget* widget = toRenderWidget(renderer)->widget();
1884    return widget && widget->isFrameView();
1885}
1886
1887void FrameSelection::setFocusedElementIfNeeded()
1888{
1889    if (isNone() || !isFocused())
1890        return;
1891
1892    bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
1893    if (caretBrowsing) {
1894        if (Element* anchor = enclosingAnchorElement(base())) {
1895            m_frame->page()->focusController()->setFocusedElement(anchor, m_frame);
1896            return;
1897        }
1898    }
1899
1900    if (Element* target = rootEditableElement()) {
1901        // Walk up the DOM tree to search for an element to focus.
1902        while (target) {
1903            // We don't want to set focus on a subframe when selecting in a parent frame,
1904            // so add the !isFrameElement check here. There's probably a better way to make this
1905            // work in the long term, but this is the safest fix at this time.
1906            if (target->isMouseFocusable() && !isFrameElement(target)) {
1907                m_frame->page()->focusController()->setFocusedElement(target, m_frame);
1908                return;
1909            }
1910            target = target->parentOrShadowHostElement();
1911        }
1912        m_frame->document()->setFocusedElement(0);
1913    }
1914
1915    if (caretBrowsing)
1916        m_frame->page()->focusController()->setFocusedElement(0, m_frame);
1917}
1918
1919void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1920{
1921#if ENABLE(TEXT_CARET)
1922    if (m_position.deepEquivalent().deprecatedNode()->document()->frame() == frame)
1923        paintCaret(m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
1924#else
1925    UNUSED_PARAM(frame);
1926    UNUSED_PARAM(p);
1927    UNUSED_PARAM(paintOffset);
1928    UNUSED_PARAM(clipRect);
1929#endif
1930}
1931
1932PassRefPtr<MutableStylePropertySet> FrameSelection::copyTypingStyle() const
1933{
1934    if (!m_typingStyle || !m_typingStyle->style())
1935        return 0;
1936    return m_typingStyle->style()->mutableCopy();
1937}
1938
1939bool FrameSelection::shouldDeleteSelection(const VisibleSelection& selection) const
1940{
1941    return m_frame->editor().client()->shouldDeleteRange(selection.toNormalizedRange().get());
1942}
1943
1944FloatRect FrameSelection::bounds(bool clipToVisibleContent) const
1945{
1946    if (!m_frame->document())
1947        return LayoutRect();
1948
1949    m_frame->document()->updateStyleIfNeeded();
1950    RenderView* root = m_frame->contentRenderer();
1951    FrameView* view = m_frame->view();
1952    if (!root || !view)
1953        return LayoutRect();
1954
1955    LayoutRect selectionRect = root->selectionBounds(clipToVisibleContent);
1956    return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect;
1957}
1958
1959void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangles) const
1960{
1961    RenderView* root = m_frame->contentRenderer();
1962    if (!root)
1963        return;
1964
1965    FloatRect visibleContentRect = m_frame->view()->visibleContentRect();
1966
1967    Vector<FloatQuad> quads;
1968    toNormalizedRange()->textQuads(quads, true);
1969
1970    size_t size = quads.size();
1971    for (size_t i = 0; i < size; ++i) {
1972        FloatRect intersectionRect = intersection(quads[i].enclosingBoundingBox(), visibleContentRect);
1973        if (!intersectionRect.isEmpty())
1974            rectangles.append(intersectionRect);
1975    }
1976}
1977
1978// Scans logically forward from "start", including any child frames.
1979static HTMLFormElement* scanForForm(Node* start)
1980{
1981    if (!start)
1982        return 0;
1983    Element* element = start->isElementNode() ? toElement(start) : ElementTraversal::next(start);
1984    for (; element; element = ElementTraversal::next(element)) {
1985        if (element->hasTagName(formTag))
1986            return static_cast<HTMLFormElement*>(element);
1987        if (element->isHTMLElement() && toHTMLElement(element)->isFormControlElement())
1988            return static_cast<HTMLFormControlElement*>(element)->form();
1989        if (element->hasTagName(frameTag) || element->hasTagName(iframeTag)) {
1990            Node* childDocument = static_cast<HTMLFrameElementBase*>(element)->contentDocument();
1991            if (HTMLFormElement* frameResult = scanForForm(childDocument))
1992                return frameResult;
1993        }
1994    }
1995    return 0;
1996}
1997
1998// We look for either the form containing the current focus, or for one immediately after it
1999HTMLFormElement* FrameSelection::currentForm() const
2000{
2001    // Start looking either at the active (first responder) node, or where the selection is.
2002    Node* start = m_frame->document()->focusedElement();
2003    if (!start)
2004        start = this->start().deprecatedNode();
2005
2006    // Try walking up the node tree to find a form element.
2007    Node* node;
2008    for (node = start; node; node = node->parentNode()) {
2009        if (node->hasTagName(formTag))
2010            return static_cast<HTMLFormElement*>(node);
2011        if (node->isHTMLElement() && toHTMLElement(node)->isFormControlElement())
2012            return static_cast<HTMLFormControlElement*>(node)->form();
2013    }
2014
2015    // Try walking forward in the node tree to find a form element.
2016    return scanForForm(start);
2017}
2018
2019void FrameSelection::revealSelection(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
2020{
2021    LayoutRect rect;
2022
2023    switch (selectionType()) {
2024    case VisibleSelection::NoSelection:
2025        return;
2026    case VisibleSelection::CaretSelection:
2027        rect = absoluteCaretBounds();
2028        break;
2029    case VisibleSelection::RangeSelection:
2030        rect = revealExtentOption == RevealExtent ? VisiblePosition(extent()).absoluteCaretBounds() : enclosingIntRect(bounds(false));
2031        break;
2032    }
2033
2034    Position start = this->start();
2035    ASSERT(start.deprecatedNode());
2036    if (start.deprecatedNode() && start.deprecatedNode()->renderer()) {
2037        // FIXME: This code only handles scrolling the startContainer's layer, but
2038        // the selection rect could intersect more than just that.
2039        // See <rdar://problem/4799899>.
2040        if (start.deprecatedNode()->renderer()->scrollRectToVisible(rect, alignment, alignment))
2041            updateAppearance();
2042    }
2043}
2044
2045void FrameSelection::setSelectionFromNone()
2046{
2047    // Put a caret inside the body if the entire frame is editable (either the
2048    // entire WebView is editable or designMode is on for this document).
2049
2050    Document* document = m_frame->document();
2051    bool caretBrowsing = m_frame->settings() && m_frame->settings()->caretBrowsingEnabled();
2052    if (!isNone() || !(document->rendererIsEditable() || caretBrowsing))
2053        return;
2054
2055    Node* node = document->documentElement();
2056    while (node && !node->hasTagName(bodyTag))
2057        node = NodeTraversal::next(node);
2058    if (node)
2059        setSelection(VisibleSelection(firstPositionInOrBeforeNode(node), DOWNSTREAM));
2060}
2061
2062bool FrameSelection::shouldChangeSelection(const VisibleSelection& newSelection) const
2063{
2064    return m_frame->editor().shouldChangeSelection(selection(), newSelection, newSelection.affinity(), false);
2065}
2066
2067bool FrameSelection::dispatchSelectStart()
2068{
2069    Node* selectStartTarget = m_selection.extent().containerNode();
2070    if (!selectStartTarget)
2071        return true;
2072
2073    return selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
2074}
2075
2076inline bool FrameSelection::visualWordMovementEnabled() const
2077{
2078    Settings* settings = m_frame ? m_frame->settings() : 0;
2079    return settings && settings->visualWordMovementEnabled();
2080}
2081
2082void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor)
2083{
2084    m_shouldShowBlockCursor = shouldShowBlockCursor;
2085
2086    m_frame->document()->updateLayoutIgnorePendingStylesheets();
2087
2088    updateAppearance();
2089}
2090
2091#ifndef NDEBUG
2092
2093void FrameSelection::formatForDebugger(char* buffer, unsigned length) const
2094{
2095    m_selection.formatForDebugger(buffer, length);
2096}
2097
2098void FrameSelection::showTreeForThis() const
2099{
2100    m_selection.showTreeForThis();
2101}
2102
2103#endif
2104
2105}
2106
2107#ifndef NDEBUG
2108
2109void showTree(const WebCore::FrameSelection& sel)
2110{
2111    sel.showTreeForThis();
2112}
2113
2114void showTree(const WebCore::FrameSelection* sel)
2115{
2116    if (sel)
2117        sel->showTreeForThis();
2118}
2119
2120#endif
2121