Reviewed by Harrison.
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Jan 2005 18:58:42 +0000 (18:58 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Jan 2005 18:58:42 +0000 (18:58 +0000)
        - fixed <rdar://problem/3980066> Double-click on single character moves insertion point to previous line

        * khtml/khtml_part.cpp:
        (KHTMLPart::selectClosestWordFromMouseEvent): Set affinity too.
        (KHTMLPart::handleMousePressEventTripleClick): Ditto.
        (KHTMLPart::handleMouseMoveEventSelection): Ditto.
        (KHTMLPart::khtmlMouseReleaseEvent): Ditto.

        * khtml/editing/selection.cpp:
        (khtml::Selection::modifyExtendingRightForward): Use endOfLine and endOfDocument.
        (khtml::Selection::modifyMovingRightForward): Ditto.
        (khtml::Selection::modifyExtendingLeftBackward): Use startOfLine and startOfDocument.
        (khtml::Selection::modifyMovingLeftBackward): Ditto.
        (khtml::Selection::validate): Rewrote the section that handles double-click. Two main fixes: 1) use isStartOfLine to
        check for another case where we want to select the word to the right, and 2) use isEndOfParagraph, which seems
        to work correctly in cases where isLastVisiblePositionInParagraph is giving the wrong answer. Also changed the line
        code to use startOfLine/endOfLine and the document code to use startOfDocument/endOfDocument.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8483 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/SelectionController.cpp
WebCore/khtml/editing/selection.cpp
WebCore/khtml/khtml_part.cpp

index 6c7df506be52467d5b9e4b61686d5f5f9d2b90c8..55e0f2402f8d02822456c129ddf7aa11280bb7a4 100644 (file)
@@ -1,3 +1,25 @@
+2005-01-31  Darin Adler  <darin@apple.com>
+
+        Reviewed by Harrison.
+
+        - fixed <rdar://problem/3980066> Double-click on single character moves insertion point to previous line
+
+        * khtml/khtml_part.cpp:
+        (KHTMLPart::selectClosestWordFromMouseEvent): Set affinity too.
+        (KHTMLPart::handleMousePressEventTripleClick): Ditto.
+        (KHTMLPart::handleMouseMoveEventSelection): Ditto.
+        (KHTMLPart::khtmlMouseReleaseEvent): Ditto.
+
+        * khtml/editing/selection.cpp:
+        (khtml::Selection::modifyExtendingRightForward): Use endOfLine and endOfDocument.
+        (khtml::Selection::modifyMovingRightForward): Ditto.
+        (khtml::Selection::modifyExtendingLeftBackward): Use startOfLine and startOfDocument.
+        (khtml::Selection::modifyMovingLeftBackward): Ditto.
+        (khtml::Selection::validate): Rewrote the section that handles double-click. Two main fixes: 1) use isStartOfLine to
+        check for another case where we want to select the word to the right, and 2) use isEndOfParagraph, which seems
+        to work correctly in cases where isLastVisiblePositionInParagraph is giving the wrong answer. Also changed the line
+        code to use startOfLine/endOfLine and the document code to use startOfDocument/endOfDocument.
+
 2005-01-31  Darin Adler  <darin@apple.com>
 
         Reviewed by Harrison.
index 818746651a02067b9f9de44bcff6dda64b5ee94b..b0eeee4f6dec33a3737a3596a514f1100903ae82 100644 (file)
@@ -65,8 +65,6 @@ using DOM::StayInBlock;
 
 namespace khtml {
 
-static Selection selectionForLine(const Position &position, EAffinity affinity);
-
 Selection::Selection()
 {
     init();
@@ -273,16 +271,14 @@ VisiblePosition Selection::modifyExtendingRightForward(ETextGranularity granular
             pos = nextLinePosition(pos, m_affinity, xPosForVerticalArrowNavigation(EXTENT));
             break;
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_end, m_affinity).end());
+            pos = endOfLine(VisiblePosition(m_end), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = endOfParagraph(VisiblePosition(m_end));
             break;
-        case DOCUMENT_BOUNDARY: {
-            NodeImpl *de = m_start.node()->getDocument()->documentElement();
-            pos = VisiblePosition(de, de ? de->childNodeCount() : 0);
+        case DOCUMENT_BOUNDARY:
+            pos = endOfDocument(pos);
             break;
-        }
     }
     return pos;
 }
