WebCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Nov 2004 11:19:25 +0000 (11:19 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Nov 2004 11:19:25 +0000 (11:19 +0000)
        Reviewed by Dave Hyatt (when I originally coded it).

WebCore part of fix for:

<rdar://problem/3759187> REGRESSION (Mail): implement firstRectForCharacterRange:

        * kwq/WebCoreBridge.h:
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge firstRectForDOMRange:]): New method to compute the rect for a
DOMRange, or if the range is split into multiple lines, the rect for the part on
the first line only.

        * khtml/rendering/render_object.cpp:
        (RenderObject::caretRect): Added extraWidthToEndOfLine parameter and ditto
for the overrides below.
        * khtml/rendering/render_object.h:
        * khtml/rendering/render_box.cpp:
        (RenderBox::caretRect):
        * khtml/rendering/render_box.h:
        * khtml/rendering/render_br.cpp:
        (RenderBR::caretRect):
        * khtml/rendering/render_br.h:
        * khtml/rendering/render_flow.cpp:
        (RenderFlow::caretRect):
        * khtml/rendering/render_flow.h:
        * khtml/rendering/render_text.cpp:
        (RenderText::caretRect):

WebKit:

        Reviewed by Dave Hyatt (when I originally coded it).

        Redid WebKit part of fix for:

        <rdar://problem/3759187> REGRESSION (Mail): implement firstRectForCharacterRange:

        * WebView.subproj/WebHTMLView.m:
        (-[WebHTMLView firstRectForCharacterRange:]): Call the appropriate new bridge method,
        and translate to screen coordinates.

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

15 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/rendering/render_box.cpp
WebCore/khtml/rendering/render_box.h
WebCore/khtml/rendering/render_br.cpp
WebCore/khtml/rendering/render_br.h
WebCore/khtml/rendering/render_flow.cpp
WebCore/khtml/rendering/render_flow.h
WebCore/khtml/rendering/render_object.cpp
WebCore/khtml/rendering/render_object.h
WebCore/khtml/rendering/render_text.cpp
WebCore/khtml/rendering/render_text.h
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/WebView.subproj/WebHTMLView.m

index 5cb33f6..6f73f30 100644 (file)
@@ -1,3 +1,33 @@
+2004-11-02  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Dave Hyatt (when I originally coded it).
+
+       WebCore part of fix for:
+
+       <rdar://problem/3759187> REGRESSION (Mail): implement firstRectForCharacterRange:
+       
+        * kwq/WebCoreBridge.h:
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge firstRectForDOMRange:]): New method to compute the rect for a
+       DOMRange, or if the range is split into multiple lines, the rect for the part on
+       the first line only.
+       
+        * khtml/rendering/render_object.cpp:
+        (RenderObject::caretRect): Added extraWidthToEndOfLine parameter and ditto
+       for the overrides below.
+        * khtml/rendering/render_object.h:
+        * khtml/rendering/render_box.cpp:
+        (RenderBox::caretRect):
+        * khtml/rendering/render_box.h:
+        * khtml/rendering/render_br.cpp:
+        (RenderBR::caretRect):
+        * khtml/rendering/render_br.h:
+        * khtml/rendering/render_flow.cpp:
+        (RenderFlow::caretRect):
+        * khtml/rendering/render_flow.h:
+        * khtml/rendering/render_text.cpp:
+        (RenderText::caretRect):
+
 2004-11-02  Ken Kocienda  <kocienda@apple.com>
 
         Reviewed by Hyatt
index 63ec06a..a6d2437 100644 (file)
@@ -1479,7 +1479,7 @@ void RenderBox::calcAbsoluteVertical()
 
 }
 
-QRect RenderBox::caretRect(int offset, EAffinity affinity)
+QRect RenderBox::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
 {
     // FIXME: Is it OK to check only first child instead of picking
     // right child based on offset? Is it OK to pass the same offset
@@ -1488,7 +1488,7 @@ QRect RenderBox::caretRect(int offset, EAffinity affinity)
     // propagate it downwards to its children, someone will feel responsible
     RenderObject *child = firstChild();
     if (child) {
-        QRect result = child->caretRect(offset, affinity);
+        QRect result = child->caretRect(offset, affinity, extraWidthToEndOfLine);
         // FIXME: in-band signalling!
         if (result.isEmpty())
             return result;
@@ -1532,6 +1532,9 @@ QRect RenderBox::caretRect(int offset, EAffinity affinity)
         return QRect();
     }
 
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = m_width - _x;
+
     return QRect(_x, _y, 1, height);
 }
 
