WebCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Sep 2004 21:02:08 +0000 (21:02 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Sep 2004 21:02:08 +0000 (21:02 +0000)
        Reviewed by Dave.

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.

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@7500 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 8478f1f..af9a4af 100644 (file)
@@ -1,3 +1,33 @@
+2004-09-08  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Dave.
+
+       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-09-06  Darin Adler  <darin@apple.com>
 
         Reviewed by Ken.
index 260c80b..fd78cfa 100644 (file)
@@ -1480,7 +1480,7 @@ void RenderBox::calcAbsoluteVertical()
 
 }
 
-QRect RenderBox::caretRect(int offset, bool override)
+QRect RenderBox::caretRect(int offset, bool override, 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
@@ -1489,7 +1489,7 @@ QRect RenderBox::caretRect(int offset, bool override)
     // propagate it downwards to its children, someone will feel responsible
     RenderObject *child = firstChild();
     if (child) {
-        QRect result = child->caretRect(offset, override);
+        QRect result = child->caretRect(offset, override, extraWidthToEndOfLine);
         // FIXME: in-band signalling!
         if (result.x() != -1)
             return result;
@@ -1534,6 +1534,9 @@ QRect RenderBox::caretRect(int offset, bool override)
         _x = _y = -1;
     }
 
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = m_width - width;
+
     return QRect(_x, _y, width, height);
 }
 
index bb84ff2..4a35c5a 100644 (file)
@@ -130,7 +130,7 @@ public:
 
     virtual RenderLayer* layer() const { return m_layer; }
     
-    virtual QRect caretRect(int offset, bool override);
+    virtual QRect caretRect(int offset, bool override, 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 ceed127..b1d3fa1 100644 (file)
@@ -112,11 +112,14 @@ Position RenderBR::positionForCoordinates(int _x, int _y)
     return Position(element(), 0);
 }
 
-QRect RenderBR::caretRect(int offset, bool override)
+QRect RenderBR::caretRect(int offset, bool override, int *extraWidthToEndOfLine)
 {
     // EDIT FIXME: This does not work yet. Some other changes are need before
     // an accurate position can be determined.
 
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = containingBlockWidth();
+
     int absx, absy;
     absolutePosition(absx,absy);
 
index 30b22ea..cf72907 100644 (file)
@@ -69,7 +69,7 @@ public:
     virtual unsigned long caretMaxRenderedOffset() const;
     
     virtual DOM::Position positionForCoordinates(int _x, int _y);
-    virtual QRect caretRect(int offset, bool override);
+    virtual QRect caretRect(int offset, bool override, int *extraWidthToEndOfLine = 0);
 
     virtual InlineBox *inlineBox(long offset);
     
index bebbf65..331699e 100644 (file)
@@ -483,11 +483,11 @@ int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf)
     return left;
 }
 
-QRect RenderFlow::caretRect(int offset, bool override)
+QRect RenderFlow::caretRect(int offset, bool override, int *extraWidthToEndOfLine)
 {
     if (firstChild() || style()->display() == INLINE) {
         // Do the normal calculation
-        return RenderContainer::caretRect(offset, override);
+        return RenderContainer::caretRect(offset, override, extraWidthToEndOfLine);
     }
 
     // This is a special case:
@@ -527,6 +527,21 @@ QRect RenderFlow::caretRect(int offset, bool override)
     }
     
     _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);
index 9815241..157154a 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, bool override);
+    virtual QRect caretRect(int offset, bool override, int *extraWidthToEndOfLine = 0);
 
 protected:
     // An inline can be split with blocks occurring in between the inline content.
index bb8015f..2cbeec5 100644 (file)
@@ -1590,8 +1590,11 @@ bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
     }
 }
 
-QRect RenderObject::caretRect(int /*offset*/, bool /*override*/)
+QRect RenderObject::caretRect(int /*offset*/, bool /*override*/, int *extraWidthToEndOfLine)
 {
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = 0;
+
     // the caret has a default width of one pixel. If you want
     // to check for validity, only test the x-coordinate for >= 0.
     return QRect(-1, -1, 1, -1);
index 11d1e28..e9c53b3 100644 (file)
@@ -708,8 +708,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, bool override);
+    virtual QRect caretRect(int offset, bool override, 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 a978f69..4d9a34a 100644 (file)
@@ -650,7 +650,7 @@ Position RenderText::positionForCoordinates(int _x, int _y)
     return Position(element(), 0);
 }
 
-QRect RenderText::caretRect(int offset, bool override)
+QRect RenderText::caretRect(int offset, bool override, int *extraWidthToEndOfLine)
 {
     if (!firstTextBox() || stringLength() == 0) {
         return QRect(-1, -1, 1, -1);
@@ -683,6 +683,11 @@ QRect RenderText::caretRect(int offset, bool override)
         _x += 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()) - (_x + 1);
+
     int absx, absy;
     absolutePosition(absx,absy);
     _x += absx;
index ced3252..a53509c 100644 (file)
@@ -212,7 +212,7 @@ public:
 
     virtual SelectionState selectionState() const {return m_selectionState;}
     virtual void setSelectionState(SelectionState s) {m_selectionState = s; }
-    virtual QRect caretRect(int offset, bool override);
+    virtual QRect caretRect(int offset, bool override, int *extraWidthToEndOfLine = 0);
     void posOfChar(int ch, int &x, int &y);
 
     virtual short marginLeft() const { return style()->marginLeft().minWidth(0); }
index 2109b3a..80ac7f2 100644 (file)
@@ -257,6 +257,7 @@ typedef enum {
 - (NSRect)visibleSelectionRect;
 - (NSImage *)selectionImage;
 - (NSRect)caretRectAtNode:(DOMNode *)node offset:(int)offset;
+- (NSRect)firstRectForDOMRange:(DOMRange *)range;
 
 - (void)setSelectedDOMRange:(DOMRange *)range affinity:(NSSelectionAffinity)selectionAffinity;
 - (DOMRange *)selectedDOMRange;
index 1c972e7..9515ce3 100644 (file)
@@ -1178,6 +1178,28 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     return [node _nodeImpl]->renderer()->caretRect(offset, true);
 }
 
+- (NSRect)firstRectForDOMRange:(DOMRange *)range
+{
+    int extraWidthToEndOfLine = 0;
+    QRect startCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range startOffset], true, &extraWidthToEndOfLine);
+    QRect endCaretRect = [[range startContainer] _nodeImpl]->renderer()->caretRect([range endOffset], true);
+
+    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
 {
     return _part->selectionImage();
index 25935d3..869bdc1 100644 (file)
@@ -1,3 +1,15 @@
+2004-09-08  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Dave.
+
+       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-09-09  Darin Adler  <darin@apple.com>
 
         Reviewed by Ken.
index 7196e09..be81fe8 100644 (file)
@@ -3834,8 +3834,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 markedDOMRange];
+    [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