@@ -326,16 +322,14 @@ VisiblePosition Selection::modifyMovingRightForward(ETextGranularity granularity
             break;
         }
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_end, m_affinity).end());
+            pos = endOfLine(VisiblePosition(m_end), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = endOfParagraph(VisiblePosition(m_end));
             break;
-        case DOCUMENT_BOUNDARY: {
-            NodeImpl *de = m_start.node()->getDocument()->documentElement();
-            pos = VisiblePosition(de, de ? de->childNodeCount() : 0);
+        case DOCUMENT_BOUNDARY:
+            pos = endOfDocument(VisiblePosition(m_end));
             break;
-        }
     }
     return pos;
 }
@@ -357,13 +351,13 @@ VisiblePosition Selection::modifyExtendingLeftBackward(ETextGranularity granular
             pos = previousLinePosition(pos, m_affinity, xPosForVerticalArrowNavigation(EXTENT));
             break;
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_start, m_affinity).start());
+            pos = startOfLine(VisiblePosition(m_start), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = startOfParagraph(VisiblePosition(m_start));
             break;
         case DOCUMENT_BOUNDARY:
-            pos = VisiblePosition(m_start.node()->getDocument()->documentElement(), 0);
+            pos = startOfDocument(pos);
             break;
     }
     return pos;
@@ -389,13 +383,13 @@ VisiblePosition Selection::modifyMovingLeftBackward(ETextGranularity granularity
             pos = previousLinePosition(VisiblePosition(m_start), m_affinity, xPosForVerticalArrowNavigation(START, isRange()));
             break;
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_start, m_affinity).start());
+            pos = startOfLine(VisiblePosition(m_start), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = startOfParagraph(VisiblePosition(m_start));
             break;
         case DOCUMENT_BOUNDARY:
-            pos = VisiblePosition(m_start.node()->getDocument()->documentElement(), 0);
+            pos = startOfDocument(VisiblePosition(m_start));
             break;
     }
     return pos;
@@ -870,53 +864,36 @@ void Selection::validate(ETextGranularity granularity)
             }
             break;
         case WORD:
-            if (m_baseIsStart) {
-                // When double clicking (i.e. isCaret() == true), generally select the previous word.  The only time to select the other 
-                // direction is when double-clicking after a hard line break.  The check for a hard line break is "end of paragraph".
-                if (isCaret()) {
-                    VisiblePosition extent = VisiblePosition(m_extent);
-                    bool atEndOfParagraph = isLastVisiblePositionInParagraph(extent);
-                    
-                    EWordSide endSide = !atEndOfParagraph ? LeftWordIfOnBoundary : RightWordIfOnBoundary;
-                    VisiblePosition wordEnd = endOfWord(extent, endSide);
-                    m_end = wordEnd.deepEquivalent();
-
-                    EWordSide startSide = !atEndOfParagraph ? LeftWordIfOnBoundary : RightWordIfOnBoundary;
-
-                    // atEndOfParagraph reflects hard line break well, except at end-of-document, so we are more careful there
-                    if (startSide == RightWordIfOnBoundary && wordEnd.next().isNull() && !isFirstVisiblePositionOnLine(wordEnd))
-                        startSide = LeftWordIfOnBoundary;
-                    m_start = startOfWord(VisiblePosition(m_base), startSide).deepEquivalent();
-                } else {
-                    m_start = startOfWord(VisiblePosition(m_base)).deepEquivalent();
-                    m_end = endOfWord(VisiblePosition(m_extent)).deepEquivalent();
-                }
+            if (isCaret()) {
+                // When double clicking (i.e. selection is a caret), generally select the previous word.
+                // One exception is double-clicking after a hard line break. The check for a hard line break is "end of paragraph".
+                // Another exception is when double-clicking at the start of a line.
+                // However, the end of the document is an exception and always selects the previous word even though it could be
+                // both the start of a line and after a hard line break.
+                VisiblePosition pos(m_base);
+                EWordSide side = LeftWordIfOnBoundary;
+                if ((isEndOfParagraph(pos) || isStartOfLine(pos, m_affinity)) && !isEndOfDocument(pos))
+                    side = RightWordIfOnBoundary;
+                m_start = startOfWord(pos, side).deepEquivalent();
+                m_end = endOfWord(pos, side).deepEquivalent();
+            } else if (m_baseIsStart) {
+                m_start = startOfWord(VisiblePosition(m_base)).deepEquivalent();
+                m_end = endOfWord(VisiblePosition(m_extent)).deepEquivalent();
             } else {
                 m_start = startOfWord(VisiblePosition(m_extent)).deepEquivalent();
                 m_end = endOfWord(VisiblePosition(m_base)).deepEquivalent();
             }
             break;
         case LINE:
-        case LINE_BOUNDARY: {
-            Selection baseSelection = *this;
-            Selection extentSelection = *this;
-            Selection baseLine = selectionForLine(m_base, m_affinity);
-            if (baseLine.isCaretOrRange()) {
-                baseSelection = baseLine;
-            }
-            Selection extentLine = selectionForLine(m_extent, m_affinity);
-            if (extentLine.isCaretOrRange()) {
-                extentSelection = extentLine;
-            }
+        case LINE_BOUNDARY:
             if (m_baseIsStart) {
-                m_start = baseSelection.m_start;
-                m_end = extentSelection.m_end;
+                m_start = startOfLine(VisiblePosition(m_base), m_affinity).deepEquivalent();
+                m_end = endOfLine(VisiblePosition(m_extent), m_affinity, IncludeLineBreak).deepEquivalent();
             } else {
-                m_start = extentSelection.m_start;
-                m_end = baseSelection.m_end;
+                m_start = startOfLine(VisiblePosition(m_extent), m_affinity).deepEquivalent();
+                m_end = endOfLine(VisiblePosition(m_base), m_affinity, IncludeLineBreak).deepEquivalent();
             }
             break;
-        }
         case PARAGRAPH:
             if (m_baseIsStart) {
                 m_start = startOfParagraph(VisiblePosition(m_base)).deepEquivalent();
@@ -926,12 +903,10 @@ void Selection::validate(ETextGranularity granularity)
                 m_end = endOfParagraph(VisiblePosition(m_base), IncludeLineBreak).deepEquivalent();
             }
             break;
-        case DOCUMENT_BOUNDARY: {
-            NodeImpl *de = m_start.node()->getDocument()->documentElement();
-            m_start = VisiblePosition(de, 0).deepEquivalent();
-            m_end = VisiblePosition(de, de ? de->childNodeCount() : 0).deepEquivalent();
+        case DOCUMENT_BOUNDARY:
+            m_start = startOfDocument(VisiblePosition(m_base)).deepEquivalent();
+            m_end = endOfDocument(VisiblePosition(m_base)).deepEquivalent();
             break;
-        }
         case PARAGRAPH_BOUNDARY:
             if (m_baseIsStart) {
                 m_start = startOfParagraph(VisiblePosition(m_base)).deepEquivalent();
@@ -970,57 +945,6 @@ void Selection::validate(ETextGranularity granularity)
 #endif
 }
 
-static NodeImpl *nodeForInlineBox(const InlineBox *box)
-{
-    if (!box || !box->object())
-        return 0;
-    return box->object()->element();
-}
-
-static Selection selectionForLine(const Position &pos, EAffinity affinity)
-{
-    if (pos.isNull())
-        return Selection();
-
-    RenderObject *renderer = pos.node()->renderer();
-    if (!renderer)
-        return Selection();
-    
-    InlineBox *box = renderer->inlineBox(pos.offset(), affinity);
-    if (!box)
-        return Selection();
-    
-    RootInlineBox *rootBox = box->root();
-    if (!rootBox)
-        return Selection();
-    
-    // Find the start position for this line.
-    InlineBox *startBox = rootBox->firstChild();
-    NodeImpl *startNode = nodeForInlineBox(startBox);
-    if (!startNode)
-        return Selection();
-    long startOffset = 0;
-    if (startBox->isInlineTextBox()) {
-        InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox);
-        startOffset = startTextBox->m_start;
-    }
-    Position start(startNode, startOffset);
-    
-    // Find the end position for this line.
-    InlineBox *endBox = rootBox->lastChild();
-    NodeImpl *endNode = nodeForInlineBox(endBox);
-    if (!endNode)
-        return Selection();
-    long endOffset = 1;
-    if (endBox->isInlineTextBox()) {
-        InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox);
-        endOffset = endTextBox->m_start + endTextBox->m_len;
-    }
-    Position end(endNode, endOffset);
-    
-    return Selection(start, end);
-}
-
 void Selection::debugRenderer(RenderObject *r, bool selected) const
 {
     if (r->node()->isElementNode()) {
index 818746651a02067b9f9de44bcff6dda64b5ee94b..b0eeee4f6dec33a3737a3596a514f1100903ae82 100644 (file)
@@ -65,8 +65,6 @@ using DOM::StayInBlock;
 
 namespace khtml {
 
-static Selection selectionForLine(const Position &position, EAffinity affinity);
-
 Selection::Selection()
 {
     init();
@@ -273,16 +271,14 @@ VisiblePosition Selection::modifyExtendingRightForward(ETextGranularity granular
             pos = nextLinePosition(pos, m_affinity, xPosForVerticalArrowNavigation(EXTENT));
             break;
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_end, m_affinity).end());
+            pos = endOfLine(VisiblePosition(m_end), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = endOfParagraph(VisiblePosition(m_end));
             break;
-        case DOCUMENT_BOUNDARY: {
-            NodeImpl *de = m_start.node()->getDocument()->documentElement();
-            pos = VisiblePosition(de, de ? de->childNodeCount() : 0);
+        case DOCUMENT_BOUNDARY:
+            pos = endOfDocument(pos);
             break;
-        }
     }
     return pos;
 }
@@ -326,16 +322,14 @@ VisiblePosition Selection::modifyMovingRightForward(ETextGranularity granularity
             break;
         }
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_end, m_affinity).end());
+            pos = endOfLine(VisiblePosition(m_end), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = endOfParagraph(VisiblePosition(m_end));
             break;
-        case DOCUMENT_BOUNDARY: {
-            NodeImpl *de = m_start.node()->getDocument()->documentElement();
-            pos = VisiblePosition(de, de ? de->childNodeCount() : 0);
+        case DOCUMENT_BOUNDARY:
+            pos = endOfDocument(VisiblePosition(m_end));
             break;
-        }
     }
     return pos;
 }
