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