WebCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Aug 2004 00:21:04 +0000 (00:21 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 11 Aug 2004 00:21:04 +0000 (00:21 +0000)
        Reviewed by Trey.

WebCore part of:

- made basic marked text highlighting work to complete basic level of <rdar://problem/3704359> input method support not yet implemented for HTML editing

        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge setMarkedDOMRange:]): Added this new call to support storing
a marked range in WebCore. The provided DOMRange must start and end in the same
node, which must be a text node.
        (-[WebCoreBridge markedDOMRange]): New call to get the marked range.
        (-[WebCoreBridge clearMarkedDOMRange]): New call to clear the marked range.
        * kwq/WebCoreBridge.h: Prototype new methods.
        * kwq/KWQKHTMLPart.mm:
        (KWQKHTMLPart::markedRange): Implementation of WebCore call above.
        (KWQKHTMLPart::setMarkedRange): Implementation of WebCore call above -
store the marked range, and repaint new and old nodes if needed.
        (KWQKHTMLPart::clear): Clear marked range.
        * kwq/KWQKHTMLPart.h: Prototype new methods.
        * khtml/rendering/render_text.cpp:
        (InlineTextBox::paintMarkedTextBackground): New method to paint the background
for marked text, modeled on paintSelection.
(RenderText::paint): Optionally handle painting marked text
background as well as selection background in the marked text
pass.
        * khtml/rendering/render_text.h: Prototype new method.

WebKit:

        Reviewed by Trey.

WebKit part of:

- made basic marked text highlighting work to complete basic level of <rdar://problem/3704359> input method support not yet implemented for HTML editing

        * WebView.subproj/WebHTMLView.m:
        (-[WebHTMLView markedRange]): Use new bridge calls instead of internal marked range storage.
        (-[WebHTMLView hasMarkedText]): Likewise.
        (-[WebHTMLView unmarkText]): Likewise.
        (-[WebHTMLView _selectMarkedText]): Likewise.
        (-[WebHTMLView _selectRangeInMarkedText:]): Likewise.
        (-[WebHTMLView _selectionIsInsideMarkedText]): Likewise.
        (-[WebHTMLView _updateSelectionForInputManager]): Likewise.
        (-[WebHTMLView setMarkedText:selectedRange:]): Use direct bridge call instead
of private _selectMarkedDOMRange: method, which would now be trivial.
        * WebView.subproj/WebHTMLViewInternal.h: Remove unneeded

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/rendering/render_text.cpp
WebCore/khtml/rendering/render_text.h
WebCore/kwq/KWQKHTMLPart.h
WebCore/kwq/KWQKHTMLPart.mm
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/WebView.subproj/WebHTMLView.m
WebKit/WebView.subproj/WebHTMLViewInternal.h

index 8239e6d..867c53b 100644 (file)
@@ -1,3 +1,32 @@
+2004-08-09  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Trey.
+
+       WebCore part of:
+
+       - made basic marked text highlighting work to complete basic level of <rdar://problem/3704359> input method support not yet implemented for HTML editing
+
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge setMarkedDOMRange:]): Added this new call to support storing
+       a marked range in WebCore. The provided DOMRange must start and end in the same
+       node, which must be a text node.
+        (-[WebCoreBridge markedDOMRange]): New call to get the marked range. 
+        (-[WebCoreBridge clearMarkedDOMRange]): New call to clear the marked range.
+        * kwq/WebCoreBridge.h: Prototype new methods.
+        * kwq/KWQKHTMLPart.mm:
+        (KWQKHTMLPart::markedRange): Implementation of WebCore call above.
+        (KWQKHTMLPart::setMarkedRange): Implementation of WebCore call above -
+       store the marked range, and repaint new and old nodes if needed.
+        (KWQKHTMLPart::clear): Clear marked range.
+        * kwq/KWQKHTMLPart.h: Prototype new methods.
+        * khtml/rendering/render_text.cpp:
+        (InlineTextBox::paintMarkedTextBackground): New method to paint the background
+       for marked text, modeled on paintSelection.
+       (RenderText::paint): Optionally handle painting marked text
+       background as well as selection background in the marked text
+       pass.
+        * khtml/rendering/render_text.h: Prototype new method.
+
 2004-08-10  Darin Adler  <darin@apple.com>
 
         Reviewed by Dave.
