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