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