Reviewed by Dave
authorkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Apr 2004 14:13:42 +0000 (14:13 +0000)
committerkocienda <kocienda@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 9 Apr 2004 14:13:42 +0000 (14:13 +0000)
        Small collection of editing improvements.

        * ChangeLog:
        * khtml/editing/htmlediting_impl.cpp:
        (shouldDeleteUpstreamPosition): This was deleting significant spaces on preceding
        lines when the caret was at the start of a line. Fixed.
        (DeleteSelectionCommandImpl::doApply): Fixed a case where caret jumped to previous
        line when deleting a character at the start of a line after a BR.
        (InputNewlineCommandImpl::doApply): Handle more cases correctly. Previously, this
        only handled inserting a newline when the caret was already in a text node.
        (InputTextCommandImpl::prepareForTextInsertion): Ditto.
        (InputTextCommandImpl::execute): Ditto.
        * khtml/editing/htmlediting_impl.h:
        * khtml/rendering/render_block.cpp:
        (khtml::RenderBlock::checkSelectionPointIgnoringContinuations): Now can place caret
        with a click in an empty block.
        * khtml/rendering/render_block.h: Added checkSelectionPointIgnoringContinuations declaration.
        * khtml/rendering/render_replaced.cpp:
        (RenderReplaced::checkSelectionPointIgnoringContinuations): Now can place caret with a click
        on a replaced element.
        * khtml/rendering/render_replaced.h: Added checkSelectionPointIgnoringContinuations declaration.
        * khtml/rendering/render_text.cpp:
        (InlineTextBox::checkSelectionPoint): Now can place caret with a click in text on a line made "tall"
        by an image on the same line.
        * khtml/xml/dom_docimpl.cpp:
        (DocumentImpl::createEditingTextNode): This creates a text node subclass that whill always create
        a renderer for itself.
        * khtml/xml/dom_docimpl.h:
        * khtml/xml/dom_position.cpp:
        (DOMPosition::isLastRenderedPositionInEditableBlock): Improved code to handle more cases.
        * khtml/xml/dom_textimpl.cpp:
        (TextImpl::TextImpl): Rolled out m_rendererIsNeeded flag.
        (TextImpl::rendererIsNeeded): Ditto.
        (EditingTextImpl::EditingTextImpl): New class.
        (EditingTextImpl::~EditingTextImpl): New.
        (EditingTextImpl::rendererIsNeeded): New. Always returns true.
        * khtml/xml/dom_textimpl.h: New EditingTextImpl class.
        * layout-tests/editing/deleting/delete-3608430-fix-expected.txt: Added.
        * layout-tests/editing/deleting/delete-3608430-fix.html: Added.
        * layout-tests/editing/deleting/delete-3608462-fix-expected.txt: Added.
        * layout-tests/editing/deleting/delete-3608462-fix.html: Added.
        * layout-tests/editing/deleting/delete-trailing-ws-002-expected.txt: Added.
        * layout-tests/editing/deleting/delete-trailing-ws-002.html: Added.

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

19 files changed:
LayoutTests/editing/deleting/delete-3608430-fix-expected.txt [new file with mode: 0644]
LayoutTests/editing/deleting/delete-3608430-fix.html [new file with mode: 0644]
LayoutTests/editing/deleting/delete-3608462-fix-expected.txt [new file with mode: 0644]
LayoutTests/editing/deleting/delete-3608462-fix.html [new file with mode: 0644]
LayoutTests/editing/deleting/delete-trailing-ws-002-expected.txt [new file with mode: 0644]
LayoutTests/editing/deleting/delete-trailing-ws-002.html [new file with mode: 0644]
WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/htmlediting_impl.cpp
WebCore/khtml/editing/htmlediting_impl.h
WebCore/khtml/rendering/render_block.cpp
WebCore/khtml/rendering/render_block.h
WebCore/khtml/rendering/render_replaced.cpp
WebCore/khtml/rendering/render_replaced.h
WebCore/khtml/rendering/render_text.cpp
WebCore/khtml/xml/dom_docimpl.cpp
WebCore/khtml/xml/dom_docimpl.h
WebCore/khtml/xml/dom_position.cpp
WebCore/khtml/xml/dom_textimpl.cpp
WebCore/khtml/xml/dom_textimpl.h

