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