@@ -357,13 +351,13 @@ VisiblePosition Selection::modifyExtendingLeftBackward(ETextGranularity granular
             pos = previousLinePosition(pos, m_affinity, xPosForVerticalArrowNavigation(EXTENT));
             break;
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_start, m_affinity).start());
+            pos = startOfLine(VisiblePosition(m_start), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = startOfParagraph(VisiblePosition(m_start));
             break;
         case DOCUMENT_BOUNDARY:
-            pos = VisiblePosition(m_start.node()->getDocument()->documentElement(), 0);
+            pos = startOfDocument(pos);
             break;
     }
     return pos;
@@ -389,13 +383,13 @@ VisiblePosition Selection::modifyMovingLeftBackward(ETextGranularity granularity
             pos = previousLinePosition(VisiblePosition(m_start), m_affinity, xPosForVerticalArrowNavigation(START, isRange()));
             break;
         case LINE_BOUNDARY:
-            pos = VisiblePosition(selectionForLine(m_start, m_affinity).start());
+            pos = startOfLine(VisiblePosition(m_start), m_affinity);
             break;
         case PARAGRAPH_BOUNDARY:
             pos = startOfParagraph(VisiblePosition(m_start));
             break;
         case DOCUMENT_BOUNDARY:
-            pos = VisiblePosition(m_start.node()->getDocument()->documentElement(), 0);
+            pos = startOfDocument(VisiblePosition(m_start));
             break;
     }
     return pos;
@@ -870,53 +864,36 @@ void Selection::validate(ETextGranularity granularity)
             }
             break;
         case WORD:
-            if (m_baseIsStart) {
-                // When double clicking (i.e. isCaret() == true), generally select the previous word.  The only time to select the other 
-                // direction is when double-clicking after a hard line break.  The check for a hard line break is "end of paragraph".
-                if (isCaret()) {
-                    VisiblePosition extent = VisiblePosition(m_extent);
-                    bool atEndOfParagraph = isLastVisiblePositionInParagraph(extent);
-                    
-                    EWordSide endSide = !atEndOfParagraph ? LeftWordIfOnBoundary : RightWordIfOnBoundary;
-                    VisiblePosition wordEnd = endOfWord(extent, endSide);
-                    m_end = wordEnd.deepEquivalent();
-
-                    EWordSide startSide = !atEndOfParagraph ? LeftWordIfOnBoundary : RightWordIfOnBoundary;
-
-                    // atEndOfParagraph reflects hard line break well, except at end-of-document, so we are more careful there
-                    if (startSide == RightWordIfOnBoundary && wordEnd.next().isNull() && !isFirstVisiblePositionOnLine(wordEnd))
-                        startSide = LeftWordIfOnBoundary;
-                    m_start = startOfWord(VisiblePosition(m_base), startSide).deepEquivalent();
-                } else {
-                    m_start = startOfWord(VisiblePosition(m_base)).deepEquivalent();
-                    m_end = endOfWord(VisiblePosition(m_extent)).deepEquivalent();
-                }
+            if (isCaret()) {
+                // When double clicking (i.e. selection is a caret), generally select the previous word.
+                // One exception is double-clicking after a hard line break. The check for a hard line break is "end of paragraph".
+                // Another exception is when double-clicking at the start of a line.
+                // However, the end of the document is an exception and always selects the previous word even though it could be
+                // both the start of a line and after a hard line break.
+                VisiblePosition pos(m_base);
+                EWordSide side = LeftWordIfOnBoundary;
+                if ((isEndOfParagraph(pos) || isStartOfLine(pos, m_affinity)) && !isEndOfDocument(pos))
+                    side = RightWordIfOnBoundary;
+                m_start = startOfWord(pos, side).deepEquivalent();
+                m_end = endOfWord(pos, side).deepEquivalent();
+            } else if (m_baseIsStart) {
+                m_start = startOfWord(VisiblePosition(m_base)).deepEquivalent();
+                m_end = endOfWord(VisiblePosition(m_extent)).deepEquivalent();
             } else {
                 m_start = startOfWord(VisiblePosition(m_extent)).deepEquivalent();
                 m_end = endOfWord(VisiblePosition(m_base)).deepEquivalent();
             }
             break;
         case LINE:
-        case LINE_BOUNDARY: {
-            Selection baseSelection = *this;
-            Selection extentSelection = *this;
-            Selection baseLine = selectionForLine(m_base, m_affinity);
-            if (baseLine.isCaretOrRange()) {
-                baseSelection = baseLine;
-            }
-            Selection extentLine = selectionForLine(m_extent, m_affinity);
-            if (extentLine.isCaretOrRange()) {
-                extentSelection = extentLine;
-            }
+        case LINE_BOUNDARY:
             if (m_baseIsStart) {
-                m_start = baseSelection.m_start;
-                m_end = extentSelection.m_end;
+                m_start = startOfLine(VisiblePosition(m_base), m_affinity).deepEquivalent();
+                m_end = endOfLine(VisiblePosition(m_extent), m_affinity, IncludeLineBreak).deepEquivalent();
             } else {
-                m_start = extentSelection.m_start;
-                m_end = baseSelection.m_end;
+                m_start = startOfLine(VisiblePosition(m_extent), m_affinity).deepEquivalent();
+                m_end = endOfLine(VisiblePosition(m_base), m_affinity, IncludeLineBreak).deepEquivalent();
             }
             break;
-        }
         case PARAGRAPH:
             if (m_baseIsStart) {
                 m_start = startOfParagraph(VisiblePosition(m_base)).deepEquivalent();
@@ -926,12 +903,10 @@ void Selection::validate(ETextGranularity granularity)
                 m_end = endOfParagraph(VisiblePosition(m_base), IncludeLineBreak).deepEquivalent();
             }
             break;
-        case DOCUMENT_BOUNDARY: {
-            NodeImpl *de = m_start.node()->getDocument()->documentElement();
-            m_start = VisiblePosition(de, 0).deepEquivalent();
-            m_end = VisiblePosition(de, de ? de->childNodeCount() : 0).deepEquivalent();
+        case DOCUMENT_BOUNDARY:
+            m_start = startOfDocument(VisiblePosition(m_base)).deepEquivalent();
+            m_end = endOfDocument(VisiblePosition(m_base)).deepEquivalent();
             break;
-        }
         case PARAGRAPH_BOUNDARY:
             if (m_baseIsStart) {
                 m_start = startOfParagraph(VisiblePosition(m_base)).deepEquivalent();
@@ -970,57 +945,6 @@ void Selection::validate(ETextGranularity granularity)
 #endif
 }
 
-static NodeImpl *nodeForInlineBox(const InlineBox *box)
-{
-    if (!box || !box->object())
-        return 0;
-    return box->object()->element();
-}
-
-static Selection selectionForLine(const Position &pos, EAffinity affinity)
-{
-    if (pos.isNull())
-        return Selection();
-
-    RenderObject *renderer = pos.node()->renderer();
-    if (!renderer)
-        return Selection();
-    
-    InlineBox *box = renderer->inlineBox(pos.offset(), affinity);
-    if (!box)
-        return Selection();
-    
-    RootInlineBox *rootBox = box->root();
-    if (!rootBox)
-        return Selection();
-    
-    // Find the start position for this line.
-    InlineBox *startBox = rootBox->firstChild();
-    NodeImpl *startNode = nodeForInlineBox(startBox);
-    if (!startNode)
-        return Selection();
-    long startOffset = 0;
-    if (startBox->isInlineTextBox()) {
-        InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox);
-        startOffset = startTextBox->m_start;
-    }
-    Position start(startNode, startOffset);
-    
-    // Find the end position for this line.
-    InlineBox *endBox = rootBox->lastChild();
-    NodeImpl *endNode = nodeForInlineBox(endBox);
-    if (!endNode)
-        return Selection();
-    long endOffset = 1;
-    if (endBox->isInlineTextBox()) {
-        InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox);
-        endOffset = endTextBox->m_start + endTextBox->m_len;
-    }
-    Position end(endNode, endOffset);
-    
-    return Selection(start, end);
-}
-
 void Selection::debugRenderer(RenderObject *r, bool selected) const
 {
     if (r->node()->isElementNode()) {
index a447901a5014e726db828ff0f2ee5a87de000d4a..ec5ee6749d91a609427f6e5e9d7c36bf7bc60391 100644 (file)
@@ -4458,9 +4458,11 @@ void KHTMLPart::selectClosestWordFromMouseEvent(QMouseEvent *mouse, DOM::Node &i
     Selection selection;
 
     if (!innerNode.isNull() && innerNode.handle()->renderer() && innerNode.handle()->renderer()->shouldSelect()) {
-        Position pos(innerNode.handle()->renderer()->positionForCoordinates(x, y));
+        EAffinity affinity;
+        Position pos(innerNode.handle()->renderer()->positionForCoordinates(x, y, &affinity));
         if (pos.isNotNull()) {
             selection.moveTo(pos);
+            selection.setAffinity(affinity);
             selection.expandUsingGranularity(WORD);
         }
     }
@@ -4491,9 +4493,11 @@ void KHTMLPart::handleMousePressEventTripleClick(khtml::MousePressEvent *event)
     
     if (mouse->button() == LeftButton && !innerNode.isNull() && innerNode.handle()->renderer() &&
         innerNode.handle()->renderer()->shouldSelect()) {
-        Position pos(innerNode.handle()->renderer()->positionForCoordinates(event->x(), event->y()));
+        EAffinity affinity;
+        Position pos(innerNode.handle()->renderer()->positionForCoordinates(event->x(), event->y(), &affinity));
         if (pos.isNotNull()) {
             selection.moveTo(pos);
+            selection.setAffinity(affinity);
             selection.expandUsingGranularity(PARAGRAPH);
         }
     }
@@ -4747,7 +4751,8 @@ void KHTMLPart::handleMouseMoveEventSelection(khtml::MouseMoveEvent *event)
        return;
 
     // handle making selection
-    Position pos(innerNode.handle()->renderer()->positionForCoordinates(event->x(), event->y()));
+    EAffinity affinity;
+    Position pos(innerNode.handle()->renderer()->positionForCoordinates(event->x(), event->y(), &affinity));
 
     // Don't modify the selection if we're not on a node.
     if (pos.isNull())
@@ -4760,6 +4765,7 @@ void KHTMLPart::handleMouseMoveEventSelection(khtml::MouseMoveEvent *event)
     if (!d->m_beganSelectingText) {
         d->m_beganSelectingText = true;
         sel.moveTo(pos);
+        sel.setAffinity(affinity);
     }
 
     sel.setExtent(pos);
@@ -4833,8 +4839,12 @@ void KHTMLPart::khtmlMouseReleaseEvent( khtml::MouseReleaseEvent *event )
             && d->m_selection.isRange()) {
         Selection selection;
         NodeImpl *node = d->m_selection.base().node();
-        if (node->isContentEditable() && node->renderer())
-            selection.moveTo(node->renderer()->positionForCoordinates(event->x(), event->y()));
+        if (node->isContentEditable() && node->renderer()) {
+            EAffinity affinity;
+            Position pos = node->renderer()->positionForCoordinates(event->x(), event->y(), &affinity);
+            selection.moveTo(pos);
+            selection.setAffinity(affinity);
+        }
         setSelection(selection);
     }