[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677

kocienda kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 08:49:22 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 6438cf29300fad0cbb706e283289b589dd1eb55a
Author: kocienda <kocienda at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Jul 9 18:31:01 2004 +0000

            Reviewed by Hyatt
    
            Some improvements to fix:
    
            <rdar://problem/3723111> Caret not drawn when selection set to unrendered content
    
            * khtml/editing/htmlediting_impl.cpp:
            (khtml::TypingCommandImpl::issueCommandForDeleteKey): Adjust selection to delete if
            selected position is not rendered.
            * khtml/rendering/render_block.cpp:
            (khtml::RenderBlock::paintObject): Use new caretPosition() function on Selection to
            figure out whether to paint.
            * khtml/xml/dom_position.cpp:
            (DOM::Position::previousCharacterPosition): Now correctly deals with a start
            position that is not rendered.
            (DOM::Position::nextCharacterPosition): Ditto.
            (DOM::Position::closestRenderedPosition): New helper.
            * khtml/xml/dom_position.h:
            (DOM::): Moved in EAffinity from Selection header. Now used in closestRenderedPosition function.
            * khtml/xml/dom_selection.cpp:
            (DOM::Selection::Selection): Added new m_caretPosition member. This is the position of the caret
            after a caret layout. This may be different from start or end if start and end are not rendered.
            (DOM::Selection::init):
            (DOM::Selection::modifyExtendingRightForward): New helper to clean up modify() and make it more readble.
            (DOM::Selection::modifyMovingRightForward): Ditto.
            (DOM::Selection::modifyExtendingLeftBackward): Ditto.
            (DOM::Selection::modifyMovingLeftBackward): Ditto.
            (DOM::Selection::modify): Use new helpers to make this more readble.
            (DOM::Selection::layoutCaret): Uses new closestRenderedPosition helper to place the caret if in unrendered
            content.
            (DOM::Selection::paintCaret): Remove moveToRenderedContent. obsolete.
            * khtml/xml/dom_selection.h:
            (DOM::Selection::caretPosition): New accessor.
            * kwq/WebCoreBridge.mm:
            (-[WebCoreBridge setSelectedDOMRange:affinity:]): EAffinity no longer a member enum of Selection class.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6984 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 44c287e..2282d1a 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,41 @@
+2004-07-09  Ken Kocienda  <kocienda at apple.com>
+
+        Reviewed by Hyatt
+        
+        Some improvements to fix:
+        
+        <rdar://problem/3723111> Caret not drawn when selection set to unrendered content
+
+        * khtml/editing/htmlediting_impl.cpp:
+        (khtml::TypingCommandImpl::issueCommandForDeleteKey): Adjust selection to delete if
+        selected position is not rendered.
+        * khtml/rendering/render_block.cpp:
+        (khtml::RenderBlock::paintObject): Use new caretPosition() function on Selection to
+        figure out whether to paint.
+        * khtml/xml/dom_position.cpp:
+        (DOM::Position::previousCharacterPosition): Now correctly deals with a start
+        position that is not rendered.
+        (DOM::Position::nextCharacterPosition): Ditto.
+        (DOM::Position::closestRenderedPosition): New helper.
+        * khtml/xml/dom_position.h:
+        (DOM::): Moved in EAffinity from Selection header. Now used in closestRenderedPosition function.
+        * khtml/xml/dom_selection.cpp:
+        (DOM::Selection::Selection): Added new m_caretPosition member. This is the position of the caret
+        after a caret layout. This may be different from start or end if start and end are not rendered. 
+        (DOM::Selection::init):
+        (DOM::Selection::modifyExtendingRightForward): New helper to clean up modify() and make it more readble.
+        (DOM::Selection::modifyMovingRightForward): Ditto.
+        (DOM::Selection::modifyExtendingLeftBackward): Ditto.
+        (DOM::Selection::modifyMovingLeftBackward): Ditto.
+        (DOM::Selection::modify): Use new helpers to make this more readble.
+        (DOM::Selection::layoutCaret): Uses new closestRenderedPosition helper to place the caret if in unrendered
+        content.
+        (DOM::Selection::paintCaret): Remove moveToRenderedContent. obsolete.
+        * khtml/xml/dom_selection.h:
+        (DOM::Selection::caretPosition): New accessor.
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge setSelectedDOMRange:affinity:]): EAffinity no longer a member enum of Selection class.
+
 2004-07-08  David Hyatt  <hyatt at apple.com>
 
 	Fix for the table layout test that failed because of a change in how innerText worked.  We need to do
diff --git a/WebCore/khtml/editing/SelectionController.cpp b/WebCore/khtml/editing/SelectionController.cpp
index 9f68914..ef99b2d 100644
--- a/WebCore/khtml/editing/SelectionController.cpp
+++ b/WebCore/khtml/editing/SelectionController.cpp
@@ -120,6 +120,7 @@ Selection::Selection(const Selection &o)
         m_caretX = o.m_caretX;
         m_caretY = o.m_caretY;
         m_caretSize = o.m_caretSize;