index 7011577..079cbb3 100644 (file)
@@ -130,7 +130,7 @@ public:
 
     virtual RenderLayer* layer() const { return m_layer; }
     
-    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM);
+    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM, int *extraWidthToEndOfLine = 0);
 
     virtual void paintBackgroundExtended(QPainter *p, const QColor &c, CachedImage *bg, int clipy, int cliph,
                                          int _tx, int _ty, int w, int height,
index ed34ddc..3be8f9d 100644 (file)
@@ -108,7 +108,7 @@ Position RenderBR::positionForCoordinates(int _x, int _y, EAffinity *affinity)
     return Position(element(), 0);
 }
 
-QRect RenderBR::caretRect(int offset, EAffinity affinity)
+QRect RenderBR::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
 {
     // EDIT FIXME: This does not work yet. Some other changes are need before
     // an accurate position can be determined.
@@ -116,6 +116,9 @@ QRect RenderBR::caretRect(int offset, EAffinity affinity)
     int absx, absy;
     absolutePosition(absx,absy);
 
+   if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = containingBlockWidth() - xPos();
     // FIXME: an older version of this code wasn't setting width at
     // all, using the default of 1...
     return QRect(xPos() + absx, yPos() + absy, 1, lineHeight(false));
index 07dd5cf..0e9c533 100644 (file)
@@ -66,7 +66,7 @@ public:
     virtual unsigned long caretMaxRenderedOffset() const;
     
     virtual DOM::Position positionForCoordinates(int x, int y, EAffinity * = 0);
-    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM);
+    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM, int *extraWidthToEndOfLine = 0);
 
     virtual InlineBox *inlineBox(long offset, EAffinity affinity = UPSTREAM);
     
index 5a8b14e..8129961 100644 (file)
@@ -519,11 +519,11 @@ int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf)
     return left;
 }
 
-QRect RenderFlow::caretRect(int offset, EAffinity affinity)
+QRect RenderFlow::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
 {
     if (firstChild() || style()->display() == INLINE) {
         // Do the normal calculation
-        return RenderContainer::caretRect(offset, affinity);
+        return RenderContainer::caretRect(offset, affinity, extraWidthToEndOfLine);
     }
 
     // This is a special case:
@@ -564,6 +564,22 @@ QRect RenderFlow::caretRect(int offset, EAffinity affinity)
     
     _y = 0;
     
+
+    if (extraWidthToEndOfLine) {
+        if (isRenderBlock()) {
+            *extraWidthToEndOfLine = this->width() - (_x + width);
+        } else {
+            int myRight = _x + width;
+            int ignore;
+            absolutePosition(myRight, ignore);
+            
+            int containerRight = containingBlock()->xPos() + containingBlockWidth();
+            absolutePosition(containerRight, ignore);
+            
+            *extraWidthToEndOfLine = containerRight - myRight;
+        }
+    }
+
     int absx, absy;
     absolutePosition(absx, absy, false);
     _x += absx + paddingLeft() + borderLeft();
index 815d4f2..19696bd 100644 (file)
@@ -81,7 +81,7 @@ public:
     virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
     virtual int leftmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
     
-    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM);
+    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM, int *extraWidthToEndOfLine = 0);
 
 protected:
     // An inline can be split with blocks occurring in between the inline content.
index 0fb4b0a..775a0b3 100644 (file)
@@ -1651,8 +1651,11 @@ bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
     }
 }
 
-QRect RenderObject::caretRect(int, EAffinity)
+QRect RenderObject::caretRect(int, EAffinity, int *extraWidthToEndOfLine)
 {
+   if (extraWidthToEndOfLine)
+       *extraWidthToEndOfLine = 0;
+
     return QRect();
 }
 
index 0474a03..7b4e146 100644 (file)
@@ -773,8 +773,10 @@ public:
      * @param offset zero-based offset determining position within the render object.
      * @param override @p true if input overrides existing characters,
      * @p false if it inserts them. The width of the caret depends on this one.
+     * @param extraWidthToEndOfLine optional out arg to give extra width to end of line -
+     * useful for character range rect computations
      */
-    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM);
+    virtual QRect caretRect(int offset, EAffinity affinity = UPSTREAM, int *extraWidthToEndOfLine = 0);
 
     virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const { return 0; }
     virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const { return 0; }
index f9cb05d..1d67d13 100644 (file)
@@ -703,7 +703,7 @@ static RenderObject *firstRendererOnNextLine(InlineBox *box)
     return firstChild->object();
 }
 
