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