+        m_caretPosition = o.m_caretPosition;
     }
 }
 
@@ -130,6 +131,7 @@ void Selection::init()
     m_caretX = 0;
     m_caretY = 0;
     m_caretSize = 0;
+    m_caretPosition = emptyPosition();
     m_baseIsStart = true;
     m_needsCaretLayout = true;
     m_modifyBiasSet = false;
@@ -194,92 +196,121 @@ void Selection::moveTo(const Position &base, const Position &extent)
     validate();
 }
 
+Position Selection::modifyExtendingRightForward(ETextGranularity granularity)
+{
+    if (!m_modifyBiasSet) {
+        m_modifyBiasSet = true;
+        assignBaseAndExtent(start(), end());
+    }
+    Position pos = extent().closestRenderedPosition(affinity());
+    switch (granularity) {
+        case CHARACTER:
+            pos = pos.nextCharacterPosition();
+            break;
+        case WORD:
+            pos = pos.nextWordPosition();
+            break;
+        case LINE:
+            pos = pos.nextLinePosition(xPosForVerticalArrowNavigation(EXTENT));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyMovingRightForward(ETextGranularity granularity)
+{
+    m_modifyBiasSet = false;
+    Position pos;
+    switch (granularity) {
+        case CHARACTER:
+            if (state() == RANGE) 
+                pos = end().closestRenderedPosition(affinity());
+            else
+                pos = extent().closestRenderedPosition(affinity()).nextCharacterPosition();
+            break;
+        case WORD:
+            pos = extent().closestRenderedPosition(affinity()).nextWordPosition();
+            break;
+        case LINE:
+            pos = end().closestRenderedPosition(affinity()).nextLinePosition(xPosForVerticalArrowNavigation(END, state() == RANGE));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyExtendingLeftBackward(ETextGranularity granularity)
+{
+    if (!m_modifyBiasSet) {
+        m_modifyBiasSet = true;
+        assignBaseAndExtent(end(), start());
+    }
+    Position pos = extent().closestRenderedPosition(affinity());
+    switch (granularity) {
+        case CHARACTER:
+            pos = pos.previousCharacterPosition();
+            break;
+        case WORD:
+            pos = pos.previousWordPosition();
+            break;
+        case LINE:
+            pos = pos.previousLinePosition(xPosForVerticalArrowNavigation(EXTENT));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyMovingLeftBackward(ETextGranularity granularity)
+{
+    m_modifyBiasSet = false;
+    Position pos;
+    switch (granularity) {
+        case CHARACTER:
+            if (state() == RANGE) 
+                pos = start().closestRenderedPosition(affinity());
+            else
+                pos = extent().closestRenderedPosition(affinity()).previousCharacterPosition();
+            break;
+        case WORD:
+            pos = extent().closestRenderedPosition(affinity()).previousWordPosition();
+            break;
+        case LINE:
+            pos = start().closestRenderedPosition(affinity()).previousLinePosition(xPosForVerticalArrowNavigation(START, state() == RANGE));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
 bool Selection::modify(EAlter alter, EDirection dir, ETextGranularity granularity)
 {
     Position pos;
-    
+
     switch (dir) {
-        // EDIT FIXME: This needs to handle bidi
+        // EDIT FIXME: These need to handle bidi
         case RIGHT:
         case FORWARD:
-            if (alter == EXTEND) {
-                if (!m_modifyBiasSet) {
-                    m_modifyBiasSet = true;
-                    assignBaseAndExtent(start(), end());
-                }
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = extent().nextCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().nextWordPosition();
-                        break;
-                    case LINE:
-                        pos = extent().nextLinePosition(xPosForVerticalArrowNavigation(EXTENT));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
-            else {
-                m_modifyBiasSet = false;
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = (state() == RANGE) ? end() : extent().nextCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().nextWordPosition();
-                        break;
-                    case LINE:
-                        pos = end().nextLinePosition(xPosForVerticalArrowNavigation(END, state() == RANGE));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
+            if (alter == EXTEND)
+                pos = modifyExtendingRightForward(granularity);
+            else
+                pos = modifyMovingRightForward(granularity);
             break;
-        // EDIT FIXME: This needs to handle bidi
         case LEFT:
         case BACKWARD:
-            if (alter == EXTEND) {
-                if (!m_modifyBiasSet) {
-                    m_modifyBiasSet = true;
-                    assignBaseAndExtent(end(), start());
-                }
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = extent().previousCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().previousWordPosition();
-                        break;
-                    case LINE:
-                        pos = extent().previousLinePosition(xPosForVerticalArrowNavigation(EXTENT));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
-            else {
-                m_modifyBiasSet = false;
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = (state() == RANGE) ? start() : extent().previousCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().previousWordPosition();
-                        break;
-                    case LINE:
-                        pos = start().previousLinePosition(xPosForVerticalArrowNavigation(START, state() == RANGE));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
+            if (alter == EXTEND)
+                pos = modifyExtendingLeftBackward(granularity);
+            else
+                pos = modifyMovingLeftBackward(granularity);
             break;
     }
     
@@ -439,15 +470,25 @@ Range Selection::toRange() const
 
 void Selection::layoutCaret()
 {
-    if (isEmpty() || !start().node()->renderer()) {
+    if (state() != CARET) {
         m_caretX = m_caretY = m_caretSize = 0;
+        return;
     }
-    else {
-        // EDIT FIXME: Enhance call to pass along selection 
-        // upstream/downstream affinity to get the right position.
-        int w;
-        start().node()->renderer()->caretPos(start().offset(), true, m_caretX, m_caretY, w, m_caretSize);
+    
+    Position pos = start();
+    if (!pos.inRenderedContent())
+        pos = pos.closestRenderedPosition(affinity());
+
+    if (pos.isEmpty() || !pos.inRenderedContent()) {
+        m_caretX = m_caretY = m_caretSize = 0;
+        return;
     }
+    
+    // EDIT FIXME: Enhance call to pass along selection 
+    // upstream/downstream affinity to get the right position.
+    int w;
+    m_caretPosition = pos;
+    pos.node()->renderer()->caretPos(pos.offset(), true, m_caretX, m_caretY, w, m_caretSize);
 
     m_needsCaretLayout = false;
 }
@@ -503,13 +544,8 @@ void Selection::paintCaret(QPainter *p, const QRect &rect)
     if (m_state != CARET)
         return;
 
-    if (m_needsCaretLayout) {
-        Position pos = start();
-        if (!pos.inRenderedContent()) {
-            moveToRenderedContent();
-        }
+    if (m_needsCaretLayout)
         layoutCaret();
-    }
 
     QRect caretRect(m_caretX, m_caretY, 1, m_caretSize);
     if (caretRect.intersects(rect)) {
diff --git a/WebCore/khtml/editing/SelectionController.h b/WebCore/khtml/editing/SelectionController.h
index 39e3933..9eb67d4 100644
--- a/WebCore/khtml/editing/SelectionController.h
+++ b/WebCore/khtml/editing/SelectionController.h
@@ -50,12 +50,6 @@ public:
     enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
     enum ETextGranularity { CHARACTER, WORD, LINE, PARAGRAPH };
 
-    // These match the AppKit values for these concepts.
-    // From NSTextView.h:
-    // NSSelectionAffinityUpstream = 0
-    // NSSelectionAffinityDownstream = 1
-    enum EAffinity { UPSTREAM = 0, DOWNSTREAM = 1 };
-
     Selection();
     Selection(const Range &);
     Selection(const Position &);
@@ -87,6 +81,7 @@ public:
     Position extent() const { return m_extent; }
     Position start() const { return m_start; }
     Position end() const { return m_end; }
+    Position caretPosition() const { return m_caretPosition; }
 
     QRect getRepaintRect() const;
     void setNeedsLayout(bool flag=true);
@@ -124,6 +119,11 @@ private:
     void assignEnd(const Position &pos) { m_end = pos; }
     void assignStartAndEnd(const Position &start, const Position &end) { m_start = start; m_end = end; }
 
+    Position modifyExtendingRightForward(ETextGranularity);
+    Position modifyMovingRightForward(ETextGranularity);
+    Position modifyExtendingLeftBackward(ETextGranularity);
+    Position modifyMovingLeftBackward(ETextGranularity);
+
     void layoutCaret();
     void needsCaretRepaint();
     void paintCaret(QPainter *p, const QRect &rect);
@@ -139,10 +139,11 @@ private:
     EState m_state;               // the state of the selection
     EAffinity m_affinity;         // the upstream/downstream affinity of the selection
 
-    int m_caretX;                 // caret coordinates and size
+    int m_caretX;                 // caret coordinates, size, and position
     int m_caretY;
     int m_caretSize;
-
+    Position m_caretPosition;               
+    
     bool m_baseIsStart : 1;       // true if base node is before the extent node
     bool m_needsCaretLayout : 1;  // true if the caret position needs to be calculated
     bool m_modifyBiasSet : 1;     // true if the selection has been horizontally 
diff --git a/WebCore/khtml/editing/htmlediting_impl.cpp b/WebCore/khtml/editing/htmlediting_impl.cpp
index a4f74f5..cf06e4c 100644
--- a/WebCore/khtml/editing/htmlediting_impl.cpp
+++ b/WebCore/khtml/editing/htmlediting_impl.cpp
@@ -2420,7 +2420,10 @@ void TypingCommandImpl::issueCommandForDeleteKey()
             // we're at the start of a root editable block...do nothing
             return;
         }
-        selectionToDelete = Selection(pos.previousCharacterPosition(), pos);
+        if (pos.inRenderedContent())
+            selectionToDelete = Selection(pos.previousCharacterPosition(), pos);
+        else
+            selectionToDelete = Selection(pos.equivalentUpstreamPosition().previousCharacterPosition(), pos.equivalentDownstreamPosition());
     }
     deleteSelection(selectionToDelete);
     typingAddedToOpenCommand();
diff --git a/WebCore/khtml/editing/selection.cpp b/WebCore/khtml/editing/selection.cpp
index 9f68914..ef99b2d 100644
--- a/WebCore/khtml/editing/selection.cpp
+++ b/WebCore/khtml/editing/selection.cpp
@@ -120,6 +120,7 @@ Selection::Selection(const Selection &o)
         m_caretX = o.m_caretX;
         m_caretY = o.m_caretY;
         m_caretSize = o.m_caretSize;
+        m_caretPosition = o.m_caretPosition;
     }
 }
 
@@ -130,6 +131,7 @@ void Selection::init()
     m_caretX = 0;
     m_caretY = 0;
     m_caretSize = 0;
+    m_caretPosition = emptyPosition();
     m_baseIsStart = true;
     m_needsCaretLayout = true;
     m_modifyBiasSet = false;
@@ -194,92 +196,121 @@ void Selection::moveTo(const Position &base, const Position &extent)
     validate();
 }
 
+Position Selection::modifyExtendingRightForward(ETextGranularity granularity)
+{
+    if (!m_modifyBiasSet) {
+        m_modifyBiasSet = true;
+        assignBaseAndExtent(start(), end());
+    }
+    Position pos = extent().closestRenderedPosition(affinity());
+    switch (granularity) {
+        case CHARACTER:
+            pos = pos.nextCharacterPosition();
+            break;
+        case WORD:
+            pos = pos.nextWordPosition();
+            break;
+        case LINE:
+            pos = pos.nextLinePosition(xPosForVerticalArrowNavigation(EXTENT));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyMovingRightForward(ETextGranularity granularity)
+{
+    m_modifyBiasSet = false;
+    Position pos;
+    switch (granularity) {
+        case CHARACTER:
+            if (state() == RANGE) 
+                pos = end().closestRenderedPosition(affinity());
+            else
+                pos = extent().closestRenderedPosition(affinity()).nextCharacterPosition();
+            break;
+        case WORD:
+            pos = extent().closestRenderedPosition(affinity()).nextWordPosition();
+            break;
+        case LINE:
+            pos = end().closestRenderedPosition(affinity()).nextLinePosition(xPosForVerticalArrowNavigation(END, state() == RANGE));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyExtendingLeftBackward(ETextGranularity granularity)
+{
+    if (!m_modifyBiasSet) {
+        m_modifyBiasSet = true;
+        assignBaseAndExtent(end(), start());
+    }
+    Position pos = extent().closestRenderedPosition(affinity());
+    switch (granularity) {
+        case CHARACTER:
+            pos = pos.previousCharacterPosition();
+            break;
+        case WORD:
+            pos = pos.previousWordPosition();
+            break;
+        case LINE:
+            pos = pos.previousLinePosition(xPosForVerticalArrowNavigation(EXTENT));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyMovingLeftBackward(ETextGranularity granularity)
+{
+    m_modifyBiasSet = false;
+    Position pos;
+    switch (granularity) {
+        case CHARACTER:
+            if (state() == RANGE) 
+                pos = start().closestRenderedPosition(affinity());
+            else
+                pos = extent().closestRenderedPosition(affinity()).previousCharacterPosition();
+            break;
+        case WORD:
+            pos = extent().closestRenderedPosition(affinity()).previousWordPosition();
+            break;
+        case LINE:
+            pos = start().closestRenderedPosition(affinity()).previousLinePosition(xPosForVerticalArrowNavigation(START, state() == RANGE));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
 bool Selection::modify(EAlter alter, EDirection dir, ETextGranularity granularity)
 {
     Position pos;
-    
+
     switch (dir) {
-        // EDIT FIXME: This needs to handle bidi
+        // EDIT FIXME: These need to handle bidi
         case RIGHT:
         case FORWARD:
-            if (alter == EXTEND) {
-                if (!m_modifyBiasSet) {
-                    m_modifyBiasSet = true;
-                    assignBaseAndExtent(start(), end());
-                }
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = extent().nextCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().nextWordPosition();
-                        break;
-                    case LINE:
-                        pos = extent().nextLinePosition(xPosForVerticalArrowNavigation(EXTENT));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
-            else {
-                m_modifyBiasSet = false;
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = (state() == RANGE) ? end() : extent().nextCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().nextWordPosition();
-                        break;
-                    case LINE:
-                        pos = end().nextLinePosition(xPosForVerticalArrowNavigation(END, state() == RANGE));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
+            if (alter == EXTEND)
+                pos = modifyExtendingRightForward(granularity);
+            else
+                pos = modifyMovingRightForward(granularity);
             break;
-        // EDIT FIXME: This needs to handle bidi
         case LEFT:
         case BACKWARD:
-            if (alter == EXTEND) {
-                if (!m_modifyBiasSet) {
-                    m_modifyBiasSet = true;
-                    assignBaseAndExtent(end(), start());
-                }
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = extent().previousCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().previousWordPosition();
-                        break;
-                    case LINE:
-                        pos = extent().previousLinePosition(xPosForVerticalArrowNavigation(EXTENT));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
-            else {
-                m_modifyBiasSet = false;
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = (state() == RANGE) ? start() : extent().previousCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().previousWordPosition();
-                        break;
-                    case LINE:
-                        pos = start().previousLinePosition(xPosForVerticalArrowNavigation(START, state() == RANGE));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
+            if (alter == EXTEND)
+                pos = modifyExtendingLeftBackward(granularity);
+            else
+                pos = modifyMovingLeftBackward(granularity);
             break;
     }
     
@@ -439,15 +470,25 @@ Range Selection::toRange() const
 
 void Selection::layoutCaret()
 {
-    if (isEmpty() || !start().node()->renderer()) {
+    if (state() != CARET) {
         m_caretX = m_caretY = m_caretSize = 0;
+        return;
     }
-    else {
-        // EDIT FIXME: Enhance call to pass along selection 
-        // upstream/downstream affinity to get the right position.
-        int w;
-        start().node()->renderer()->caretPos(start().offset(), true, m_caretX, m_caretY, w, m_caretSize);
+    
+    Position pos = start();
+    if (!pos.inRenderedContent())
+        pos = pos.closestRenderedPosition(affinity());
+
+    if (pos.isEmpty() || !pos.inRenderedContent()) {
+        m_caretX = m_caretY = m_caretSize = 0;
+        return;
     }
+    
+    // EDIT FIXME: Enhance call to pass along selection 
+    // upstream/downstream affinity to get the right position.
+    int w;
+    m_caretPosition = pos;
+    pos.node()->renderer()->caretPos(pos.offset(), true, m_caretX, m_caretY, w, m_caretSize);
 
     m_needsCaretLayout = false;
 }
@@ -503,13 +544,8 @@ void Selection::paintCaret(QPainter *p, const QRect &rect)
     if (m_state != CARET)
         return;
 
-    if (m_needsCaretLayout) {
-        Position pos = start();
-        if (!pos.inRenderedContent()) {
-            moveToRenderedContent();
-        }
+    if (m_needsCaretLayout)
         layoutCaret();
-    }
 
     QRect caretRect(m_caretX, m_caretY, 1, m_caretSize);
     if (caretRect.intersects(rect)) {
diff --git a/WebCore/khtml/editing/selection.h b/WebCore/khtml/editing/selection.h
index 39e3933..9eb67d4 100644
--- a/WebCore/khtml/editing/selection.h
+++ b/WebCore/khtml/editing/selection.h
@@ -50,12 +50,6 @@ public:
     enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
     enum ETextGranularity { CHARACTER, WORD, LINE, PARAGRAPH };
 
-    // These match the AppKit values for these concepts.
-    // From NSTextView.h:
-    // NSSelectionAffinityUpstream = 0
-    // NSSelectionAffinityDownstream = 1
-    enum EAffinity { UPSTREAM = 0, DOWNSTREAM = 1 };
-
     Selection();
     Selection(const Range &);
     Selection(const Position &);
@@ -87,6 +81,7 @@ public:
     Position extent() const { return m_extent; }
     Position start() const { return m_start; }
     Position end() const { return m_end; }
+    Position caretPosition() const { return m_caretPosition; }
 
     QRect getRepaintRect() const;
     void setNeedsLayout(bool flag=true);
@@ -124,6 +119,11 @@ private:
     void assignEnd(const Position &pos) { m_end = pos; }
     void assignStartAndEnd(const Position &start, const Position &end) { m_start = start; m_end = end; }
 
+    Position modifyExtendingRightForward(ETextGranularity);
+    Position modifyMovingRightForward(ETextGranularity);
+    Position modifyExtendingLeftBackward(ETextGranularity);
+    Position modifyMovingLeftBackward(ETextGranularity);
+
     void layoutCaret();
     void needsCaretRepaint();
     void paintCaret(QPainter *p, const QRect &rect);
@@ -139,10 +139,11 @@ private:
     EState m_state;               // the state of the selection
     EAffinity m_affinity;         // the upstream/downstream affinity of the selection
 
-    int m_caretX;                 // caret coordinates and size
+    int m_caretX;                 // caret coordinates, size, and position
     int m_caretY;
     int m_caretSize;
-
+    Position m_caretPosition;               
+    
     bool m_baseIsStart : 1;       // true if base node is before the extent node
     bool m_needsCaretLayout : 1;  // true if the caret position needs to be calculated
     bool m_modifyBiasSet : 1;     // true if the selection has been horizontally 
diff --git a/WebCore/khtml/rendering/render_block.cpp b/WebCore/khtml/rendering/render_block.cpp
index 1227efb..a978411 100644
--- a/WebCore/khtml/rendering/render_block.cpp
+++ b/WebCore/khtml/rendering/render_block.cpp
@@ -1309,9 +1309,9 @@ void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
     */
     if (paintAction == PaintActionForeground) {
         const Selection &s = document()->part()->selection();
-        NodeImpl *baseNode = s.base().node();
-        RenderObject *renderer = baseNode ? baseNode->renderer() : 0;
-        if (renderer && renderer->containingBlock() == this && baseNode->isContentEditable()) {
+        NodeImpl *caretNode = s.caretPosition().node();
+        RenderObject *renderer = caretNode ? caretNode->renderer() : 0;
+        if (renderer && renderer->containingBlock() == this && caretNode->isContentEditable()) {
             document()->part()->paintCaret(i.p, i.r);
             document()->part()->paintDragCaret(i.p, i.r);
         }
diff --git a/WebCore/khtml/xml/dom_position.cpp b/WebCore/khtml/xml/dom_position.cpp
index e958195..00962fd 100644
--- a/WebCore/khtml/xml/dom_position.cpp
+++ b/WebCore/khtml/xml/dom_position.cpp
@@ -237,6 +237,7 @@ Position Position::previousCharacterPosition() const
     PositionIterator it(*this);
 
     bool atStartOfLine = isFirstRenderedPositionOnLine();
+    bool rendered = inRenderedContent();
     
     while (!it.atStart()) {
         Position pos = it.previous();
@@ -244,7 +245,7 @@ Position Position::previousCharacterPosition() const
         if (pos.node()->rootEditableElement() != fromRootEditableElement)
             return *this;
 
-        if (atStartOfLine) {
+        if (atStartOfLine || !rendered) {
             if (pos.inRenderedContent())
                 return pos;
         }
@@ -264,6 +265,7 @@ Position Position::nextCharacterPosition() const
     PositionIterator it(*this);
 
     bool atEndOfLine = isLastRenderedPositionOnLine();
+    bool rendered = inRenderedContent();
     
     while (!it.atEnd()) {
         Position pos = it.next();
@@ -271,7 +273,7 @@ Position Position::nextCharacterPosition() const
         if (pos.node()->rootEditableElement() != fromRootEditableElement)
             return *this;
 
-        if (atEndOfLine) {
+        if (atEndOfLine || !rendered) {
             if (pos.inRenderedContent())
                 return pos;
         }
@@ -558,6 +560,42 @@ Position Position::equivalentShallowPosition() const
     return pos;
 }
 
+Position Position::closestRenderedPosition(EAffinity affinity) const
+{
+    if (inRenderedContent())
+        return *this;
+
+    Position pos;
+    
+    pos = affinity == UPSTREAM ? equivalentUpstreamPosition() : equivalentDownstreamPosition();
+    if (pos.inRenderedContent())
+        return pos;
+
+    pos = affinity == DOWNSTREAM ? equivalentDownstreamPosition() : equivalentUpstreamPosition();
+    if (pos.inRenderedContent())
+        return pos;
+    
+    pos = *this;
+    Position prev(previousCharacterPosition());    
+    while (prev != pos && prev.node()->inSameContainingBlockFlowElement(node())) {
+        if (prev.inRenderedContent())
+            return prev;
+        pos = prev;
+        prev = pos.previousCharacterPosition();
+    }
+    
+    pos = *this;
+    Position next(nextCharacterPosition());    
+    while (next != pos && next.node()->inSameContainingBlockFlowElement(node())) {
+        if (next.inRenderedContent())
+            return next;
+        pos = next;
+        next = pos.nextCharacterPosition();
+    }
+    
+    return Position();
+}
+
 bool Position::atStartOfContainingEditableBlock() const
 {
     return renderedOffset() == 0 && inFirstEditableInContainingEditableBlock();
diff --git a/WebCore/khtml/xml/dom_position.h b/WebCore/khtml/xml/dom_position.h
index f22ac39..8809134 100644
--- a/WebCore/khtml/xml/dom_position.h
+++ b/WebCore/khtml/xml/dom_position.h
@@ -31,6 +31,12 @@ namespace DOM {
 class ElementImpl;
 class NodeImpl;
 
+// These match the AppKit values for these concepts.
+// From NSTextView.h:
+// NSSelectionAffinityUpstream = 0
+// NSSelectionAffinityDownstream = 1
+enum EAffinity { UPSTREAM = 0, DOWNSTREAM = 1 };
+
 class Position
 {
 public:
@@ -62,6 +68,7 @@ public:
     Position equivalentDownstreamPosition() const;
     Position equivalentRangeCompliantPosition() const;
     Position equivalentShallowPosition() const;
+    Position closestRenderedPosition(EAffinity) const;
     bool atStartOfContainingEditableBlock() const;
     bool atStartOfRootEditableElement() const;
     bool inRenderedContent() const;
diff --git a/WebCore/khtml/xml/dom_selection.cpp b/WebCore/khtml/xml/dom_selection.cpp
index 9f68914..ef99b2d 100644
--- a/WebCore/khtml/xml/dom_selection.cpp
+++ b/WebCore/khtml/xml/dom_selection.cpp
@@ -120,6 +120,7 @@ Selection::Selection(const Selection &o)
         m_caretX = o.m_caretX;
         m_caretY = o.m_caretY;
         m_caretSize = o.m_caretSize;
+        m_caretPosition = o.m_caretPosition;
     }
 }
 
@@ -130,6 +131,7 @@ void Selection::init()
     m_caretX = 0;
     m_caretY = 0;
     m_caretSize = 0;
+    m_caretPosition = emptyPosition();
     m_baseIsStart = true;
     m_needsCaretLayout = true;
     m_modifyBiasSet = false;
@@ -194,92 +196,121 @@ void Selection::moveTo(const Position &base, const Position &extent)
     validate();
 }
 
+Position Selection::modifyExtendingRightForward(ETextGranularity granularity)
+{
+    if (!m_modifyBiasSet) {
+        m_modifyBiasSet = true;
+        assignBaseAndExtent(start(), end());
+    }
+    Position pos = extent().closestRenderedPosition(affinity());
+    switch (granularity) {
+        case CHARACTER:
+            pos = pos.nextCharacterPosition();
+            break;
+        case WORD:
+            pos = pos.nextWordPosition();
+            break;
+        case LINE:
+            pos = pos.nextLinePosition(xPosForVerticalArrowNavigation(EXTENT));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyMovingRightForward(ETextGranularity granularity)
+{
+    m_modifyBiasSet = false;
+    Position pos;
+    switch (granularity) {
+        case CHARACTER:
+            if (state() == RANGE) 
+                pos = end().closestRenderedPosition(affinity());
+            else
+                pos = extent().closestRenderedPosition(affinity()).nextCharacterPosition();
+            break;
+        case WORD:
+            pos = extent().closestRenderedPosition(affinity()).nextWordPosition();
+            break;
+        case LINE:
+            pos = end().closestRenderedPosition(affinity()).nextLinePosition(xPosForVerticalArrowNavigation(END, state() == RANGE));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyExtendingLeftBackward(ETextGranularity granularity)
+{
+    if (!m_modifyBiasSet) {
+        m_modifyBiasSet = true;
+        assignBaseAndExtent(end(), start());
+    }
+    Position pos = extent().closestRenderedPosition(affinity());
+    switch (granularity) {
+        case CHARACTER:
+            pos = pos.previousCharacterPosition();
+            break;
+        case WORD:
+            pos = pos.previousWordPosition();
+            break;
+        case LINE:
+            pos = pos.previousLinePosition(xPosForVerticalArrowNavigation(EXTENT));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
+Position Selection::modifyMovingLeftBackward(ETextGranularity granularity)
+{
+    m_modifyBiasSet = false;
+    Position pos;
+    switch (granularity) {
+        case CHARACTER:
+            if (state() == RANGE) 
+                pos = start().closestRenderedPosition(affinity());
+            else
+                pos = extent().closestRenderedPosition(affinity()).previousCharacterPosition();
+            break;
+        case WORD:
+            pos = extent().closestRenderedPosition(affinity()).previousWordPosition();
+            break;
+        case LINE:
+            pos = start().closestRenderedPosition(affinity()).previousLinePosition(xPosForVerticalArrowNavigation(START, state() == RANGE));
+            break;
+        case PARAGRAPH:
+            // not implemented
+            break;
+    }
+    return pos;
+}
+
 bool Selection::modify(EAlter alter, EDirection dir, ETextGranularity granularity)
 {
     Position pos;
-    
+
     switch (dir) {
-        // EDIT FIXME: This needs to handle bidi
+        // EDIT FIXME: These need to handle bidi
         case RIGHT:
         case FORWARD:
-            if (alter == EXTEND) {
-                if (!m_modifyBiasSet) {
-                    m_modifyBiasSet = true;
-                    assignBaseAndExtent(start(), end());
-                }
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = extent().nextCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().nextWordPosition();
-                        break;
-                    case LINE:
-                        pos = extent().nextLinePosition(xPosForVerticalArrowNavigation(EXTENT));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
-            else {
-                m_modifyBiasSet = false;
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = (state() == RANGE) ? end() : extent().nextCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().nextWordPosition();
-                        break;
-                    case LINE:
-                        pos = end().nextLinePosition(xPosForVerticalArrowNavigation(END, state() == RANGE));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
+            if (alter == EXTEND)
+                pos = modifyExtendingRightForward(granularity);
+            else
+                pos = modifyMovingRightForward(granularity);
             break;
-        // EDIT FIXME: This needs to handle bidi
         case LEFT:
         case BACKWARD:
-            if (alter == EXTEND) {
-                if (!m_modifyBiasSet) {
-                    m_modifyBiasSet = true;
-                    assignBaseAndExtent(end(), start());
-                }
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = extent().previousCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().previousWordPosition();
-                        break;
-                    case LINE:
-                        pos = extent().previousLinePosition(xPosForVerticalArrowNavigation(EXTENT));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
-            else {
-                m_modifyBiasSet = false;
-                switch (granularity) {
-                    case CHARACTER:
-                        pos = (state() == RANGE) ? start() : extent().previousCharacterPosition();
-                        break;
-                    case WORD:
-                        pos = extent().previousWordPosition();
-                        break;
-                    case LINE:
-                        pos = start().previousLinePosition(xPosForVerticalArrowNavigation(START, state() == RANGE));
-                        break;
-                    case PARAGRAPH:
-                        // not implemented
-                        break;
-                }
-            }
+            if (alter == EXTEND)
+                pos = modifyExtendingLeftBackward(granularity);
+            else
+                pos = modifyMovingLeftBackward(granularity);
             break;
     }
     
@@ -439,15 +470,25 @@ Range Selection::toRange() const
 
 void Selection::layoutCaret()
 {
-    if (isEmpty() || !start().node()->renderer()) {
+    if (state() != CARET) {
         m_caretX = m_caretY = m_caretSize = 0;
+        return;
     }
-    else {
-        // EDIT FIXME: Enhance call to pass along selection 
-        // upstream/downstream affinity to get the right position.
-        int w;
-        start().node()->renderer()->caretPos(start().offset(), true, m_caretX, m_caretY, w, m_caretSize);
+    
+    Position pos = start();
+    if (!pos.inRenderedContent())
+        pos = pos.closestRenderedPosition(affinity());
+
+    if (pos.isEmpty() || !pos.inRenderedContent()) {
+        m_caretX = m_caretY = m_caretSize = 0;
+        return;
     }
+    
+    // EDIT FIXME: Enhance call to pass along selection 
+    // upstream/downstream affinity to get the right position.
+    int w;
+    m_caretPosition = pos;
+    pos.node()->renderer()->caretPos(pos.offset(), true, m_caretX, m_caretY, w, m_caretSize);
 
     m_needsCaretLayout = false;
 }
@@ -503,13 +544,8 @@ void Selection::paintCaret(QPainter *p, const QRect &rect)
     if (m_state != CARET)
         return;
 
-    if (m_needsCaretLayout) {
-        Position pos = start();
-        if (!pos.inRenderedContent()) {
-            moveToRenderedContent();
-        }
+    if (m_needsCaretLayout)
         layoutCaret();
-    }
 
     QRect caretRect(m_caretX, m_caretY, 1, m_caretSize);
     if (caretRect.intersects(rect)) {
diff --git a/WebCore/khtml/xml/dom_selection.h b/WebCore/khtml/xml/dom_selection.h
index 39e3933..9eb67d4 100644
--- a/WebCore/khtml/xml/dom_selection.h
+++ b/WebCore/khtml/xml/dom_selection.h
@@ -50,12 +50,6 @@ public:
     enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
     enum ETextGranularity { CHARACTER, WORD, LINE, PARAGRAPH };
 
-    // These match the AppKit values for these concepts.
-    // From NSTextView.h:
-    // NSSelectionAffinityUpstream = 0
-    // NSSelectionAffinityDownstream = 1
-    enum EAffinity { UPSTREAM = 0, DOWNSTREAM = 1 };
-
     Selection();
     Selection(const Range &);
     Selection(const Position &);
@@ -87,6 +81,7 @@ public:
     Position extent() const { return m_extent; }
     Position start() const { return m_start; }
     Position end() const { return m_end; }
+    Position caretPosition() const { return m_caretPosition; }
 
     QRect getRepaintRect() const;
     void setNeedsLayout(bool flag=true);
@@ -124,6 +119,11 @@ private:
     void assignEnd(const Position &pos) { m_end = pos; }
     void assignStartAndEnd(const Position &start, const Position &end) { m_start = start; m_end = end; }
 
+    Position modifyExtendingRightForward(ETextGranularity);
+    Position modifyMovingRightForward(ETextGranularity);
+    Position modifyExtendingLeftBackward(ETextGranularity);
+    Position modifyMovingLeftBackward(ETextGranularity);
+
     void layoutCaret();
     void needsCaretRepaint();
     void paintCaret(QPainter *p, const QRect &rect);
@@ -139,10 +139,11 @@ private:
     EState m_state;               // the state of the selection
     EAffinity m_affinity;         // the upstream/downstream affinity of the selection
 
-    int m_caretX;                 // caret coordinates and size
+    int m_caretX;                 // caret coordinates, size, and position
     int m_caretY;
     int m_caretSize;
-
+    Position m_caretPosition;               
+    
     bool m_baseIsStart : 1;       // true if base node is before the extent node
     bool m_needsCaretLayout : 1;  // true if the caret position needs to be calculated
     bool m_modifyBiasSet : 1;     // true if the selection has been horizontally 
diff --git a/WebCore/kwq/WebCoreBridge.mm b/WebCore/kwq/WebCoreBridge.mm
index 3c306cd..10e6965 100644
--- a/WebCore/kwq/WebCoreBridge.mm
+++ b/WebCore/kwq/WebCoreBridge.mm
@@ -1395,7 +1395,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     DocumentImpl *doc = startContainer->getDocument();
     doc->updateLayout();
     Selection selection(Position(startContainer, [range startOffset]), Position(endContainer, [range endOffset]));
-    selection.setAffinity(static_cast<Selection::EAffinity>(selectionAffinity));
+    selection.setAffinity(static_cast<DOM::EAffinity>(selectionAffinity));
     _part->setSelection(selection);
 }
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list