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