diff --git a/LayoutTests/editing/deleting/delete-3608430-fix-expected.txt b/LayoutTests/editing/deleting/delete-3608430-fix-expected.txt
new file mode 100644 (file)
index 0000000..255efbf
--- /dev/null
@@ -0,0 +1,14 @@
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x72
+  RenderBlock {HTML} at (0,0) size 800x72
+    RenderBody {BODY} at (8,8) size 784x56
+      RenderBlock {DIV} at (0,0) size 784x56 [border: (2px solid #FF0000)]
+        RenderInline {SPAN} at (0,0) size 129x28
+          RenderText {TEXT} at (14,14) size 129x28
+            text run at (14,14) width 129: "start-deleting"
+        RenderText {TEXT} at (0,0) size 0x0
+selection is CARET:
+start:      position 0 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
+upstream:   position 0 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
+downstream: position 0 of child 1 {TEXT} of child 1 {SPAN} of root {DIV}
diff --git a/LayoutTests/editing/deleting/delete-3608430-fix.html b/LayoutTests/editing/deleting/delete-3608430-fix.html
new file mode 100644 (file)
index 0000000..446cbcb
--- /dev/null
@@ -0,0 +1,39 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    border: 2px solid red; 
+    padding: 12px; 
+    font-size: 24px; 
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+    for (i = 0; i < 28; i++) {
+        moveSelectionForwardByCharacterCommand();    
+    }
+    for (i = 0; i < 28; i++) {
+        deleteCommand(); 
+    }
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body>
+<div contenteditable id="root" class="editing">
+<span id="test">foo 
+<br>foo <i>  </i> <img src="../abe.gif""> select-in-me-and-start-deleting</span>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/editing/deleting/delete-3608462-fix-expected.txt b/LayoutTests/editing/deleting/delete-3608462-fix-expected.txt
new file mode 100644 (file)
index 0000000..b69ffa1
--- /dev/null
@@ -0,0 +1,21 @@
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x262
+  RenderBlock {HTML} at (0,0) size 800x262
+    RenderBody {BODY} at (8,8) size 784x246
+      RenderBlock {DIV} at (0,0) size 784x246 [border: (2px solid #FF0000)]
+        RenderInline {SPAN} at (0,0) size 181x137
+          RenderText {TEXT} at (14,95) size 11x28
+            text run at (14,95) width 11: "a"
+          RenderImage {IMG} at (25,14) size 76x103
+          RenderText {TEXT} at (101,95) size 46x28
+            text run at (101,95) width 46: "new "
+          RenderBR {BR} at (0,0) size 0x0
+          RenderImage {IMG} at (14,123) size 76x103
+          RenderText {TEXT} at (90,204) size 105x28
+            text run at (90,204) width 105: " conceived"
+        RenderText {TEXT} at (0,0) size 0x0
+selection is CARET:
+start:      position 0 of child 5 {IMG} of child 2 {SPAN} of root {DIV}
+upstream:   position 1 of child 4 {BR} of child 2 {SPAN} of root {DIV}
+downstream: position 0 of child 5 {IMG} of child 2 {SPAN} of root {DIV}
diff --git a/LayoutTests/editing/deleting/delete-3608462-fix.html b/LayoutTests/editing/deleting/delete-3608462-fix.html
new file mode 100644 (file)
index 0000000..b2e0dac
--- /dev/null
@@ -0,0 +1,39 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    border: 2px solid red; 
+    padding: 12px; 
+    font-size: 24px; 
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+    for (i = 0; i < 11; i++) {
+        moveSelectionForwardByCharacterCommand();    
+    }
+    for (i = 0; i < 4; i++) {
+        deleteCommand(); 
+    }
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body>
+<div contenteditable id="root" class="editing">
+<span id="test">a<img src="../abe.jpg">new 
+<br>foo <i>  </i> <img src="../abe.jpg"> conceived</span>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/editing/deleting/delete-trailing-ws-002-expected.txt b/LayoutTests/editing/deleting/delete-trailing-ws-002-expected.txt
new file mode 100644 (file)
index 0000000..e718063
--- /dev/null
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x100
+  RenderBlock {HTML} at (0,0) size 800x100
+    RenderBody {BODY} at (8,8) size 784x84
+      RenderBlock {DIV} at (0,0) size 784x84 [border: (2px solid #FF0000)]
+        RenderInline {SPAN} at (0,0) size 40x56
+          RenderText {TEXT} at (14,14) size 32x28
+            text run at (14,14) width 32: "foo"
+          RenderBR {BR} at (0,0) size 0x0
+          RenderText {TEXT} at (14,42) size 40x28
+            text run at (14,42) width 40: " baz"
+        RenderText {TEXT} at (0,0) size 0x0
+selection is CARET:
+start:      position 0 of child 3 {TEXT} of child 2 {SPAN} of root {DIV}
+upstream:   position 1 of child 2 {BR} of child 2 {SPAN} of root {DIV}
+downstream: position 0 of child 3 {TEXT} of child 2 {SPAN} of root {DIV}
diff --git a/LayoutTests/editing/deleting/delete-trailing-ws-002.html b/LayoutTests/editing/deleting/delete-trailing-ws-002.html
new file mode 100644 (file)
index 0000000..3b61c06
--- /dev/null
@@ -0,0 +1,38 @@
+<html> 
+<head>
+
+<style>
+.editing { 
+    border: 2px solid red; 
+    padding: 12px; 
+    font-size: 24px; 
+}
+</style>
+<script src=../editing.js language="JavaScript" type="text/JavaScript" ></script>
+
+<script>
+
+function editingTest() {
+    for (i = 0; i < 7; i++) {
+        moveSelectionForwardByCharacterCommand();    
+    }
+    for (i = 0; i < 3; i++) {
+        deleteCommand(); 
+    }
+}
+
+</script>
+
+<title>Editing Test</title> 
+</head> 
+<body>
+<div contenteditable id="root" class="editing">
+<span id="test">foo<br>bar baz</span>
+</div>
+
+<script>
+runEditingTest();
+</script>
+
+</body>
+</html>
index 71dfd9bb8b8bd853a7f0d7f648a26688e54be2b2..2784451c2a60b202656bde469258c3747bbd7cda 100644 (file)
@@ -1,3 +1,51 @@
+2004-04-09  Ken Kocienda  <kocienda@apple.com>
+
+        Reviewed by Dave
+        
+        Small collection of editing improvements.
+
+        * ChangeLog:
+        * khtml/editing/htmlediting_impl.cpp:
+        (shouldDeleteUpstreamPosition): This was deleting significant spaces on preceding
+        lines when the caret was at the start of a line. Fixed. 
+        (DeleteSelectionCommandImpl::doApply): Fixed a case where caret jumped to previous
+        line when deleting a character at the start of a line after a BR.
+        (InputNewlineCommandImpl::doApply): Handle more cases correctly. Previously, this
+        only handled inserting a newline when the caret was already in a text node.
+        (InputTextCommandImpl::prepareForTextInsertion): Ditto.
+        (InputTextCommandImpl::execute): Ditto.
+        * khtml/editing/htmlediting_impl.h:
+        * khtml/rendering/render_block.cpp:
+        (khtml::RenderBlock::checkSelectionPointIgnoringContinuations): Now can place caret
+        with a click in an empty block.
+        * khtml/rendering/render_block.h: Added checkSelectionPointIgnoringContinuations declaration.
+        * khtml/rendering/render_replaced.cpp: 
+        (RenderReplaced::checkSelectionPointIgnoringContinuations): Now can place caret with a click 
+        on a replaced element.
+        * khtml/rendering/render_replaced.h: Added checkSelectionPointIgnoringContinuations declaration.
+        * khtml/rendering/render_text.cpp:
+        (InlineTextBox::checkSelectionPoint): Now can place caret with a click in text on a line made "tall"
+        by an image on the same line.
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::createEditingTextNode): This creates a text node subclass that whill always create
+        a renderer for itself.
+        * khtml/xml/dom_docimpl.h:
+        * khtml/xml/dom_position.cpp:
+        (DOMPosition::isLastRenderedPositionInEditableBlock): Improved code to handle more cases.
+        * khtml/xml/dom_textimpl.cpp:
+        (TextImpl::TextImpl): Rolled out m_rendererIsNeeded flag.
+        (TextImpl::rendererIsNeeded): Ditto.
+        (EditingTextImpl::EditingTextImpl): New class.
+        (EditingTextImpl::~EditingTextImpl): New.
+        (EditingTextImpl::rendererIsNeeded): New. Always returns true.
+        * khtml/xml/dom_textimpl.h: New EditingTextImpl class.
+        * layout-tests/editing/deleting/delete-3608430-fix-expected.txt: Added.
+        * layout-tests/editing/deleting/delete-3608430-fix.html: Added.
+        * layout-tests/editing/deleting/delete-3608462-fix-expected.txt: Added.
+        * layout-tests/editing/deleting/delete-3608462-fix.html: Added.
+        * layout-tests/editing/deleting/delete-trailing-ws-002-expected.txt: Added.
+        * layout-tests/editing/deleting/delete-trailing-ws-002.html: Added.
+
 2004-04-08  Chris Blumenberg  <cblu@apple.com>
 
        Renamed the PasteHTMLCommand to PasteMarkupCommand. Removed PasteImageCommand because we will use PasteMarkupCommand for pasting images.
index 276b90a04dbbe3654507a5452fc6717ce2e8441f..5c45aa21af170ac448016019f2795ae66f061517 100644 (file)
@@ -54,6 +54,7 @@ using DOM::DocumentImpl;
 using DOM::DOMPosition;
 using DOM::DOMString;
 using DOM::DOMStringImpl;
+using DOM::EditingTextImpl;
 using DOM::EditIterator;
 using DOM::ElementImpl;
 using DOM::HTMLElementImpl;
@@ -625,7 +626,7 @@ static bool shouldDeleteUpstreamPosition(const DOMPosition &pos)
     if (pos.isLastRenderedPositionInEditableBlock())
         return false;
 
-    if (pos.isFirstRenderedPositionOnLine())
+    if (pos.isFirstRenderedPositionOnLine() || pos.isLastRenderedPositionOnLine())
         return false;
 
     RenderText *textRenderer = static_cast<RenderText *>(renderer);
@@ -836,7 +837,6 @@ void DeleteSelectionCommandImpl::doApply()
          (downstreamStart.offset() <= downstreamStart.node()->caretMinOffset()));
 
     unsigned long startRenderedOffset = downstreamStart.renderedOffset();
-    //unsigned long endRenderedOffset = upstreamEnd.renderedOffset();
     
     bool startAtStartOfRootEditableBlock = startRenderedOffset == 0 && downstreamStart.inFirstEditableInRootEditableBlock();
     bool startAtStartOfBlock = startAtStartOfRootEditableBlock || 
@@ -869,12 +869,14 @@ void DeleteSelectionCommandImpl::doApply()
         endingPosition = upstreamStart;
         if (downstreamStart.node()->id() == ID_BR && downstreamStart.offset() == 0)
             adjustEndingPositionDownstream = true;
+        if (upstreamStart.node()->id() == ID_BR && upstreamStart.offset() == 1)
+            adjustEndingPositionDownstream = true;
     }
    
     //
     // Figure out the whitespace conversions to do
     //
-    if (startAtStartOfBlock && !endAtEndOfBlock) {
+    if ((startAtStartOfBlock && !endAtEndOfBlock) || (!startCompletelySelected && adjustEndingPositionDownstream)) {
         // convert trailing whitespace
         DOMPosition trailing = trailingWhitespacePosition(downstreamEnd.equivalentDownstreamPosition());
         if (trailing.notEmpty()) {
@@ -1031,47 +1033,50 @@ int InputNewlineCommandImpl::commandID() const
 
 void InputNewlineCommandImpl::doApply()
 {
-    KHTMLSelection selection = endingSelection();
-
-    if (!selection.startNode()->isTextNode())
-        return;
-
-    // Delete the current selection
     deleteSelection();
-    
-    // reset the selection since it may have changed due to the delete
-    selection = endingSelection();
+    KHTMLSelection selection = endingSelection();
 
     int exceptionCode = 0;
     ElementImpl *breakNode = document()->createHTMLElement("BR", exceptionCode);
     ASSERT(exceptionCode == 0);
 
-    TextImpl *textNode = static_cast<TextImpl *>(selection.startNode());
-    bool atStart = selection.startOffset() == textNode->renderer()->caretMinOffset();
-    bool atEnd = selection.startOffset() == textNode->renderer()->caretMaxOffset();
-    if (atStart) {
-        // Set the cursor at the beginning of text node now following the new BR.
-        insertNodeBefore(breakNode, textNode);
-        selection = KHTMLSelection(textNode, 0);
-        setEndingSelection(selection);
+    DOMPosition pos = selection.startPosition().equivalentDownstreamPosition();
+    bool atEnd = pos.offset() >= pos.node()->caretMaxOffset();
+    bool atStart = pos.offset() <= pos.node()->caretMinOffset();
+    bool atEndOfBlock = pos.isLastRenderedPositionInEditableBlock();
+    
+    if (atEndOfBlock) {
+        LOG(Editing, "input newline case 1");
+        appendNode(pos.node()->containingEditableBlock(), breakNode);
+        // EDIT FIXME: This should not insert a non-breaking space after the BR.
+        // But for right now, it gets the BR to render.
+        TextImpl *editingTextNode = document()->createEditingTextNode(nonBreakingSpaceString());
+        insertNodeAfter(editingTextNode, breakNode);
+        setEndingSelection(DOMPosition(editingTextNode, 1));
+        editingTextNode->deref();
     }
     else if (atEnd) {
-        insertNodeAfter(breakNode, textNode);
-        // Set the cursor at the beginning of the the BR.
-        DOMPosition pos(breakNode, 0);
-        setEndingSelection(pos);
+        LOG(Editing, "input newline case 2");
+        insertNodeAfter(breakNode, pos.node());
+        setEndingSelection(DOMPosition(breakNode, 0));
+    }
+    else if (atStart) {
+        LOG(Editing, "input newline case 3");
+        insertNodeAt(breakNode, pos.node(), 0);
+        setEndingSelection(DOMPosition(pos.node(), 0));
     }
     else {
+        LOG(Editing, "input newline case 4");
+        ASSERT(pos.node()->isTextNode());
+        TextImpl *textNode = static_cast<TextImpl *>(pos.node());
         TextImpl *textBeforeNode = document()->createTextNode(textNode->substringData(0, selection.startOffset(), exceptionCode));
         deleteText(textNode, 0, selection.startOffset());
         insertNodeBefore(textBeforeNode, textNode);
         insertNodeBefore(breakNode, textNode);
         textBeforeNode->deref();
-        // Set the cursor at the beginning of the node after the BR.
-        selection = KHTMLSelection(textNode, 0);
-        setEndingSelection(selection);
+        setEndingSelection(DOMPosition(textNode, 0));
     }
-    
+        
     breakNode->deref();
 }
 
@@ -1124,34 +1129,41 @@ void InputTextCommandImpl::deleteCharacter()
     }
 }
 
-DOMPosition InputTextCommandImpl::prepareForTextInsertion()
+DOMPosition InputTextCommandImpl::prepareForTextInsertion(bool adjustDownstream)
 {
     // Prepare for text input by looking at the current position.
     // It may be necessary to insert a text node to receive characters.
     KHTMLSelection selection = endingSelection();
     ASSERT(selection.state() == KHTMLSelection::CARET);
     
-    DOMPosition pos = selection.startPosition().equivalentUpstreamPosition();
-    if (!pos.inRenderedContent())
-        pos = pos.nextRenderedEditablePosition();
-    if (!pos.node()->inSameContainingEditableBlock(selection.startNode()))
-        pos = selection.startPosition();
+    DOMPosition pos = selection.startPosition();
+    if (adjustDownstream)
+        pos = pos.equivalentDownstreamPosition();
+    else
+        pos = pos.equivalentUpstreamPosition();
     
     if (!pos.node()->isTextNode()) {
         if (!m_insertedTextNode) {
-            m_insertedTextNode = document()->createTextNode("");
-            m_insertedTextNode->setRendererIsNeeded();
+            m_insertedTextNode = document()->createEditingTextNode("");
             m_insertedTextNode->ref();
         }
         
-        if (pos.node()->isEditableBlock())
+        if (pos.node()->isEditableBlock()) {
+            LOG(Editing, "prepareForTextInsertion case 1");
             appendNode(pos.node(), m_insertedTextNode);
-        else if (pos.node()->id() == ID_BR && pos.offset() == 1)
+        }
+        else if (pos.node()->id() == ID_BR && pos.offset() == 1) {
+            LOG(Editing, "prepareForTextInsertion case 2");
             insertNodeBefore(m_insertedTextNode, pos.node());
-        else if (pos.node()->caretMinOffset() == pos.offset())
+        }
+        else if (pos.node()->caretMinOffset() == pos.offset()) {
+            LOG(Editing, "prepareForTextInsertion case 3");
             insertNodeBefore(m_insertedTextNode, pos.node());
-        else if (pos.node()->caretMaxOffset() == pos.offset())
+        }
+        else if (pos.node()->caretMaxOffset() == pos.offset()) {
+            LOG(Editing, "prepareForTextInsertion case 4");
             insertNodeAfter(m_insertedTextNode, pos.node());
+        }
         else
             ASSERT_NOT_REACHED();
         
@@ -1164,15 +1176,18 @@ DOMPosition InputTextCommandImpl::prepareForTextInsertion()
 void InputTextCommandImpl::execute(const DOMString &text)
 {
     KHTMLSelection selection = endingSelection();
+    bool adjustDownstream = selection.startPosition().isFirstRenderedPositionOnLine();
 
     // Delete the current selection, or collapse whitespace, as needed
     if (selection.state() == KHTMLSelection::RANGE)
         deleteSelection();
     else
         deleteCollapsibleWhitespace();
+
+    // EDIT FIXME: Need to take typing style from upstream text, if any.
     
     // Make sure the document is set up to receive text
-    DOMPosition pos = prepareForTextInsertion();
+    DOMPosition pos = prepareForTextInsertion(adjustDownstream);
     
     TextImpl *textNode = static_cast<TextImpl *>(pos.node());
     long offset = pos.offset();
@@ -1184,8 +1199,7 @@ void InputTextCommandImpl::execute(const DOMString &text)
         insertSpace(textNode, offset);
     else
         insertText(textNode, offset, text);
-    selection = KHTMLSelection(textNode, offset + text.length());
-    setEndingSelection(selection);
+    setEndingSelection(DOMPosition(textNode, offset + text.length()));
     m_charactersAdded += text.length();
 }
 
index 47fec0209c466881799f1116a7699804099acd42..e1526565ecf5942a5908ad2b92430d0dc57f5b6b 100644 (file)
@@ -260,7 +260,7 @@ public:
     unsigned long charactersAdded() const { return m_charactersAdded; }
     
 private:
-    DOM::DOMPosition prepareForTextInsertion();
+    DOM::DOMPosition prepareForTextInsertion(bool adjustDownstream);
     void execute(const DOM::DOMString &text);
     void insertSpace(DOM::TextImpl *textNode, unsigned long offset);
 
index 0154eaa65f5d4e477d82c037ffbf14e12b7b940c..29416daa1d88064a76845f0fc6b76b478321d228 100644 (file)
@@ -2022,6 +2022,17 @@ bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
     return inBox;
 }
 
+FindSelectionResult RenderBlock::checkSelectionPointIgnoringContinuations(int _x, int _y, int _tx, int _ty, DOM::NodeImpl *&node, int &offset)
+{
+    if (!firstChild() && element()) {
+        node = element();
+        offset = 0;
+        return SelectionPointBefore;
+    }
+    
+    return RenderFlow::checkSelectionPointIgnoringContinuations(_x, _y, _tx, _ty, node, offset);
+}
+
 void RenderBlock::calcMinMaxWidth()
 {
     KHTMLAssert( !minMaxKnown() );
index 1c32dafae66d84ac7066472762e9f1fca344cfcc..592dbad98b83ab9bcb983e643f5c1537b627b2b5 100644 (file)
@@ -167,6 +167,9 @@ public:
                              HitTestAction hitTestAction = HitTestAll, bool inside=false);
 
     bool isPointInScrollbar(int x, int y, int tx, int ty);
+
+    virtual FindSelectionResult checkSelectionPointIgnoringContinuations
+        (int _x, int _y, int _tx, int _ty, DOM::NodeImpl *&, int &);
     
     virtual void calcMinMaxWidth();
     void calcInlineMinMaxWidth();
index a9a399c51247bbf998d4332f1ae3ce12b80a85fe..adfed15136bbf89af5c64ee865c4940f8333d7ae 100644 (file)
@@ -126,6 +126,28 @@ unsigned long RenderReplaced::caretMaxRenderedOffset() const
     return 1; 
 }
 
+FindSelectionResult RenderReplaced::checkSelectionPointIgnoringContinuations(int _x, int _y, int _tx, int _ty, DOM::NodeImpl *&node, int &offset)
+{
+    int l = xPos() + _tx;
+    int r = xPos() + _tx + width();
+    int t = yPos() + _ty;
+    int b = yPos() + _ty + height();
+    
+    bool pointIsInside = (_x >= l && _x <= r && _y >= t && _y <= b);
+    
+    if (pointIsInside && element()) {
+        node = element();
+        if (_x < l + (width() / 2)) {
+            offset = 0;
+            return SelectionPointBefore;
+        }
+        offset = 1;
+        return SelectionPointAfter;
+    }
+    
+    return RenderBox::checkSelectionPointIgnoringContinuations(_x, _y, _tx, _ty, node, offset);
+}
+
 // -----------------------------------------------------------------------------
 
 RenderWidget::RenderWidget(DOM::NodeImpl* node)
index 1f7e91fb655a3d2dab56221669c5d8b42e89cd6d..3a0a123a8c5d1709029886090eb00557e3182f79 100644 (file)
@@ -55,6 +55,9 @@ public:
     virtual long caretMinOffset() const;
     virtual long caretMaxOffset() const;
     virtual unsigned long caretMaxRenderedOffset() const;
+
+    virtual FindSelectionResult checkSelectionPointIgnoringContinuations
+        (int _x, int _y, int _tx, int _ty, DOM::NodeImpl *&, int &);
     
 private:
     int m_intrinsicWidth;
index 8b1120c3ebcdf5c58ea8e702bf4f15800f5f01f4..021008b68b8c47666321aea55296ea12a6d517ad 100644 (file)
@@ -208,10 +208,10 @@ FindSelectionResult InlineTextBox::checkSelectionPoint(int _x, int _y, int _tx,
 //                   << " _tx+m_x=" << _tx+m_x << " _ty+m_y=" << _ty+m_y << endl;
     offset = 0;
 
-    if ( _y < _ty + m_y )
+    if ( _y < _ty + root()->topOverflow() )
         return SelectionPointBefore; // above -> before
 
-    if ( _y > _ty + m_y + m_height ) {
+    if ( _y > _ty + root()->bottomOverflow() ) {
         // below -> after
         // Set the offset to the max
         offset = m_len;
index c351083ebdbcb8058ee01d5b2ce55415dcc670a1..e321b21c2caa5b92df38474c5b38282b6535f4fe 100644 (file)
@@ -462,6 +462,11 @@ EntityReferenceImpl *DocumentImpl::createEntityReference ( const DOMString &name
     return new EntityReferenceImpl(docPtr(), name.implementation());
 }
 
+EditingTextImpl *DocumentImpl::createEditingTextNode(const DOMString &text)
+{
+    return new EditingTextImpl(docPtr(), text);
+}
+
 NodeImpl *DocumentImpl::importNode(NodeImpl *importedNode, bool deep, int &exceptioncode)
 {
        NodeImpl *result = 0;
index 09f587dfe30acd59e69ec56bea2ec424d95a044a..c3db8eae861410a78c664d569c7f88af11faa08c 100644 (file)
@@ -85,6 +85,7 @@ namespace DOM {
 #if APPLE_CHANGES
     class DOMImplementation;
 #endif
+    class EditingTextImpl;
     class ElementImpl;
     class EntityReferenceImpl;
     class EventImpl;
@@ -245,6 +246,9 @@ public:
     TreeWalkerImpl *createTreeWalker(const Node &root, unsigned long whatToShow, const NodeFilter &filter,
                             bool entityReferenceExpansion);
 
+    // Special support for editing
+    EditingTextImpl *createEditingTextNode(const DOMString &text);
+
     virtual void recalcStyle( StyleChange = NoChange );
     static QPtrList<DocumentImpl> * changedDocuments;
     virtual void updateRendering();
index e2ef22adb72ce0bd28c1b40e9f790eaa1fc9385b..553f37c3619fd316744ba418a7df215f1a2b3ae6 100644 (file)
@@ -643,8 +643,16 @@ bool DOMPosition::isLastRenderedPositionInEditableBlock() const
     if (renderedOffset() != (long)node()->caretMaxRenderedOffset())
         return false;
 
-    NodeImpl *next = node()->nextEditable();
-    return !next || !node()->inSameContainingEditableBlock(next);
+    DOMPosition pos(node(), offset());
+    EditIterator it(pos);
+    while (!it.atEnd()) {
+        it.next();
+        if (!it.current().node()->inSameContainingEditableBlock(node()))
+            return true;
+        if (it.current().inRenderedContent())
+            return false;
+    }
+    return true;
 }
 
 bool DOMPosition::inFirstEditableInRootEditableBlock() const
index 344c6e6b437b7e0b6c63d93ac055c2358a88354e..1398effbf4c5264b96ee9fb976b7728c282e2968 100644 (file)
@@ -319,12 +319,12 @@ DOMString CommentImpl::toString() const
 // ### allow having children in text nodes for entities, comments etc.
 
 TextImpl::TextImpl(DocumentPtr *doc, const DOMString &_text)
-    : CharacterDataImpl(doc, _text), m_rendererIsNeeded(false)
+    : CharacterDataImpl(doc, _text)
 {
 }
 
 TextImpl::TextImpl(DocumentPtr *doc)
-    : CharacterDataImpl(doc), m_rendererIsNeeded(false)
+    : CharacterDataImpl(doc)
 {
 }
 
@@ -389,11 +389,6 @@ NodeImpl *TextImpl::cloneNode(bool /*deep*/)
 
 bool TextImpl::rendererIsNeeded(RenderStyle *style)
 {
-    if (m_rendererIsNeeded) {
-        m_rendererIsNeeded = false;
-        return true;
-    }
-
     if (!CharacterDataImpl::rendererIsNeeded(style)) {
         return false;
     }
@@ -528,5 +523,24 @@ DOMString CDATASectionImpl::toString() const
     return DOMString("<![CDATA[") + nodeValue() + "]]>";
 }
 
+// ---------------------------------------------------------------------------
+
+EditingTextImpl::EditingTextImpl(DocumentPtr *impl, const DOMString &text)
+    : TextImpl(impl, text)
+{
+}
+
+EditingTextImpl::EditingTextImpl(DocumentPtr *impl)
+    : TextImpl(impl)
+{
+}
 
+EditingTextImpl::~EditingTextImpl()
+{
+}
+
+bool EditingTextImpl::rendererIsNeeded(RenderStyle *style)
+{
+    return true;
+}
 
index e6f2469eb2ff0482d4f17b6606ede529fa401a7f..2f71c43917fcac9210c998e1361ad701a77f48d2 100644 (file)
@@ -138,8 +138,6 @@ public:
     virtual bool childTypeAllowed( unsigned short type );
 
     virtual DOMString toString() const;
-    
-    void setRendererIsNeeded(bool flag=true) { m_rendererIsNeeded = flag; }
 
 #if APPLE_CHANGES
     static Text createInstance(TextImpl *impl);
@@ -147,9 +145,6 @@ public:
 
 protected:
     virtual TextImpl *createNew(DOMStringImpl *_str);
-    
-private:
-    bool m_rendererIsNeeded;
 };
 
 // ----------------------------------------------------------------------------
@@ -177,5 +172,17 @@ protected:
     virtual TextImpl *createNew(DOMStringImpl *_str);
 };
 
-}; //namespace
+// ----------------------------------------------------------------------------
+
+class EditingTextImpl : public TextImpl
+{
+public:
+    EditingTextImpl(DocumentPtr *impl, const DOMString &text);
+    EditingTextImpl(DocumentPtr *impl);
+    virtual ~EditingTextImpl();
+
+    virtual bool rendererIsNeeded(khtml::RenderStyle *);
+};
+
+} //namespace
 #endif