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