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