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