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