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