4b1e67dc50895c4cfc56385de155345dee8708b0
[WebKit-https.git] / Source / WebCore / editing / FrameSelection.cpp
1 /*
2  * Copyright (C) 2004, 2008, 2009, 2010 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 COMPUTER, 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 COMPUTER, 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 "CharacterData.h"
30 #include "DeleteSelectionCommand.h"
31 #include "Document.h"
32 #include "Editor.h"
33 #include "EditorClient.h"
34 #include "Element.h"
35 #include "ElementIterator.h"
36 #include "EventHandler.h"
37 #include "ExceptionCode.h"
38 #include "FloatQuad.h"
39 #include "FocusController.h"
40 #include "Frame.h"
41 #include "FrameTree.h"
42 #include "FrameView.h"
43 #include "GraphicsContext.h"
44 #include "HTMLFormElement.h"
45 #include "HTMLFrameElementBase.h"
46 #include "HTMLInputElement.h"
47 #include "HTMLSelectElement.h"
48 #include "HTMLNames.h"
49 #include "HitTestRequest.h"
50 #include "HitTestResult.h"
51 #include "InlineTextBox.h"
52 #include "Page.h"
53 #include "RenderText.h"
54 #include "RenderTextControl.h"
55 #include "RenderTheme.h"
56 #include "RenderView.h"
57 #include "RenderWidget.h"
58 #include "RenderedPosition.h"
59 #include "Settings.h"
60 #include "SpatialNavigation.h"
61 #include "StyleProperties.h"
62 #include "TypingCommand.h"
63 #include "VisibleUnits.h"
64 #include "htmlediting.h"
65 #include <stdio.h>
66 #include <wtf/text/CString.h>
67
68 #define EDIT_DEBUG 0
69
70 namespace WebCore {
71
72 using namespace HTMLNames;
73
74 static inline LayoutUnit NoXPosForVerticalArrowNavigation()
75 {
76     return LayoutUnit::min();
77 }
78
79 CaretBase::CaretBase(CaretVisibility visibility)
80     : m_caretRectNeedsUpdate(true)
81     , m_caretVisibility(visibility)
82 {
83 }
84
85 DragCaretController::DragCaretController()
86     : CaretBase(Visible)
87 {
88 }
89
90 bool DragCaretController::isContentRichlyEditable() const
91 {
92     return isRichlyEditablePosition(m_position.deepEquivalent());
93 }
94
95 static inline bool shouldAlwaysUseDirectionalSelection(Frame* frame)
96 {
97     return !frame || frame->editor().behavior().shouldConsiderSelectionAsDirectional();
98 }
99
100 FrameSelection::FrameSelection(Frame* frame)
101     : m_frame(frame)
102     , m_xPosForVerticalArrowNavigation(NoXPosForVerticalArrowNavigation())
103     , m_granularity(CharacterGranularity)
104     , m_caretBlinkTimer(this, &FrameSelection::caretBlinkTimerFired)
105     , m_absCaretBoundsDirty(true)
106     , m_caretPaint(true)
107     , m_isCaretBlinkingSuspended(false)
108     , m_focused(frame && frame->page() && frame->page()->focusController().focusedFrame() == frame)
109     , m_shouldShowBlockCursor(false)
110 {
111     if (shouldAlwaysUseDirectionalSelection(m_frame))
112         m_selection.setIsDirectional(true);
113 }
114
115 Element* FrameSelection::rootEditableElementOrDocumentElement() const
116 {
117     Element* selectionRoot = m_selection.rootEditableElement();
118     return selectionRoot ? selectionRoot : m_frame->document()->documentElement();
119 }
120
121 void FrameSelection::moveTo(const VisiblePosition &pos, EUserTriggered userTriggered, CursorAlignOnScroll align)
122 {
123     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
124     setSelection(VisibleSelection(pos.deepEquivalent(), pos.deepEquivalent(), pos.affinity(), m_selection.isDirectional()), options, align);
125 }
126
127 void FrameSelection::moveTo(const VisiblePosition &base, const VisiblePosition &extent, EUserTriggered userTriggered)
128 {
129     const bool selectionHasDirection = true;
130     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
131     setSelection(VisibleSelection(base.deepEquivalent(), extent.deepEquivalent(), base.affinity(), selectionHasDirection), options);
132 }
133
134 void FrameSelection::moveTo(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
135 {
136     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
137     setSelection(VisibleSelection(pos, affinity, m_selection.isDirectional()), options);
138 }
139
140 void FrameSelection::moveTo(const Range *r, EAffinity affinity, EUserTriggered userTriggered)
141 {
142     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
143     VisibleSelection selection = r ? VisibleSelection(r->startPosition(), r->endPosition(), affinity) : VisibleSelection(Position(), Position(), affinity);
144     setSelection(selection, options);
145 }
146
147 void FrameSelection::moveTo(const Position &base, const Position &extent, EAffinity affinity, EUserTriggered userTriggered)
148 {
149     const bool selectionHasDirection = true;
150     SetSelectionOptions options = CloseTyping | ClearTypingStyle | userTriggered;
151     setSelection(VisibleSelection(base, extent, affinity, selectionHasDirection), options);
152 }
153
154 void DragCaretController::setCaretPosition(const VisiblePosition& position)
155 {
156     if (Node* node = m_position.deepEquivalent().deprecatedNode())
157         invalidateCaretRect(node);
158     m_position = position;
159     setCaretRectNeedsUpdate();
160     Document* document = 0;
161     if (Node* node = m_position.deepEquivalent().deprecatedNode()) {
162         invalidateCaretRect(node);
163         document = &node->document();
164     }
165     if (m_position.isNull() || m_position.isOrphan())
166         clearCaretRect();
167     else
168         updateCaretRect(document, m_position);
169 }
170
171 static void adjustEndpointsAtBidiBoundary(VisiblePosition& visibleBase, VisiblePosition& visibleExtent)
172 {
173     RenderedPosition base(visibleBase);
174     RenderedPosition extent(visibleExtent);
175
176     if (base.isNull() || extent.isNull() || base.isEquivalent(extent))
177         return;
178
179     if (base.atLeftBoundaryOfBidiRun()) {
180         if (!extent.atRightBoundaryOfBidiRun(base.bidiLevelOnRight())
181             && base.isEquivalent(extent.leftBoundaryOfBidiRun(base.bidiLevelOnRight()))) {
182             visibleBase = base.positionAtLeftBoundaryOfBiDiRun();
183             return;
184         }
185         return;
186     }
187
188     if (base.atRightBoundaryOfBidiRun()) {
189         if (!extent.atLeftBoundaryOfBidiRun(base.bidiLevelOnLeft())
190             && base.isEquivalent(extent.rightBoundaryOfBidiRun(base.bidiLevelOnLeft()))) {
191             visibleBase = base.positionAtRightBoundaryOfBiDiRun();
192             return;
193         }
194         return;
195     }
196
197     if (extent.atLeftBoundaryOfBidiRun() && extent.isEquivalent(base.leftBoundaryOfBidiRun(extent.bidiLevelOnRight()))) {
198         visibleExtent = extent.positionAtLeftBoundaryOfBiDiRun();
199         return;
200     }
201
202     if (extent.atRightBoundaryOfBidiRun() && extent.isEquivalent(base.rightBoundaryOfBidiRun(extent.bidiLevelOnLeft()))) {
203         visibleExtent = extent.positionAtRightBoundaryOfBiDiRun();
204         return;
205     }
206 }
207
208 void FrameSelection::setNonDirectionalSelectionIfNeeded(const VisibleSelection& passedNewSelection, TextGranularity granularity,
209     EndPointsAdjustmentMode endpointsAdjustmentMode)
210 {
211     VisibleSelection newSelection = passedNewSelection;
212     bool isDirectional = shouldAlwaysUseDirectionalSelection(m_frame) || newSelection.isDirectional();
213
214     VisiblePosition base = m_originalBase.isNotNull() ? m_originalBase : newSelection.visibleBase();
215     VisiblePosition newBase = base;
216     VisiblePosition extent = newSelection.visibleExtent();
217     VisiblePosition newExtent = extent;
218     if (endpointsAdjustmentMode == AdjustEndpointsAtBidiBoundary)
219         adjustEndpointsAtBidiBoundary(newBase, newExtent);
220
221     if (newBase != base || newExtent != extent) {
222         m_originalBase = base;
223         newSelection.setBase(newBase);
224         newSelection.setExtent(newExtent);
225     } else if (m_originalBase.isNotNull()) {
226         if (m_selection.base() == newSelection.base())
227             newSelection.setBase(m_originalBase);
228         m_originalBase.clear();
229     }
230
231     newSelection.setIsDirectional(isDirectional); // Adjusting base and extent will make newSelection always directional
232     if (m_selection == newSelection || !shouldChangeSelection(newSelection))
233         return;
234
235     setSelection(newSelection, granularity);
236 }
237
238 void FrameSelection::setSelection(const VisibleSelection& newSelection, SetSelectionOptions options, CursorAlignOnScroll align, TextGranularity granularity)
239 {
240     bool closeTyping = options & CloseTyping;
241     bool shouldClearTypingStyle = options & ClearTypingStyle;
242     EUserTriggered userTriggered = selectionOptionsToUserTriggered(options);
243
244     VisibleSelection s = newSelection;
245     if (shouldAlwaysUseDirectionalSelection(m_frame))
246         s.setIsDirectional(true);
247
248     if (!m_frame) {
249         m_selection = s;
250         return;
251     }
252
253     // <http://bugs.webkit.org/show_bug.cgi?id=23464>: Infinite recursion at FrameSelection::setSelection
254     // if document->frame() == m_frame we can get into an infinite loop
255     if (s.base().anchorNode()) {
256         Document& document = s.base().anchorNode()->document();
257         if (document.frame() && document.frame() != m_frame && &document != m_frame->document()) {
258             RefPtr<Frame> guard = document.frame();
259             document.frame()->selection().setSelection(s, options, align, granularity);
260             // It's possible that during the above set selection, this FrameSelection has been modified by
261             // selectFrameElementInParentIfFullySelected, but that the selection is no longer valid since
262             // the frame is about to be destroyed. If this is the case, clear our selection.
263             if (guard->hasOneRef() && !m_selection.isNonOrphanedCaretOrRange())
264                 clear();
265             return;
266         }
267     }
268
269     m_granularity = granularity;
270
271     if (closeTyping)
272         TypingCommand::closeTyping(m_frame);
273
274     if (shouldClearTypingStyle)
275         clearTypingStyle();
276
277     if (m_selection == s) {
278         // Even if selection was not changed, selection offsets may have been changed.
279         notifyRendererOfSelectionChange(userTriggered);
280         return;
281     }
282
283     VisibleSelection oldSelection = m_selection;
284
285     m_selection = s;
286     setCaretRectNeedsUpdate();
287     
288     if (!s.isNone() && !(options & DoNotSetFocus))
289         setFocusedElementIfNeeded();
290
291     if (!(options & DoNotUpdateAppearance)) {
292 #if ENABLE(TEXT_CARET)
293         m_frame->document()->updateLayoutIgnorePendingStylesheets();
294 #else
295         m_frame->document()->updateStyleIfNeeded();
296 #endif
297         updateAppearance();
298     }
299
300     // Always clear the x position used for vertical arrow navigation.
301     // It will be restored by the vertical arrow navigation code if necessary.
302     m_xPosForVerticalArrowNavigation = NoXPosForVerticalArrowNavigation();
303     selectFrameElementInParentIfFullySelected();
304     notifyRendererOfSelectionChange(userTriggered);
305     m_frame->editor().respondToChangedSelection(oldSelection, options);
306     if (userTriggered == UserTriggered) {
307         ScrollAlignment alignment;
308
309         if (m_frame->editor().behavior().shouldCenterAlignWhenSelectionIsRevealed())
310             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignCenterAlways : ScrollAlignment::alignCenterIfNeeded;
311         else
312             alignment = (align == AlignCursorOnScrollAlways) ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
313
314         revealSelection(alignment, RevealExtent);
315     }
316 #if HAVE(ACCESSIBILITY)
317     notifyAccessibilityForSelectionChange();
318 #endif
319     m_frame->document()->enqueueDocumentEvent(Event::create(eventNames().selectionchangeEvent, false, false));
320 }
321
322 static bool removingNodeRemovesPosition(Node* node, const Position& position)
323 {
324     if (!position.anchorNode())
325         return false;
326
327     if (position.anchorNode() == node)
328         return true;
329
330     if (!node->isElementNode())
331         return false;
332
333     Element* element = toElement(node);
334     return element->containsIncludingShadowDOM(position.anchorNode());
335 }
336
337 static void clearRenderViewSelection(const Position& position)
338 {
339     Ref<Document> document(position.anchorNode()->document());
340     document->updateStyleIfNeeded();
341     if (RenderView* view = document->renderView())
342         view->clearSelection();
343 }
344
345 void DragCaretController::nodeWillBeRemoved(Node* node)
346 {
347     if (!hasCaret() || (node && !node->inDocument()))
348         return;
349
350     if (!removingNodeRemovesPosition(node, m_position.deepEquivalent()))
351         return;
352
353     clearRenderViewSelection(m_position.deepEquivalent());
354     clear();
355 }
356
357 void FrameSelection::nodeWillBeRemoved(Node* node)
358 {
359     // There can't be a selection inside a fragment, so if a fragment's node is being removed,
360     // the selection in the document that created the fragment needs no adjustment.
361     if (isNone() || (node && !node->inDocument()))
362         return;
363
364     respondToNodeModification(node, removingNodeRemovesPosition(node, m_selection.base()), removingNodeRemovesPosition(node, m_selection.extent()),
365         removingNodeRemovesPosition(node, m_selection.start()), removingNodeRemovesPosition(node, m_selection.end()));
366 }
367
368 void FrameSelection::respondToNodeModification(Node* node, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved)
369 {
370     bool clearRenderTreeSelection = false;
371     bool clearDOMTreeSelection = false;
372
373     if (startRemoved || endRemoved) {
374         Position start = m_selection.start();
375         Position end = m_selection.end();
376         if (startRemoved)
377             updatePositionForNodeRemoval(start, node);
378         if (endRemoved)
379             updatePositionForNodeRemoval(end, node);
380
381         if (start.isNotNull() && end.isNotNull()) {
382             if (m_selection.isBaseFirst())
383                 m_selection.setWithoutValidation(start, end);
384             else
385                 m_selection.setWithoutValidation(end, start);
386         } else
387             clearDOMTreeSelection = true;
388
389         clearRenderTreeSelection = true;
390     } else if (baseRemoved || extentRemoved) {
391         // The base and/or extent are about to be removed, but the start and end aren't.
392         // Change the base and extent to the start and end, but don't re-validate the
393         // selection, since doing so could move the start and end into the node
394         // that is about to be removed.
395         if (m_selection.isBaseFirst())
396             m_selection.setWithoutValidation(m_selection.start(), m_selection.end());
397         else
398             m_selection.setWithoutValidation(m_selection.end(), m_selection.start());
399     } else if (RefPtr<Range> range = m_selection.firstRange()) {
400         ExceptionCode ec = 0;
401         Range::CompareResults compareResult = range->compareNode(node, ec);
402         if (!ec && (compareResult == Range::NODE_BEFORE_AND_AFTER || compareResult == Range::NODE_INSIDE)) {
403             // If we did nothing here, when this node's renderer was destroyed, the rect that it 
404             // occupied would be invalidated, but, selection gaps that change as a result of 
405             // the removal wouldn't be invalidated.
406             // FIXME: Don't do so much unnecessary invalidation.
407             clearRenderTreeSelection = true;
408         }
409     }
410
411     if (clearRenderTreeSelection)
412         clearRenderViewSelection(m_selection.start());
413
414     if (clearDOMTreeSelection)
415         setSelection(VisibleSelection(), DoNotSetFocus);
416 }
417
418 static void updatePositionAfterAdoptingTextReplacement(Position& position, CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
419 {
420     if (!position.anchorNode() || position.anchorNode() != node || position.anchorType() != Position::PositionIsOffsetInAnchor)
421         return;
422
423     // See: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/ranges.html#Level-2-Range-Mutation
424     ASSERT(position.offsetInContainerNode() >= 0);
425     unsigned positionOffset = static_cast<unsigned>(position.offsetInContainerNode());
426     // Replacing text can be viewed as a deletion followed by insertion.
427     if (positionOffset >= offset && positionOffset <= offset + oldLength)
428         position.moveToOffset(offset);
429
430     // Adjust the offset if the position is after the end of the deleted contents
431     // (positionOffset > offset + oldLength) to avoid having a stale offset.
432     if (positionOffset > offset + oldLength)
433         position.moveToOffset(positionOffset - oldLength + newLength);
434
435     ASSERT(static_cast<unsigned>(position.offsetInContainerNode()) <= node->length());
436 }
437
438 void FrameSelection::textWasReplaced(CharacterData* node, unsigned offset, unsigned oldLength, unsigned newLength)
439 {
440     // The fragment check is a performance optimization. See http://trac.webkit.org/changeset/30062.
441     if (isNone() || !node || !node->inDocument())
442         return;
443
444     Position base = m_selection.base();
445     Position extent = m_selection.extent();
446     Position start = m_selection.start();
447     Position end = m_selection.end();
448     updatePositionAfterAdoptingTextReplacement(base, node, offset, oldLength, newLength);
449     updatePositionAfterAdoptingTextReplacement(extent, node, offset, oldLength, newLength);
450     updatePositionAfterAdoptingTextReplacement(start, node, offset, oldLength, newLength);
451     updatePositionAfterAdoptingTextReplacement(end, node, offset, oldLength, newLength);
452
453     if (base != m_selection.base() || extent != m_selection.extent() || start != m_selection.start() || end != m_selection.end()) {
454         VisibleSelection newSelection;
455         if (base != extent)
456             newSelection.setWithoutValidation(base, extent);
457         else if (m_selection.isDirectional() && !m_selection.isBaseFirst())
458             newSelection.setWithoutValidation(end, start);
459         else
460             newSelection.setWithoutValidation(start, end);
461
462         m_frame->document()->updateLayout();
463         setSelection(newSelection, DoNotSetFocus);
464     }
465 }
466
467 TextDirection FrameSelection::directionOfEnclosingBlock()
468 {
469     return WebCore::directionOfEnclosingBlock(m_selection.extent());
470 }
471
472 TextDirection FrameSelection::directionOfSelection()
473 {
474     InlineBox* startBox = 0;
475     InlineBox* endBox = 0;
476     int unusedOffset;
477     if (m_selection.start().isNotNull())
478         m_selection.visibleStart().getInlineBoxAndOffset(startBox, unusedOffset);
479     if (m_selection.end().isNotNull())
480         m_selection.visibleEnd().getInlineBoxAndOffset(endBox, unusedOffset);
481     if (startBox && endBox && startBox->direction() == endBox->direction())
482         return startBox->direction();
483
484     return directionOfEnclosingBlock();
485 }
486
487 void FrameSelection::willBeModified(EAlteration alter, SelectionDirection direction)
488 {
489     if (alter != AlterationExtend)
490         return;
491
492     Position start = m_selection.start();
493     Position end = m_selection.end();
494
495     bool baseIsStart = true;
496
497     if (m_selection.isDirectional()) {
498         // Make base and extent match start and end so we extend the user-visible selection.
499         // This only matters for cases where base and extend point to different positions than
500         // start and end (e.g. after a double-click to select a word).
501         if (m_selection.isBaseFirst())
502             baseIsStart = true;
503         else
504             baseIsStart = false;
505     } else {
506         switch (direction) {
507         case DirectionRight:
508             if (directionOfSelection() == LTR)
509                 baseIsStart = true;
510             else
511                 baseIsStart = false;
512             break;
513         case DirectionForward:
514             baseIsStart = true;
515             break;
516         case DirectionLeft:
517             if (directionOfSelection() == LTR)
518                 baseIsStart = false;
519             else
520                 baseIsStart = true;
521             break;
522         case DirectionBackward:
523             baseIsStart = false;
524             break;
525         }
526     }
527     if (baseIsStart) {
528         m_selection.setBase(start);
529         m_selection.setExtent(end);
530     } else {
531         m_selection.setBase(end);
532         m_selection.setExtent(start);
533     }
534 }
535
536 VisiblePosition FrameSelection::positionForPlatform(bool isGetStart) const
537 {
538     if (m_frame && m_frame->settings().editingBehaviorType() == EditingMacBehavior)
539         return isGetStart ? m_selection.visibleStart() : m_selection.visibleEnd();
540     // Linux and Windows always extend selections from the extent endpoint.
541     // FIXME: VisibleSelection should be fixed to ensure as an invariant that
542     // base/extent always point to the same nodes as start/end, but which points
543     // to which depends on the value of isBaseFirst. Then this can be changed
544     // to just return m_sel.extent().
545     return m_selection.isBaseFirst() ? m_selection.visibleEnd() : m_selection.visibleStart();
546 }
547
548 VisiblePosition FrameSelection::startForPlatform() const
549 {
550     return positionForPlatform(true);
551 }
552
553 VisiblePosition FrameSelection::endForPlatform() const
554 {
555     return positionForPlatform(false);
556 }
557
558 VisiblePosition FrameSelection::nextWordPositionForPlatform(const VisiblePosition &originalPosition)
559 {
560     VisiblePosition positionAfterCurrentWord = nextWordPosition(originalPosition);
561
562     if (m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight()) {
563         // In order to skip spaces when moving right, we advance one
564         // word further and then move one word back. Given the
565         // semantics of previousWordPosition() this will put us at the
566         // beginning of the word following.
567         VisiblePosition positionAfterSpacingAndFollowingWord = nextWordPosition(positionAfterCurrentWord);
568         if (positionAfterSpacingAndFollowingWord != positionAfterCurrentWord)
569             positionAfterCurrentWord = previousWordPosition(positionAfterSpacingAndFollowingWord);
570
571         bool movingBackwardsMovedPositionToStartOfCurrentWord = positionAfterCurrentWord == previousWordPosition(nextWordPosition(originalPosition));
572         if (movingBackwardsMovedPositionToStartOfCurrentWord)
573             positionAfterCurrentWord = positionAfterSpacingAndFollowingWord;
574     }
575     return positionAfterCurrentWord;
576 }
577
578 #if ENABLE(USERSELECT_ALL)
579 static void adjustPositionForUserSelectAll(VisiblePosition& pos, bool isForward)
580 {
581     if (Node* rootUserSelectAll = Position::rootUserSelectAllForNode(pos.deepEquivalent().anchorNode()))
582         pos = isForward ? positionAfterNode(rootUserSelectAll).downstream(CanCrossEditingBoundary) : positionBeforeNode(rootUserSelectAll).upstream(CanCrossEditingBoundary);
583 }
584 #endif
585
586 VisiblePosition FrameSelection::modifyExtendingRight(TextGranularity granularity)
587 {
588     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
589
590     // The difference between modifyExtendingRight and modifyExtendingForward is:
591     // modifyExtendingForward always extends forward logically.
592     // modifyExtendingRight behaves the same as modifyExtendingForward except for extending character or word,
593     // it extends forward logically if the enclosing block is LTR direction,
594     // but it extends backward logically if the enclosing block is RTL direction.
595     switch (granularity) {
596     case CharacterGranularity:
597         if (directionOfEnclosingBlock() == LTR)
598             pos = pos.next(CannotCrossEditingBoundary);
599         else
600             pos = pos.previous(CannotCrossEditingBoundary);
601         break;
602     case WordGranularity:
603         if (directionOfEnclosingBlock() == LTR)
604             pos = nextWordPositionForPlatform(pos);
605         else
606             pos = previousWordPosition(pos);
607         break;
608     case LineBoundary:
609         if (directionOfEnclosingBlock() == LTR)
610             pos = modifyExtendingForward(granularity);
611         else
612             pos = modifyExtendingBackward(granularity);
613         break;
614     case SentenceGranularity:
615     case LineGranularity:
616     case ParagraphGranularity:
617     case SentenceBoundary:
618     case ParagraphBoundary:
619     case DocumentBoundary:
620         // FIXME: implement all of the above?
621         pos = modifyExtendingForward(granularity);
622         break;
623     }
624 #if ENABLE(USERSELECT_ALL)
625     adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
626 #endif
627     return pos;
628 }
629
630 VisiblePosition FrameSelection::modifyExtendingForward(TextGranularity granularity)
631 {
632     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
633     switch (granularity) {
634     case CharacterGranularity:
635         pos = pos.next(CannotCrossEditingBoundary);
636         break;
637     case WordGranularity:
638         pos = nextWordPositionForPlatform(pos);
639         break;
640     case SentenceGranularity:
641         pos = nextSentencePosition(pos);
642         break;
643     case LineGranularity:
644         pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
645         break;
646     case ParagraphGranularity:
647         pos = nextParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
648         break;
649     case SentenceBoundary:
650         pos = endOfSentence(endForPlatform());
651         break;
652     case LineBoundary:
653         pos = logicalEndOfLine(endForPlatform());
654         break;
655     case ParagraphBoundary:
656         pos = endOfParagraph(endForPlatform());
657         break;
658     case DocumentBoundary:
659         pos = endForPlatform();
660         if (isEditablePosition(pos.deepEquivalent()))
661             pos = endOfEditableContent(pos);
662         else
663             pos = endOfDocument(pos);
664         break;
665     }
666 #if ENABLE(USERSELECT_ALL)
667      adjustPositionForUserSelectAll(pos, directionOfEnclosingBlock() == LTR);
668 #endif
669     return pos;
670 }
671
672 VisiblePosition FrameSelection::modifyMovingRight(TextGranularity granularity)
673 {
674     VisiblePosition pos;
675     switch (granularity) {
676     case CharacterGranularity:
677         if (isRange()) {
678             if (directionOfSelection() == LTR)
679                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
680             else
681                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
682         } else
683             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).right(true);
684         break;
685     case WordGranularity: {
686 #if USE(ICU_UNICODE)
687         // Visual word movement relies on isWordTextBreak which is not implemented in WinCE and QT.
688         // https://bugs.webkit.org/show_bug.cgi?id=81136.
689         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
690         pos = rightWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
691         break;
692 #endif
693     }
694     case SentenceGranularity:
695     case LineGranularity:
696     case ParagraphGranularity:
697     case SentenceBoundary:
698     case ParagraphBoundary:
699     case DocumentBoundary:
700         // FIXME: Implement all of the above.
701         pos = modifyMovingForward(granularity);
702         break;
703     case LineBoundary:
704         pos = rightBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
705         break;
706     }
707     return pos;
708 }
709
710 VisiblePosition FrameSelection::modifyMovingForward(TextGranularity granularity)
711 {
712     VisiblePosition pos;
713     // FIXME: Stay in editable content for the less common granularities.
714     switch (granularity) {
715     case CharacterGranularity:
716         if (isRange())
717             pos = VisiblePosition(m_selection.end(), m_selection.affinity());
718         else
719             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).next(CannotCrossEditingBoundary);
720         break;
721     case WordGranularity:
722         pos = nextWordPositionForPlatform(VisiblePosition(m_selection.extent(), m_selection.affinity()));
723         break;
724     case SentenceGranularity:
725         pos = nextSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
726         break;
727     case LineGranularity: {
728         // down-arrowing from a range selection that ends at the start of a line needs
729         // to leave the selection at that line start (no need to call nextLinePosition!)
730         pos = endForPlatform();
731         if (!isRange() || !isStartOfLine(pos))
732             pos = nextLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(START));
733         break;
734     }
735     case ParagraphGranularity:
736         pos = nextParagraphPosition(endForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
737         break;
738     case SentenceBoundary:
739         pos = endOfSentence(endForPlatform());
740         break;
741     case LineBoundary:
742         pos = logicalEndOfLine(endForPlatform());
743         break;
744     case ParagraphBoundary:
745         pos = endOfParagraph(endForPlatform());
746         break;
747     case DocumentBoundary:
748         pos = endForPlatform();
749         if (isEditablePosition(pos.deepEquivalent()))
750             pos = endOfEditableContent(pos);
751         else
752             pos = endOfDocument(pos);
753         break;
754     }
755     return pos;
756 }
757
758 VisiblePosition FrameSelection::modifyExtendingLeft(TextGranularity granularity)
759 {
760     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
761
762     // The difference between modifyExtendingLeft and modifyExtendingBackward is:
763     // modifyExtendingBackward always extends backward logically.
764     // modifyExtendingLeft behaves the same as modifyExtendingBackward except for extending character or word,
765     // it extends backward logically if the enclosing block is LTR direction,
766     // but it extends forward logically if the enclosing block is RTL direction.
767     switch (granularity) {
768     case CharacterGranularity:
769         if (directionOfEnclosingBlock() == LTR)
770             pos = pos.previous(CannotCrossEditingBoundary);
771         else
772             pos = pos.next(CannotCrossEditingBoundary);
773         break;
774     case WordGranularity:
775         if (directionOfEnclosingBlock() == LTR)
776             pos = previousWordPosition(pos);
777         else
778             pos = nextWordPositionForPlatform(pos);
779         break;
780     case LineBoundary:
781         if (directionOfEnclosingBlock() == LTR)
782             pos = modifyExtendingBackward(granularity);
783         else
784             pos = modifyExtendingForward(granularity);
785         break;
786     case SentenceGranularity:
787     case LineGranularity:
788     case ParagraphGranularity:
789     case SentenceBoundary:
790     case ParagraphBoundary:
791     case DocumentBoundary:
792         pos = modifyExtendingBackward(granularity);
793         break;
794     }
795 #if ENABLE(USERSELECT_ALL)
796     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
797 #endif
798     return pos;
799 }
800        
801 VisiblePosition FrameSelection::modifyExtendingBackward(TextGranularity granularity)
802 {
803     VisiblePosition pos(m_selection.extent(), m_selection.affinity());
804
805     // Extending a selection backward by word or character from just after a table selects
806     // the table.  This "makes sense" from the user perspective, esp. when deleting.
807     // It was done here instead of in VisiblePosition because we want VPs to iterate
808     // over everything.
809     switch (granularity) {
810     case CharacterGranularity:
811         pos = pos.previous(CannotCrossEditingBoundary);
812         break;
813     case WordGranularity:
814         pos = previousWordPosition(pos);
815         break;
816     case SentenceGranularity:
817         pos = previousSentencePosition(pos);
818         break;
819     case LineGranularity:
820         pos = previousLinePosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
821         break;
822     case ParagraphGranularity:
823         pos = previousParagraphPosition(pos, lineDirectionPointForBlockDirectionNavigation(EXTENT));
824         break;
825     case SentenceBoundary:
826         pos = startOfSentence(startForPlatform());
827         break;
828     case LineBoundary:
829         pos = logicalStartOfLine(startForPlatform());
830         break;
831     case ParagraphBoundary:
832         pos = startOfParagraph(startForPlatform());
833         break;
834     case DocumentBoundary:
835         pos = startForPlatform();
836         if (isEditablePosition(pos.deepEquivalent()))
837             pos = startOfEditableContent(pos);
838         else
839             pos = startOfDocument(pos);
840         break;
841     }
842 #if ENABLE(USERSELECT_ALL)
843     adjustPositionForUserSelectAll(pos, !(directionOfEnclosingBlock() == LTR));
844 #endif
845     return pos;
846 }
847
848 VisiblePosition FrameSelection::modifyMovingLeft(TextGranularity granularity)
849 {
850     VisiblePosition pos;
851     switch (granularity) {
852     case CharacterGranularity:
853         if (isRange())
854             if (directionOfSelection() == LTR)
855                 pos = VisiblePosition(m_selection.start(), m_selection.affinity());
856             else
857                 pos = VisiblePosition(m_selection.end(), m_selection.affinity());
858         else
859             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).left(true);
860         break;
861     case WordGranularity: {
862 #if USE(ICU_UNICODE)
863         bool skipsSpaceWhenMovingRight = m_frame && m_frame->editor().behavior().shouldSkipSpaceWhenMovingRight();
864         pos = leftWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()), skipsSpaceWhenMovingRight);
865         break;
866 #endif
867     }
868     case SentenceGranularity:
869     case LineGranularity:
870     case ParagraphGranularity:
871     case SentenceBoundary:
872     case ParagraphBoundary:
873     case DocumentBoundary:
874         // FIXME: Implement all of the above.
875         pos = modifyMovingBackward(granularity);
876         break;
877     case LineBoundary:
878         pos = leftBoundaryOfLine(startForPlatform(), directionOfEnclosingBlock());
879         break;
880     }
881     return pos;
882 }
883
884 VisiblePosition FrameSelection::modifyMovingBackward(TextGranularity granularity)
885 {
886     VisiblePosition pos;
887     switch (granularity) {
888     case CharacterGranularity:
889         if (isRange())
890             pos = VisiblePosition(m_selection.start(), m_selection.affinity());
891         else
892             pos = VisiblePosition(m_selection.extent(), m_selection.affinity()).previous(CannotCrossEditingBoundary);
893         break;
894     case WordGranularity:
895         pos = previousWordPosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
896         break;
897     case SentenceGranularity:
898         pos = previousSentencePosition(VisiblePosition(m_selection.extent(), m_selection.affinity()));
899         break;
900     case LineGranularity:
901         pos = previousLinePosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
902         break;
903     case ParagraphGranularity:
904         pos = previousParagraphPosition(startForPlatform(), lineDirectionPointForBlockDirectionNavigation(START));
905         break;
906     case SentenceBoundary:
907         pos = startOfSentence(startForPlatform());
908         break;
909     case LineBoundary:
910         pos = logicalStartOfLine(startForPlatform());
911         break;
912     case ParagraphBoundary:
913         pos = startOfParagraph(startForPlatform());
914         break;
915     case DocumentBoundary:
916         pos = startForPlatform();
917         if (isEditablePosition(pos.deepEquivalent()))
918             pos = startOfEditableContent(pos);
919         else
920             pos = startOfDocument(pos);
921         break;
922     }
923     return pos;
924 }
925
926 static bool isBoundary(TextGranularity granularity)
927 {
928     return granularity == LineBoundary || granularity == ParagraphBoundary || granularity == DocumentBoundary;
929 }    
930
931 bool FrameSelection::modify(EAlteration alter, SelectionDirection direction, TextGranularity granularity, EUserTriggered userTriggered)
932 {
933     if (userTriggered == UserTriggered) {
934         FrameSelection trialFrameSelection;
935         trialFrameSelection.setSelection(m_selection);
936         trialFrameSelection.modify(alter, direction, granularity, NotUserTriggered);
937
938         bool change = shouldChangeSelection(trialFrameSelection.selection());
939         if (!change)
940             return false;
941
942         if (trialFrameSelection.selection().isRange() && m_selection.isCaret() && !dispatchSelectStart())
943             return false;
944     }
945
946     willBeModified(alter, direction);
947
948     bool wasRange = m_selection.isRange();
949     Position originalStartPosition = m_selection.start();
950     VisiblePosition position;
951     switch (direction) {
952     case DirectionRight:
953         if (alter == AlterationMove)
954             position = modifyMovingRight(granularity);
955         else
956             position = modifyExtendingRight(granularity);
957         break;
958     case DirectionForward:
959         if (alter == AlterationExtend)
960             position = modifyExtendingForward(granularity);
961         else
962             position = modifyMovingForward(granularity);
963         break;
964     case DirectionLeft:
965         if (alter == AlterationMove)
966             position = modifyMovingLeft(granularity);
967         else
968             position = modifyExtendingLeft(granularity);
969         break;
970     case DirectionBackward:
971         if (alter == AlterationExtend)
972             position = modifyExtendingBackward(granularity);
973         else
974             position = modifyMovingBackward(granularity);
975         break;
976     }
977
978     if (position.isNull())
979         return false;
980
981     if (isSpatialNavigationEnabled(m_frame))
982         if (!wasRange && alter == AlterationMove && position == originalStartPosition)
983             return false;
984
985     // Some of the above operations set an xPosForVerticalArrowNavigation.
986     // Setting a selection will clear it, so save it to possibly restore later.
987     // Note: the START position type is arbitrary because it is unused, it would be
988     // the requested position type if there were no xPosForVerticalArrowNavigation set.
989     LayoutUnit x = lineDirectionPointForBlockDirectionNavigation(START);
990     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
991
992     switch (alter) {
993     case AlterationMove:
994         moveTo(position, userTriggered);
995         break;
996     case AlterationExtend:
997
998         if (!m_selection.isCaret()
999             && (granularity == WordGranularity || granularity == ParagraphGranularity || granularity == LineGranularity)
1000             && m_frame && !m_frame->editor().behavior().shouldExtendSelectionByWordOrLineAcrossCaret()) {
1001             // Don't let the selection go across the base position directly. Needed to match mac
1002             // behavior when, for instance, word-selecting backwards starting with the caret in
1003             // the middle of a word and then word-selecting forward, leaving the caret in the
1004             // same place where it was, instead of directly selecting to the end of the word.
1005             VisibleSelection newSelection = m_selection;
1006             newSelection.setExtent(position);
1007             if (m_selection.isBaseFirst() != newSelection.isBaseFirst())
1008                 position = m_selection.base();
1009         }
1010
1011         // Standard Mac behavior when extending to a boundary is grow the selection rather than leaving the
1012         // base in place and moving the extent. Matches NSTextView.
1013         if (!m_frame || !m_frame->editor().behavior().shouldAlwaysGrowSelectionWhenExtendingToBoundary() || m_selection.isCaret() || !isBoundary(granularity))
1014             setExtent(position, userTriggered);
1015         else {
1016             TextDirection textDirection = directionOfEnclosingBlock();
1017             if (direction == DirectionForward || (textDirection == LTR && direction == DirectionRight) || (textDirection == RTL && direction == DirectionLeft))
1018                 setEnd(position, userTriggered);
1019             else
1020                 setStart(position, userTriggered);
1021         }
1022         break;
1023     }
1024     
1025     if (granularity == LineGranularity || granularity == ParagraphGranularity)
1026         m_xPosForVerticalArrowNavigation = x;
1027
1028     if (userTriggered == UserTriggered)
1029         m_granularity = CharacterGranularity;
1030
1031     setCaretRectNeedsUpdate();
1032
1033     return true;
1034 }
1035
1036 // FIXME: Maybe baseline would be better?
1037 static bool absoluteCaretY(const VisiblePosition &c, int &y)
1038 {
1039     IntRect rect = c.absoluteCaretBounds();
1040     if (rect.isEmpty())
1041         return false;
1042     y = rect.y() + rect.height() / 2;
1043     return true;
1044 }
1045
1046 bool FrameSelection::modify(EAlteration alter, unsigned verticalDistance, VerticalDirection direction, EUserTriggered userTriggered, CursorAlignOnScroll align)
1047 {
1048     if (!verticalDistance)
1049         return false;
1050
1051     if (userTriggered == UserTriggered) {
1052         FrameSelection trialFrameSelection;
1053         trialFrameSelection.setSelection(m_selection);
1054         trialFrameSelection.modify(alter, verticalDistance, direction, NotUserTriggered);
1055
1056         bool change = shouldChangeSelection(trialFrameSelection.selection());
1057         if (!change)
1058             return false;
1059     }
1060
1061     willBeModified(alter, direction == DirectionUp ? DirectionBackward : DirectionForward);
1062
1063     VisiblePosition pos;
1064     LayoutUnit xPos = 0;
1065     switch (alter) {
1066     case AlterationMove:
1067         pos = VisiblePosition(direction == DirectionUp ? m_selection.start() : m_selection.end(), m_selection.affinity());
1068         xPos = lineDirectionPointForBlockDirectionNavigation(direction == DirectionUp ? START : END);
1069         m_selection.setAffinity(direction == DirectionUp ? UPSTREAM : DOWNSTREAM);
1070         break;
1071     case AlterationExtend:
1072         pos = VisiblePosition(m_selection.extent(), m_selection.affinity());
1073         xPos = lineDirectionPointForBlockDirectionNavigation(EXTENT);
1074         m_selection.setAffinity(DOWNSTREAM);
1075         break;
1076     }
1077
1078     int startY;
1079     if (!absoluteCaretY(pos, startY))
1080         return false;
1081     if (direction == DirectionUp)
1082         startY = -startY;
1083     int lastY = startY;
1084
1085     VisiblePosition result;
1086     VisiblePosition next;
1087     for (VisiblePosition p = pos; ; p = next) {
1088         if (direction == DirectionUp)
1089             next = previousLinePosition(p, xPos);
1090         else
1091             next = nextLinePosition(p, xPos);
1092
1093         if (next.isNull() || next == p)
1094             break;
1095         int nextY;
1096         if (!absoluteCaretY(next, nextY))
1097             break;
1098         if (direction == DirectionUp)
1099             nextY = -nextY;
1100         if (nextY - startY > static_cast<int>(verticalDistance))
1101             break;
1102         if (nextY >= lastY) {
1103             lastY = nextY;
1104             result = next;
1105         }
1106     }
1107
1108     if (result.isNull())
1109         return false;
1110
1111     switch (alter) {
1112     case AlterationMove:
1113         moveTo(result, userTriggered, align);
1114         break;
1115     case AlterationExtend:
1116         setExtent(result, userTriggered);
1117         break;
1118     }
1119
1120     if (userTriggered == UserTriggered)
1121         m_granularity = CharacterGranularity;
1122
1123     m_selection.setIsDirectional(shouldAlwaysUseDirectionalSelection(m_frame) || alter == AlterationExtend);
1124
1125     return true;
1126 }
1127
1128 LayoutUnit FrameSelection::lineDirectionPointForBlockDirectionNavigation(EPositionType type)
1129 {
1130     LayoutUnit x = 0;
1131
1132     if (isNone())
1133         return x;
1134
1135     Position pos;
1136     switch (type) {
1137     case START:
1138         pos = m_selection.start();
1139         break;
1140     case END:
1141         pos = m_selection.end();
1142         break;
1143     case BASE:
1144         pos = m_selection.base();
1145         break;
1146     case EXTENT:
1147         pos = m_selection.extent();
1148         break;
1149     }
1150
1151     Frame* frame = pos.anchorNode()->document().frame();
1152     if (!frame)
1153         return x;
1154         
1155     if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation()) {
1156         VisiblePosition visiblePosition(pos, m_selection.affinity());
1157         // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
1158         // after the selection is created and before this function is called.
1159         x = visiblePosition.isNotNull() ? visiblePosition.lineDirectionPointForBlockDirectionNavigation() : 0;
1160         m_xPosForVerticalArrowNavigation = x;
1161     } else
1162         x = m_xPosForVerticalArrowNavigation;
1163         
1164     return x;
1165 }
1166
1167 void FrameSelection::clear()
1168 {
1169     m_granularity = CharacterGranularity;
1170     setSelection(VisibleSelection());
1171 }
1172
1173 void FrameSelection::prepareForDestruction()
1174 {
1175     m_granularity = CharacterGranularity;
1176
1177 #if ENABLE(TEXT_CARET)
1178     m_caretBlinkTimer.stop();
1179 #endif
1180
1181     RenderView* view = m_frame->contentRenderer();
1182     if (view)
1183         view->clearSelection();
1184
1185     setSelection(VisibleSelection(), CloseTyping | ClearTypingStyle | DoNotUpdateAppearance);
1186     m_previousCaretNode.clear();
1187 }
1188
1189 void FrameSelection::setStart(const VisiblePosition &pos, EUserTriggered trigger)
1190 {
1191     if (m_selection.isBaseFirst())
1192         setBase(pos, trigger);
1193     else
1194         setExtent(pos, trigger);
1195 }
1196
1197 void FrameSelection::setEnd(const VisiblePosition &pos, EUserTriggered trigger)
1198 {
1199     if (m_selection.isBaseFirst())
1200         setExtent(pos, trigger);
1201     else
1202         setBase(pos, trigger);
1203 }
1204
1205 void FrameSelection::setBase(const VisiblePosition &pos, EUserTriggered userTriggered)
1206 {
1207     const bool selectionHasDirection = true;
1208     setSelection(VisibleSelection(pos.deepEquivalent(), m_selection.extent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1209 }
1210
1211 void FrameSelection::setExtent(const VisiblePosition &pos, EUserTriggered userTriggered)
1212 {
1213     const bool selectionHasDirection = true;
1214     setSelection(VisibleSelection(m_selection.base(), pos.deepEquivalent(), pos.affinity(), selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1215 }
1216
1217 void FrameSelection::setBase(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1218 {
1219     const bool selectionHasDirection = true;
1220     setSelection(VisibleSelection(pos, m_selection.extent(), affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1221 }
1222
1223 void FrameSelection::setExtent(const Position &pos, EAffinity affinity, EUserTriggered userTriggered)
1224 {
1225     const bool selectionHasDirection = true;
1226     setSelection(VisibleSelection(m_selection.base(), pos, affinity, selectionHasDirection), CloseTyping | ClearTypingStyle | userTriggered);
1227 }
1228
1229 void CaretBase::clearCaretRect()
1230 {
1231     m_caretLocalRect = LayoutRect();
1232 }
1233
1234 static inline bool caretRendersInsideNode(Node* node)
1235 {
1236     return node && !isTableElement(node) && !editingIgnoresContent(node);
1237 }
1238
1239 static RenderObject* caretRenderer(Node* node)
1240 {
1241     if (!node)
1242         return 0;
1243
1244     RenderObject* renderer = node->renderer();
1245     if (!renderer)
1246         return 0;
1247
1248     // if caretNode is a block and caret is inside it then caret should be painted by that block
1249     bool paintedByBlock = renderer->isRenderBlockFlow() && caretRendersInsideNode(node);
1250     return paintedByBlock ? renderer : renderer->containingBlock();
1251 }
1252
1253 bool CaretBase::updateCaretRect(Document* document, const VisiblePosition& caretPosition)
1254 {
1255     document->updateStyleIfNeeded();
1256     m_caretLocalRect = LayoutRect();
1257
1258     m_caretRectNeedsUpdate = false;
1259
1260     if (caretPosition.isNull())
1261         return false;
1262
1263     ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());
1264
1265     // First compute a rect local to the renderer at the selection start.
1266     RenderObject* renderer;
1267     LayoutRect localRect = caretPosition.localCaretRect(renderer);
1268
1269     // Get the renderer that will be responsible for painting the caret
1270     // (which is either the renderer we just found, or one of its containers).
1271     RenderObject* caretPainter = caretRenderer(caretPosition.deepEquivalent().deprecatedNode());
1272
1273     // Compute an offset between the renderer and the caretPainter.
1274     bool unrooted = false;
1275     while (renderer != caretPainter) {
1276         RenderObject* containerObject = renderer->container();
1277         if (!containerObject) {
1278             unrooted = true;
1279             break;
1280         }
1281         localRect.move(renderer->offsetFromContainer(containerObject, localRect.location()));
1282         renderer = containerObject;
1283     }
1284
1285     if (!unrooted)
1286         m_caretLocalRect = localRect;
1287
1288     return true;
1289 }
1290
1291 RenderObject* FrameSelection::caretRenderer() const
1292 {
1293     return WebCore::caretRenderer(m_selection.start().deprecatedNode());
1294 }
1295
1296 RenderObject* DragCaretController::caretRenderer() const
1297 {
1298     return WebCore::caretRenderer(m_position.deepEquivalent().deprecatedNode());
1299 }
1300
1301 static bool isNonOrphanedCaret(const VisibleSelection& selection)
1302 {
1303     return selection.isCaret() && !selection.start().isOrphan() && !selection.end().isOrphan();
1304 }
1305
1306 LayoutRect FrameSelection::localCaretRect()
1307 {
1308     if (shouldUpdateCaretRect()) {
1309         if (!isNonOrphanedCaret(m_selection))
1310             clearCaretRect();
1311         else if (updateCaretRect(m_frame->document(), VisiblePosition(m_selection.start(), m_selection.affinity())))
1312             m_absCaretBoundsDirty = true;
1313     }
1314
1315     return localCaretRectWithoutUpdate();
1316 }
1317
1318 IntRect CaretBase::absoluteBoundsForLocalRect(Node* node, const LayoutRect& rect) const
1319 {
1320     RenderObject* caretPainter = caretRenderer(node);
1321     if (!caretPainter)
1322         return IntRect();
1323     
1324     LayoutRect localRect(rect);
1325     if (caretPainter->isBox())
1326         toRenderBox(caretPainter)->flipForWritingMode(localRect);
1327     return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
1328 }
1329
1330 IntRect FrameSelection::absoluteCaretBounds()
1331 {
1332     recomputeCaretRect();
1333     return m_absCaretBounds;
1334 }
1335
1336 static void repaintCaretForLocalRect(Node* node, const LayoutRect& rect)
1337 {
1338     RenderObject* caretPainter = caretRenderer(node);
1339     if (!caretPainter)
1340         return;
1341
1342     caretPainter->repaintRectangle(rect);
1343 }
1344
1345 bool FrameSelection::recomputeCaretRect()
1346 {
1347     if (!shouldUpdateCaretRect())
1348         return false;
1349
1350     if (!m_frame)
1351         return false;
1352
1353     FrameView* v = m_frame->document()->view();
1354     if (!v)
1355         return false;
1356
1357     Node* caretNode = m_selection.start().deprecatedNode();
1358
1359     LayoutRect oldRect = localCaretRectWithoutUpdate();
1360     LayoutRect newRect = localCaretRect();
1361
1362     if (caretNode == m_previousCaretNode && oldRect == newRect && !m_absCaretBoundsDirty)
1363         return false;
1364
1365     IntRect oldAbsCaretBounds = m_absCaretBounds;
1366     m_absCaretBounds = absoluteBoundsForLocalRect(caretNode, localCaretRectWithoutUpdate());
1367     m_absCaretBoundsDirty = false;
1368
1369     if (caretNode == m_previousCaretNode && oldAbsCaretBounds == m_absCaretBounds)
1370         return false;
1371
1372 #if ENABLE(TEXT_CARET)
1373     if (RenderView* view = m_frame->document()->renderView()) {
1374         bool previousOrNewCaretNodeIsContentEditable = isContentEditable() || (m_previousCaretNode && m_previousCaretNode->isContentEditable());
1375         if (shouldRepaintCaret(view, previousOrNewCaretNodeIsContentEditable)) {
1376             if (m_previousCaretNode)
1377                 repaintCaretForLocalRect(m_previousCaretNode.get(), oldRect);
1378             m_previousCaretNode = caretNode;
1379             repaintCaretForLocalRect(caretNode, newRect);
1380         }
1381     }
1382 #endif
1383     return true;
1384 }
1385
1386 bool CaretBase::shouldRepaintCaret(const RenderView* view, bool isContentEditable) const
1387 {
1388     ASSERT(view);
1389     Frame* frame = &view->frameView().frame(); // The frame where the selection started.
1390     bool caretBrowsing = frame && frame->settings().caretBrowsingEnabled();
1391     return (caretBrowsing || isContentEditable);
1392 }
1393
1394 void FrameSelection::invalidateCaretRect()
1395 {
1396     if (!isCaret())
1397         return;
1398
1399     CaretBase::invalidateCaretRect(m_selection.start().deprecatedNode(), recomputeCaretRect());
1400 }
1401
1402 void CaretBase::invalidateCaretRect(Node* node, bool caretRectChanged)
1403 {
1404     // EDIT FIXME: This is an unfortunate hack.
1405     // Basically, we can't trust this layout position since we 
1406     // can't guarantee that the check to see if we are in unrendered 
1407     // content will work at this point. We may have to wait for
1408     // a layout and re-render of the document to happen. So, resetting this
1409     // flag will cause another caret layout to happen the first time
1410     // that we try to paint the caret after this call. That one will work since
1411     // it happens after the document has accounted for any editing
1412     // changes which may have been done.
1413     // And, we need to leave this layout here so the caret moves right 
1414     // away after clicking.
1415     m_caretRectNeedsUpdate = true;
1416
1417     if (caretRectChanged)
1418         return;
1419
1420     if (RenderView* view = node->document().renderView()) {
1421         if (shouldRepaintCaret(view, node->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable)))
1422             repaintCaretForLocalRect(node, localCaretRectWithoutUpdate());
1423     }
1424 }
1425
1426 void FrameSelection::paintCaret(GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect)
1427 {
1428     if (m_selection.isCaret() && m_caretPaint)
1429         CaretBase::paintCaret(m_selection.start().deprecatedNode(), context, paintOffset, clipRect);
1430 }
1431
1432 void CaretBase::paintCaret(Node* node, GraphicsContext* context, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1433 {
1434 #if ENABLE(TEXT_CARET)
1435     if (m_caretVisibility == Hidden)
1436         return;
1437
1438     LayoutRect drawingRect = localCaretRectWithoutUpdate();
1439     RenderObject* renderer = caretRenderer(node);
1440     if (renderer && renderer->isBox())
1441         toRenderBox(renderer)->flipForWritingMode(drawingRect);
1442     drawingRect.moveBy(roundedIntPoint(paintOffset));
1443     LayoutRect caret = intersection(drawingRect, clipRect);
1444     if (caret.isEmpty())
1445         return;
1446
1447     Color caretColor = Color::black;
1448     ColorSpace colorSpace = ColorSpaceDeviceRGB;
1449     Element* element = node->isElementNode() ? toElement(node) : node->parentElement();
1450
1451     if (element && element->renderer()) {
1452         caretColor = element->renderer()->style().visitedDependentColor(CSSPropertyColor);
1453         colorSpace = element->renderer()->style().colorSpace();
1454     }
1455
1456     context->fillRect(caret, caretColor, colorSpace);
1457 #else
1458     UNUSED_PARAM(node);
1459     UNUSED_PARAM(context);
1460     UNUSED_PARAM(paintOffset);
1461     UNUSED_PARAM(clipRect);
1462 #endif
1463 }
1464
1465 void FrameSelection::debugRenderer(RenderObject* r, bool selected) const
1466 {
1467     if (r->node()->isElementNode()) {
1468         Element* element = toElement(r->node());
1469         fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());
1470     } else if (r->isText()) {
1471         RenderText* textRenderer = toRenderText(r);
1472         if (!textRenderer->textLength() || !textRenderer->firstTextBox()) {
1473             fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");
1474             return;
1475         }
1476         
1477         static const int max = 36;
1478         String text = textRenderer->text();
1479         int textLength = text.length();
1480         if (selected) {
1481             int offset = 0;
1482             if (r->node() == m_selection.start().containerNode())
1483                 offset = m_selection.start().computeOffsetInContainerNode();
1484             else if (r->node() == m_selection.end().containerNode())
1485                 offset = m_selection.end().computeOffsetInContainerNode();
1486
1487             int pos;
1488             InlineTextBox* box = textRenderer->findNextInlineTextBox(offset, pos);
1489             text = text.substring(box->start(), box->len());
1490             
1491             String show;
1492             int mid = max / 2;
1493             int caret = 0;
1494             
1495             // text is shorter than max
1496             if (textLength < max) {
1497                 show = text;
1498                 caret = pos;
1499             } else if (pos - mid < 0) {
1500                 // too few characters to left
1501                 show = text.left(max - 3) + "...";
1502                 caret = pos;
1503             } else if (pos - mid >= 0 && pos + mid <= textLength) {
1504                 // enough characters on each side
1505                 show = "..." + text.substring(pos - mid + 3, max - 6) + "...";
1506                 caret = mid;
1507             } else {
1508                 // too few characters on right
1509                 show = "..." + text.right(max - 3);
1510                 caret = pos - (textLength - show.length());
1511             }
1512             
1513             show.replace('\n', ' ');
1514             show.replace('\r', ' ');
1515             fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);
1516             fprintf(stderr, "           ");
1517             for (int i = 0; i < caret; i++)
1518                 fprintf(stderr, " ");
1519             fprintf(stderr, "^\n");
1520         } else {
1521             if ((int)text.length() > max)
1522                 text = text.left(max - 3) + "...";
1523             else
1524                 text = text.left(max);
1525             fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());
1526         }
1527     }
1528 }
1529
1530 bool FrameSelection::contains(const LayoutPoint& point)
1531 {
1532     Document* document = m_frame->document();
1533     
1534     // Treat a collapsed selection like no selection.
1535     if (!isRange())
1536         return false;
1537     if (!document->renderView()) 
1538         return false;
1539     
1540     HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent);
1541     HitTestResult result(point);
1542     document->renderView()->hitTest(request, result);
1543     Node* innerNode = result.innerNode();
1544     if (!innerNode || !innerNode->renderer())
1545         return false;
1546     
1547     VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));
1548     if (visiblePos.isNull())
1549         return false;
1550         
1551     if (m_selection.visibleStart().isNull() || m_selection.visibleEnd().isNull())
1552         return false;
1553         
1554     Position start(m_selection.visibleStart().deepEquivalent());
1555     Position end(m_selection.visibleEnd().deepEquivalent());
1556     Position p(visiblePos.deepEquivalent());
1557
1558     return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;
1559 }
1560
1561 // Workaround for the fact that it's hard to delete a frame.
1562 // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
1563 // Can't do this implicitly as part of every setSelection call because in some contexts it might not be good
1564 // for the focus to move to another frame. So instead we call it from places where we are selecting with the
1565 // mouse or the keyboard after setting the selection.
1566 void FrameSelection::selectFrameElementInParentIfFullySelected()
1567 {
1568     // Find the parent frame; if there is none, then we have nothing to do.
1569     Frame* parent = m_frame->tree().parent();
1570     if (!parent)
1571         return;
1572     Page* page = m_frame->page();
1573     if (!page)
1574         return;
1575
1576     // Check if the selection contains the entire frame contents; if not, then there is nothing to do.
1577     if (!isRange())
1578         return;
1579     if (!isStartOfDocument(selection().visibleStart()))
1580         return;
1581     if (!isEndOfDocument(selection().visibleEnd()))
1582         return;
1583
1584     // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.
1585     Element* ownerElement = m_frame->ownerElement();
1586     if (!ownerElement)
1587         return;
1588     ContainerNode* ownerElementParent = ownerElement->parentNode();
1589     if (!ownerElementParent)
1590         return;
1591         
1592     // 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.
1593     if (!ownerElementParent->hasEditableStyle())
1594         return;
1595
1596     // Create compute positions before and after the element.
1597     unsigned ownerElementNodeIndex = ownerElement->nodeIndex();
1598     VisiblePosition beforeOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex, Position::PositionIsOffsetInAnchor)));
1599     VisiblePosition afterOwnerElement(VisiblePosition(Position(ownerElementParent, ownerElementNodeIndex + 1, Position::PositionIsOffsetInAnchor), VP_UPSTREAM_IF_POSSIBLE));
1600
1601     // Focus on the parent frame, and then select from before this element to after.
1602     VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);
1603     if (parent->selection().shouldChangeSelection(newSelection)) {
1604         page->focusController().setFocusedFrame(parent);
1605         parent->selection().setSelection(newSelection);
1606     }
1607 }
1608
1609 void FrameSelection::selectAll()
1610 {
1611     Document* document = m_frame->document();
1612
1613     if (document->focusedElement() && document->focusedElement()->hasTagName(selectTag)) {
1614         HTMLSelectElement* selectElement = toHTMLSelectElement(document->focusedElement());
1615         if (selectElement->canSelectAll()) {
1616             selectElement->selectAll();
1617             return;
1618         }
1619     }
1620
1621     RefPtr<Node> root = 0;
1622     Node* selectStartTarget = 0;
1623     if (isContentEditable()) {
1624         root = highestEditableRoot(m_selection.start());
1625         if (Node* shadowRoot = m_selection.nonBoundaryShadowTreeRootNode())
1626             selectStartTarget = shadowRoot->shadowHost();
1627         else
1628             selectStartTarget = root.get();
1629     } else {
1630         root = m_selection.nonBoundaryShadowTreeRootNode();
1631         if (root)
1632             selectStartTarget = root->shadowHost();
1633         else {
1634             root = document->documentElement();
1635             selectStartTarget = document->body();
1636         }
1637     }
1638     if (!root)
1639         return;
1640
1641     if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)))
1642         return;
1643
1644     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root.get()));
1645
1646     if (shouldChangeSelection(newSelection))
1647         setSelection(newSelection);
1648
1649     selectFrameElementInParentIfFullySelected();
1650     notifyRendererOfSelectionChange(UserTriggered);
1651 }
1652
1653 bool FrameSelection::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping)
1654 {
1655     if (!range || !range->startContainer() || !range->endContainer())
1656         return false;
1657     ASSERT(&range->startContainer()->document() == &range->endContainer()->document());
1658
1659     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1660
1661     // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,
1662     // they start at the beginning of the next line instead
1663     ExceptionCode ec = 0;
1664     bool collapsed = range->collapsed(ec);
1665     if (ec)
1666         return false;
1667
1668     // FIXME: Can we provide extentAffinity?
1669     VisiblePosition visibleStart(range->startPosition(), collapsed ? affinity : DOWNSTREAM);
1670     VisiblePosition visibleEnd(range->endPosition(), SEL_DEFAULT_AFFINITY);
1671     setSelection(VisibleSelection(visibleStart, visibleEnd), ClearTypingStyle | (closeTyping ? CloseTyping : 0));
1672     return true;
1673 }
1674
1675 bool FrameSelection::isInPasswordField() const
1676 {
1677     HTMLTextFormControlElement* textControl = enclosingTextFormControl(start());
1678     return textControl && isHTMLInputElement(textControl) && toHTMLInputElement(textControl)->isPasswordField();
1679 }
1680
1681 void FrameSelection::focusedOrActiveStateChanged()
1682 {
1683     bool activeAndFocused = isFocusedAndActive();
1684     Ref<Document> document(*m_frame->document());
1685
1686     document->updateStyleIfNeeded();
1687
1688     // Because RenderObject::selectionBackgroundColor() and
1689     // RenderObject::selectionForegroundColor() check if the frame is active,
1690     // we have to update places those colors were painted.
1691     if (RenderView* view = document->renderView())
1692         view->repaintSelection();
1693
1694     // Caret appears in the active frame.
1695     if (activeAndFocused)
1696         setSelectionFromNone();
1697     setCaretVisibility(activeAndFocused ? Visible : Hidden);
1698
1699     // Update for caps lock state
1700     m_frame->eventHandler().capsLockStateMayHaveChanged();
1701
1702     // Because StyleResolver::checkOneSelector() and
1703     // RenderTheme::isFocused() check if the frame is active, we have to
1704     // update style and theme state that depended on those.
1705     if (Element* element = document->focusedElement()) {
1706         element->setNeedsStyleRecalc();
1707         if (RenderObject* renderer = element->renderer())
1708             if (renderer && renderer->style().hasAppearance())
1709                 renderer->theme().stateChanged(renderer, FocusState);
1710     }
1711 }
1712
1713 void FrameSelection::pageActivationChanged()
1714 {
1715     focusedOrActiveStateChanged();
1716 }
1717
1718 void FrameSelection::setFocused(bool flag)
1719 {
1720     if (m_focused == flag)
1721         return;
1722     m_focused = flag;
1723
1724     focusedOrActiveStateChanged();
1725 }
1726
1727 bool FrameSelection::isFocusedAndActive() const
1728 {
1729     return m_focused && m_frame->page() && m_frame->page()->focusController().isActive();
1730 }
1731
1732 #if ENABLE(TEXT_CARET)
1733 inline static bool shouldStopBlinkingDueToTypingCommand(Frame* frame)
1734 {
1735     return frame->editor().lastEditCommand() && frame->editor().lastEditCommand()->shouldStopCaretBlinking();
1736 }
1737 #endif
1738
1739 void FrameSelection::updateAppearance()
1740 {
1741     // Paint a block cursor instead of a caret in overtype mode unless the caret is at the end of a line (in this case
1742     // the FrameSelection will paint a blinking caret as usual).
1743     VisiblePosition forwardPosition;
1744     if (m_shouldShowBlockCursor && m_selection.isCaret()) {
1745         forwardPosition = modifyExtendingForward(CharacterGranularity);
1746         m_caretPaint = forwardPosition.isNull();
1747     }
1748
1749 #if ENABLE(TEXT_CARET)
1750     bool caretRectChangedOrCleared = recomputeCaretRect();
1751
1752     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
1753     bool shouldBlink = caretIsVisible() && isCaret() && (isContentEditable() || caretBrowsing) && forwardPosition.isNull();
1754
1755     // If the caret moved, stop the blink timer so we can restart with a
1756     // black caret in the new location.
1757     if (caretRectChangedOrCleared || !shouldBlink || shouldStopBlinkingDueToTypingCommand(m_frame))
1758         m_caretBlinkTimer.stop();
1759
1760     // Start blinking with a black caret. Be sure not to restart if we're
1761     // already blinking in the right location.
1762     if (shouldBlink && !m_caretBlinkTimer.isActive()) {
1763         if (double blinkInterval = m_frame->page()->theme().caretBlinkInterval())
1764             m_caretBlinkTimer.startRepeating(blinkInterval);
1765
1766         if (!m_caretPaint) {
1767             m_caretPaint = true;
1768             invalidateCaretRect();
1769         }
1770     }
1771 #endif
1772
1773     RenderView* view = m_frame->contentRenderer();
1774     if (!view)
1775         return;
1776
1777     // Construct a new VisibleSolution, since m_selection is not necessarily valid, and the following steps
1778     // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69563> and <rdar://problem/10232866>.
1779     VisibleSelection selection(m_selection.visibleStart(), forwardPosition.isNotNull() ? forwardPosition : m_selection.visibleEnd());
1780
1781     if (!selection.isRange()) {
1782         view->clearSelection();
1783         return;
1784     }
1785
1786     // Use the rightmost candidate for the start of the selection, and the leftmost candidate for the end of the selection.
1787     // Example: foo <a>bar</a>.  Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.   If we pass [foo, 3]
1788     // as the start of the selection, the selection painting code will think that content on the line containing 'foo' is selected
1789     // and will fill the gap before 'bar'.
1790     Position startPos = selection.start();
1791     Position candidate = startPos.downstream();
1792     if (candidate.isCandidate())
1793         startPos = candidate;
1794     Position endPos = selection.end();
1795     candidate = endPos.upstream();
1796     if (candidate.isCandidate())
1797         endPos = candidate;
1798
1799     // We can get into a state where the selection endpoints map to the same VisiblePosition when a selection is deleted
1800     // because we don't yet notify the FrameSelection of text removal.
1801     if (startPos.isNotNull() && endPos.isNotNull() && selection.visibleStart() != selection.visibleEnd()) {
1802         RenderObject* startRenderer = startPos.deprecatedNode()->renderer();
1803         RenderObject* endRenderer = endPos.deprecatedNode()->renderer();
1804         view->setSelection(startRenderer, startPos.deprecatedEditingOffset(), endRenderer, endPos.deprecatedEditingOffset());
1805     }
1806 }
1807
1808 void FrameSelection::setCaretVisibility(CaretVisibility visibility)
1809 {
1810     if (caretVisibility() == visibility)
1811         return;
1812
1813 #if ENABLE(TEXT_CARET)
1814     m_frame->document()->updateLayoutIgnorePendingStylesheets();
1815     if (m_caretPaint) {
1816         m_caretPaint = false;
1817         invalidateCaretRect();
1818     }
1819     CaretBase::setCaretVisibility(visibility);
1820 #else
1821     m_frame->document()->updateStyleIfNeeded();
1822 #endif
1823
1824     updateAppearance();
1825 }
1826
1827 void FrameSelection::caretBlinkTimerFired(Timer<FrameSelection>*)
1828 {
1829 #if ENABLE(TEXT_CARET)
1830     ASSERT(caretIsVisible());
1831     ASSERT(isCaret());
1832     bool caretPaint = m_caretPaint;
1833     if (isCaretBlinkingSuspended() && caretPaint)
1834         return;
1835     m_caretPaint = !caretPaint;
1836     invalidateCaretRect();
1837 #endif
1838 }
1839
1840 void FrameSelection::notifyRendererOfSelectionChange(EUserTriggered userTriggered)
1841 {
1842     m_frame->document()->updateStyleIfNeeded();
1843
1844     if (HTMLTextFormControlElement* textControl = enclosingTextFormControl(start()))
1845         textControl->selectionChanged(userTriggered == UserTriggered);
1846 }
1847
1848 // Helper function that tells whether a particular node is an element that has an entire
1849 // Frame and FrameView, a <frame>, <iframe>, or <object>.
1850 static bool isFrameElement(const Node* n)
1851 {
1852     if (!n)
1853         return false;
1854     RenderObject* renderer = n->renderer();
1855     if (!renderer || !renderer->isWidget())
1856         return false;
1857     Widget* widget = toRenderWidget(renderer)->widget();
1858     return widget && widget->isFrameView();
1859 }
1860
1861 void FrameSelection::setFocusedElementIfNeeded()
1862 {
1863     if (isNone() || !isFocused())
1864         return;
1865
1866     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
1867     if (caretBrowsing) {
1868         if (Element* anchor = enclosingAnchorElement(base())) {
1869             m_frame->page()->focusController().setFocusedElement(anchor, m_frame);
1870             return;
1871         }
1872     }
1873
1874     if (Element* target = rootEditableElement()) {
1875         // Walk up the DOM tree to search for an element to focus.
1876         while (target) {
1877             // We don't want to set focus on a subframe when selecting in a parent frame,
1878             // so add the !isFrameElement check here. There's probably a better way to make this
1879             // work in the long term, but this is the safest fix at this time.
1880             if (target->isMouseFocusable() && !isFrameElement(target)) {
1881                 m_frame->page()->focusController().setFocusedElement(target, m_frame);
1882                 return;
1883             }
1884             target = target->parentOrShadowHostElement();
1885         }
1886         m_frame->document()->setFocusedElement(0);
1887     }
1888
1889     if (caretBrowsing)
1890         m_frame->page()->focusController().setFocusedElement(0, m_frame);
1891 }
1892
1893 void DragCaretController::paintDragCaret(Frame* frame, GraphicsContext* p, const LayoutPoint& paintOffset, const LayoutRect& clipRect) const
1894 {
1895 #if ENABLE(TEXT_CARET)
1896     if (m_position.deepEquivalent().deprecatedNode()->document().frame() == frame)
1897         paintCaret(m_position.deepEquivalent().deprecatedNode(), p, paintOffset, clipRect);
1898 #else
1899     UNUSED_PARAM(frame);
1900     UNUSED_PARAM(p);
1901     UNUSED_PARAM(paintOffset);
1902     UNUSED_PARAM(clipRect);
1903 #endif
1904 }
1905
1906 PassRefPtr<MutableStyleProperties> FrameSelection::copyTypingStyle() const
1907 {
1908     if (!m_typingStyle || !m_typingStyle->style())
1909         return 0;
1910     return m_typingStyle->style()->mutableCopy();
1911 }
1912
1913 bool FrameSelection::shouldDeleteSelection(const VisibleSelection& selection) const
1914 {
1915     return m_frame->editor().client()->shouldDeleteRange(selection.toNormalizedRange().get());
1916 }
1917
1918 FloatRect FrameSelection::bounds(bool clipToVisibleContent) const
1919 {
1920     if (!m_frame->document())
1921         return LayoutRect();
1922
1923     m_frame->document()->updateStyleIfNeeded();
1924     RenderView* root = m_frame->contentRenderer();
1925     FrameView* view = m_frame->view();
1926     if (!root || !view)
1927         return LayoutRect();
1928
1929     LayoutRect selectionRect = root->selectionBounds(clipToVisibleContent);
1930     return clipToVisibleContent ? intersection(selectionRect, view->visibleContentRect()) : selectionRect;
1931 }
1932
1933 void FrameSelection::getClippedVisibleTextRectangles(Vector<FloatRect>& rectangles) const
1934 {
1935     RenderView* root = m_frame->contentRenderer();
1936     if (!root)
1937         return;
1938
1939     FloatRect visibleContentRect = m_frame->view()->visibleContentRect();
1940
1941     Vector<FloatQuad> quads;
1942     toNormalizedRange()->textQuads(quads, true);
1943
1944     size_t size = quads.size();
1945     for (size_t i = 0; i < size; ++i) {
1946         FloatRect intersectionRect = intersection(quads[i].enclosingBoundingBox(), visibleContentRect);
1947         if (!intersectionRect.isEmpty())
1948             rectangles.append(intersectionRect);
1949     }
1950 }
1951
1952 // Scans logically forward from "start", including any child frames.
1953 static HTMLFormElement* scanForForm(Element* start)
1954 {
1955     if (!start)
1956         return nullptr;
1957
1958     auto descendants = descendantsOfType<HTMLElement>(start->document());
1959     for (auto it = descendants.from(*start), end = descendants.end(); it != end; ++it) {
1960         HTMLElement& element = *it;
1961         if (isHTMLFormElement(&element))
1962             return toHTMLFormElement(&element);
1963         if (isHTMLFormControlElement(element))
1964             return toHTMLFormControlElement(element).form();
1965         if (isHTMLFrameElementBase(element)) {
1966             Document* contentDocument = toHTMLFrameElementBase(element).contentDocument();
1967             if (!contentDocument)
1968                 continue;
1969             if (HTMLFormElement* frameResult = scanForForm(contentDocument->documentElement()))
1970                 return frameResult;
1971         }
1972     }
1973     return nullptr;
1974 }
1975
1976 // We look for either the form containing the current focus, or for one immediately after it
1977 HTMLFormElement* FrameSelection::currentForm() const
1978 {
1979     // Start looking either at the active (first responder) node, or where the selection is.
1980     Element* start = m_frame->document()->focusedElement();
1981     if (!start)
1982         start = this->start().element();
1983     if (!start)
1984         return nullptr;
1985
1986     if (auto form = lineageOfType<HTMLFormElement>(*start).first())
1987         return form;
1988     if (auto formControl = lineageOfType<HTMLFormControlElement>(*start).first())
1989         return formControl->form();
1990
1991     // Try walking forward in the node tree to find a form element.
1992     return scanForForm(start);
1993 }
1994
1995 void FrameSelection::revealSelection(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
1996 {
1997     LayoutRect rect;
1998
1999     switch (selectionType()) {
2000     case VisibleSelection::NoSelection:
2001         return;
2002     case VisibleSelection::CaretSelection:
2003         rect = absoluteCaretBounds();
2004         break;
2005     case VisibleSelection::RangeSelection:
2006         rect = revealExtentOption == RevealExtent ? VisiblePosition(extent()).absoluteCaretBounds() : enclosingIntRect(bounds(false));
2007         break;
2008     }
2009
2010     Position start = this->start();
2011     ASSERT(start.deprecatedNode());
2012     if (start.deprecatedNode() && start.deprecatedNode()->renderer()) {
2013         // FIXME: This code only handles scrolling the startContainer's layer, but
2014         // the selection rect could intersect more than just that.
2015         // See <rdar://problem/4799899>.
2016         if (start.deprecatedNode()->renderer()->scrollRectToVisible(rect, alignment, alignment))
2017             updateAppearance();
2018     }
2019 }
2020
2021 void FrameSelection::setSelectionFromNone()
2022 {
2023     // Put a caret inside the body if the entire frame is editable (either the
2024     // entire WebView is editable or designMode is on for this document).
2025
2026     Document* document = m_frame->document();
2027     bool caretBrowsing = m_frame->settings().caretBrowsingEnabled();
2028     if (!isNone() || !(document->hasEditableStyle() || caretBrowsing))
2029         return;
2030
2031     Node* node = document->documentElement();
2032     while (node && !node->hasTagName(bodyTag))
2033         node = NodeTraversal::next(node);
2034     if (node)
2035         setSelection(VisibleSelection(firstPositionInOrBeforeNode(node), DOWNSTREAM));
2036 }
2037
2038 bool FrameSelection::shouldChangeSelection(const VisibleSelection& newSelection) const
2039 {
2040     return m_frame->editor().shouldChangeSelection(selection(), newSelection, newSelection.affinity(), false);
2041 }
2042
2043 bool FrameSelection::dispatchSelectStart()
2044 {
2045     Node* selectStartTarget = m_selection.extent().containerNode();
2046     if (!selectStartTarget)
2047         return true;
2048
2049     return selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
2050 }
2051
2052 void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor)
2053 {
2054     m_shouldShowBlockCursor = shouldShowBlockCursor;
2055
2056     m_frame->document()->updateLayoutIgnorePendingStylesheets();
2057
2058     updateAppearance();
2059 }
2060
2061 #ifndef NDEBUG
2062
2063 void FrameSelection::formatForDebugger(char* buffer, unsigned length) const
2064 {
2065     m_selection.formatForDebugger(buffer, length);
2066 }
2067
2068 void FrameSelection::showTreeForThis() const
2069 {
2070     m_selection.showTreeForThis();
2071 }
2072
2073 #endif
2074
2075 }
2076
2077 #ifndef NDEBUG
2078
2079 void showTree(const WebCore::FrameSelection& sel)
2080 {
2081     sel.showTreeForThis();
2082 }
2083
2084 void showTree(const WebCore::FrameSelection* sel)
2085 {
2086     if (sel)
2087         sel->showTreeForThis();
2088 }
2089
2090 #endif