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