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