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