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