Text caret changes to color of text in Mail and Notes
[WebKit-https.git] / Source / WebCore / editing / FrameSelection.cpp
1 /*
2  * Copyright (C) 2004, 2008, 2009, 2010, 2014 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 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 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 "ElementIterator.h"
36 #include "EventHandler.h"
37 #include "ExceptionCode.h"
38 #include "FloatQuad.h"
39 #include "FocusController.h"
40 #include "Frame.h"
41 #include "FrameTree.h"
42 #include "FrameView.h"
43 #include "GraphicsContext.h"
44 #include "HTMLFormElement.h"
45 #include "HTMLFrameElementBase.h"
46 #include "HTMLInputElement.h"
47 #include "HTMLSelectElement.h"
48 #include "HTMLNames.h"
49 #include "HitTestRequest.h"
50 #include "HitTestResult.h"
51 #include "InlineTextBox.h"
52 #include "Page.h"
53 #include "RenderText.h"
54 #include "RenderTextControl.h"
55 #include "RenderTheme.h"
56 #include "RenderView.h"
57 #include "RenderWidget.h"
58 #include "RenderedPosition.h"
59 #include "Settings.h"
60 #include "SpatialNavigation.h"
61 #include "StyleProperties.h"
62 #include "TypingCommand.h"
63 #include "VisibleUnits.h"
64 #include "htmlediting.h"
65 #include <stdio.h>
66 #include <wtf/text/CString.h>
67
68 #if PLATFORM(IOS)
69 #include "Chrome.h"
70 #include "ChromeClient.h"
71 #include "Color.h"
72 #include "RenderLayer.h"
73 #include "RenderObject.h"
74 #include "RenderStyle.h"
75 #endif
76
77 #define EDIT_DEBUG 0
78
79 namespace WebCore {
80
81 using namespace HTMLNames;
82
83 static inline LayoutUnit NoXPosForVerticalArrowNavigation()
84 {
85     return LayoutUnit::min();
86 }
87
88 CaretBase::CaretBase(CaretVisibility visibility)
89     : m_caretRectNeedsUpdate(true)
90     , m_caretVisibility(visibility)
91 {
92 }
93
94 DragCaretController::DragCaretController()
95     : CaretBase(Visible)
96 {
97 }
98
99 bool DragCaretController::isContentRichlyEditable() const
100 {
101     return isRichlyEditablePosition(m_position.deepEquivalent());
102 }
103
104 static inline bool shouldAlwaysUseDirectionalSelection(Frame* frame)
105 {
106     return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirectional();
107 }
108
109 FrameSelection::FrameSelection(Frame* frame)
110     : m_frame(frame)
111     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
112     , m_granularity(CharacterGranularity)
113     , m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired)
114     , m_absCaretBoundsDirty(true)
115     , m_caretPaint(true)
116     , m_isCaretBlinkingSuspended(false)
117     , m_focused(frame && frame->page() && frame->page()->focusController().focusedFrame() == frame)
118     , m_shouldShowBlockCursor(false)
119     , m_pendingSelectionUpdate(false)
120     , m_shouldRevealSelection(false)
121     , m_alwaysAlignCursorOnScrollWhenRevealingSelection(false)
122 #if PLATFORM(IOS)
123     , m_updateAppearanceEnabled(false)
124     , m_caretBlinks(true)
125     , m_scrollingSuppressCount(0)
126 #endif
127 {
128     if (shouldAlwaysUseDirectionalSelection(m_frame))
129         m_selection.setIsDirectional(true);
130 }
131
132 Element* FrameSelection::rootEditableElementOrDocumentElement() const
133 {
134     Element* selectionRoot = m_selection.rootEditableElement();
135     return selectionRoot ? selectionRoot : m_frame->document()->documentElement();
136 }
137
138 void FrameSelection::moveTo(const VisiblePosition &pos, EUserTriggered userTriggered, CursorAlignOnScroll align)
139 {
140     setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity(), m_selection.isDirectional()),
141         defaultSetSelectionOptions(userTriggered), align);
142 }
143
144 void FrameSelection::moveTo(const VisiblePosition &base, const VisiblePosition &extent, EUserTriggered userTriggered)
145 {
146     const bool selectionHasDirection = true;
147     setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity(), selectionHasDirection), defaultSetSelectionOptions(userTriggered));
148 }
149
150 void FrameSelection::moveTo(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
151 {
152     setSelection(VisibleSelection(pos, affinity, m_selection.isDirectional()), defaultSetSelectionOptions(userTriggered));
153 }
154
155 void FrameSelection::moveTo(const Range* range)
156 {
157     VisibleSelection selection = range ? VisibleSelection(range->startPosition(), range->endPosition()) : VisibleSelection();
158     setSelection(selection);
159 }
160
161 void FrameSelection::moveTo(const Position &base, const Position &extent, EAffinity affinity, EUserTriggered userTriggered)
162 {
163     const bool selectionHasDirection = true;
164     setSelection(VisibleSelection(base, extent, affinity, selectionHasDirection), defaultSetSelectionOptions(userTriggered));
165 }
166
167 void FrameSelection::moveWithoutValidationTo(const Position& base, const Position& extent, bool selectionHasDirection, bool shouldSetFocus)
168 {
169     VisibleSelection newSelection;
170     newSelection.setWithoutValidation(base, extent);
171     newSelection.setIsDirectional(selectionHasDirection);
172     setSelection(newSelection, defaultSetSelectionOptions() | (shouldSetFocus ? 0 : DoNotSetFocus));
173 }
174
175 void DragCaretController::setCaretPosition(const VisiblePosition& position)
176 {
177     if (Node* node = m_position.deepEquivalent().deprecatedNode())
178         invalidateCaretRect(node);
179     m_position = position;
180     setCaretRectNeedsUpdate();
181     Document* document = 0;
182     if (Node* node = m_position.deepEquivalent().deprecatedNode()) {
183         invalidateCaretRect(node);
184         document = &node->document();
185     }
186     if (m_position.isNull() || m_position.isOrphan())
187         clearCaretRect();
188     else
189         updateCaretRect(document, m_position);
190 }
191
192 static void adjustEndpointsAtBidiBoundary(VisiblePosition& visibleBase, VisiblePosition& visibleExtent)
193 {
194     RenderedPosition base(visibleBase);
195     RenderedPosition extent(visibleExtent);
196
197     if (base.isNull() || extent.isNull() || base.isEquivalent(extent))
198         return;
199
200     if (base.atLeftBoundaryOfBidiRun()) {
201         if (!extent.atRightBoundaryOfBidiRun(base.bidiLevelOnRight())
202             && base.isEquivalent(extent.leftBoundaryOfBidiRun(base.bidiLevelOnRight()))) {
203             visibleBase = base.positionAtLeftBoundaryOfBiDiRun();
204             return;
205         }
206         return;
207     }
208
209     if (base.atRightBoundaryOfBidiRun()) {
210         if (!extent.atLeftBoundaryOfBidiRun(base.bidiLevelOnLeft())
211             && base.isEquivalent(extent.rightBoundaryOfBidiRun(base.bidiLevelOnLeft()))) {
212             visibleBase = base.positionAtRightBoundaryOfBiDiRun();
213             return;
214         }
215         return;
216     }
217
218     if (extent.atLeftBoundaryOfBidiRun() && extent.isEquivalent(base.leftBoundaryOfBidiRun(extent.bidiLevelOnRight()))) {
219         visibleExtent = extent.positionAtLeftBoundaryOfBiDiRun();
220         return;
221     }
222
223     if (extent.atRightBoundaryOfBidiRun() && extent.isEquivalent(base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) {
224         visibleExtent = extent.positionAtRightBoundaryOfBiDiRun();
225         return;
226     }
227 }
228
229 void FrameSelection::setSelectionByMouseIfDifferent(const VisibleSelection& passedNewSelection, TextGranularity granularity,
230     EndPointsAdjustmentMode endpointsAdjustmentMode)
231 {
232     VisibleSelection newSelection = passedNewSelection;
233     bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || newSelection.isDirectional();
234
235     VisiblePosition base = m_originalBase.isNotNull() ? m_originalBase : newSelection.visibleBase();
236     VisiblePosition newBase = base;
237     VisiblePosition extent = newSelection.visibleExtent();
238     VisiblePosition newExtent = extent;
239     if (endpointsAdjustmentMode == AdjustEndpointsAtBidiBoundary)
240         adjustEndpointsAtBidiBoundary(newBase, newExtent);
241
242     if (newBase != base || newExtent != extent) {
243         m_originalBase = base;
244         newSelection.setBase(newBase);
245         newSelection.setExtent(newExtent);
246     } else if (m_originalBase.isNotNull()) {
247         if (m_selection.base() == newSelection.base())
248             newSelection.setBase(m_originalBase);
249         m_originalBase.clear();
250     }
251
252     newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
253     if (m_selection == newSelection || !shouldChangeSelection(newSelection))
254         return;
255
256     setSelection(newSelection, defaultSetSelectionOptions() | FireSelectEvent, AlignCursorOnScrollIfNeeded, granularity);
257 }
258
259 bool FrameSelection::setSelectionWithoutUpdatingAppearance(const VisibleSelection& newSelectionPossiblyWithoutDirection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity)
260 {
261     bool closeTyping = options & CloseTyping;
262     bool shouldClearTypingStyle = options & ClearTypingStyle;
263
264     VisibleSelection newSelection = newSelectionPossiblyWithoutDirection;
265     if (shouldAlwaysUseDirectionalSelection(m_frame))
266         newSelection.setIsDirectional(true);
267
268     if (!m_frame) {
269         m_selection = newSelection;
270         return false;
271     }
272
273     // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at FrameSelection::setSelection
274     // if document->frame() == m_frame we can get into an infinite loop
275     if (Document* newSelectionDocument = newSelection.base().document()) {
276         if (RefPtr<Frame> newSelectionFrame = newSelectionDocument->frame()) {
277             if (newSelectionFrame != m_frame && newSelectionDocument != m_frame->document()) {
278                 newSelectionFrame->selection().setSelection(newSelection, options, align, granularity);
279                 // It's possible that during the above set selection, this FrameSelection has been modified by
280                 // selectFrameElementInParentIfFullySelected, but that the selection is no longer valid since
281                 // the frame is about to be destroyed. If this is the case, clear our selection.
282                 if (newSelectionFrame->hasOneRef() && !m_selection.isNonOrphanedCaretOrRange())
283                     clear();
284                 return false;
285             }
286         }
287     }
288
289     m_granularity = granularity;
290
291     if (closeTyping)
292         TypingCommand::closeTyping(m_frame);
293
294     if (shouldClearTypingStyle)
295         clearTypingStyle();
296
297     VisibleSelection oldSelection = m_selection;
298     m_selection = newSelection;
299
300     // Selection offsets should increase when LF is inserted before the caret in InsertLineBreakCommand. See <https://webkit.org/b/56061>.
301     if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(newSelection.start()))
302         textControl->selectionChanged(options & FireSelectEvent);
303
304     if (oldSelection == newSelection)
305         return false;
306
307     setCaretRectNeedsUpdate();
308
309     if (!newSelection.isNone() && !(options & DoNotSetFocus))
310         setFocusedElementIfNeeded();
311
312     // Always clear the x position used for vertical arrow navigation.
313     // It will be restored by the vertical arrow navigation code if necessary.
314     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
315     selectFrameElementInParentIfFullySelected();
316     m_frame->editor().respondToChangedSelection(oldSelection, options);
317     m_frame->document()->enqueueDocumentEvent(Event::create(eventNames().selectionchangeEvent, false, false));
318
319     return true;
320 }
321
322 void FrameSelection::setSelection(const VisibleSelection& selection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity)
323 {
324     if (!setSelectionWithoutUpdatingAppearance(selection, options, align, granularity))
325         return;
326
327     Document* document = m_frame->document();
328     if (!document)
329         return;
330
331     m_shouldRevealSelection = options & RevealSelection;
332     m_alwaysAlignCursorOnScrollWhenRevealingSelection = align == AlignCursorOnScrollAlways;
333
334     m_pendingSelectionUpdate = true;
335
336     if (document->hasPendingStyleRecalc())
337         return;
338
339     FrameView* frameView = document->view();
340     if (frameView && frameView->layoutPending())
341         return;
342
343     updateAndRevealSelection();
344 }
345
346 static void updateSelectionByUpdatingLayoutOrStyle(Frame& frame)
347 {
348 #if ENABLE(TEXT_CARET)
349     frame.document()->updateLayoutIgnorePendingStylesheets();
350 #else
351     frame.document()->updateStyleIfNeeded();
352 #endif
353 }
354
355 void FrameSelection::setNeedsSelectionUpdate()
356 {
357     m_pendingSelectionUpdate = true;
358     if (RenderView* view = m_frame->contentRenderer())
359         view->clearSelection();
360 }
361
362 void FrameSelection::updateAndRevealSelection()
363 {
364     if (!m_pendingSelectionUpdate)
365         return;
366
367     m_pendingSelectionUpdate = false;
368
369     updateAppearance();
370
371     if (m_shouldRevealSelection) {
372         ScrollAlignment alignment;
373
374         if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
375             alignment = m_alwaysAlignCursorOnScrollWhenRevealingSelection ? ScrollAlignment::alignCenterAlways : ScrollAlignment::alignCenterIfNeeded;
376         else
377             alignment = m_alwaysAlignCursorOnScrollWhenRevealingSelection ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
378
379         revealSelection(alignment, RevealExtent);
380     }
381
382     notifyAccessibilityForSelectionChange();
383 }
384
385 void FrameSelection::updateDataDetectorsForSelection()
386 {
387 #if ENABLE(TELEPHONE_NUMBER_DETECTION) && !PLATFORM(IOS)
388     m_frame->editor().scanSelectionForTelephoneNumbers();
389 #endif
390 }
391
392 static bool removingNodeRemovesPosition(Node* node, const Position& position)
393 {
394     if (!position.anchorNode())
395         return false;
396
397     if (position.anchorNode() == node)
398         return true;
399
400     if (!node->isElementNode())
401         return false;
402
403     Element* element = toElement(node);
404     return element->containsIncludingShadowDOM(position.anchorNode());
405 }
406
407 static void clearRenderViewSelection(Node& node)
408 {
409     Ref<Document> document(node.document());
410     document->updateStyleIfNeeded();
411     if (RenderView* view = document->renderView())
412         view->clearSelection();
413 }
414
415 void DragCaretController::nodeWillBeRemoved(Node* node)
416 {
417     if (!hasCaret() || (node && !node->inDocument()))
418         return;
419
420     if (!removingNodeRemovesPosition(node, m_position.deepEquivalent()))
421         return;
422
423     clearRenderViewSelection(*node);
424     clear();
425 }
426
427 void FrameSelection::nodeWillBeRemoved(Node* node)
428 {
429     // There can't be a selection inside a fragment, so if a fragment's node is being removed,
430     // the selection in the document that created the fragment needs no adjustment.
431     if (isNone() || (node && !node->inDocument()))
432         return;
433
434     respondToNodeModification(node, removingNodeRemovesPosition(node, m_selection.base()), removingNodeRemovesPosition(node, m_selection.extent()),
435         removingNodeRemovesPosition(node, m_selection.start()), removingNodeRemovesPosition(node, m_selection.end()));
436 }
437
438 void FrameSelection::respondToNodeModification(Node* node, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved)
439 {
440     bool clearRenderTreeSelection = false;
441     bool clearDOMTreeSelection = false;
442
443     if (startRemoved || endRemoved) {
444         Position start = m_selection.start();
445         Position end = m_selection.end();
446         if (startRemoved)
447             updatePositionForNodeRemoval(start, node);
448         if (endRemoved)
449             updatePositionForNodeRemoval(end, node);
450
451         if (start.isNotNull() && end.isNotNull()) {
452             if (m_selection.isBaseFirst())
453                 m_selection.setWithoutValidation(start, end);
454             else
455                 m_selection.setWithoutValidation(end, start);
456         } else
457             clearDOMTreeSelection = true;
458
459         clearRenderTreeSelection = true;
460     } else if (baseRemoved || extentRemoved) {
461         // The base and/or extent are about to be removed, but the start and end aren't.
462         // Change the base and extent to the start and end, but don't re-validate the
463         // selection, since doing so could move the start and end into the node
464         // that is about to be removed.
465         if (m_selection.isBaseFirst())
466             m_selection.setWithoutValidation(m_selection.start(), m_selection.end());
467         else
468             m_selection.setWithoutValidation(m_selection.end(), m_selection.start());
469     } else if (RefPtr<Range> range = m_selection.firstRange()) {
470         ExceptionCode ec = 0;
471         Range::CompareResults compareResult = range->compareNode(node, ec);
472         if (!ec && (compareResult == Range::NODE_BEFORE_AND_AFTER || compareResult == Range::NODE_INSIDE)) {
473             // If we did nothing here, when this node's renderer was destroyed, the rect that it 
474             // occupied would be invalidated, but, selection gaps that change as a result of 
475             // the removal wouldn't be invalidated.
476             // FIXME: Don't do so much unnecessary invalidation.
477             clearRenderTreeSelection = true;
478         }
479     }
480
481     if (clearRenderTreeSelection) {
482         clearRenderViewSelection(*node);
483
484         // Trigger a selection update so the selection will be set again.
485         if (auto* renderView = node->document().renderView()) {
486             m_pendingSelectionUpdate = true;
487             renderView->setNeedsLayout();
488         }
489     }
490
491     if (clearDOMTreeSelection)
492         setSelection(VisibleSelection(), DoNotSetFocus);
493 }
494
495 static void updatePositionAfterAdoptingTextReplacement(Position& position, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
496 {
497     if (!position.anchorNode() || position.anchorNode() != node || position.anchorType() != Position::PositionIsOffsetInAnchor)
498         return;
499
500     // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation
501     ASSERT(position.offsetInContainerNode() >= 0);
502     unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
503     // Replacing text can be viewed as a deletion followed by insertion.
504     if (positionOffset >= offset && positionOffset <= offset + oldLength)
505         position.moveToOffset(offset);
506
507     // Adjust the offset if the position is after the end of the deleted contents
508     // (positionOffset > offset + oldLength) to avoid having a stale offset.
509     if (positionOffset > offset + oldLength)
510         position.moveToOffset(positionOffset - oldLength + newLength);
511
512     ASSERT(static_cast<unsigned>(position.offsetInContainerNode()) <= node->length());
513 }
514
515 void FrameSelection::textWasReplaced(CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
516 {
517     // The fragment check is a performance optimization. See http://trac.webkit.org/changeset/30062.
518     if (isNone() || !node || !node->inDocument())
519         return;
520
521     Position base = m_selection.base();
522     Position extent = m_selection.extent();
523     Position start = m_selection.start();
524     Position end = m_selection.end();
525     updatePositionAfterAdoptingTextReplacement(base, node, offset, oldLength, newLength);
526     updatePositionAfterAdoptingTextReplacement(extent, node, offset, oldLength, newLength);
527     updatePositionAfterAdoptingTextReplacement(start, node, offset, oldLength, newLength);
528     updatePositionAfterAdoptingTextReplacement(end, node, offset, oldLength, newLength);
529
530     if (base != m_selection.base() || extent != m_selection.extent() || start != m_selection.start() || end != m_selection.end()) {
531         VisibleSelection newSelection;
532         if (base != extent)
533             newSelection.setWithoutValidation(base, extent);
534         else if (m_selection.isDirectional() && !m_selection.isBaseFirst())
535             newSelection.setWithoutValidation(end, start);
536         else
537             newSelection.setWithoutValidation(start, end);
538
539         setSelection(newSelection, DoNotSetFocus);
540     }
541 }
542
543 TextDirection FrameSelection::directionOfEnclosingBlock()
544 {
545     return WebCore::directionOfEnclosingBlock(m_selection.extent());
546 }
547
548 TextDirection FrameSelection::directionOfSelection()
549 {
550     InlineBox* startBox = 0;
551     InlineBox* endBox = 0;
552     int unusedOffset;
553     // Cache the VisiblePositions because visibleStart() and visibleEnd()
554     // can cause layout, which has the potential to invalidate lineboxes.
555     VisiblePosition startPosition = m_selection.visibleStart();
556     VisiblePosition endPosition = m_selection.visibleEnd();
557     if (startPosition.isNotNull())
558         startPosition.getInlineBoxAndOffset(startBox, unusedOffset);
559     if (endPosition.isNotNull())
560         endPosition.getInlineBoxAndOffset(endBox, unusedOffset);
561     if (startBox && endBox && startBox->direction() == endBox->direction())
562         return startBox->direction();
563
564     return directionOfEnclosingBlock();
565 }
566
567 void FrameSelection::willBeModified(EAlteration alter, SelectionDirection direction)
568 {
569     if (alter != AlterationExtend)
570         return;
571
572     Position start = m_selection.start();
573     Position end = m_selection.end();
574
575     bool baseIsStart = true;
576
577     if (m_selection.isDirectional()) {
578         // Make base and extent match start and end so we extend the user-visible selection.
579         // This only matters for cases where base and extend point to different positions than
580         // start and end (e.g. after a double-click to select a word).
581         if (m_selection.isBaseFirst())
582             baseIsStart = true;
583         else
584             baseIsStart = false;
585     } else {
586         switch (direction) {
587         case DirectionRight:
588             if (directionOfSelection() == LTR)
589                 baseIsStart = true;
590             else
591                 baseIsStart = false;
592             break;
593         case DirectionForward:
594             baseIsStart = true;
595             break;
596         case DirectionLeft:
597             if (directionOfSelection() == LTR)
598                 baseIsStart = false;
599             else
600                 baseIsStart = true;
601             break;
602         case DirectionBackward:
603             baseIsStart = false;
604             break;
605         }
606     }
607     if (baseIsStart) {
608         m_selection.setBase(start);
609         m_selection.setExtent(end);
610     } else {
611         m_selection.setBase(end);
612         m_selection.setExtent(start);
613     }
614 }
615
616 VisiblePosition FrameSelection::positionForPlatform(bool isGetStart) const
617 {
618     if (m_frame && m_frame->settings().editingBehaviorType() == EditingMacBehavior)
619         return isGetStart ? m_selection.visibleStart() : m_selection.visibleEnd();
620     // Linux and Windows always extend selections from the extent endpoint.
621     // FIXME: VisibleSelection should be fixed to ensure as an invariant that
622     // base/extent always point to the same nodes as start/end, but which points
623     // to which depends on the value of isBaseFirst. Then this can be changed
624     // to just return m_sel.extent().
625     return m_selection.isBaseFirst() ? m_selection.visibleEnd() : m_selection.visibleStart();
626 }
627
628 VisiblePosition FrameSelection::startForPlatform() const
629 {
630     return positionForPlatform(true);
631 }
632
633 VisiblePosition FrameSelection::endForPlatform() const
634 {
635     return positionForPlatform(false);
636 }
637
638 VisiblePosition FrameSelection::nextWordPositionForPlatform(const VisiblePosition &originalPosition)
639 {
640     VisiblePosition positionAfterCurrentWord = nextWordPosition(originalPosition);
641
642     if (m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight()) {
643         // In order to skip spaces when moving right, we advance one
644         // word further and then move one word back. Given the
645         // semantics of previousWordPosition() this will put us at the
646         // beginning of the word following.
647         VisiblePosition positionAfterSpacingAndFollowingWord = nextWordPosition(positionAfterCurrentWord);
648         if (positionAfterSpacingAndFollowingWord != positionAfterCurrentWord)
649             positionAfterCurrentWord = previousWordPosition(positionAfterSpacingAndFollowingWord);
650
651         bool movingBackwardsMovedPositionToStartOfCurrentWord = positionAfterCurrentWord == previousWordPosition(nextWordPosition(originalPosition));
652         if (movingBackwardsMovedPositionToStartOfCurrentWord)
653             positionAfterCurrentWord = positionAfterSpacingAndFollowingWord;
654     }
655     return positionAfterCurrentWord;
656 }
657
658 #if ENABLE(USERSELECT_ALL)
659 static void adjustPositionForUserSelectAll(VisiblePosition& pos, bool isForward)
660 {
661     if (Node* rootUserSelectAll = Position::rootUserSelectAllForNode(pos.deepEquivalent().anchorNode()))
662         pos = isForward ? positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary) : positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary);
663 }
664 #endif
665
666 VisiblePosition FrameSelection::modifyExtendingRight(TextGranularity granularity)
667 {
668     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
669
670     // The difference between modifyExtendingRight and modifyExtendingForward is:
671     // modifyExtendingForward always extends forward logically.
672     // modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
673     // it extends forward logically if the enclosing block is LTR direction,
674     // but it extends backward logically if the enclosing block is RTL direction.
675     switch (granularity) {
676     case CharacterGranularity:
677         if (directionOfEnclosingBlock() == LTR)
678             pos = pos.next(CannotCrossEditingBoundary);
679         else
680             pos = pos.previous(CannotCrossEditingBoundary);
681         break;
682     case WordGranularity:
683         if (directionOfEnclosingBlock() == LTR)
684             pos = nextWordPositionForPlatform(pos);
685         else
686             pos = previousWordPosition(pos);
687         break;
688     case LineBoundary:
689         if (directionOfEnclosingBlock() == LTR)
690             pos = modifyExtendingForward(granularity);
691         else
692             pos = modifyExtendingBackward(granularity);
693         break;
694     case SentenceGranularity:
695     case LineGranularity:
696     case ParagraphGranularity:
697     case SentenceBoundary:
698     case ParagraphBoundary:
699     case DocumentBoundary:
700         // FIXME: implement all of the above?
701         pos = modifyExtendingForward(granularity);
702         break;
703     case DocumentGranularity:
704         ASSERT_NOT_REACHED();
705         break;
706     }
707 #if ENABLE(USERSELECT_ALL)
708     adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
709 #endif
710     return pos;
711 }
712
713 VisiblePosition FrameSelection::modifyExtendingForward(TextGranularity granularity)
714 {
715     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
716     switch (granularity) {
717     case CharacterGranularity:
718         pos = pos.next(CannotCrossEditingBoundary);
719         break;
720     case WordGranularity:
721         pos = nextWordPositionForPlatform(pos);
722         break;
723     case SentenceGranularity:
724         pos = nextSentencePosition(pos);
725         break;
726     case LineGranularity:
727         pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
728         break;
729     case ParagraphGranularity:
730         pos = nextParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
731         break;
732     case DocumentGranularity:
733         ASSERT_NOT_REACHED();
734         break;
735     case SentenceBoundary:
736         pos = endOfSentence(endForPlatform());
737         break;
738     case LineBoundary:
739         pos = logicalEndOfLine(endForPlatform());
740         break;
741     case ParagraphBoundary:
742         pos = endOfParagraph(endForPlatform());
743         break;
744     case DocumentBoundary:
745         pos = endForPlatform();
746         if (isEditablePosition(pos.deepEquivalent()))
747             pos = endOfEditableContent(pos);
748         else
749             pos = endOfDocument(pos);
750         break;
751     }
752 #if ENABLE(USERSELECT_ALL)
753      adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
754 #endif
755     return pos;
756 }
757
758 VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
759 {
760     VisiblePosition pos;
761     switch (granularity) {
762     case CharacterGranularity:
763         if (isRange()) {
764             if (directionOfSelection() == LTR)
765                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
766             else
767                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
768         } else
769             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
770         break;
771     case WordGranularity: {
772         // Visual word movement relies on isWordTextBreak which is not implemented in WinCE and QT.
773         // https://bugs.webkit.org/show_bug.cgi?id=81136.
774         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
775         pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
776         break;
777     }
778     case SentenceGranularity:
779     case LineGranularity:
780     case ParagraphGranularity:
781     case SentenceBoundary:
782     case ParagraphBoundary:
783     case DocumentBoundary:
784         // FIXME: Implement all of the above.
785         pos = modifyMovingForward(granularity);
786         break;
787     case LineBoundary:
788         pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
789         break;
790     case DocumentGranularity:
791         ASSERT_NOT_REACHED();
792         break;
793     }
794     return pos;
795 }
796
797 VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity)
798 {
799     VisiblePosition pos;
800     // FIXME: Stay in editable content for the less common granularities.
801     switch (granularity) {
802     case CharacterGranularity:
803         if (isRange())
804             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
805         else
806             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CannotCrossEditingBoundary);
807         break;
808     case WordGranularity:
809         pos = nextWordPositionForPlatform(VisiblePosition(m_selection.extent(), m_selection.affinity()));
810         break;
811     case SentenceGranularity:
812         pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
813         break;
814     case LineGranularity: {
815         // down-arrowing from a range selection that ends at the start of a line needs
816         // to leave the selection at that line start (no need to call nextLinePosition!)
817         pos = endForPlatform();
818         if (!isRange() || !isStartOfLine(pos))
819             pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(START));
820         break;
821     }
822     case ParagraphGranularity:
823         pos = nextParagraphPosition(endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
824         break;
825     case DocumentGranularity:
826         ASSERT_NOT_REACHED();
827         break;
828     case SentenceBoundary:
829         pos = endOfSentence(endForPlatform());
830         break;
831     case LineBoundary:
832         pos = logicalEndOfLine(endForPlatform());
833         break;
834     case ParagraphBoundary:
835         pos = endOfParagraph(endForPlatform());
836         break;
837     case DocumentBoundary:
838         pos = endForPlatform();
839         if (isEditablePosition(pos.deepEquivalent()))
840             pos = endOfEditableContent(pos);
841         else
842             pos = endOfDocument(pos);
843         break;
844     }
845     return pos;
846 }
847
848 VisiblePosition FrameSelection::modifyExtendingLeft(TextGranularity granularity)
849 {
850     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
851
852     // The difference between modifyExtendingLeft and modifyExtendingBackward is:
853     // modifyExtendingBackward always extends backward logically.
854     // modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
855     // it extends backward logically if the enclosing block is LTR direction,
856     // but it extends forward logically if the enclosing block is RTL direction.
857     switch (granularity) {
858     case CharacterGranularity:
859         if (directionOfEnclosingBlock() == LTR)
860             pos = pos.previous(CannotCrossEditingBoundary);
861         else
862             pos = pos.next(CannotCrossEditingBoundary);
863         break;
864     case WordGranularity:
865         if (directionOfEnclosingBlock() == LTR)
866             pos = previousWordPosition(pos);
867         else
868             pos = nextWordPositionForPlatform(pos);
869         break;
870     case LineBoundary:
871         if (directionOfEnclosingBlock() == LTR)
872             pos = modifyExtendingBackward(granularity);
873         else
874             pos = modifyExtendingForward(granularity);
875         break;
876     case SentenceGranularity:
877     case LineGranularity:
878     case ParagraphGranularity:
879     case SentenceBoundary:
880     case ParagraphBoundary:
881     case DocumentBoundary:
882         pos = modifyExtendingBackward(granularity);
883         break;
884     case DocumentGranularity:
885         ASSERT_NOT_REACHED();
886         break;
887     }
888 #if ENABLE(USERSELECT_ALL)
889     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
890 #endif
891     return pos;
892 }
893        
894 VisiblePosition FrameSelection::modifyExtendingBackward(TextGranularity granularity)
895 {
896     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
897
898     // Extending a selection backward by word or character from just after a table selects
899     // the table.  This "makes sense" from the user perspective, esp. when deleting.
900     // It was done here instead of in VisiblePosition because we want VPs to iterate
901     // over everything.
902     switch (granularity) {
903     case CharacterGranularity:
904         pos = pos.previous(CannotCrossEditingBoundary);
905         break;
906     case WordGranularity:
907         pos = previousWordPosition(pos);
908         break;
909     case SentenceGranularity:
910         pos = previousSentencePosition(pos);
911         break;
912     case LineGranularity:
913         pos = previousLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
914         break;
915     case ParagraphGranularity:
916         pos = previousParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
917         break;
918     case SentenceBoundary:
919         pos = startOfSentence(startForPlatform());
920         break;
921     case LineBoundary:
922         pos = logicalStartOfLine(startForPlatform());
923         break;
924     case ParagraphBoundary:
925         pos = startOfParagraph(startForPlatform());
926         break;
927     case DocumentBoundary:
928         pos = startForPlatform();
929         if (isEditablePosition(pos.deepEquivalent()))
930             pos = startOfEditableContent(pos);
931         else
932             pos = startOfDocument(pos);
933         break;
934     case DocumentGranularity:
935         ASSERT_NOT_REACHED();
936         break;
937     }
938 #if ENABLE(USERSELECT_ALL)
939     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
940 #endif
941     return pos;
942 }
943
944 VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
945 {
946     VisiblePosition pos;
947     switch (granularity) {
948     case CharacterGranularity:
949         if (isRange())
950             if (directionOfSelection() == LTR)
951                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
952             else
953                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
954         else
955             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
956         break;
957     case WordGranularity: {
958         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
959         pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
960         break;
961     }
962     case SentenceGranularity:
963     case LineGranularity:
964     case ParagraphGranularity:
965     case SentenceBoundary:
966     case ParagraphBoundary:
967     case DocumentBoundary:
968         // FIXME: Implement all of the above.
969         pos = modifyMovingBackward(granularity);
970         break;
971     case LineBoundary:
972         pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
973         break;
974     case DocumentGranularity:
975         ASSERT_NOT_REACHED();
976         break;
977     }
978     return pos;
979 }
980
981 VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity)
982 {
983     VisiblePosition pos;
984     switch (granularity) {
985     case CharacterGranularity:
986         if (isRange())
987             pos = VisiblePosition(m_selection.start(), m_selection.affinity());
988         else
989             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CannotCrossEditingBoundary);
990         break;
991     case WordGranularity:
992         pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
993         break;
994     case SentenceGranularity:
995         pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
996         break;
997     case LineGranularity:
998         pos = previousLinePosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
999         break;
1000     case ParagraphGranularity:
1001         pos = previousParagraphPosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
1002         break;
1003     case SentenceBoundary:
1004         pos = startOfSentence(startForPlatform());
1005         break;
1006     case LineBoundary:
1007         pos = logicalStartOfLine(startForPlatform());
1008         break;
1009     case ParagraphBoundary:
1010         pos = startOfParagraph(startForPlatform());
1011         break;
1012     case DocumentBoundary:
1013         pos = startForPlatform();
1014         if (isEditablePosition(pos.deepEquivalent()))
1015             pos = startOfEditableContent(pos);
1016         else
1017             pos = startOfDocument(pos);
1018         break;
1019     case DocumentGranularity:
1020         ASSERT_NOT_REACHED();
1021         break;
1022     }
1023     return pos;
1024 }
1025
1026 static bool isBoundary(TextGranularity granularity)
1027 {
1028     return granularity == LineBoundary || granularity == ParagraphBoundary || granularity == DocumentBoundary;
1029 }    
1030
1031 bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered userTriggered)
1032 {
1033     if (userTriggered == UserTriggered) {
1034         FrameSelection trialFrameSelection;
1035         trialFrameSelection.setSelection(m_selection);
1036         trialFrameSelection.modify(alter, direction, granularity, NotUserTriggered);
1037
1038         bool change = shouldChangeSelection(trialFrameSelection.selection());
1039         if (!change)
1040             return false;
1041
1042         if (trialFrameSelection.selection().isRange() && m_selection.isCaret() && !dispatchSelectStart())
1043             return false;
1044     }
1045
1046     willBeModified(alter, direction);
1047
1048     bool wasRange = m_selection.isRange();
1049     Position originalStartPosition = m_selection.start();
1050     VisiblePosition position;
1051     switch (direction) {
1052     case DirectionRight:
1053         if (alter == AlterationMove)
1054             position = modifyMovingRight(granularity);
1055         else
1056             position = modifyExtendingRight(granularity);
1057         break;
1058     case DirectionForward:
1059         if (alter == AlterationExtend)
1060             position = modifyExtendingForward(granularity);
1061         else
1062             position = modifyMovingForward(granularity);
1063         break;
1064     case DirectionLeft:
1065         if (alter == AlterationMove)
1066             position = modifyMovingLeft(granularity);
1067         else
1068             position = modifyExtendingLeft(granularity);
1069         break;
1070     case DirectionBackward:
1071         if (alter == AlterationExtend)
1072             position = modifyExtendingBackward(granularity);
1073         else
1074             position = modifyMovingBackward(granularity);
1075         break;
1076     }
1077
1078     if (position.isNull())
1079         return false;
1080
1081     if (isSpatialNavigationEnabled(m_frame))
1082         if (!wasRange && alter == AlterationMove && position == originalStartPosition)
1083             return false;
1084
1085     // Some of the above operations set an xPosForVerticalArrowNavigation.
1086     // Setting a selection will clear it, so save it to possibly restore later.
1087     // Note: the START position type is arbitrary because it is unused, it would be
1088     // the requested position type if there were no xPosForVerticalArrowNavigation set.
1089     LayoutUnit x = lineDirectionPointForBlockDirectionNavigation(START);
1090     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1091
1092     switch (alter) {
1093     case AlterationMove:
1094         moveTo(position, userTriggered);
1095         break;
1096     case AlterationExtend:
1097
1098         if (!m_selection.isCaret()
1099             && (granularity == WordGranularity || granularity == ParagraphGranularity || granularity == LineGranularity)
1100             && m_frame && !m_frame->editor().behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
1101             // Don't let the selection go across the base position directly. Needed to match mac
1102             // behavior when, for instance, word-selecting backwards starting with the caret in
1103             // the middle of a word and then word-selecting forward, leaving the caret in the
1104             // same place where it was, instead of directly selecting to the end of the word.
1105             VisibleSelection newSelection = m_selection;
1106             newSelection.setExtent(position);
1107             if (m_selection.isBaseFirst() != newSelection.isBaseFirst())
1108                 position = m_selection.base();
1109         }
1110
1111         // Standard Mac behavior when extending to a boundary is grow the selection rather than leaving the
1112         // base in place and moving the extent. Matches NSTextView.
1113         if (!m_frame || !m_frame->editor().behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
1114             setExtent(position, userTriggered);
1115         else {
1116             TextDirection textDirection = directionOfEnclosingBlock();
1117             if (direction == DirectionForward || (textDirection == LTR && direction == DirectionRight) || (textDirection == RTL && direction == DirectionLeft))
1118                 setEnd(position, userTriggered);
1119             else
1120                 setStart(position, userTriggered);
1121         }
1122         break;
1123     }
1124     
1125     if (granularity == LineGranularity || granularity == ParagraphGranularity)
1126         m_xPosForVerticalArrowNavigation = x;
1127
1128     if (userTriggered == UserTriggered)
1129         m_granularity = CharacterGranularity;
1130
1131     setCaretRectNeedsUpdate();
1132
1133     return true;
1134 }
1135
1136 // FIXME: Maybe baseline would be better?
1137 static bool absoluteCaretY(const VisiblePosition &c, int &y)
1138 {
1139     IntRect rect = c.absoluteCaretBounds();
1140     if (rect.isEmpty())
1141         return false;
1142     y = rect.y() + rect.height() / 2;
1143     return true;
1144 }
1145
1146 bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, VerticalDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align)
1147 {
1148     if (!verticalDistance)
1149         return false;
1150
1151     if (userTriggered == UserTriggered) {
1152         FrameSelection trialFrameSelection;
1153         trialFrameSelection.setSelection(m_selection);
1154         trialFrameSelection.modify(alter, verticalDistance, direction, NotUserTriggered);
1155
1156         bool change = shouldChangeSelection(trialFrameSelection.selection());
1157         if (!change)
1158             return false;
1159     }
1160
1161     willBeModified(alter, direction == DirectionUp ? DirectionBackward : DirectionForward);
1162
1163     VisiblePosition pos;
1164     LayoutUnit xPos = 0;
1165     switch (alter) {
1166     case AlterationMove:
1167         pos = VisiblePosition(direction == DirectionUp ? m_selection.start() : m_selection.end(), m_selection.affinity());
1168         xPos = lineDirectionPointForBlockDirectionNavigation(direction == DirectionUp ? START : END);
1169         m_selection.setAffinity(direction == DirectionUp ? UPSTREAM : DOWNSTREAM);
1170         break;
1171     case AlterationExtend:
1172         pos = VisiblePosition(m_selection.extent(), m_selection.affinity());
1173         xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
1174         m_selection.setAffinity(DOWNSTREAM);
1175         break;
1176     }
1177
1178     int startY;
1179     if (!absoluteCaretY(pos, startY))
1180         return false;
1181     if (direction == DirectionUp)
1182         startY = -startY;
1183     int lastY = startY;
1184
1185     VisiblePosition result;
1186     VisiblePosition next;
1187     for (VisiblePosition p = pos; ; p = next) {
1188         if (direction == DirectionUp)
1189             next = previousLinePosition(p, xPos);
1190         else
1191             next = nextLinePosition(p, xPos);
1192
1193         if (next.isNull() || next == p)
1194             break;
1195         int nextY;
1196         if (!absoluteCaretY(next, nextY))
1197             break;
1198         if (direction == DirectionUp)
1199             nextY = -nextY;
1200         if (nextY - startY > static_cast<int>(verticalDistance))
1201             break;
1202         if (nextY >= lastY) {
1203             lastY = nextY;
1204             result = next;
1205         }
1206     }
1207
1208     if (result.isNull())
1209         return false;
1210
1211     switch (alter) {
1212     case AlterationMove:
1213         moveTo(result, userTriggered, align);
1214         break;
1215     case AlterationExtend:
1216         setExtent(result, userTriggered);
1217         break;
1218     }
1219
1220     if (userTriggered == UserTriggered)
1221         m_granularity = CharacterGranularity;
1222
1223     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1224
1225     return true;
1226 }
1227
1228 LayoutUnit FrameSelection::lineDirectionPointForBlockDirectionNavigation(EPositionType type)
1229 {
1230     LayoutUnit x = 0;
1231
1232     if (isNone())
1233         return x;
1234
1235     Position pos;
1236     switch (type) {
1237     case START:
1238         pos = m_selection.start();
1239         break;
1240     case END:
1241         pos = m_selection.end();
1242         break;
1243     case BASE:
1244         pos = m_selection.base();
1245         break;
1246     case EXTENT:
1247         pos = m_selection.extent();
1248         break;
1249     }
1250
1251     Frame* frame = pos.anchorNode()->document().frame();
1252     if (!frame)
1253         return x;
1254         
1255     if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation()) {
1256         VisiblePosition visiblePosition(pos, m_selection.affinity());
1257         // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
1258         // after the selection is created and before this function is called.
1259         x = visiblePosition.isNotNull() ? visiblePosition.lineDirectionPointForBlockDirectionNavigation() : 0;
1260         m_xPosForVerticalArrowNavigation = x;
1261     } else
1262         x = m_xPosForVerticalArrowNavigation;
1263         
1264     return x;
1265 }
1266
1267 void FrameSelection::clear()
1268 {
1269     m_granularity = CharacterGranularity;
1270     setSelection(VisibleSelection());
1271 }
1272
1273 void FrameSelection::prepareForDestruction()
1274 {
1275     m_granularity = CharacterGranularity;
1276
1277 #if ENABLE(TEXT_CARET)
1278     m_caretBlinkTimer.stop();
1279 #endif
1280
1281     RenderView* view = m_frame->contentRenderer();
1282     if (view)
1283         view->clearSelection();
1284
1285     setSelectionWithoutUpdatingAppearance(VisibleSelection(), defaultSetSelectionOptions(), AlignCursorOnScrollIfNeeded, CharacterGranularity);
1286     m_previousCaretNode.clear();
1287 }
1288
1289 void FrameSelection::setStart(const VisiblePosition &pos, EUserTriggered trigger)
1290 {
1291     if (m_selection.isBaseFirst())
1292         setBase(pos, trigger);
1293     else
1294         setExtent(pos, trigger);
1295 }
1296
1297 void FrameSelection::setEnd(const VisiblePosition &pos, EUserTriggered trigger)
1298 {
1299     if (m_selection.isBaseFirst())
1300         setExtent(pos, trigger);
1301     else
1302         setBase(pos, trigger);
1303 }
1304
1305 void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTriggered)
1306 {
1307     const bool selectionHasDirection = true;
1308     setSelection(VisibleSelection(pos.deepEquivalent(), m_selection.extent(), pos.affinity(), selectionHasDirection), defaultSetSelectionOptions(userTriggered));
1309 }
1310
1311 void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTriggered)
1312 {
1313     const bool selectionHasDirection = true;
1314     setSelection(VisibleSelection(m_selection.base(), pos.deepEquivalent(), pos.affinity(), selectionHasDirection), defaultSetSelectionOptions(userTriggered));
1315 }
1316
1317 void FrameSelection::setBase(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1318 {
1319     const bool selectionHasDirection = true;
1320     setSelection(VisibleSelection(pos, m_selection.extent(), affinity, selectionHasDirection), defaultSetSelectionOptions(userTriggered));
1321 }
1322
1323 void FrameSelection::setExtent(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1324 {
1325     const bool selectionHasDirection = true;
1326     setSelection(VisibleSelection(m_selection.base(), pos, affinity, selectionHasDirection), defaultSetSelectionOptions(userTriggered));
1327 }
1328
1329 void CaretBase::clearCaretRect()
1330 {
1331     m_caretLocalRect = LayoutRect();
1332 }
1333
1334 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caretPosition)
1335 {
1336     document->updateLayoutIgnorePendingStylesheets();
1337     m_caretRectNeedsUpdate = false;
1338     RenderObject* renderer;
1339     m_caretLocalRect = localCaretRectInRendererForCaretPainting(caretPosition, renderer);
1340     return !m_caretLocalRect.isEmpty();
1341 }
1342
1343 RenderObject* FrameSelection::caretRendererWithoutUpdatingLayout() const
1344 {
1345     return rendererForCaretPainting(m_selection.start().deprecatedNode());
1346 }
1347
1348 RenderObject* DragCaretController::caretRenderer() const
1349 {
1350     return rendererForCaretPainting(m_position.deepEquivalent().deprecatedNode());
1351 }
1352
1353 static bool isNonOrphanedCaret(const VisibleSelection& selection)
1354 {
1355     return selection.isCaret() && !selection.start().isOrphan() && !selection.end().isOrphan();
1356 }
1357
1358 IntRect FrameSelection::absoluteCaretBounds()
1359 {
1360     if (!m_frame)
1361         return IntRect();
1362     updateSelectionByUpdatingLayoutOrStyle(*m_frame);
1363     recomputeCaretRect();
1364     return m_absCaretBounds;
1365 }
1366
1367 static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect)
1368 {
1369     RenderObject* caretPainter = rendererForCaretPainting(node);
1370     if (!caretPainter)
1371         return;
1372
1373     caretPainter->repaintRectangle(rect);
1374 }
1375
1376 bool 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
1390     RefPtr<Node> caretNode = m_previousCaretNode;
1391     if (shouldUpdateCaretRect()) {
1392         if (!isNonOrphanedCaret(m_selection))
1393             clearCaretRect();
1394         else {
1395             VisiblePosition visibleStart = m_selection.visibleStart();
1396             if (updateCaretRect(m_frame->document(), visibleStart)) {
1397                 caretNode = visibleStart.deepEquivalent().deprecatedNode();
1398                 m_absCaretBoundsDirty = true;
1399             }
1400         }
1401     }
1402     LayoutRect newRect = localCaretRectWithoutUpdate();
1403
1404     if (caretNode == m_previousCaretNode && oldRect == newRect && !m_absCaretBoundsDirty)
1405         return false;
1406
1407     IntRect oldAbsCaretBounds = m_absCaretBounds;
1408     m_absCaretBounds = absoluteBoundsForLocalCaretRect(rendererForCaretPainting(caretNode.get()), newRect);
1409
1410     if (m_absCaretBoundsDirty && m_selection.isCaret()) // We should be able to always assert this condition.
1411         ASSERT(m_absCaretBounds == m_selection.visibleStart().absoluteCaretBounds());
1412
1413     m_absCaretBoundsDirty = false;
1414
1415     if (caretNode == m_previousCaretNode && oldAbsCaretBounds == m_absCaretBounds)
1416         return false;
1417
1418 #if ENABLE(TEXT_CARET)
1419     if (RenderView* view = m_frame->document()->renderView()) {
1420         bool previousOrNewCaretNodeIsContentEditable = m_selection.isContentEditable() || (m_previousCaretNode && m_previousCaretNode->isContentEditable());
1421         if (shouldRepaintCaret(view, previousOrNewCaretNodeIsContentEditable)) {
1422             if (m_previousCaretNode)
1423                 repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect);
1424             m_previousCaretNode = caretNode;
1425             repaintCaretForLocalRect(caretNode.get(), newRect);
1426         }
1427     }
1428 #endif
1429     return true;
1430 }
1431
1432 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditable) const
1433 {
1434     ASSERT(view);
1435     Frame* frame = &view->frameView().frame(); // The frame where the selection started.
1436     bool caretBrowsing = frame && frame->settings().caretBrowsingEnabled();
1437     return (caretBrowsing || isContentEditable);
1438 }
1439
1440 void FrameSelection::invalidateCaretRect()
1441 {
1442     if (!isCaret())
1443         return;
1444
1445     CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect());
1446 }
1447
1448 void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
1449 {
1450     // EDIT FIXME: This is an unfortunate hack.
1451     // Basically, we can't trust this layout position since we 
1452     // can't guarantee that the check to see if we are in unrendered 
1453     // content will work at this point. We may have to wait for
1454     // a layout and re-render of the document to happen. So, resetting this
1455     // flag will cause another caret layout to happen the first time
1456     // that we try to paint the caret after this call. That one will work since
1457     // it happens after the document has accounted for any editing
1458     // changes which may have been done.
1459     // And, we need to leave this layout here so the caret moves right 
1460     // away after clicking.
1461     m_caretRectNeedsUpdate = true;
1462
1463     if (caretRectChanged)
1464         return;
1465
1466     if (RenderView* view = node->document().renderView()) {
1467         if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)))
1468             repaintCaretForLocalRect(node, localCaretRectWithoutUpdate());
1469     }
1470 }
1471
1472 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
1473 {
1474     if (m_selection.isCaret() && m_caretPaint)
1475         CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
1476 }
1477
1478 void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1479 {
1480 #if ENABLE(TEXT_CARET)
1481     if (m_caretVisibility == Hidden)
1482         return;
1483
1484     LayoutRect drawingRect = localCaretRectWithoutUpdate();
1485     RenderObject* renderer = rendererForCaretPainting(node);
1486     if (renderer && renderer->isBox())
1487         toRenderBox(renderer)->flipForWritingMode(drawingRect);
1488     drawingRect.moveBy(roundedIntPoint(paintOffset));
1489     LayoutRect caret = intersection(drawingRect, clipRect);
1490     if (caret.isEmpty())
1491         return;
1492
1493     Color caretColor = Color::black;
1494     ColorSpace colorSpace = ColorSpaceDeviceRGB;
1495     Element* element = node->isElementNode() ? toElement(node) : node->parentElement();
1496     Element* rootEditableElement = node->rootEditableElement();
1497
1498     if (element && element->renderer()) {
1499         bool setToRootEditableElement = false;
1500         if (rootEditableElement && rootEditableElement->renderer()) {
1501             const auto& rootEditableStyle = rootEditableElement->renderer()->style();
1502             const auto& elementStyle = element->renderer()->style();
1503             if (rootEditableStyle.visitedDependentColor(CSSPropertyBackgroundColor) == elementStyle.visitedDependentColor(CSSPropertyBackgroundColor)) {
1504                 caretColor = rootEditableElement->renderer()->style().visitedDependentColor(CSSPropertyColor);
1505                 colorSpace = rootEditableElement->renderer()->style().colorSpace();
1506                 setToRootEditableElement = true;
1507             }
1508         }
1509         if (!setToRootEditableElement) {
1510             caretColor = element->renderer()->style().visitedDependentColor(CSSPropertyColor);
1511             colorSpace = element->renderer()->style().colorSpace();
1512         }
1513     }
1514
1515     context->fillRect(caret, caretColor, colorSpace);
1516 #else
1517     UNUSED_PARAM(node);
1518     UNUSED_PARAM(context);
1519     UNUSED_PARAM(paintOffset);
1520     UNUSED_PARAM(clipRect);
1521 #endif
1522 }
1523
1524 void FrameSelection::debugRenderer(RenderObject* r, bool selected) const
1525 {
1526     if (r->node()->isElementNode()) {
1527         Element* element = toElement(r->node());
1528         fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
1529     } else if (r->isText()) {
1530         RenderText* textRenderer = toRenderText(r);
1531         if (!textRenderer->textLength() || !textRenderer->firstTextBox()) {
1532             fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");
1533             return;
1534         }
1535         
1536         static const int max = 36;
1537         String text = textRenderer->text();
1538         int textLength = text.length();
1539         if (selected) {
1540             int offset = 0;
1541             if (r->node() == m_selection.start().containerNode())
1542                 offset = m_selection.start().computeOffsetInContainerNode();
1543             else if (r->node() == m_selection.end().containerNode())
1544                 offset = m_selection.end().computeOffsetInContainerNode();
1545
1546             int pos;
1547             InlineTextBox* box = textRenderer->findNextInlineTextBox(offset, pos);
1548             text = text.substring(box->start(), box->len());
1549             
1550             String show;
1551             int mid = max / 2;
1552             int caret = 0;
1553             
1554             // text is shorter than max
1555             if (textLength < max) {
1556                 show = text;
1557                 caret = pos;
1558             } else if (pos - mid < 0) {
1559                 // too few characters to left
1560                 show = text.left(max - 3) + "...";
1561                 caret = pos;
1562             } else if (pos - mid >= 0 && pos + mid <= textLength) {
1563                 // enough characters on each side
1564                 show = "..." + text.substring(pos - mid + 3, max - 6) + "...";
1565                 caret = mid;
1566             } else {
1567                 // too few characters on right
1568                 show = "..." + text.right(max - 3);
1569                 caret = pos - (textLength - show.length());
1570             }
1571             
1572             show.replace('\n', ' ');
1573             show.replace('\r', ' ');
1574             fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);
1575             fprintf(stderr, "           ");
1576             for (int i = 0; i < caret; i++)
1577                 fprintf(stderr, " ");
1578             fprintf(stderr, "^\n");
1579         } else {
1580             if ((int)text.length() > max)
1581                 text = text.left(max - 3) + "...";
1582             else
1583                 text = text.left(max);
1584             fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());
1585         }
1586     }
1587 }
1588
1589 bool FrameSelection::contains(const LayoutPoint& point)
1590 {
1591     Document* document = m_frame->document();
1592     
1593     // Treat a collapsed selection like no selection.
1594     if (!isRange())
1595         return false;
1596     if (!document->renderView()) 
1597         return false;
1598     
1599     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1600     HitTestResult result(point);
1601     document->renderView()->hitTest(request, result);
1602     Node* innerNode = result.innerNode();
1603     if (!innerNode || !innerNode->renderer())
1604         return false;
1605     
1606     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint(), nullptr));
1607     if (visiblePos.isNull())
1608         return false;
1609         
1610     if (m_selection.visibleStart().isNull() || m_selection.visibleEnd().isNull())
1611         return false;
1612         
1613     Position start(m_selection.visibleStart().deepEquivalent());
1614     Position end(m_selection.visibleEnd().deepEquivalent());
1615     Position p(visiblePos.deepEquivalent());
1616
1617     return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
1618 }
1619
1620 // Workaround for the fact that it's hard to delete a frame.
1621 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
1622 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
1623 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
1624 // mouse or the keyboard after setting the selection.
1625 void FrameSelection::selectFrameElementInParentIfFullySelected()
1626 {
1627     // Find the parent frame; if there is none, then we have nothing to do.
1628     Frame* parent = m_frame->tree().parent();
1629     if (!parent)
1630         return;
1631     Page* page = m_frame->page();
1632     if (!page)
1633         return;
1634
1635     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
1636     if (!isRange())
1637         return;
1638     if (!isStartOfDocument(selection().visibleStart()))
1639         return;
1640     if (!isEndOfDocument(selection().visibleEnd()))
1641         return;
1642
1643     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
1644     Element* ownerElement = m_frame->ownerElement();
1645     if (!ownerElement)
1646         return;
1647     ContainerNode* ownerElementParent = ownerElement->parentNode();
1648     if (!ownerElementParent)
1649         return;
1650         
1651     // 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.
1652     if (!ownerElementParent->hasEditableStyle())
1653         return;
1654
1655     // Create compute positions before and after the element.
1656     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
1657     VisiblePosition beforeOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex, Position::PositionIsOffsetInAnchor)));
1658     VisiblePosition afterOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex + 1, Position::PositionIsOffsetInAnchor), VP_UPSTREAM_IF_POSSIBLE));
1659
1660     // Focus on the parent frame, and then select from before this element to after.
1661     VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
1662     if (parent->selection().shouldChangeSelection(newSelection)) {
1663         page->focusController().setFocusedFrame(parent);
1664         parent->selection().setSelection(newSelection);
1665     }
1666 }
1667
1668 void FrameSelection::selectAll()
1669 {
1670     Document* document = m_frame->document();
1671
1672     Element* focusedElement = document->focusedElement();
1673     if (focusedElement && focusedElement->hasTagName(selectTag)) {
1674         HTMLSelectElement* selectElement = toHTMLSelectElement(document->focusedElement());
1675         if (selectElement->canSelectAll()) {
1676             selectElement->selectAll();
1677             return;
1678         }
1679     }
1680
1681     RefPtr<Node> root = 0;
1682     Node* selectStartTarget = 0;
1683     if (m_selection.isContentEditable()) {
1684         root = highestEditableRoot(m_selection.start());
1685         if (Node* shadowRoot = m_selection.nonBoundaryShadowTreeRootNode())
1686             selectStartTarget = shadowRoot->shadowHost();
1687         else
1688             selectStartTarget = root.get();
1689     } else {
1690         if (m_selection.isNone() && focusedElement) {
1691             if (focusedElement->isTextFormControl()) {
1692                 toHTMLTextFormControlElement(focusedElement)->select();
1693                 return;
1694             }
1695             root = focusedElement->nonBoundaryShadowTreeRootNode();
1696         } else
1697             root = m_selection.nonBoundaryShadowTreeRootNode();
1698
1699         if (root)
1700             selectStartTarget = root->shadowHost();
1701         else {
1702             root = document->documentElement();
1703             selectStartTarget = document->body();
1704         }
1705     }
1706     if (!root)
1707         return;
1708
1709     if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)))
1710         return;
1711
1712     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root.get()));
1713
1714     if (shouldChangeSelection(newSelection))
1715         setSelection(newSelection, defaultSetSelectionOptions() | FireSelectEvent);
1716 }
1717
1718 bool FrameSelection::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping)
1719 {
1720     if (!range || !range->startContainer() || !range->endContainer())
1721         return false;
1722     ASSERT(&range->startContainer()->document() == &range->endContainer()->document());
1723
1724     VisibleSelection newSelection(range, affinity);
1725
1726 #if PLATFORM(IOS)
1727     // FIXME: Why do we need this check only in iOS?
1728     if (range->startContainer() && range->endContainer() && newSelection.isNone())
1729         return false;
1730 #endif
1731
1732     setSelection(newSelection, ClearTypingStyle | (closeTyping ? CloseTyping : 0));
1733     return true;
1734 }
1735
1736 void FrameSelection::focusedOrActiveStateChanged()
1737 {
1738     bool activeAndFocused = isFocusedAndActive();
1739     Ref<Document> document(*m_frame->document());
1740
1741     document->updateStyleIfNeeded();
1742
1743 #if USE(UIKIT_EDITING)
1744     // Caret blinking (blinks | does not blink)
1745     if (activeAndFocused)
1746         setSelectionFromNone();
1747     setCaretVisible(activeAndFocused);
1748 #else
1749     // Because RenderObject::selectionBackgroundColor() and
1750     // RenderObject::selectionForegroundColor() check if the frame is active,
1751     // we have to update places those colors were painted.
1752     if (RenderView* view = document->renderView())
1753         view->repaintSelection();
1754
1755     // Caret appears in the active frame.
1756     if (activeAndFocused)
1757         setSelectionFromNone();
1758     setCaretVisibility(activeAndFocused ? Visible : Hidden);
1759
1760     // Update for caps lock state
1761     m_frame->eventHandler().capsLockStateMayHaveChanged();
1762
1763     // Because StyleResolver::checkOneSelector() and
1764     // RenderTheme::isFocused() check if the frame is active, we have to
1765     // update style and theme state that depended on those.
1766     if (Element* element = document->focusedElement()) {
1767         element->setNeedsStyleRecalc();
1768         if (RenderObject* renderer = element->renderer())
1769             if (renderer && renderer->style().hasAppearance())
1770                 renderer->theme().stateChanged(*renderer, ControlStates::FocusState);
1771     }
1772 #endif
1773 }
1774
1775 void FrameSelection::pageActivationChanged()
1776 {
1777     focusedOrActiveStateChanged();
1778 }
1779
1780 void FrameSelection::setFocused(bool flag)
1781 {
1782     if (m_focused == flag)
1783         return;
1784     m_focused = flag;
1785
1786     focusedOrActiveStateChanged();
1787 }
1788
1789 bool FrameSelection::isFocusedAndActive() const
1790 {
1791     return m_focused && m_frame->page() && m_frame->page()->focusController().isActive();
1792 }
1793
1794 #if ENABLE(TEXT_CARET)
1795 inline static bool shouldStopBlinkingDueToTypingCommand(Frame* frame)
1796 {
1797     return frame->editor().lastEditCommand() && frame->editor().lastEditCommand()->shouldStopCaretBlinking();
1798 }
1799 #endif
1800
1801 void FrameSelection::updateAppearance()
1802 {
1803 #if PLATFORM(IOS)
1804     if (!m_updateAppearanceEnabled)
1805         return;
1806 #endif
1807
1808     // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case
1809     // the FrameSelection will paint a blinking caret as usual).
1810     VisibleSelection oldSelection = selection();
1811     VisiblePosition forwardPosition;
1812     if (m_shouldShowBlockCursor && oldSelection.isCaret()) {
1813         forwardPosition = modifyExtendingForward(CharacterGranularity);
1814         m_caretPaint = forwardPosition.isNull();
1815     }
1816
1817 #if ENABLE(TEXT_CARET)
1818     bool caretRectChangedOrCleared = recomputeCaretRect();
1819
1820     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
1821     bool shouldBlink = caretIsVisible() && isCaret() && (oldSelection.isContentEditable() || caretBrowsing) && forwardPosition.isNull();
1822
1823     // If the caret moved, stop the blink timer so we can restart with a
1824     // black caret in the new location.
1825     if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame))
1826         m_caretBlinkTimer.stop();
1827
1828     // Start blinking with a black caret. Be sure not to restart if we're
1829     // already blinking in the right location.
1830     if (shouldBlink && !m_caretBlinkTimer.isActive()) {
1831         if (double blinkInterval = m_frame->page()->theme().caretBlinkInterval())
1832             m_caretBlinkTimer.startRepeating(blinkInterval);
1833
1834         if (!m_caretPaint) {
1835             m_caretPaint = true;
1836             invalidateCaretRect();
1837         }
1838     }
1839 #endif
1840
1841     RenderView* view = m_frame->contentRenderer();
1842     if (!view)
1843         return;
1844
1845     // Construct a new VisibleSolution, since m_selection is not necessarily valid, and the following steps
1846     // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69563> and <rdar://problem/10232866>.
1847     VisibleSelection selection(oldSelection.visibleStart(), forwardPosition.isNotNull() ? forwardPosition : oldSelection.visibleEnd());
1848
1849     if (!selection.isRange()) {
1850         view->clearSelection();
1851         return;
1852     }
1853
1854     // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
1855     // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
1856     // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
1857     // and will fill the gap before 'bar'.
1858     Position startPos = selection.start();
1859     Position candidate = startPos.downstream();
1860     if (candidate.isCandidate())
1861         startPos = candidate;
1862     Position endPos = selection.end();
1863     candidate = endPos.upstream();
1864     if (candidate.isCandidate())
1865         endPos = candidate;
1866
1867     // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
1868     // because we don't yet notify the FrameSelection of text removal.
1869     if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
1870         RenderObject* startRenderer = startPos.deprecatedNode()->renderer();
1871         RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
1872         view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset());
1873     }
1874 }
1875
1876 void FrameSelection::setCaretVisibility(CaretVisibility visibility)
1877 {
1878     if (caretVisibility() == visibility)
1879         return;
1880
1881     // FIXME: We shouldn't trigger a synchrnously layout here.
1882     if (m_frame)
1883         updateSelectionByUpdatingLayoutOrStyle(*m_frame);
1884
1885 #if ENABLE(TEXT_CARET)
1886     if (m_caretPaint) {
1887         m_caretPaint = false;
1888         invalidateCaretRect();
1889     }
1890     CaretBase::setCaretVisibility(visibility);
1891 #endif
1892
1893     updateAppearance();
1894 }
1895
1896 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>&)
1897 {
1898 #if ENABLE(TEXT_CARET)
1899     ASSERT(caretIsVisible());
1900     ASSERT(isCaret());
1901     bool caretPaint = m_caretPaint;
1902     if (isCaretBlinkingSuspended() && caretPaint)
1903         return;
1904     m_caretPaint = !caretPaint;
1905     invalidateCaretRect();
1906 #endif
1907 }
1908
1909 // Helper function that tells whether a particular node is an element that has an entire
1910 // Frame and FrameView, a <frame>, <iframe>, or <object>.
1911 static bool isFrameElement(const Node* n)
1912 {
1913     if (!n)
1914         return false;
1915     RenderObject* renderer = n->renderer();
1916     if (!renderer || !renderer->isWidget())
1917         return false;
1918     Widget* widget = toRenderWidget(renderer)->widget();
1919     return widget && widget->isFrameView();
1920 }
1921
1922 void FrameSelection::setFocusedElementIfNeeded()
1923 {
1924     if (isNone() || !isFocused())
1925         return;
1926
1927     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
1928     if (caretBrowsing) {
1929         if (Element* anchor = enclosingAnchorElement(m_selection.base())) {
1930             m_frame->page()->focusController().setFocusedElement(anchor, m_frame);
1931             return;
1932         }
1933     }
1934
1935     if (Element* target = m_selection.rootEditableElement()) {
1936         // Walk up the DOM tree to search for an element to focus.
1937         while (target) {
1938             // We don't want to set focus on a subframe when selecting in a parent frame,
1939             // so add the !isFrameElement check here. There's probably a better way to make this
1940             // work in the long term, but this is the safest fix at this time.
1941             if (target->isMouseFocusable() && !isFrameElement(target)) {
1942                 m_frame->page()->focusController().setFocusedElement(target, m_frame);
1943                 return;
1944             }
1945             target = target->parentOrShadowHostElement();
1946         }
1947         m_frame->document()->setFocusedElement(0);
1948     }
1949
1950     if (caretBrowsing)
1951         m_frame->page()->focusController().setFocusedElement(0, m_frame);
1952 }
1953
1954 void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1955 {
1956 #if ENABLE(TEXT_CARET)
1957     if (m_position.deepEquivalent().deprecatedNode()->document().frame() == frame)
1958         paintCaret(m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
1959 #else
1960     UNUSED_PARAM(frame);
1961     UNUSED_PARAM(p);
1962     UNUSED_PARAM(paintOffset);
1963     UNUSED_PARAM(clipRect);
1964 #endif
1965 }
1966
1967 PassRefPtr<MutableStyleProperties> FrameSelection::copyTypingStyle() const
1968 {
1969     if (!m_typingStyle || !m_typingStyle->style())
1970         return 0;
1971     return m_typingStyle->style()->mutableCopy();
1972 }
1973
1974 bool FrameSelection::shouldDeleteSelection(const VisibleSelection& selection) const
1975 {
1976 #if PLATFORM(IOS)
1977     if (m_frame->selectionChangeCallbacksDisabled())
1978         return true;
1979 #endif
1980     return m_frame->editor().client()->shouldDeleteRange(selection.toNormalizedRange().get());
1981 }
1982
1983 FloatRect FrameSelection::selectionBounds(bool clipToVisibleContent) const
1984 {
1985     if (!m_frame->document())
1986         return LayoutRect();
1987
1988     updateSelectionByUpdatingLayoutOrStyle(*m_frame);
1989     RenderView* root = m_frame->contentRenderer();
1990     FrameView* view = m_frame->view();
1991     if (!root || !view)
1992         return LayoutRect();
1993
1994     LayoutRect selectionRect = root->selectionBounds(clipToVisibleContent);
1995     return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect)) : selectionRect;
1996 }
1997
1998 void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangles) const
1999 {
2000     RenderView* root = m_frame->contentRenderer();
2001     if (!root)
2002         return;
2003
2004     FloatRect visibleContentRect = m_frame->view()->visibleContentRect(ScrollableArea::LegacyIOSDocumentVisibleRect);
2005
2006     Vector<FloatQuad> quads;
2007     toNormalizedRange()->textQuads(quads, true);
2008
2009     size_t size = quads.size();
2010     for (size_t i = 0; i < size; ++i) {
2011         FloatRect intersectionRect = intersection(quads[i].enclosingBoundingBox(), visibleContentRect);
2012         if (!intersectionRect.isEmpty())
2013             rectangles.append(intersectionRect);
2014     }
2015 }
2016
2017 // Scans logically forward from "start", including any child frames.
2018 static HTMLFormElement* scanForForm(Element* start)
2019 {
2020     if (!start)
2021         return nullptr;
2022
2023     auto descendants = descendantsOfType<HTMLElement>(start->document());
2024     for (auto it = descendants.from(*start), end = descendants.end(); it != end; ++it) {
2025         HTMLElement& element = *it;
2026         if (isHTMLFormElement(&element))
2027             return toHTMLFormElement(&element);
2028         if (isHTMLFormControlElement(element))
2029             return toHTMLFormControlElement(element).form();
2030         if (isHTMLFrameElementBase(element)) {
2031             Document* contentDocument = toHTMLFrameElementBase(element).contentDocument();
2032             if (!contentDocument)
2033                 continue;
2034             if (HTMLFormElement* frameResult = scanForForm(contentDocument->documentElement()))
2035                 return frameResult;
2036         }
2037     }
2038     return nullptr;
2039 }
2040
2041 // We look for either the form containing the current focus, or for one immediately after it
2042 HTMLFormElement* FrameSelection::currentForm() const
2043 {
2044     // Start looking either at the active (first responder) node, or where the selection is.
2045     Element* start = m_frame->document()->focusedElement();
2046     if (!start)
2047         start = m_selection.start().element();
2048     if (!start)
2049         return nullptr;
2050
2051     if (auto form = lineageOfType<HTMLFormElement>(*start).first())
2052         return form;
2053     if (auto formControl = lineageOfType<HTMLFormControlElement>(*start).first())
2054         return formControl->form();
2055
2056     // Try walking forward in the node tree to find a form element.
2057     return scanForForm(start);
2058 }
2059
2060 void FrameSelection::revealSelection(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
2061 {
2062     LayoutRect rect;
2063
2064     switch (m_selection.selectionType()) {
2065     case VisibleSelection::NoSelection:
2066         return;
2067     case VisibleSelection::CaretSelection:
2068         rect = absoluteCaretBounds();
2069         break;
2070     case VisibleSelection::RangeSelection:
2071         rect = revealExtentOption == RevealExtent ? VisiblePosition(m_selection.extent()).absoluteCaretBounds() : enclosingIntRect(selectionBounds(false));
2072         break;
2073     }
2074
2075     Position start = m_selection.start();
2076     ASSERT(start.deprecatedNode());
2077     if (start.deprecatedNode() && start.deprecatedNode()->renderer()) {
2078 #if PLATFORM(IOS)
2079         if (RenderLayer* layer = start.deprecatedNode()->renderer()->enclosingLayer()) {
2080             if (!m_scrollingSuppressCount) {
2081                 layer->setAdjustForIOSCaretWhenScrolling(true);
2082                 layer->scrollRectToVisible(rect, alignment, alignment);
2083                 layer->setAdjustForIOSCaretWhenScrolling(false);
2084                 updateAppearance();
2085                 if (m_frame->page())
2086                     m_frame->page()->chrome().client().notifyRevealedSelectionByScrollingFrame(m_frame);
2087             }
2088         }
2089 #else
2090         // FIXME: This code only handles scrolling the startContainer's layer, but
2091         // the selection rect could intersect more than just that.
2092         // See <rdar://problem/4799899>.
2093         if (start.deprecatedNode()->renderer()->scrollRectToVisible(rect, alignment, alignment))
2094             updateAppearance();
2095 #endif
2096     }
2097 }
2098
2099 void FrameSelection::setSelectionFromNone()
2100 {
2101     // Put a caret inside the body if the entire frame is editable (either the
2102     // entire WebView is editable or designMode is on for this document).
2103
2104     Document* document = m_frame->document();
2105 #if !PLATFORM(IOS)
2106     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
2107     if (!isNone() || !(document->hasEditableStyle() || caretBrowsing))
2108         return;
2109 #else
2110     if (!document || !(isNone() || isStartOfDocument(VisiblePosition(m_selection.start(), m_selection.affinity()))) || !document->hasEditableStyle())
2111         return;
2112 #endif
2113
2114     Node* node = document->documentElement();
2115     while (node && !node->hasTagName(bodyTag))
2116         node = NodeTraversal::next(node);
2117     if (node)
2118         setSelection(VisibleSelection(firstPositionInOrBeforeNode(node), DOWNSTREAM));
2119 }
2120
2121 bool FrameSelection::shouldChangeSelection(const VisibleSelection& newSelection) const
2122 {
2123 #if PLATFORM(IOS)
2124     if (m_frame->selectionChangeCallbacksDisabled())
2125         return true;
2126 #endif
2127     return m_frame->editor().shouldChangeSelection(selection(), newSelection, newSelection.affinity(), false);
2128 }
2129
2130 bool FrameSelection::dispatchSelectStart()
2131 {
2132     Node* selectStartTarget = m_selection.extent().containerNode();
2133     if (!selectStartTarget)
2134         return true;
2135
2136     return selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
2137 }
2138
2139 void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor)
2140 {
2141     m_shouldShowBlockCursor = shouldShowBlockCursor;
2142
2143     m_frame->document()->updateLayoutIgnorePendingStylesheets();
2144
2145     updateAppearance();
2146 }
2147
2148 void FrameSelection::didLayout()
2149 {
2150     setCaretRectNeedsUpdate();
2151     updateAndRevealSelection();
2152     updateDataDetectorsForSelection();
2153 }
2154
2155 #ifndef NDEBUG
2156
2157 void FrameSelection::formatForDebugger(char* buffer, unsigned length) const
2158 {
2159     m_selection.formatForDebugger(buffer, length);
2160 }
2161
2162 void FrameSelection::showTreeForThis() const
2163 {
2164     m_selection.showTreeForThis();
2165 }
2166
2167 #endif
2168
2169 #if PLATFORM(IOS)
2170 void FrameSelection::expandSelectionToElementContainingCaretSelection()
2171 {
2172     RefPtr<Range> range = elementRangeContainingCaretSelection();
2173     if (!range)
2174         return;
2175     VisibleSelection selection(range.get(), DOWNSTREAM);
2176     setSelection(selection);
2177 }
2178
2179 PassRefPtr<Range> FrameSelection::elementRangeContainingCaretSelection() const
2180 {
2181     if (m_selection.isNone())
2182         return nullptr;
2183
2184     VisibleSelection selection = m_selection;
2185     if (selection.isNone())
2186         return nullptr;
2187
2188     VisiblePosition visiblePos(selection.start(), VP_DEFAULT_AFFINITY);
2189     if (visiblePos.isNull())
2190         return nullptr;
2191
2192     Node* node = visiblePos.deepEquivalent().deprecatedNode();
2193     Element* element = deprecatedEnclosingBlockFlowElement(node);
2194     if (!element)
2195         return nullptr;
2196
2197     Position startPos = createLegacyEditingPosition(element, 0);
2198     Position endPos = createLegacyEditingPosition(element, element->childNodeCount());
2199     
2200     VisiblePosition startVisiblePos(startPos, VP_DEFAULT_AFFINITY);
2201     VisiblePosition endVisiblePos(endPos, VP_DEFAULT_AFFINITY);
2202     if (startVisiblePos.isNull() || endVisiblePos.isNull())
2203         return nullptr;
2204
2205     selection.setBase(startVisiblePos);
2206     selection.setExtent(endVisiblePos);
2207
2208     return selection.toNormalizedRange();
2209 }
2210
2211 void FrameSelection::expandSelectionToWordContainingCaretSelection()
2212 {
2213     VisibleSelection selection(wordSelectionContainingCaretSelection(m_selection));        
2214     if (selection.isCaretOrRange())
2215         setSelection(selection);
2216 }
2217
2218 PassRefPtr<Range> FrameSelection::wordRangeContainingCaretSelection()
2219 {
2220     return wordSelectionContainingCaretSelection(m_selection).toNormalizedRange();
2221 }
2222
2223 void FrameSelection::expandSelectionToStartOfWordContainingCaretSelection()
2224 {
2225     if (m_selection.isNone() || isStartOfDocument(m_selection.start()))
2226         return;
2227
2228     VisiblePosition s1(m_selection.start());
2229     VisiblePosition e1(m_selection.end());
2230
2231     VisibleSelection expanded(wordSelectionContainingCaretSelection(m_selection));
2232     VisiblePosition s2(expanded.start());
2233
2234     // Don't allow the start to become greater after the expansion.
2235     if (s2.isNull() || s2 > s1)
2236         s2 = s1;
2237
2238     moveTo(s2, e1);
2239 }
2240
2241 UChar FrameSelection::characterInRelationToCaretSelection(int amount) const
2242 {
2243     if (m_selection.isNone())
2244         return 0;
2245
2246     VisibleSelection selection = m_selection;
2247     ASSERT(selection.isCaretOrRange());
2248
2249     VisiblePosition visiblePosition(selection.start(), VP_DEFAULT_AFFINITY);
2250
2251     if (amount < 0) {
2252         int count = abs(amount);
2253         for (int i = 0; i < count; i++)
2254             visiblePosition = visiblePosition.previous();    
2255         return visiblePosition.characterBefore();
2256     }
2257     for (int i = 0; i < amount; i++)
2258         visiblePosition = visiblePosition.next();    
2259     return visiblePosition.characterAfter();
2260 }
2261
2262 UChar FrameSelection::characterBeforeCaretSelection() const
2263 {
2264     if (m_selection.isNone())
2265         return 0;
2266
2267     VisibleSelection selection = m_selection;
2268     ASSERT(selection.isCaretOrRange());
2269
2270     VisiblePosition visiblePosition(selection.start(), VP_DEFAULT_AFFINITY);
2271     return visiblePosition.characterBefore();
2272 }
2273
2274 UChar FrameSelection::characterAfterCaretSelection() const
2275 {
2276     if (m_selection.isNone())
2277         return 0;
2278
2279     VisibleSelection selection = m_selection;
2280     ASSERT(selection.isCaretOrRange());
2281
2282     VisiblePosition visiblePosition(selection.end(), VP_DEFAULT_AFFINITY);
2283     return visiblePosition.characterAfter();
2284 }
2285
2286 int FrameSelection::wordOffsetInRange(const Range *range) const
2287 {
2288     if (!range)
2289         return -1;
2290
2291     VisibleSelection selection = m_selection;
2292     if (!selection.isCaret())
2293         return -1;
2294
2295     // FIXME: This will only work in cases where the selection remains in
2296     // the same node after it is expanded. Improve to handle more complicated
2297     // cases.
2298     ExceptionCode ec = 0;
2299     int result = selection.start().deprecatedEditingOffset() - range->startOffset(ec);
2300     ASSERT(!ec);
2301     if (result < 0)
2302         result = 0;
2303     return result;
2304 }
2305
2306 bool FrameSelection::spaceFollowsWordInRange(const Range *range) const
2307 {
2308     if (!range)
2309         return false;
2310     ExceptionCode ec = 0;
2311     Node* node = range->endContainer(ec);
2312     ASSERT(!ec);
2313     int endOffset = range->endOffset(ec);
2314     ASSERT(!ec);
2315     VisiblePosition pos(createLegacyEditingPosition(node, endOffset), VP_DEFAULT_AFFINITY);
2316     return isSpaceOrNewline(pos.characterAfter());
2317 }
2318
2319 bool FrameSelection::selectionAtDocumentStart() const
2320 {
2321     VisibleSelection selection = m_selection;
2322     if (selection.isNone())
2323         return false;
2324
2325     Position startPos(selection.start());
2326     VisiblePosition pos(createLegacyEditingPosition(startPos.deprecatedNode(), startPos.deprecatedEditingOffset()), VP_DEFAULT_AFFINITY);
2327     if (pos.isNull())
2328         return false;
2329
2330     return isStartOfDocument(pos);
2331 }
2332
2333 bool FrameSelection::selectionAtSentenceStart() const
2334 {
2335     VisibleSelection selection = m_selection;
2336     if (selection.isNone())
2337         return false;
2338
2339     return actualSelectionAtSentenceStart(selection);
2340 }
2341
2342 bool FrameSelection::selectionAtWordStart() const
2343 {
2344     VisibleSelection selection = m_selection;
2345     if (selection.isNone())
2346         return false;
2347
2348     Position startPos(selection.start());
2349     VisiblePosition pos(createLegacyEditingPosition(startPos.deprecatedNode(), startPos.deprecatedEditingOffset()), VP_DEFAULT_AFFINITY);
2350     if (pos.isNull())
2351         return false;
2352
2353     if (isStartOfParagraph(pos))
2354         return true;
2355         
2356     bool result = true;
2357     unsigned previousCount = 0;
2358     for (pos = pos.previous(); !pos.isNull(); pos = pos.previous()) {
2359         previousCount++;
2360         if (isStartOfParagraph(pos)) {
2361             if (previousCount == 1)
2362                 result = false;
2363             break;
2364         }
2365         UChar c(pos.characterAfter());
2366         if (c) {
2367             result = isSpaceOrNewline(c) || c == 0xA0 || (u_ispunct(c) && c != ',' && c != '-' && c != '\'');
2368             break;
2369         }
2370     }
2371
2372     return result;
2373 }
2374
2375 PassRefPtr<Range> FrameSelection::rangeByMovingCurrentSelection(int amount) const
2376 {
2377     return rangeByAlteringCurrentSelection(AlterationMove, amount);
2378 }
2379
2380 PassRefPtr<Range> FrameSelection::rangeByExtendingCurrentSelection(int amount) const
2381 {
2382     return rangeByAlteringCurrentSelection(AlterationExtend, amount);
2383 }
2384
2385 void FrameSelection::selectRangeOnElement(unsigned location, unsigned length, Node* node)
2386 {
2387     RefPtr<Range> resultRange = m_frame->document()->createRange();
2388     ExceptionCode ec = 0;
2389     resultRange->setStart(node, location, ec);
2390     ASSERT(!ec);
2391     resultRange->setEnd(node, location + length, ec);
2392     ASSERT(!ec);
2393     VisibleSelection selection = VisibleSelection(resultRange.get(), SEL_DEFAULT_AFFINITY);
2394     setSelection(selection, true);
2395 }
2396
2397 VisibleSelection FrameSelection::wordSelectionContainingCaretSelection(const VisibleSelection& selection)
2398 {
2399     if (selection.isNone())
2400         return VisibleSelection();
2401
2402     ASSERT(selection.isCaretOrRange());
2403     FrameSelection frameSelection;
2404     frameSelection.setSelection(selection);
2405
2406     Position startPosBeforeExpansion(selection.start());
2407     Position endPosBeforeExpansion(selection.end());
2408     VisiblePosition startVisiblePosBeforeExpansion(startPosBeforeExpansion, VP_DEFAULT_AFFINITY);
2409     VisiblePosition endVisiblePosBeforeExpansion(endPosBeforeExpansion, VP_DEFAULT_AFFINITY);
2410     if (endVisiblePosBeforeExpansion.isNull())
2411         return VisibleSelection();
2412
2413     if (isEndOfParagraph(endVisiblePosBeforeExpansion)) {
2414         UChar c(endVisiblePosBeforeExpansion.characterBefore());
2415         if (isSpaceOrNewline(c) || c == 0xA0) {
2416             // End of paragraph with space.
2417             return VisibleSelection();
2418         }
2419     }
2420
2421     // If at end of paragraph, move backwards one character.
2422     // This has the effect of selecting the word on the line (which is
2423     // what we want, rather than selecting past the end of the line).
2424     if (isEndOfParagraph(endVisiblePosBeforeExpansion) && !isStartOfParagraph(endVisiblePosBeforeExpansion))
2425         frameSelection.modify(FrameSelection::AlterationMove, DirectionBackward, CharacterGranularity);
2426
2427     VisibleSelection newSelection = frameSelection.selection();
2428     newSelection.expandUsingGranularity(WordGranularity);
2429     frameSelection.setSelection(newSelection, defaultSetSelectionOptions(), AlignCursorOnScrollIfNeeded, frameSelection.granularity());
2430
2431     Position startPos(frameSelection.selection().start());
2432     Position endPos(frameSelection.selection().end());
2433
2434     // Expansion cannot be allowed to change selection so that it is no longer
2435     // touches (or contains) the original, unexpanded selection.
2436     // Enforce this on the way into these additional calculations to give them
2437     // the best chance to yield a suitable answer.
2438     if (startPos > startPosBeforeExpansion)
2439         startPos = startPosBeforeExpansion;
2440     if (endPos < endPosBeforeExpansion)
2441         endPos = endPosBeforeExpansion;
2442
2443     VisiblePosition startVisiblePos(startPos, VP_DEFAULT_AFFINITY);
2444     VisiblePosition endVisiblePos(endPos, VP_DEFAULT_AFFINITY);
2445
2446     if (startVisiblePos.isNull() || endVisiblePos.isNull()) {
2447         // Start or end is nil
2448         return VisibleSelection();
2449     }
2450
2451     if (isEndOfLine(endVisiblePosBeforeExpansion)) {
2452         VisiblePosition previous(endVisiblePos.previous());
2453         if (previous == endVisiblePos) {
2454             // Empty document
2455             return VisibleSelection();
2456         }
2457         UChar c(previous.characterAfter());
2458         if (isSpaceOrNewline(c) || c == 0xA0) {
2459             // Space at end of line
2460             return VisibleSelection();
2461         }
2462     }
2463
2464     // Expansion has selected past end of line.
2465     // Try repositioning backwards.
2466     if (isEndOfLine(startVisiblePos) && isStartOfLine(endVisiblePos)) {
2467         VisiblePosition previous(startVisiblePos.previous());
2468         if (isEndOfLine(previous)) {
2469             // On empty line
2470             return VisibleSelection();
2471         }
2472         UChar c(previous.characterAfter());
2473         if (isSpaceOrNewline(c) || c == 0xA0) {
2474             // Space at end of line
2475             return VisibleSelection();
2476         }
2477         frameSelection.moveTo(startVisiblePos);
2478         frameSelection.modify(FrameSelection::AlterationExtend, DirectionBackward, WordGranularity);
2479         startPos = frameSelection.selection().start();
2480         endPos = frameSelection.selection().end();
2481         startVisiblePos = VisiblePosition(startPos, VP_DEFAULT_AFFINITY);
2482         endVisiblePos = VisiblePosition(endPos, VP_DEFAULT_AFFINITY);
2483         if (startVisiblePos.isNull() || endVisiblePos.isNull()) {
2484             // Start or end is nil
2485             return VisibleSelection();
2486         }
2487     }
2488
2489     // Now loop backwards until we find a non-space.
2490     while (endVisiblePos != startVisiblePos) {
2491         VisiblePosition previous(endVisiblePos.previous());
2492         UChar c(previous.characterAfter());
2493         if (!isSpaceOrNewline(c) && c != 0xA0)
2494             break;
2495         endVisiblePos = previous;
2496     }
2497
2498     // Expansion cannot be allowed to change selection so that it is no longer
2499     // touches (or contains) the original, unexpanded selection.
2500     // Enforce this on the way out of the function to preserve the invariant.
2501     if (startVisiblePos > startVisiblePosBeforeExpansion)
2502         startVisiblePos = startVisiblePosBeforeExpansion;
2503     if (endVisiblePos < endVisiblePosBeforeExpansion)
2504         endVisiblePos = endVisiblePosBeforeExpansion;
2505
2506     return VisibleSelection(startVisiblePos, endVisiblePos);    
2507 }
2508
2509 bool FrameSelection::actualSelectionAtSentenceStart(const VisibleSelection& sel) const
2510 {
2511     Position startPos(sel.start());
2512     VisiblePosition pos(createLegacyEditingPosition(startPos.deprecatedNode(), startPos.deprecatedEditingOffset()), VP_DEFAULT_AFFINITY);
2513     if (pos.isNull())
2514         return false;
2515
2516     if (isStartOfParagraph(pos))
2517         return true;
2518  
2519     bool result = true;
2520     bool sawSpace = false;
2521     unsigned previousCount = 0;
2522     for (pos = pos.previous(); !pos.isNull(); pos = pos.previous()) {
2523         previousCount++;
2524         if (isStartOfParagraph(pos)) {
2525             if (previousCount == 1 || (previousCount == 2 && sawSpace))
2526                 result = false;
2527             break;
2528         }
2529         UChar c(pos.characterAfter());
2530         if (c) {
2531             if (isSpaceOrNewline(c) || c == 0xA0) {
2532                 sawSpace = true;
2533             }
2534             else {
2535                 result = (c == '.' || c == '!' || c == '?');
2536                 break;
2537             }
2538         }
2539     }
2540     
2541     return result;
2542 }
2543
2544 PassRefPtr<Range> FrameSelection::rangeByAlteringCurrentSelection(EAlteration alteration, int amount) const
2545 {
2546     if (m_selection.isNone())
2547         return nullptr;
2548
2549     if (!amount)
2550         return toNormalizedRange();
2551
2552     FrameSelection frameSelection;
2553     frameSelection.setSelection(m_selection);
2554     SelectionDirection direction = amount > 0 ? DirectionForward : DirectionBackward;
2555     for (int i = 0; i < abs(amount); i++)
2556         frameSelection.modify(alteration, direction, CharacterGranularity);
2557     return frameSelection.toNormalizedRange();
2558 }
2559
2560 void FrameSelection::clearCurrentSelection()
2561 {
2562     setSelection(VisibleSelection());
2563 }
2564
2565 void FrameSelection::setCaretBlinks(bool caretBlinks)
2566 {
2567     if (m_caretBlinks == caretBlinks)
2568         return;
2569 #if ENABLE(TEXT_CARET)
2570     m_frame->document()->updateLayoutIgnorePendingStylesheets(); 
2571     if (m_caretPaint) {
2572         m_caretPaint = false; 
2573         invalidateCaretRect(); 
2574     }
2575 #endif
2576     if (caretBlinks)
2577         setFocusedElementIfNeeded();
2578     m_caretBlinks = caretBlinks;
2579     updateAppearance();
2580 }
2581
2582 void FrameSelection::setCaretColor(const Color& caretColor)
2583 {
2584     if (m_caretColor != caretColor) {
2585         m_caretColor = caretColor;
2586         if (caretIsVisible() && m_caretBlinks && isCaret())
2587             invalidateCaretRect();
2588     }
2589 }
2590 #endif // PLATFORM(IOS)
2591
2592 }
2593
2594 #ifndef NDEBUG
2595
2596 void showTree(const WebCore::FrameSelection& sel)
2597 {
2598     sel.showTreeForThis();
2599 }
2600
2601 void showTree(const WebCore::FrameSelection* sel)
2602 {
2603     if (sel)
2604         sel->showTreeForThis();
2605 }
2606
2607 #endif