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