index 42fdf42..611a9e0 100644 (file)
@@ -28,6 +28,7 @@
 #include "rendering/render_object.h"
 #include "rendering/render_text.h"
 #include "rendering/break_lines.h"
+#include "dom/dom2_range.h"
 #include "xml/dom_nodeimpl.h"
 #include "xml/dom_docimpl.h"
 #include "xml/dom_position.h"
@@ -35,6 +36,8 @@
 
 #include "misc/loader.h"
 
+#include "khtml_part.h"
+
 #include <qpainter.h>
 #include <kdebug.h>
 #include <assert.h>
@@ -217,6 +220,65 @@ void InlineTextBox::paintSelection(const Font *f, RenderText *text, QPainter *p,
     p->restore();
 }
 
+#if APPLE_CHANGES
+void InlineTextBox::paintMarkedTextBackground(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos)
+{
+    int offset = m_start;
+    int sPos = kMax(startPos - offset, 0);
+    int ePos = kMin(endPos - offset, (int)m_len);
+
+    if (sPos >= ePos)
+        return;
+
+    p->save();
+
+    QColor c = QColor(225, 221, 85);
+    
+    p->setPen(c); // Don't draw text at all!
+    
+    // Do the calculations to draw marked text background as tall as the line.
+    // Use the bottom of the line above as the y position (if there is one, 
+    // otherwise use the top of this renderer's line) and the height of the line as the height. 
+    // This mimics Cocoa.
+    RenderBlock *cb = object()->containingBlock();
+
+    int y = 0;
+    if (root()->prevRootBox())
+        y = root()->prevRootBox()->bottomOverflow();
+    else
+        y = root()->topOverflow();
+
+    int h = root()->bottomOverflow() - y;
+
+    int x = m_x;
+    int minX = x;
+    int maxX = x;
+
+    // Extend selection to the start of the line if:
+    // 1. The starting point of the selection is at or beyond the start of the text box; and
+    // 2. This box is the first box on the line; and
+    // 3. There is a another line before this one (first lines have special behavior;
+    //    the selection never extends on the first line); and 
+    // 4. The last leaf renderer on the previous line is selected.
+    RenderObject *prevLineLastLeaf = root()->prevRootBox() ? root()->prevRootBox()->lastLeafChild()->object() : 0;
+    if (startPos <= m_start && root()->firstLeafChild() == this && root()->prevRootBox() && prevLineLastLeaf && 
+        prevLineLastLeaf->selectionState() != RenderObject::SelectionNone)
+        minX = kMax(cb->leftOffset(y), cb->leftOffset(root()->blockHeight()));
+        
+    // Extend selection to the end of the line if:
+    // 1. The ending point of the selection is at or beyond the end of the text box; and
+    // 2. There is a another line after this one (last lines have special behavior;
+    //    the selection never extends on the last line); and 
+    // 3. The last leaf renderer of the root box is this box.
+    if (endPos >= m_start + m_len && root()->nextRootBox() && root()->lastLeafChild() == this)
+        maxX = kMin(cb->rightOffset(y), cb->rightOffset(root()->blockHeight()));
+    
+    f->drawHighlightForText(p, x + tx, minX + tx, maxX + tx, y + ty, h, text->str->s, text->str->l, m_start, m_len,
+               m_toAdd, m_reversed ? QPainter::RTL : QPainter::LTR, style->visuallyOrdered(), sPos, ePos, c);
+    p->restore();
+}
+#endif
+
 #ifdef APPLE_CHANGES
 void InlineTextBox::paintDecoration( QPainter *pt, int _tx, int _ty, int deco)
 {
@@ -728,10 +790,14 @@ void RenderText::paint(PaintInfo& i, int tx, int ty)
     InlineTextBox* startBox = s;
     QValueList<DocumentMarker> markers = document()->markersForNode(node());
     QValueListIterator <DocumentMarker> markerIt = markers.begin();
-    for (int pass = 0; pass < (haveSelection ? 2 : 1); pass++) {
+    Range markedTextRange = KWQ(document()->part())->markedRange();
+    bool haveMarkedText = markedTextRange.handle() != 0 && markedTextRange.startContainer() == node();
+
+    for (int pass = 0; pass < (haveSelection || haveMarkedText ? 2 : 1); pass++) {
         s = startBox;
         bool drawSelectionBackground = haveSelection && pass == 0 && i.phase != PaintActionSelection;
-        bool drawText = !haveSelection || pass == 1;
+        bool drawMarkedTextBackground = haveMarkedText && pass == 0 && i.phase != PaintActionSelection;
+        bool drawText = !(haveSelection || haveMarkedText) || pass == 1;
 #endif
 
     // run until we find one that is outside the range, then we
@@ -925,11 +991,18 @@ void RenderText::paint(PaintInfo& i, int tx, int ty)
 #endif
 
 #if APPLE_CHANGES
+        if (drawMarkedTextBackground && !isPrinting)
+           s->paintMarkedTextBackground(font, this, p, _style, tx, ty, markedTextRange.startOffset(), markedTextRange.endOffset());
+
+#endif
+
+#if APPLE_CHANGES
         if (drawSelectionBackground)
 #endif
         if (!isPrinting && (selectionState() != SelectionNone))
             s->paintSelection(font, this, p, _style, tx, ty, startPos, endPos);
 
+
 #ifdef BIDI_DEBUG
         {
             int h = lineHeight( false ) + paddingTop() + paddingBottom() + borderTop() + borderBottom();
index 79d8361..90dd36a 100644 (file)
@@ -102,6 +102,9 @@ public:
     
     void paintDecoration( QPainter *pt, int _tx, int _ty, int decoration);
     void paintSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos);
+#if APPLE_CHANGES
+    void paintMarkedTextBackground(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos);
+#endif
     void paintMarker(QPainter *pt, int _tx, int _ty, DOM::DocumentMarker marker);
 
     virtual long caretMinOffset() const;
index 20e1c82..bc5b5e5 100644 (file)
@@ -327,6 +327,8 @@ public:
     // Implementation of CSS property -khtml-user-drag == auto
     bool shouldDragAutoNode(DOM::NodeImpl*, int x, int y) const;
 
+    DOM::Range markedRange() const;
+    void setMarkedRange(const DOM::Range &);
 private:
     virtual void khtmlMousePressEvent(khtml::MousePressEvent *);
     virtual void khtmlMouseDoubleClickEvent(khtml::MouseDoubleClickEvent *);
@@ -409,6 +411,8 @@ private:
     KWQClipboard *_dragClipboard;   // used on only the source side of dragging
     
     mutable DOM::Node _elementToDraw;
+
+    DOM::Range m_markedRange;
 };
 
 inline KWQKHTMLPart *KWQ(KHTMLPart *part) { return static_cast<KWQKHTMLPart *>(part); }
index e23b8ba..2568561 100644 (file)
@@ -3524,6 +3524,7 @@ bool KWQKHTMLPart::haveToldBridgeAboutLoad(const QString &urlString)
 void KWQKHTMLPart::clear()
 {
     urlsBridgeKnowsAbout.clear();
+    setMarkedRange(0);
     KHTMLPart::clear();
 }
 
@@ -3772,3 +3773,26 @@ bool KWQKHTMLPart::shouldEndEditing(const Range &range) const
     ASSERT(!range.isNull());
     return [_bridge shouldEndEditing:[DOMRange _rangeWithImpl:range.handle()]];
 }
+
+DOM::Range KWQKHTMLPart::markedRange() const
+{
+    return m_markedRange;
+}
+
+void KWQKHTMLPart::setMarkedRange(const DOM::Range &range)
+{
+    ASSERT(!range.handle() || range.startContainer() == range.endContainer());
+    ASSERT(!range.handle() || range.startContainer().nodeType() == Node::TEXT_NODE);
+
+    if (m_markedRange.handle() && xmlDocImpl() 
+       && m_markedRange.startContainer().handle()->renderer()) {
+       m_markedRange.startContainer().handle()->renderer()->repaint();
+    }
+
+    m_markedRange = range;
+
+    if (m_markedRange.handle() && xmlDocImpl() 
+       && m_markedRange.startContainer().handle()->renderer()) {
+       m_markedRange.startContainer().handle()->renderer()->repaint();
+    }
+}
index 724c63c..d9f639e 100644 (file)
@@ -263,6 +263,10 @@ typedef enum {
 - (DOMRange *)selectedDOMRange;
 - (NSSelectionAffinity)selectionAffinity;
 
+- (void)setMarkedDOMRange:(DOMRange *)range;
+- (DOMRange *)markedDOMRange;
+- (void)clearMarkedDOMRange;
+
 - (NSAttributedString *)attributedStringFrom:(DOMNode *)startNode startOffset:(int)startOffset to:(DOMNode *)endNode endOffset:(int)endOffset;
 - (NSFont *)renderedFontForNode:(DOMNode *)node;
 
index 8154c78..1aca048 100644 (file)
@@ -1434,6 +1434,22 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     return static_cast<NSSelectionAffinity>(_part->selection().affinity());
 }
 
+- (void)setMarkedDOMRange:(DOMRange *)range
+{
+    _part->setMarkedRange([range _rangeImpl]);
+}
+
+- (DOMRange *)markedDOMRange
+{
+    DOM::RangeImpl *range = _part->markedRange().handle();
+    return range ? [DOMRange _rangeWithImpl:range] : nil;
+}
+
+- (void)clearMarkedDOMRange
+{
+    _part->setMarkedRange(Range(0));
+}
+
 - (DOMDocumentFragment *)documentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString 
 {
     DOM::DocumentImpl *document = _part->xmlDocImpl();
index e254f53..549b6ad 100644 (file)
@@ -1,3 +1,23 @@
+2004-08-09  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Trey.
+
+       WebKit part of:
+
+       - made basic marked text highlighting work to complete basic level of <rdar://problem/3704359> input method support not yet implemented for HTML editing
+
+        * WebView.subproj/WebHTMLView.m:
+        (-[WebHTMLView markedRange]): Use new bridge calls instead of internal marked range storage.
+        (-[WebHTMLView hasMarkedText]): Likewise.
+        (-[WebHTMLView unmarkText]): Likewise.
+        (-[WebHTMLView _selectMarkedText]): Likewise.
+        (-[WebHTMLView _selectRangeInMarkedText:]): Likewise.
+        (-[WebHTMLView _selectionIsInsideMarkedText]): Likewise.
+        (-[WebHTMLView _updateSelectionForInputManager]): Likewise.
+        (-[WebHTMLView setMarkedText:selectedRange:]): Use direct bridge call instead
+       of private _selectMarkedDOMRange: method, which would now be trivial.
+        * WebView.subproj/WebHTMLViewInternal.h: Remove unneeded
+
 2004-08-10  Darin Adler  <darin@apple.com>
 
         Reviewed by Ken.
index 05629a0..074dc56 100644 (file)
@@ -3348,7 +3348,16 @@ static WebHTMLView *lastHitView = nil;
 
 - (NSRange)markedRange
 {
-    return _private->markedRangeInNode;
+    if (![self hasMarkedText]) {
+       return NSMakeRange(NSNotFound,0);
+    }
+
+    DOMRange *markedDOMRange = [[self _bridge] markedDOMRange];
+
+    unsigned rangeLocation = [markedDOMRange startOffset];
+    unsigned rangeLength = [markedDOMRange endOffset] - rangeLocation;
+
+    return NSMakeRange(rangeLocation, rangeLength);
 }
 
 - (NSAttributedString *)attributedSubstringFromRange:(NSRange)theRange
@@ -3364,52 +3373,38 @@ static WebHTMLView *lastHitView = nil;
 
 - (BOOL)hasMarkedText
 {
-    return _private->markedTextNode != nil;
+    return [[self _bridge] markedDOMRange] != nil;
 }
 
 - (void)unmarkText
 {
-    [_private->markedTextNode release];
-    _private->markedTextNode = nil;
+    [[self _bridge] clearMarkedDOMRange];
 }
 
 - (void)_selectMarkedText
 {
     if ([self hasMarkedText]) {
        WebBridge *bridge = [self _bridge];
-       DOMRange *markedTextRange = [[bridge DOMDocument] createRange];
-
-       [markedTextRange setStart:_private->markedTextNode :_private->markedRangeInNode.location];
-       [markedTextRange setEnd:_private->markedTextNode :(_private->markedRangeInNode.location + _private->markedRangeInNode.length)];
-
+       DOMRange *markedTextRange = [bridge markedDOMRange];
        [bridge setSelectedDOMRange:markedTextRange affinity:NSSelectionAffinityUpstream];
     }
 }
 
-- (void)_setMarkedDOMRange:(DOMRange *)range
-{
-    ASSERT([range startContainer] == [range endContainer]);
-    ASSERT([[range startContainer] nodeType] == DOM_TEXT_NODE);
-
-    DOMNode *newMarkedTextNode = [[range startContainer] retain];
-    [_private->markedTextNode release];
-    _private->markedTextNode = [newMarkedTextNode retain];
-
-    long startOffset = [range startOffset];
-    long endOffset = [range endOffset];
-    _private->markedRangeInNode = NSMakeRange(startOffset, endOffset - startOffset);
-}
-
 - (void)_selectRangeInMarkedText:(NSRange)range
 {
+    ASSERT([self hasMarkedText]);
+
     WebBridge *bridge = [self _bridge];
     DOMRange *selectedRange = [[bridge DOMDocument] createRange];
+    DOMRange *markedRange = [bridge markedDOMRange];
     
-    unsigned selectionStart = _private->markedRangeInNode.location + range.location;
+    ASSERT([markedRange startContainer] == [markedRange endContainer]);
+
+    unsigned selectionStart = [markedRange startOffset] + range.location;
     unsigned selectionEnd = selectionStart + range.length;
 
-    [selectedRange setStart:_private->markedTextNode :selectionStart];
-    [selectedRange setEnd:_private->markedTextNode :selectionEnd];
+    [selectedRange setStart:[markedRange startContainer] :selectionStart];
+    [selectedRange setEnd:[markedRange startContainer] :selectionEnd];
 
     [bridge setSelectedDOMRange:selectedRange affinity:NSSelectionAffinityUpstream];
 }
@@ -3436,7 +3431,7 @@ static WebHTMLView *lastHitView = nil;
     }
 
     [bridge replaceSelectionWithText:text selectReplacement:YES];
-    [self _setMarkedDOMRange:[bridge selectedDOMRange]];
+    [bridge setMarkedDOMRange:[bridge selectedDOMRange]];
     [self _selectRangeInMarkedText:newSelRange];
 
     _private->ignoreMarkedTextSelectionChange = NO;
@@ -3499,18 +3494,22 @@ static WebHTMLView *lastHitView = nil;
 
 - (BOOL)_selectionIsInsideMarkedText
 {
-    DOMRange *selection = [[self _bridge] selectedDOMRange];
+    WebBridge *bridge = [self _bridge];
+    DOMRange *selection = [bridge selectedDOMRange];
+    DOMRange *markedRange = [bridge markedDOMRange];
+
+    ASSERT([markedRange startContainer] == [markedRange endContainer]);
 
-    if ([selection startContainer] != _private->markedTextNode
+    if ([selection startContainer] != [markedRange startContainer]
        return NO;
 
-    if ([selection endContainer] != _private->markedTextNode)
+    if ([selection endContainer] != [markedRange startContainer])
        return NO;
 
-    if ((unsigned)[selection startOffset] < _private->markedRangeInNode.location)
+    if ([selection startOffset] < [markedRange startOffset])
        return NO;
 
-    if ((unsigned)[selection endOffset] > _private->markedRangeInNode.location + _private->markedRangeInNode.length)
+    if ([selection endOffset] > [markedRange endOffset])
        return NO;
 
     return YES;
@@ -3523,8 +3522,9 @@ static WebHTMLView *lastHitView = nil;
 
     if ([self _selectionIsInsideMarkedText]) {
        DOMRange *selection = [[self _bridge] selectedDOMRange];
-       
-       unsigned markedSelectionStart = [selection startOffset] - _private->markedRangeInNode.location;
+       DOMRange *markedDOMRange = [[self _bridge] markedDOMRange];
+
+       unsigned markedSelectionStart = [selection startOffset] - [markedDOMRange startOffset];
        unsigned markedSelectionLength = [selection endOffset] - [selection startOffset];
        NSRange newSelectionRange = NSMakeRange(markedSelectionStart, markedSelectionLength);
        
index 41ef161..ed22901 100644 (file)
@@ -44,8 +44,6 @@
 
     BOOL resigningFirstResponder;
 
-    DOMNode *markedTextNode;
-    NSRange markedRangeInNode;
     BOOL ignoreMarkedTextSelectionChange;
 }
 @end