-QRect RenderText::caretRect(int offset, EAffinity affinity)
+QRect RenderText::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
 {
     if (!firstTextBox() || stringLength() == 0) {
         return QRect();
@@ -749,6 +749,11 @@ QRect RenderText::caretRect(int offset, EAffinity affinity)
         left += fm.rightBearing(*(str->s + box->m_start + offset));
 #endif
 
+    // FIXME: should we use the width of the root inline box or the
+    // width of the containing block for this?
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = (box->root()->width() + box->root()->xPos()) - (left + 1);
+
     int absx, absy;
     absolutePosition(absx,absy);
     left += absx;
index 61b6a7e..5d661a0 100644 (file)
@@ -225,7 +225,7 @@ public:
     virtual SelectionState selectionState() const {return m_selectionState;}
     virtual void setSelectionState(SelectionState s);
     virtual QRect selectionRect();
-    virtual QRect caretRect(int offset, EAffinity affinity);
+    virtual QRect caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine = 0);
     void posOfChar(int ch, int &x, int &y);
 
     virtual int marginLeft() const { return style()->marginLeft().minWidth(0); }
index 2041a7e..29ba729 100644 (file)
@@ -276,6 +276,7 @@ typedef enum {
 - (void)centerSelectionInVisibleArea;
 - (NSImage *)selectionImage;
 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity;
+- (NSRect)firstRectForDOMRange:(DOMRange *)range;
 
 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity;
 - (DOMRange *)selectedDOMRange;
index 96f1bf7..074512a 100644 (file)
@@ -1208,6 +1208,26 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
 {
     return [node _nodeImpl]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
 }
+- (NSRect)firstRectForDOMRange:(DOMRange *)range
+{
+    int extraWidthToEndOfLine = 0;
+    QRect startCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range startOffset], UPSTREAM, &extraWidthToEndOfLine);
+    QRect endCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range endOffset], UPSTREAM);
+
+    if (startCaretRect.y() == endCaretRect.y()) {
+        // start and end are on the same line
+        return QRect(MIN(startCaretRect.x(), endCaretRect.x()), 
+                     startCaretRect.y(), 
+                     abs(endCaretRect.x() - startCaretRect.x()),
+                     MAX(startCaretRect.height(), endCaretRect.height()));
+    }
+
+    // start and end aren't on the same line, so go from start to the end of its line
+    return QRect(startCaretRect.x(), 
+                 startCaretRect.y(),
+                 startCaretRect.width() + extraWidthToEndOfLine,
+                 startCaretRect.height());
+}
 
 - (NSImage *)selectionImage
 {
index 247fad4..49d3207 100644 (file)
@@ -1,3 +1,15 @@
+2004-11-02  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Dave Hyatt (when I originally coded it).
+
+        Redid WebKit part of fix for:
+
+        <rdar://problem/3759187> REGRESSION (Mail): implement firstRectForCharacterRange:
+       
+        * WebView.subproj/WebHTMLView.m:
+        (-[WebHTMLView firstRectForCharacterRange:]): Call the appropriate new bridge method,
+        and translate to screen coordinates.
+
 2004-11-02  John Sullivan  <sullivan@apple.com>
 
         Reviewed by Hyatt.
index 08bd499..01b2c26 100644 (file)
@@ -4148,8 +4148,25 @@ static DOMRange *unionDOMRanges(DOMRange *a, DOMRange *b)
 
 - (NSRect)firstRectForCharacterRange:(NSRange)theRange
 {
-    ERROR("TEXTINPUT: firstRectForCharacterRange: not yet implemented");
-    return NSMakeRect(0,0,0,0);
+    NSLog(@"location: %d  length: %d\n", theRange.location, theRange.length);
+
+    if (![self hasMarkedText]) {
+        return NSMakeRect(0,0,0,0);
+    }
+
+    WebBridge *bridge = [self _bridge];
+
+    DOMRange *rectRange = [[bridge DOMDocument] createRange];
+    DOMRange *markedRange = [bridge markedTextDOMRange];
+    [rectRange setStart:[markedRange startContainer] :theRange.location];
+    [rectRange setEnd:[markedRange startContainer] :(theRange.location + theRange.length)];
+
+    NSRect resultRect = [self convertRect:[bridge firstRectForDOMRange:rectRange] toView:nil];
+    resultRect.origin = [[self window] convertBaseToScreen:resultRect.origin];
+
+    NSLog(@"(%d,%d) %dx%d\n", (int)resultRect.origin.x, (int)resultRect.origin.y, (int)resultRect.size.width, (int)resultRect.size.height);
+
+    return resultRect;
 }
 
 - (NSRange)selectedRange