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

hyatt hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 08:27:20 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 0c3a9867928cb96d8b8032d6db61062901aa09a5
Author: hyatt <hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Feb 23 21:26:26 2004 +0000

    	Fix for 3558717, make sure that form elements that are removed from a document also remove themselves
    	from the form.
    
    	Reviewed by darin.
    
            * khtml/html/html_formimpl.cpp:
            (HTMLGenericFormElementImpl::removedFromDocument):
            * khtml/html/html_formimpl.h:
            * khtml/xml/dom_nodeimpl.cpp:
            * khtml/xml/dom_nodeimpl.h:
    
    	Implement smarter line layout for faster typing and repainting when individual lines change.
    
    	Reviewed by kocienda.
    
    	* khtml/khtmlview.cpp:
            (KHTMLViewPrivate::KHTMLViewPrivate):
            (KHTMLViewPrivate::~KHTMLViewPrivate):
            (KHTMLViewPrivate::reset):
            (KHTMLView::addRepaintInfo):
            (KHTMLView::layout):
            * khtml/khtmlview.h:
            * khtml/rendering/bidi.cpp:
            (khtml::Bidinext):
            (khtml::appendRun):
            (khtml::embed):
            (khtml::RenderBlock::constructLine):
            (khtml::RenderBlock::computeHorizontalPositionsForLine):
            (khtml::RenderBlock::computeVerticalPositionsForLine):
            (khtml::RenderBlock::bidiReorderLine):
            (khtml::buildCompactRuns):
            (khtml::RenderBlock::layoutInlineChildren):
            (khtml::RenderBlock::determineStartPosition):
            (khtml::RenderBlock::determineEndPosition):
            (khtml::RenderBlock::matchedEndLine):
            (khtml::RenderBlock::findNextLineBreak):
            * khtml/rendering/render_block.cpp:
            (khtml:::RenderFlow):
            (khtml::RenderBlock::layoutBlock):
            (khtml::RenderBlock::layoutBlockChildren):
            (khtml::RenderBlock::positionNewFloats):
            (khtml::RenderBlock::lowestPosition):
            (khtml::RenderBlock::rightmostPosition):
            (khtml::RenderBlock::leftmostPosition):
            * khtml/rendering/render_block.h:
            (khtml::RenderBlock::firstRootBox):
            (khtml::RenderBlock::lastRootBox):
            (khtml::RenderBlock::setLinesAppended):
            (khtml::RenderBlock::linesAppended):
            * khtml/rendering/render_box.cpp:
            (RenderBox::dirtyLineBoxes):
            (RenderBox::deleteLineBoxWrapper):
            (RenderBox::setInlineBoxWrapper):
            * khtml/rendering/render_box.h:
            * khtml/rendering/render_br.cpp:
            (RenderBR::createInlineBox):
            (RenderBR::position):
            * khtml/rendering/render_br.h:
            * khtml/rendering/render_container.cpp:
            (RenderContainer::appendChildNode):
            (RenderContainer::insertChildNode):
            * khtml/rendering/render_flexbox.cpp:
            (khtml::RenderFlexibleBox::placeChild):
            * khtml/rendering/render_flow.cpp:
            (RenderFlow::extractLineBox):
            (RenderFlow::attachLineBox):
            (RenderFlow::removeLineBox):
            (RenderFlow::dirtyLinesFromChangedChild):
            (RenderFlow::dirtyLineBoxes):
            (RenderFlow::createInlineBox):
            * khtml/rendering/render_flow.h:
            * khtml/rendering/render_line.cpp:
            (InlineBox::dirtyLineBoxes):
            (InlineBox::deleteLine):
            (InlineBox::extractLine):
            (InlineBox::attachLine):
            (InlineBox::adjustVerticalPosition):
            (InlineBox::root):
            (InlineBox::nextOnLineExists):
            (InlineBox::prevOnLineExists):
            (InlineFlowBox::removeChild):
            (InlineFlowBox::deleteLine):
            (InlineFlowBox::extractLine):
            (InlineFlowBox::attachLine):
            (InlineFlowBox::adjustVerticalPosition):
            (InlineFlowBox::verticallyAlignBoxes):
            (InlineFlowBox::adjustMaxAscentAndDescent):
            (RootInlineBox::adjustVerticalPosition):
            (RootInlineBox::childRemoved):
            * khtml/rendering/render_line.h:
            (khtml::InlineBox::m_extracted):
            (khtml::InlineBox::setExtracted):
            (khtml::InlineBox::object):
            (khtml::InlineBox::parent):
            (khtml::InlineBox::isDirty):
            (khtml::InlineBox::markDirty):
            (khtml::InlineFlowBox::prevFlowBox):
            (khtml::InlineFlowBox::nextFlowBox):
            (khtml::RootInlineBox::RootInlineBox):
            (khtml::RootInlineBox::nextRootBox):
            (khtml::RootInlineBox::prevRootBox):
            (khtml::RootInlineBox::setLineBreakInfo):
            (khtml::RootInlineBox::setLineBreakPos):
            (khtml::RootInlineBox::setBlockHeight):
            (khtml::RootInlineBox::setEndsWithBreak):
            (khtml::RootInlineBox::blockHeight):
            (khtml::RootInlineBox::endsWithBreak):
            (khtml::RootInlineBox::lineBreakObj):
            (khtml::RootInlineBox::lineBreakPos):
            * khtml/rendering/render_object.cpp:
            (RenderObject::repaintAfterLayoutIfNeeded):
            (RenderObject::repaintObjectsBeforeLayout):
            (RenderObject::dirtyLinesFromChangedChild):
            (RenderObject::createInlineBox):
            (RenderObject::dirtyLineBoxes):
            (RenderObject::setInlineBoxWrapper):
            (RenderObject::deleteLineBoxWrapper):
            * khtml/rendering/render_object.h:
            (khtml::RenderObject::RepaintInfo::m_repaintRect):
            * khtml/rendering/render_table.cpp:
            (RenderTableSection::layoutRows):
            * khtml/rendering/render_text.cpp:
            (InlineTextBox::deleteLine):
            (InlineTextBox::extractLine):
            (InlineTextBox::attachLine):
            (RenderText::RenderText):
            (RenderText::detach):
            (RenderText::extractTextBox):
            (RenderText::attachTextBox):
            (RenderText::removeTextBox):
            (RenderText::setTextWithOffset):
            (RenderText::setText):
            (RenderText::dirtyLineBoxes):
            (RenderText::createInlineBox):
            * khtml/rendering/render_text.h:
            (khtml::InlineTextBox::start):
            (khtml::InlineTextBox::end):
            (khtml::InlineTextBox::offsetRun):
            * khtml/xml/dom_textimpl.cpp:
            (CharacterDataImpl::setData):
            (CharacterDataImpl::appendData):
            (CharacterDataImpl::insertData):
            (CharacterDataImpl::deleteData):
            (CharacterDataImpl::replaceData):
            (TextImpl::splitText):
            * kwq/KWQRenderTreeDebug.cpp:
            (write):
    
    	RenderBlock contains two other fixes.  The first is a fix to rightmost/lowestPosition to properly add in
    	margins to floats.
    
    	Reviewed by mjs
    
    	The second fix is to repair a bug in block-level replaced elements with margins.  If the floats they moved to
    	dodge can fit in their margins, then they don't technically have to move at all.
    
    	Reviewed by john
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@6107 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 7346623..55def2b 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,163 @@
+2004-02-23  David Hyatt  <hyatt at apple.com>
+
+	Fix for 3558717, make sure that form elements that are removed from a document also remove themselves
+	from the form.
+
+	Reviewed by darin.
+	
+        * khtml/html/html_formimpl.cpp:
+        (HTMLGenericFormElementImpl::removedFromDocument):
+        * khtml/html/html_formimpl.h:
+        * khtml/xml/dom_nodeimpl.cpp:
+        * khtml/xml/dom_nodeimpl.h:
+
+	Implement smarter line layout for faster typing and repainting when individual lines change.
+
+	Reviewed by kocienda.
+	
+	* khtml/khtmlview.cpp:
+        (KHTMLViewPrivate::KHTMLViewPrivate):
+        (KHTMLViewPrivate::~KHTMLViewPrivate):
+        (KHTMLViewPrivate::reset):
+        (KHTMLView::addRepaintInfo):
+        (KHTMLView::layout):
+        * khtml/khtmlview.h:
+        * khtml/rendering/bidi.cpp:
+        (khtml::Bidinext):
+        (khtml::appendRun):
+        (khtml::embed):
+        (khtml::RenderBlock::constructLine):
+        (khtml::RenderBlock::computeHorizontalPositionsForLine):
+        (khtml::RenderBlock::computeVerticalPositionsForLine):
+        (khtml::RenderBlock::bidiReorderLine):
+        (khtml::buildCompactRuns):
+        (khtml::RenderBlock::layoutInlineChildren):
+        (khtml::RenderBlock::determineStartPosition):
+        (khtml::RenderBlock::determineEndPosition):
+        (khtml::RenderBlock::matchedEndLine):
+        (khtml::RenderBlock::findNextLineBreak):
+        * khtml/rendering/render_block.cpp:
+        (khtml:::RenderFlow):
+        (khtml::RenderBlock::layoutBlock):
+        (khtml::RenderBlock::layoutBlockChildren):
+        (khtml::RenderBlock::positionNewFloats):
+        (khtml::RenderBlock::lowestPosition):
+        (khtml::RenderBlock::rightmostPosition):
+        (khtml::RenderBlock::leftmostPosition):
+        * khtml/rendering/render_block.h:
+        (khtml::RenderBlock::firstRootBox):
+        (khtml::RenderBlock::lastRootBox):
+        (khtml::RenderBlock::setLinesAppended):
+        (khtml::RenderBlock::linesAppended):
+        * khtml/rendering/render_box.cpp:
+        (RenderBox::dirtyLineBoxes):
+        (RenderBox::deleteLineBoxWrapper):
+        (RenderBox::setInlineBoxWrapper):
+        * khtml/rendering/render_box.h:
+        * khtml/rendering/render_br.cpp:
+        (RenderBR::createInlineBox):
+        (RenderBR::position):
+        * khtml/rendering/render_br.h:
+        * khtml/rendering/render_container.cpp:
+        (RenderContainer::appendChildNode):
+        (RenderContainer::insertChildNode):
+        * khtml/rendering/render_flexbox.cpp:
+        (khtml::RenderFlexibleBox::placeChild):
+        * khtml/rendering/render_flow.cpp:
+        (RenderFlow::extractLineBox):
+        (RenderFlow::attachLineBox):
+        (RenderFlow::removeLineBox):
+        (RenderFlow::dirtyLinesFromChangedChild):
+        (RenderFlow::dirtyLineBoxes):
+        (RenderFlow::createInlineBox):
+        * khtml/rendering/render_flow.h:
+        * khtml/rendering/render_line.cpp:
+        (InlineBox::dirtyLineBoxes):
+        (InlineBox::deleteLine):
+        (InlineBox::extractLine):
+        (InlineBox::attachLine):
+        (InlineBox::adjustVerticalPosition):
+        (InlineBox::root):
+        (InlineBox::nextOnLineExists):
+        (InlineBox::prevOnLineExists):
+        (InlineFlowBox::removeChild):
+        (InlineFlowBox::deleteLine):
+        (InlineFlowBox::extractLine):
+        (InlineFlowBox::attachLine):
+        (InlineFlowBox::adjustVerticalPosition):
+        (InlineFlowBox::verticallyAlignBoxes):
+        (InlineFlowBox::adjustMaxAscentAndDescent):
+        (RootInlineBox::adjustVerticalPosition):
+        (RootInlineBox::childRemoved):
+        * khtml/rendering/render_line.h:
+        (khtml::InlineBox::m_extracted):
+        (khtml::InlineBox::setExtracted):
+        (khtml::InlineBox::object):
+        (khtml::InlineBox::parent):
+        (khtml::InlineBox::isDirty):
+        (khtml::InlineBox::markDirty):
+        (khtml::InlineFlowBox::prevFlowBox):
+        (khtml::InlineFlowBox::nextFlowBox):
+        (khtml::RootInlineBox::RootInlineBox):
+        (khtml::RootInlineBox::nextRootBox):
+        (khtml::RootInlineBox::prevRootBox):
+        (khtml::RootInlineBox::setLineBreakInfo):
+        (khtml::RootInlineBox::setLineBreakPos):
+        (khtml::RootInlineBox::setBlockHeight):
+        (khtml::RootInlineBox::setEndsWithBreak):
+        (khtml::RootInlineBox::blockHeight):
+        (khtml::RootInlineBox::endsWithBreak):
+        (khtml::RootInlineBox::lineBreakObj):
+        (khtml::RootInlineBox::lineBreakPos):
+        * khtml/rendering/render_object.cpp:
+        (RenderObject::repaintAfterLayoutIfNeeded):
+        (RenderObject::repaintObjectsBeforeLayout):
+        (RenderObject::dirtyLinesFromChangedChild):
+        (RenderObject::createInlineBox):
+        (RenderObject::dirtyLineBoxes):
+        (RenderObject::setInlineBoxWrapper):
+        (RenderObject::deleteLineBoxWrapper):
+        * khtml/rendering/render_object.h:
+        (khtml::RenderObject::RepaintInfo::m_repaintRect):
+        * khtml/rendering/render_table.cpp:
+        (RenderTableSection::layoutRows):
+        * khtml/rendering/render_text.cpp:
+        (InlineTextBox::deleteLine):
+        (InlineTextBox::extractLine):
+        (InlineTextBox::attachLine):
+        (RenderText::RenderText):
+        (RenderText::detach):
+        (RenderText::extractTextBox):
+        (RenderText::attachTextBox):
+        (RenderText::removeTextBox):
+        (RenderText::setTextWithOffset):
+        (RenderText::setText):
+        (RenderText::dirtyLineBoxes):
+        (RenderText::createInlineBox):
+        * khtml/rendering/render_text.h:
+        (khtml::InlineTextBox::start):
+        (khtml::InlineTextBox::end):
+        (khtml::InlineTextBox::offsetRun):
+        * khtml/xml/dom_textimpl.cpp:
+        (CharacterDataImpl::setData):
+        (CharacterDataImpl::appendData):
+        (CharacterDataImpl::insertData):
+        (CharacterDataImpl::deleteData):
+        (CharacterDataImpl::replaceData):
+        (TextImpl::splitText):
+        * kwq/KWQRenderTreeDebug.cpp:
+        (write):
+
+	RenderBlock contains two other fixes.  The first is a fix to rightmost/lowestPosition to properly add in
+	margins to floats.
+
+	Reviewed by mjs
+
+	The second fix is to repair a bug in block-level replaced elements with margins.  If the floats they moved to
+	dodge can fit in their margins, then they don't technically have to move at all.
+
+	Reviewed by john
+
 2004-02-20  Maciej Stachowiak  <mjs at apple.com>
 
         Reviewed by Darin.
diff --git a/WebCore/khtml/html/html_formimpl.cpp b/WebCore/khtml/html/html_formimpl.cpp
index d1af261..135a7cd 100644
--- a/WebCore/khtml/html/html_formimpl.cpp
+++ b/WebCore/khtml/html/html_formimpl.cpp
@@ -780,6 +780,15 @@ void HTMLGenericFormElementImpl::attach()
     }
 }
 
+void HTMLGenericFormElementImpl::removedFromDocument()
+{
+    if (m_form)
+        m_form->removeFormElement(this);
+    m_form = 0;
+   
+    HTMLElementImpl::removedFromDocument();
+}
+
 HTMLFormElementImpl *HTMLGenericFormElementImpl::getForm() const
 {
     NodeImpl *p = parentNode();
diff --git a/WebCore/khtml/html/html_formimpl.h b/WebCore/khtml/html/html_formimpl.h
index 147d263..e894b41 100644
--- a/WebCore/khtml/html/html_formimpl.h
+++ b/WebCore/khtml/html/html_formimpl.h
@@ -144,6 +144,8 @@ public:
 
     virtual void parseHTMLAttribute(HTMLAttributeImpl *attr);
     virtual void attach();
+    virtual void removedFromDocument();
+
     virtual void reset() {}
 
     void onSelect();
diff --git a/WebCore/khtml/khtmlview.cpp b/WebCore/khtml/khtmlview.cpp
index 041b5ab..f470029 100644
--- a/WebCore/khtml/khtmlview.cpp
+++ b/WebCore/khtml/khtmlview.cpp
@@ -96,6 +96,7 @@ class KHTMLViewPrivate {
 public:
     KHTMLViewPrivate()
     {
+        repaintRects = 0;
         underMouse = 0;
         reset();
         tp=0;
@@ -123,6 +124,7 @@ public:
         if (underMouse)
 	    underMouse->deref();
 	delete tooltip;
+        delete repaintRects;
     }
     void reset()
     {
@@ -162,6 +164,8 @@ public:
 #if APPLE_CHANGES
         firstLayout = true;
 #endif
+        if (repaintRects)
+            repaintRects->clear();
     }
 
     QPainter *tp;
@@ -204,6 +208,10 @@ public:
 #endif
     bool mousePressed;
     KHTMLToolTip *tooltip;
+    
+    // Used by objects during layout to communicate repaints that need to take place only
+    // after all layout has been completed.
+    QPtrList<RenderObject::RepaintInfo>* repaintRects;
 };
 
 #ifndef QT_NO_TOOLTIP
@@ -503,6 +511,16 @@ bool KHTMLView::needsFullRepaint() const
     return d->doFullRepaint;
 }
 
+void KHTMLView::addRepaintInfo(RenderObject* o, const QRect& r)
+{
+    if (!d->repaintRects) {
+        d->repaintRects = new QPtrList<RenderObject::RepaintInfo>;
+        d->repaintRects->setAutoDelete(true);
+    }
+    
+    d->repaintRects->append(new RenderObject::RepaintInfo(o, r));
+}
+
 void KHTMLView::layout()
 {
     if (d->layoutSuppressed)
@@ -549,6 +567,8 @@ void KHTMLView::layout()
     }
 
     d->doFullRepaint = d->firstLayout || root->printingMode();
+    if (d->repaintRects)
+        d->repaintRects->clear();
 
 #if APPLE_CHANGES
     // Now set our scrollbar state for the layout.
@@ -617,6 +637,16 @@ void KHTMLView::layout()
     root->updateWidgetPositions();
 #endif
     
+    if (d->repaintRects && !d->repaintRects->isEmpty()) {
+        // FIXME: Could optimize this and have objects removed from this list
+        // if they ever do full repaints.
+        RenderObject::RepaintInfo* r;
+        QPtrListIterator<RenderObject::RepaintInfo> it(*d->repaintRects);
+        for ( ; (r = it.current()); ++it)
+            r->m_object->repaintRectangle(r->m_repaintRect);
+        d->repaintRects->clear();
+    }
+    
     if (root->needsLayout()) {
         //qDebug("needs layout, delaying repaint");
         scheduleRelayout();
diff --git a/WebCore/khtml/khtmlview.h b/WebCore/khtml/khtmlview.h
index 03b7094..687c07e 100644
--- a/WebCore/khtml/khtmlview.h
+++ b/WebCore/khtml/khtmlview.h
@@ -158,6 +158,8 @@ public:
 
     bool needsFullRepaint() const;
     
+    void addRepaintInfo(khtml::RenderObject* o, const QRect& r);
+
 #if APPLE_CHANGES
     void resetScrollBars();
 #endif
diff --git a/WebCore/khtml/rendering/bidi.cpp b/WebCore/khtml/rendering/bidi.cpp
index c97726c..3ceb121 100644
--- a/WebCore/khtml/rendering/bidi.cpp
+++ b/WebCore/khtml/rendering/bidi.cpp
@@ -93,9 +93,9 @@ static uint sCurrMidpoint;
 static bool betweenMidpoints;
 
 static bool isLineEmpty = true;
-static bool previousLineBrokeAtBR = true;
+static bool previousLineBrokeCleanly = true;
 static QChar::Direction dir;
-static bool adjustEmbeddding;
+static bool adjustEmbedding;
 static bool emptyRun = true;
 static int numSpaces;
 
@@ -250,7 +250,7 @@ static inline RenderObject *Bidinext(RenderObject *par, RenderObject *current, B
         //kdDebug( 6040 ) << "current = " << current << endl;
         if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) {
             next = current->firstChild();
-            if ( next && adjustEmbeddding ) {
+            if ( next && adjustEmbedding ) {
                 EUnicodeBidi ub = next->style()->unicodeBidi();
                 if ( ub != UBNormal && !emptyRun ) {
                     EDirection dir = next->style()->direction();
@@ -272,7 +272,7 @@ QChar::Direction d = ( ub == Embed ? ( dir == RTL ? QChar::DirRLE : QChar::DirLR
             while (current && current != par) {
                 next = current->nextSibling();
                 if (next) break;
-                if ( adjustEmbeddding && current->style()->unicodeBidi() != UBNormal && !emptyRun ) {
+                if ( adjustEmbedding && current->style()->unicodeBidi() != UBNormal && !emptyRun ) {
                     embed( QChar::DirPDF, bidi );
                 }
                 current = current->parent();
@@ -516,8 +516,8 @@ static void appendRun( BidiState &bidi )
     kdDebug(6041) << "appendRun: dir="<<(int)dir<<endl;
 #endif
 
-    bool b = adjustEmbeddding;
-    adjustEmbeddding = false;
+    bool b = adjustEmbedding;
+    adjustEmbedding = false;
 
     int start = bidi.sor.pos;
     RenderObject *obj = bidi.sor.obj;
@@ -533,7 +533,7 @@ static void appendRun( BidiState &bidi )
     bidi.sor = bidi.eor;
     dir = QChar::DirON;
     bidi.status.eor = QChar::DirON;
-    adjustEmbeddding = b;
+    adjustEmbedding = b;
 }
 
 static void embed( QChar::Direction d, BidiState &bidi )
@@ -541,8 +541,8 @@ static void embed( QChar::Direction d, BidiState &bidi )
 #if BIDI_DEBUG > 1
     qDebug("*** embed dir=%d emptyrun=%d", d, emptyRun );
 #endif
-    bool b = adjustEmbeddding ;
-    adjustEmbeddding = false;
+    bool b = adjustEmbedding ;
+    adjustEmbedding = false;
     if ( d == QChar::DirPDF ) {
 	BidiContext *c = bidi.context->parent;
 	if (c) {
@@ -602,7 +602,7 @@ static void embed( QChar::Direction d, BidiState &bidi )
 	    bidi.status.lastStrong = runDir;
 	}
     }
-    adjustEmbeddding = b;
+    adjustEmbedding = b;
 }
 
 InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
@@ -641,7 +641,7 @@ InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
     return box;
 }
 
-InlineFlowBox* RenderBlock::constructLine(const BidiIterator &start, const BidiIterator &end)
+RootInlineBox* RenderBlock::constructLine(const BidiIterator &start, const BidiIterator &end)
 {
     if (!sFirstBidiRun)
         return 0; // We had no runs. Don't make a root inline box at all. The line is empty.
@@ -649,17 +649,18 @@ InlineFlowBox* RenderBlock::constructLine(const BidiIterator &start, const BidiI
     InlineFlowBox* parentBox = 0;
     for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
         // Create a box for our object.
-        r->box = r->obj->createInlineBox(r->obj->isPositioned(), false);
-        
-        // If we have no parent box yet, or if the run is not simply a sibling,
-        // then we need to construct inline boxes as necessary to properly enclose the
-        // run's inline box.
-        if (!parentBox || (parentBox->object() != r->obj->parent()))
-            // Create new inline boxes all the way back to the appropriate insertion point.
-            parentBox = createLineBoxes(r->obj->parent());
-
-        // Append the inline box to this line.
-        parentBox->addToLine(r->box);
+        r->box = r->obj->createInlineBox(r->obj->isPositioned(), false, sBidiRunCount == 1);
+        if (r->box) {
+            // If we have no parent box yet, or if the run is not simply a sibling,
+            // then we need to construct inline boxes as necessary to properly enclose the
+            // run's inline box.
+            if (!parentBox || (parentBox->object() != r->obj->parent()))
+                // Create new inline boxes all the way back to the appropriate insertion point.
+                parentBox = createLineBoxes(r->obj->parent());
+
+            // Append the inline box to this line.
+            parentBox->addToLine(r->box);
+        }
     }
 
     // We should have a root inline box.  It should be unconstructed and
@@ -680,16 +681,16 @@ InlineFlowBox* RenderBlock::constructLine(const BidiIterator &start, const BidiI
     lastLineBox()->setConstructed();
 
     // Return the last line.
-    return lastLineBox();
+    return lastRootBox();
 }
 
-void RenderBlock::computeHorizontalPositionsForLine(InlineFlowBox* lineBox, BidiState &bidi)
+void RenderBlock::computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiState &bidi)
 {
     // First determine our total width.
     int totWidth = lineBox->getFlowSpacingWidth();
     BidiRun* r = 0;
     for (r = sFirstBidiRun; r; r = r->nextRun) {
-        if (r->obj->isPositioned())
+        if (!r->box || r->obj->isPositioned())
             continue; // Positioned objects are only participating to figure out their
                       // correct static x position.  They have no effect on the width.
         if (r->obj->isText())
@@ -718,7 +719,7 @@ void RenderBlock::computeHorizontalPositionsForLine(InlineFlowBox* lineBox, Bidi
             numSpaces = 0;
             break;
         case JUSTIFY:
-            if (numSpaces != 0 && !bidi.current.atEnd() && !bidi.current.obj->isBR() )
+            if (numSpaces != 0 && !bidi.current.atEnd() && !lineBox->endsWithBreak())
                 break;
             // fall through
         case TAAUTO:
@@ -741,6 +742,8 @@ void RenderBlock::computeHorizontalPositionsForLine(InlineFlowBox* lineBox, Bidi
 
     if (numSpaces > 0) {
         for (r = sFirstBidiRun; r; r = r->nextRun) {
+            if (!r->box) continue;
+
             int spaceAdd = 0;
             if (numSpaces > 0 && r->obj->isText() && !r->compact) {
                 // get the number of spaces in the run
@@ -771,9 +774,10 @@ void RenderBlock::computeHorizontalPositionsForLine(InlineFlowBox* lineBox, Bidi
         m_overflowWidth = rightPos; // FIXME: Work for rtl overflow also.
 }
 
-void RenderBlock::computeVerticalPositionsForLine(InlineFlowBox* lineBox)
+void RenderBlock::computeVerticalPositionsForLine(RootInlineBox* lineBox)
 {
     lineBox->verticallyAlignBoxes(m_height);
+    lineBox->setBlockHeight(m_height);
 
     // See if the line spilled out.  If so set overflow height accordingly.
     int bottomOfLine = lineBox->bottomOverflow();
@@ -782,6 +786,8 @@ void RenderBlock::computeVerticalPositionsForLine(InlineFlowBox* lineBox)
         
     // Now make sure we place replaced render objects correctly.
     for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
+        if (!r->box) continue; // Skip runs with no line boxes.
+
         // Align positioned boxes with the top of the line box.  This is
         // a reasonable approximation of an appropriate y position.
         if (r->obj->isPositioned())
@@ -1154,9 +1160,9 @@ void RenderBlock::bidiReorderLine(const BidiIterator &start, const BidiIterator
 
 	// this causes the operator ++ to open and close embedding levels as needed
 	// for the CSS unicode-bidi property
-	adjustEmbeddding = true;
+	adjustEmbedding = true;
         bidi.current.increment( bidi );
-	adjustEmbeddding = false;
+	adjustEmbedding = false;
 
 	if ( bidi.current == end ) {
 	    if ( emptyRun )
@@ -1249,14 +1255,14 @@ static void buildCompactRuns(RenderObject* compactObj, BidiState &bidi)
         // Format the compact like it is its own single line.  We build up all the runs for
         // the little compact and then reorder them for bidi.
         RenderBlock* compactBlock = static_cast<RenderBlock*>(compactObj);
-        adjustEmbeddding = true;
+        adjustEmbedding = true;
         BidiIterator start(compactBlock, first(compactBlock, bidi), 0);
-        adjustEmbeddding = false;
+        adjustEmbedding = false;
         BidiIterator end = start;
     
         betweenMidpoints = false;
         isLineEmpty = true;
-        previousLineBrokeAtBR = true;
+        previousLineBrokeCleanly = true;
         
         end = compactBlock->findNextLineBreak(start, bidi);
         if (!isLineEmpty)
@@ -1274,10 +1280,13 @@ static void buildCompactRuns(RenderObject* compactObj, BidiState &bidi)
     sBuildingCompactRuns = false;
 }
 
-void RenderBlock::layoutInlineChildren(bool relayoutChildren)
+QRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
 {
     BidiState bidi;
 
+    bool useRepaintRect = false;
+    QRect repaintRect(0,0,0,0);
+
     m_overflowHeight = 0;
     
     invalidateVerticalPositions();
@@ -1295,37 +1304,47 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren)
     if (style()->hidesOverflow() && m_layer)
         toAdd += m_layer->horizontalScrollbarHeight();
     
-    // Clear out our line boxes.
-    deleteLineBoxes();
+    // Figure out if we should clear out our line boxes.
+    // FIXME: Handle resize eventually!
+    // FIXME: Do something better when floats are present.
+    bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren || containsFloats();
+    if (fullLayout)
+        deleteLineBoxes();
     
     if (firstChild()) {
         // layout replaced elements
         bool endOfInline = false;
-        RenderObject *o = first( this, bidi, false );
-        while ( o ) {
-            if(o->isReplaced() || o->isFloating() || o->isPositioned()) {
-                //kdDebug(6041) << "layouting replaced or floating child" << endl;
+        RenderObject *o = first(this, bidi, false);
+        bool hasFloat = false;
+        while (o) {
+            if (o->isReplaced() || o->isFloating() || o->isPositioned()) {
                 if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent())
                     o->setChildNeedsLayout(true, false);
                 if (o->isPositioned())
                     o->containingBlock()->insertPositionedObject(o);
-                else
+                else {
+                    if (o->isFloating())
+                        hasFloat = true;
+                    else if (fullLayout || o->needsLayout()) // Replaced elements
+                        o->dirtyLineBoxes(fullLayout);
                     o->layoutIfNeeded();
-                
-                if (o->isReplaced())
-                    o->deleteLineBoxWrapper();
-            }
-            else if(o->isText()) {
-                static_cast<RenderText *>(o)->deleteTextBoxes();
-                o->setNeedsLayout(false);
+                }
             }
-            else if (o->isInlineFlow() && !endOfInline) {
-                static_cast<RenderFlow*>(o)->deleteLineBoxes();
+            else if (o->isText() || (o->isInlineFlow() && !endOfInline)) {
+                if (fullLayout || o->selfNeedsLayout())
+                    o->dirtyLineBoxes(fullLayout);
                 o->setNeedsLayout(false);
             }
             o = Bidinext( this, o, bidi, false, &endOfInline);
         }
 
+        if (hasFloat)
+            fullLayout = true; // FIXME: Will need to find a way to optimize floats some day.
+        
+        if (fullLayout && !selfNeedsLayout())
+            setNeedsLayout(true, false);  // Mark ourselves as needing a full layout. This way we'll repaint like
+                                          // we're supposed to.
+
         BidiContext *startEmbed;
         if( style()->direction() == LTR ) {
             startEmbed = new BidiContext( 0, QChar::DirL );
@@ -1338,27 +1357,48 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren)
 
 	bidi.status.lastStrong = QChar::DirON;
 	bidi.status.last = QChar::DirON;
-
         bidi.context = startEmbed;
-        adjustEmbeddding = true;
-        BidiIterator start(this, first(this, bidi), 0);
-        adjustEmbeddding = false;
-        BidiIterator end = start;
-
-        m_firstLine = true;
         
         if (!smidpoints)
             smidpoints = new QMemArray<BidiIterator>;
-
+        
         sNumMidpoints = 0;
         sCurrMidpoint = 0;
         sCompactFirstBidiRun = sCompactLastBidiRun = 0;
         sCompactBidiRunCount = 0;
-
-        previousLineBrokeAtBR = true;
         
-        while( !end.atEnd() ) {
+        // We want to skip ahead to the first dirty line
+        BidiIterator start;
+        RootInlineBox* startLine = determineStartPosition(fullLayout, start, bidi);
+        
+        // We also find the first clean line and extract these lines.  We will add them back
+        // if we determine that we're able to synchronize after handling all our dirty lines.
+        BidiIterator cleanLineStart;
+        int endLineYPos;
+        RootInlineBox* endLine = (fullLayout || !startLine) ? 
+                                 0 : determineEndPosition(startLine, cleanLineStart, endLineYPos);
+        
+        if (startLine) {
+            useRepaintRect = true;
+            repaintRect.setY(m_height);
+            RenderArena* arena = renderArena();
+            RootInlineBox* box = startLine;
+            while (box) {
+                RootInlineBox* next = box->nextRootBox();
+                box->deleteLine(arena);
+                box = next;
+            }
+            startLine = 0;
+        }
+        
+        BidiIterator end = start;
+
+        bool endLineMatched = false;
+        while (!end.atEnd()) {
             start = end;
+            if (endLine && (endLineMatched = matchedEndLine(start, cleanLineStart, endLine, endLineYPos)))
+                break;
+
             betweenMidpoints = false;
             isLineEmpty = true;
             if (m_firstLine && firstChild() && firstChild()->isCompact()) {
@@ -1382,9 +1422,12 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren)
                     sBidiRunCount += sCompactBidiRunCount;
                 }
 
+                RootInlineBox* lineBox = 0;
                 if (sBidiRunCount) {
-                    InlineFlowBox* lineBox = constructLine(start, end);
+                    lineBox = constructLine(start, end);
                     if (lineBox) {
+                        lineBox->setEndsWithBreak(previousLineBrokeCleanly);
+                        
                         // Now we position all of our text runs horizontally.
                         computeHorizontalPositionsForLine(lineBox, bidi);
         
@@ -1395,16 +1438,15 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren)
                     }
                 }
                 
-                if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) {
-                    adjustEmbeddding = true;
+                if (end == start || (end.obj && end.obj->style()->whiteSpace() == PRE && end.current() == QChar('\n'))) {
+                    adjustEmbedding = true;
                     end.increment(bidi);
-                    adjustEmbeddding = false;
-                } else if (end.obj && end.obj->style()->whiteSpace() == PRE && end.current() == QChar('\n')) {
-                    adjustEmbeddding = true;
-                    end.increment(bidi);
-                    adjustEmbeddding = false;
+                    adjustEmbedding = false;
                 }
 
+                if (lineBox)
+                    lineBox->setLineBreakInfo(end.obj, end.pos);
+                
                 m_firstLine = false;
                 newLine();
             }
@@ -1416,6 +1458,45 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren)
         }
         startEmbed->deref();
         //embed->deref();
+        
+        if (endLine) {
+            if (endLineMatched) {
+                // Attach all the remaining lines, and then adjust their y-positions as needed.
+                for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
+                    line->attachLine();
+                
+                // Now apply the offset to each line if needed.
+                int delta = m_height - endLineYPos;
+                if (delta)
+                    for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
+                        line->adjustVerticalPosition(delta);
+
+                // Now set our height and check for overflow.
+                int currYPos = m_height;
+                m_height = lastRootBox()->blockHeight();
+                m_overflowHeight = kMax(m_height, m_overflowHeight);
+                int bottomOfLine = lastRootBox()->bottomOverflow();
+                if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
+                    m_overflowHeight = bottomOfLine;
+                if (delta)
+                    repaintRect.setHeight(kMax(m_overflowHeight-delta, m_overflowHeight) - repaintRect.y());
+                else
+                    repaintRect.setHeight(currYPos - repaintRect.y());
+            }
+            else {
+                // Delete all the remaining lines.
+                m_overflowHeight = kMax(m_height, m_overflowHeight);
+                InlineRunBox* line = endLine;
+                RenderArena* arena = renderArena();
+                while (line) {
+                    InlineRunBox* next = line->nextLineBox();
+                    if (!next)
+                        repaintRect.setHeight(kMax(m_overflowHeight, line->bottomOverflow()) - repaintRect.y());
+                    line->deleteLine(arena);
+                    line = next;
+                }
+            }
+        }
     }
 
     sNumMidpoints = 0;
@@ -1430,9 +1511,18 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren)
     m_height += toAdd;
 
     // Always make sure this is at least our height.
-    if (m_overflowHeight < m_height)
-        m_overflowHeight = m_height;
+    m_overflowHeight = kMax(m_height, m_overflowHeight);
+    
+    if (useRepaintRect) {
+        repaintRect.setWidth(kMax((int)m_width, m_overflowWidth));
+        if (repaintRect.height() == 0)
+            repaintRect.setHeight(m_overflowHeight - repaintRect.y());
+    }
+    
+    setLinesAppended(false);
     
+    return repaintRect;
+
 #if BIDI_DEBUG > 1
     kdDebug(6041) << " ------- bidi end " << this << " -------" << endl;
 #endif
@@ -1440,6 +1530,128 @@ void RenderBlock::layoutInlineChildren(bool relayoutChildren)
     //kdDebug(6040) << "height = " << m_height <<endl;
 }
 
+RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiIterator& start, BidiState& bidi)
+{
+    RootInlineBox* curr = 0;
+    RootInlineBox* last = 0;
+    RenderObject* startObj = 0;
+    int pos = 0;
+    
+    if (fullLayout) {
+        // Nuke all our lines.
+        if (firstRootBox()) {
+            RenderArena* arena = renderArena();
+            curr = firstRootBox(); 
+            while (curr) {
+                RootInlineBox* next = curr->nextRootBox();
+                curr->deleteLine(arena);
+                curr = next;
+            }
+            KHTMLAssert(!m_firstLineBox && !m_lastLineBox);
+        }
+    }
+    else {
+        for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox());
+        if (curr) {
+            // We have a dirty line.
+            if (curr->prevRootBox()) {
+                // We have a previous line.
+                if (!curr->prevRootBox()->endsWithBreak())
+                    curr = curr->prevRootBox();  // The previous line didn't break cleanly, so treat it as dirty also.
+            }
+        }
+        else {
+            // No dirty lines were found.
+            // If the last line didn't break cleanly, treat it as dirty.
+            if (lastRootBox() && !lastRootBox()->endsWithBreak())
+                curr = lastRootBox();
+        }
+        
+        // If we have no dirty lines, then last is just the last root box.
+        last = curr ? curr->prevRootBox() : lastRootBox();
+    }
+    
+    m_firstLine = !last;
+    previousLineBrokeCleanly = !last || last->endsWithBreak();
+    if (last) {
+        m_height = last->blockHeight();
+        int bottomOfLine = last->bottomOverflow();
+        if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
+            m_overflowHeight = bottomOfLine;
+        startObj = last->lineBreakObj();
+        pos = last->lineBreakPos();
+    }
+    else
+        startObj = first(this, bidi, 0);
+        
+    adjustEmbedding = true;
+    start = BidiIterator(this, startObj, pos);
+    adjustEmbedding = false;
+    
+    return curr;
+}
+
+RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiIterator& cleanLineStart,
+                                                 int& yPos)
+{
+    RootInlineBox* last = 0;
+    if (m_linesAppended)
+        last = 0;
+    else {
+        for (RootInlineBox* curr = startLine; curr; curr = curr->nextRootBox())
+            if (curr->isDirty() && curr->nextRootBox() && !curr->nextRootBox()->isDirty())
+                last = curr->nextRootBox();
+    }
+    
+    if (!last)
+        return 0;
+    
+    cleanLineStart = BidiIterator(this, last->prevRootBox()->lineBreakObj(), last->prevRootBox()->lineBreakPos());
+    yPos = last->prevRootBox()->blockHeight();
+    
+    for (RootInlineBox* line = last; line; line = line->nextRootBox())
+        line->extractLine(); // Disconnect all line boxes from their render objects while preserving
+                             // their connections to one another.
+    
+    return last;
+}
+
+bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiIterator& endLineStart, 
+                                 RootInlineBox*& endLine, int& endYPos)
+{
+    if (start == endLineStart)
+        return true; // The common case. All the data we already have is correct.
+    else {
+        // The first clean line doesn't match, but we can check a handful of following lines to try
+        // to match back up.
+        static int numLines = 8; // The # of lines we're willing to match against.
+        RootInlineBox* line = endLine;
+        for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
+            if (line->lineBreakObj() == start.obj && line->lineBreakPos() == start.pos) {
+                // We have a match.
+                RootInlineBox* result = line->nextRootBox();
+                                
+                // Set our yPos to be the block height of endLine.
+                if (result)
+                    endYPos = line->blockHeight();
+                
+                // Now delete the lines that we failed to sync.
+                RootInlineBox* boxToDelete = endLine;
+                RenderArena* arena = renderArena();
+                while (boxToDelete && boxToDelete != result) {
+                    RootInlineBox* next = boxToDelete->nextRootBox();
+                    boxToDelete->deleteLine(arena);
+                    boxToDelete = next;
+                }
+
+                endLine = result;
+                return result;
+            }
+        }
+    }
+    return false;
+}
+
 BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi)
 {
     int width = lineWidth(m_height);
@@ -1473,9 +1685,9 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi
             }
         }
         
-        adjustEmbeddding = true;
+        adjustEmbedding = true;
         start.increment(bidi);
-        adjustEmbeddding = false;
+        adjustEmbedding = false;
     }
     
     if ( start.atEnd() ){
@@ -1502,18 +1714,19 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi
     RenderObject *last = o;
     int pos = start.pos;
 
-    bool prevLineBrokeCleanly = previousLineBrokeAtBR;
-    previousLineBrokeAtBR = false;
+    bool prevLineBrokeCleanly = previousLineBrokeCleanly;
+    previousLineBrokeCleanly = false;
     
     while( o ) {
 #ifdef DEBUG_LINEBREAKS
         kdDebug(6041) << "new object "<< o <<" width = " << w <<" tmpw = " << tmpW << endl;
 #endif
         if(o->isBR()) {
-            if( w + tmpW <= width ) {
+            if (w + tmpW <= width) {
                 lBreak.obj = o;
                 lBreak.pos = 0;
-             
+                lBreak.increment(bidi);
+
                 // A <br> always breaks a line, so don't let the line be collapsed
                 // away. Also, the space at the end of a line with a <br> does not
                 // get collapsed away.  It only does this if the previous line broke
@@ -1522,7 +1735,7 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi
                 if (prevLineBrokeCleanly)
                     isLineEmpty = false;
                 trailingSpaceObject = 0;
-                previousLineBrokeAtBR = true;
+                previousLineBrokeCleanly = true;
 
                 if (!isLineEmpty) {
                     // only check the clear status for non-empty lines.
@@ -1720,6 +1933,7 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi
                     if( *(str+pos) == '\n' && isPre) {
                         lBreak.obj = o;
                         lBreak.pos = pos;
+                        previousLineBrokeCleanly = true;
                         
 #ifdef DEBUG_LINEBREAKS
                         kdDebug(6041) << "forced break sol: " << start.obj << " " << start.pos << "   end: " << lBreak.obj << " " << lBreak.pos << "   width=" << w << endl;
diff --git a/WebCore/khtml/rendering/render_block.cpp b/WebCore/khtml/rendering/render_block.cpp
index c910114..38e51fd 100644
--- a/WebCore/khtml/rendering/render_block.cpp
+++ b/WebCore/khtml/rendering/render_block.cpp
@@ -53,6 +53,7 @@ RenderBlock::RenderBlock(DOM::NodeImpl* node)
     m_positionedObjects = 0;
     m_pre = false;
     m_firstLine = false;
+    m_linesAppended = false;
     m_clearStatus = CNONE;
     m_maxTopPosMargin = m_maxTopNegMargin = m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
     m_topMarginQuirk = m_bottomMarginQuirk = false;
@@ -434,8 +435,9 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
     }
     
     //    kdDebug( 6040 ) << "childrenInline()=" << childrenInline() << endl;
+    QRect repaintRect(0,0,0,0);
     if (childrenInline())
-        layoutInlineChildren( relayoutChildren );
+        repaintRect = layoutInlineChildren( relayoutChildren );
     else
         layoutBlockChildren( relayoutChildren );
 
@@ -495,9 +497,14 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
         m_layer->updateScrollInfoAfterLayout();
 
     // Repaint with our new bounds if they are different from our old bounds.
+    bool didFullRepaint = false;
     if (checkForRepaint)
-        repaintAfterLayoutIfNeeded(oldBounds, oldFullBounds);
-
+        didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldFullBounds);
+    if (!didFullRepaint && !repaintRect.isEmpty()) {
+        RenderCanvas* c = canvas();
+        if (c && c->view())
+            c->view()->addRepaintInfo(this, repaintRect); // We need to do a partial repaint of our content.
+    }
     setNeedsLayout(false);
 }
 
@@ -967,7 +974,9 @@ void RenderBlock::layoutBlockChildren( bool relayoutChildren )
             // to shift over as necessary to dodge any floats that might get in the way.
             if (child->avoidsFloats()) {
                 int leftOff = leftOffset(m_height);
-                if (leftOff != xPos) {
+                if (style()->textAlign() != KHTML_CENTER && child->style()->marginLeft().type != Variable)
+                    chPos = kMax(chPos, leftOff); // Let the float sit in the child's margin if it can fit.
+                else if (leftOff != xPos) {
                     // The object is shifting right. The object might be centered, so we need to
                     // recalculate our horizontal margins. Note that the containing block content
                     // width computation will take into account the delta between |leftOff| and |xPos|
@@ -982,8 +991,23 @@ void RenderBlock::layoutBlockChildren( bool relayoutChildren )
             }
         } else {
             chPos -= child->width() + child->marginRight();
-            if (child->avoidsFloats())
-                chPos -= (xPos - rightOffset(m_height));
+            if (child->avoidsFloats()) {
+                int rightOff = rightOffset(m_height);
+                if (style()->textAlign() != KHTML_CENTER && child->style()->marginRight().type != Variable)
+                    chPos = kMin(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit.
+                else if (rightOff != xPos) {
+                    // The object is shifting left. The object might be centered, so we need to
+                    // recalculate our horizontal margins. Note that the containing block content
+                    // width computation will take into account the delta between |rightOff| and |xPos|
+                    // so that we can just pass the content width in directly to the |calcHorizontalMargins|
+                    // function.
+                    // -dwh
+                    int cw = lineWidth( child->yPos() );
+                    static_cast<RenderBox*>(child)->calcHorizontalMargins
+                        ( child->style()->marginLeft(), child->style()->marginRight(), cw);
+                    chPos = rightOff - child->marginRight() - child->width();
+                }
+            }
         }
 
         child->setPos(chPos, child->yPos());
@@ -1034,7 +1058,7 @@ void RenderBlock::layoutBlockChildren( bool relayoutChildren )
         // If the child moved, we have to repaint it as well as any floating/positioned
         // descendants.  An exception is if we need a layout.  In this case, we know we're going to
         // repaint ourselves (and the child) anyway.
-        if (!selfNeedsLayout() && checkForRepaintDuringLayout())
+        if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
             child->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
         
         child = child->nextSibling();
@@ -1475,7 +1499,7 @@ void RenderBlock::positionNewFloats()
         f->endY = f->startY + _height;
 
         // If the child moved, we have to repaint it.
-        if (checkForRepaintDuringLayout())
+        if (o->checkForRepaintDuringLayout())
             o->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
 
         //kdDebug( 6040 ) << "floatingObject x/y= (" << f->left << "/" << f->startY << "-" << f->width << "/" << f->endY - f->startY << ")" << endl;
@@ -1638,7 +1662,7 @@ RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) cons
         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
         for ( ; (r = it.current()); ++it ) {
             if (!r->noPaint) {
-                int lp = r->startY + r->node->lowestPosition(false);
+                int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false);
                 bottom = kMax(bottom, lp);
             }
         }
@@ -1676,7 +1700,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
         for ( ; (r = it.current()); ++it ) {
             if (!r->noPaint) {
-                int rp = r->left + r->node->rightmostPosition(false);
+                int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false);
            	right = kMax(right, rp);
             }
         }
@@ -1714,7 +1738,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
         for ( ; (r = it.current()); ++it ) {
             if (!r->noPaint) {
-                int lp = r->left + r->node->leftmostPosition(false);
+                int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false);
                 left = kMin(left, lp);
             }
         }
diff --git a/WebCore/khtml/rendering/render_block.h b/WebCore/khtml/rendering/render_block.h
index 1c7d4c3..49d73e2 100644
--- a/WebCore/khtml/rendering/render_block.h
+++ b/WebCore/khtml/rendering/render_block.h
@@ -102,7 +102,7 @@ public:
     virtual void layout();
     virtual void layoutBlock( bool relayoutChildren );
     void layoutBlockChildren( bool relayoutChildren );
-    void layoutInlineChildren( bool relayoutChildren );
+    QRect layoutInlineChildren( bool relayoutChildren );
 
     void layoutPositionedObjects( bool relayoutChildren );
     void insertPositionedObject(RenderObject *o);
@@ -113,11 +113,15 @@ public:
     
     // the implementation of the following functions is in bidi.cpp
     void bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi );
+    RootInlineBox* determineStartPosition(bool fullLayout, BidiIterator &start, BidiState &bidi);
+    RootInlineBox* determineEndPosition(RootInlineBox* startBox, BidiIterator& cleanLineStart, int& yPos);
+    bool matchedEndLine(const BidiIterator& start, const BidiIterator& endLineStart, 
+                        RootInlineBox*& endLine, int& endYPos);
     BidiIterator findNextLineBreak(BidiIterator &start, BidiState &info );
-    InlineFlowBox* constructLine(const BidiIterator& start, const BidiIterator& end);
+    RootInlineBox* constructLine(const BidiIterator& start, const BidiIterator& end);
     InlineFlowBox* createLineBoxes(RenderObject* obj);
-    void computeHorizontalPositionsForLine(InlineFlowBox* lineBox, BidiState &bidi);
-    void computeVerticalPositionsForLine(InlineFlowBox* lineBox);
+    void computeHorizontalPositionsForLine(RootInlineBox* lineBox, BidiState &bidi);
+    void computeVerticalPositionsForLine(RootInlineBox* lineBox);
     // end bidi.cpp functions
     
     virtual void paint(PaintInfo& i, int tx, int ty);
@@ -171,6 +175,9 @@ public:
     virtual int getBaselineOfFirstLineBox();
     virtual InlineFlowBox* getFirstLineBox();
     
+    RootInlineBox* firstRootBox() { return static_cast<RootInlineBox*>(m_firstLineBox); }
+    RootInlineBox* lastRootBox() { return static_cast<RootInlineBox*>(m_lastLineBox); }
+
     // overrides RenderObject
     virtual bool requiresLayer();
     
@@ -181,6 +188,9 @@ public:
     
     bool inRootBlockContext() const;
     
+    void setLinesAppended(bool b=true) { m_linesAppended = b; }
+    bool linesAppended() const { return m_linesAppended; }
+
 #ifndef NDEBUG
     virtual void printTree(int indent=0) const;
     virtual void dump(QTextStream *stream, QString ind = "") const;
@@ -225,6 +235,7 @@ protected:
     EClear m_clearStatus  : 2; // used during layuting of paragraphs
     bool m_topMarginQuirk : 1;
     bool m_bottomMarginQuirk : 1;
+    bool m_linesAppended : 1; // Whether or not a block with inline children has had lines appended.
 
     short m_maxTopPosMargin;
     short m_maxTopNegMargin;
diff --git a/WebCore/khtml/rendering/render_box.cpp b/WebCore/khtml/rendering/render_box.cpp
index a5393c5..a3f9cb4 100644
--- a/WebCore/khtml/rendering/render_box.cpp
+++ b/WebCore/khtml/rendering/render_box.cpp
@@ -542,6 +542,19 @@ bool RenderBox::absolutePosition(int &xPos, int &yPos, bool f)
     }
 }
 
+void RenderBox::dirtyLineBoxes(bool fullLayout, bool)
+{
+    if (m_inlineBoxWrapper) {
+        if (fullLayout) {
+            m_inlineBoxWrapper->remove();
+            m_inlineBoxWrapper->detach(renderArena());
+            m_inlineBoxWrapper = 0;
+        }
+        else
+            m_inlineBoxWrapper->dirtyLineBoxes();
+    }
+}
+
 void RenderBox::position(InlineBox* box, int from, int len, bool reverse)
 {
     if (isPositioned()) {
@@ -586,6 +599,11 @@ void RenderBox::deleteLineBoxWrapper()
         m_inlineBoxWrapper->detach(renderArena());
 }
 
+void RenderBox::setInlineBoxWrapper(InlineBox* b)
+{
+    m_inlineBoxWrapper = b;
+}
+
 QRect RenderBox::getAbsoluteRepaintRect()
 {
     int ow = style() ? style()->outlineSize() : 0;
diff --git a/WebCore/khtml/rendering/render_box.h b/WebCore/khtml/rendering/render_box.h
index 8401afe..9dbd94e 100644
--- a/WebCore/khtml/rendering/render_box.h
+++ b/WebCore/khtml/rendering/render_box.h
@@ -83,10 +83,13 @@ public:
 
     virtual void position(InlineBox* box, int from, int len, bool reverse);
     
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox=false);
+
     // For inline replaced elements, this function returns the inline box that owns us.  Enables
     // the replaced RenderObject to quickly determine what line it is contained on and to easily
     // iterate over structures on the line.
     virtual InlineBox* inlineBoxWrapper() const;
+    virtual void setInlineBoxWrapper(InlineBox* b);
     void deleteLineBoxWrapper();
     
     virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
diff --git a/WebCore/khtml/rendering/render_br.cpp b/WebCore/khtml/rendering/render_br.cpp
index c1ed931..e6fb2a0 100644
--- a/WebCore/khtml/rendering/render_br.cpp
+++ b/WebCore/khtml/rendering/render_br.cpp
@@ -34,6 +34,15 @@ RenderBR::~RenderBR()
 {
 }
 
+InlineBox* RenderBR::createInlineBox(bool makePlaceholder, bool isRootLineBox, bool isOnlyRun)
+{
+    // We only make a box for a <br> if we are on a line by ourself or in strict mode
+    // (Note the use of strict mode.  In "almost strict" mode, we don't make a box for <br>.)
+    if (isOnlyRun || document()->inStrictMode())
+        return RenderText::createInlineBox(makePlaceholder, isRootLineBox, isOnlyRun);
+    return 0;
+}
+
 void RenderBR::position(InlineBox* box, int from, int len, bool reverse)
 {
     InlineTextBox *s = static_cast<InlineTextBox*>(box);
@@ -42,10 +51,6 @@ void RenderBR::position(InlineBox* box, int from, int len, bool reverse)
     m_x = s->xPos();
     m_y = s->yPos();
     m_height = s->height();
-    
-    s->remove();
-    s->detach(renderArena());
-    m_firstTextBox = m_lastTextBox = 0;
 }
 
 short RenderBR::lineHeight(bool firstLine, bool isRootLineBox) const
diff --git a/WebCore/khtml/rendering/render_br.h b/WebCore/khtml/rendering/render_br.h
index 180827c..decaf29 100644
--- a/WebCore/khtml/rendering/render_br.h
+++ b/WebCore/khtml/rendering/render_br.h
@@ -48,6 +48,7 @@ public:
     virtual void setStyle(RenderStyle* _style);
 
     // overrides
+    virtual InlineBox* createInlineBox(bool, bool, bool isOnlyRun = false);
     virtual void calcMinMaxWidth() {}
     virtual short minWidth() const { return 0; }
     virtual short maxWidth() const { return 0; }
diff --git a/WebCore/khtml/rendering/render_container.cpp b/WebCore/khtml/rendering/render_container.cpp
index acb7990..3c45cd7 100644
--- a/WebCore/khtml/rendering/render_container.cpp
+++ b/WebCore/khtml/rendering/render_container.cpp
@@ -346,6 +346,9 @@ void RenderContainer::appendChildNode(RenderObject* newChild)
     newChild->setNeedsLayoutAndMinMaxRecalc(); // Goes up the containing block hierarchy.
     if (!normalChildNeedsLayout())
         setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+    
+    if (!newChild->isFloatingOrPositioned() && childrenInline())
+        dirtyLinesFromChangedChild(newChild);
 }
 
 void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild)
@@ -378,6 +381,9 @@ void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeC
     child->setNeedsLayoutAndMinMaxRecalc();
     if (!normalChildNeedsLayout())
         setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+    
+    if (!child->isFloatingOrPositioned() && childrenInline())
+        dirtyLinesFromChangedChild(child);
 }
 
 
diff --git a/WebCore/khtml/rendering/render_flexbox.cpp b/WebCore/khtml/rendering/render_flexbox.cpp
index 0d38078..a67c750 100644
--- a/WebCore/khtml/rendering/render_flexbox.cpp
+++ b/WebCore/khtml/rendering/render_flexbox.cpp
@@ -921,7 +921,7 @@ void RenderFlexibleBox::placeChild(RenderObject* child, int x, int y)
     // If the child moved, we have to repaint it as well as any floating/positioned
     // descendants.  An exception is if we need a layout.  In this case, we know we're going to
     // repaint ourselves (and the child) anyway.
-    if (!selfNeedsLayout() && checkForRepaintDuringLayout())
+    if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
         child->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
 }
 
diff --git a/WebCore/khtml/rendering/render_flow.cpp b/WebCore/khtml/rendering/render_flow.cpp
index c038de0..4a7713c 100644
--- a/WebCore/khtml/rendering/render_flow.cpp
+++ b/WebCore/khtml/rendering/render_flow.cpp
@@ -125,6 +125,46 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
     return addChildToFlow(newChild, beforeChild);
 }
 
+void RenderFlow::extractLineBox(InlineFlowBox* box)
+{
+    m_lastLineBox = box->prevFlowBox();
+    if (box == m_firstLineBox)
+        m_firstLineBox = 0;
+    if (box->prevLineBox())
+        box->prevLineBox()->setNextLineBox(0);
+    box->setPreviousLineBox(0);
+    for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
+        curr->setExtracted();
+}
+
+void RenderFlow::attachLineBox(InlineFlowBox* box)
+{
+    if (m_lastLineBox) {
+        m_lastLineBox->setNextLineBox(box);
+        box->setPreviousLineBox(m_lastLineBox);
+    }
+    else
+        m_firstLineBox = box;
+    InlineFlowBox* last = box;
+    for (InlineFlowBox* curr = box; curr; curr = curr->nextFlowBox()) {
+        curr->setExtracted(false);
+        last = curr;
+    }
+    m_lastLineBox = last;
+}
+
+void RenderFlow::removeLineBox(InlineFlowBox* box)
+{
+    if (box == m_firstLineBox)
+        m_firstLineBox = box->nextFlowBox();
+    if (box == m_lastLineBox)
+        m_lastLineBox = box->prevFlowBox();
+    if (box->nextLineBox())
+        box->nextLineBox()->setPreviousLineBox(box->prevLineBox());
+    if (box->prevLineBox())
+        box->prevLineBox()->setNextLineBox(box->nextLineBox());
+}
+
 void RenderFlow::deleteLineBoxes()
 {
     if (m_firstLineBox) {
@@ -151,6 +191,63 @@ void RenderFlow::detach()
     RenderBox::detach();
 }
 
+void RenderFlow::dirtyLinesFromChangedChild(RenderObject* child)
+{
+    if (!parent() || selfNeedsLayout() || isTable())
+        return;
+    
+    if (!isInline() && (!child->nextSibling() || !firstLineBox())) {
+        // An append onto the end of a block or we don't have any lines anyway.  
+        // In this case we don't have to dirty any specific lines.
+        static_cast<RenderBlock*>(this)->setLinesAppended();
+        return;
+    }
+    
+    // For an empty inline, go ahead and propagate the check up to our parent.
+    if (isInline() && !firstLineBox())
+        return parent()->dirtyLinesFromChangedChild(this);
+    
+    // Try to figure out which line box we belong in.  First try to find a previous
+    // line box by examining our siblings.  If we didn't find a line box, then use our 
+    // parent's first line box.
+    RootInlineBox* box = 0;
+    for (RenderObject* curr = child->previousSibling(); curr; curr = curr->previousSibling()) {
+        if (curr->isFloatingOrPositioned())
+            continue;
+        
+        if (curr->isReplaced()) {
+            InlineBox* wrapper = curr->inlineBoxWrapper();
+            if (wrapper)
+                box = wrapper->root();
+        }
+        else if (curr->isText()) {
+            InlineTextBox* textBox = static_cast<RenderText*>(curr)->lastTextBox();
+            if (textBox)
+                box = textBox->root();
+        }
+        else if (curr->isInlineFlow()) {
+            InlineRunBox* runBox = static_cast<RenderFlow*>(curr)->lastLineBox();
+            if (runBox)
+                box = runBox->root();
+        }
+        
+        if (box)
+            break;
+    }
+    if (!box)
+        box = lastLineBox()->root();
+
+    // If we found a line box, then dirty it.
+    if (box) {
+        box->markDirty();
+        if (child->isBR()) {
+            RootInlineBox* next = box->nextRootBox();
+            if (next)
+                next->markDirty();
+        }
+    }
+}
+
 short RenderFlow::lineHeight(bool firstLine, bool isRootLineBox) const
 {
     if (firstLine) {
@@ -174,7 +271,20 @@ short RenderFlow::lineHeight(bool firstLine, bool isRootLineBox) const
     return m_lineHeight;
 }
 
-InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox)
+void RenderFlow::dirtyLineBoxes(bool fullLayout, bool isRootLineBox)
+{
+    if (!isRootLineBox && isReplaced())
+        return RenderBox::dirtyLineBoxes(isRootLineBox);
+    
+    if (fullLayout)
+        deleteLineBoxes();
+    else {
+        for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+            curr->dirtyLineBoxes();
+    }
+}
+
+InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun)
 {
     if (!isRootLineBox &&
 	(isReplaced() || makePlaceHolderBox))                     // Inline tables and inline blocks
diff --git a/WebCore/khtml/rendering/render_flow.h b/WebCore/khtml/rendering/render_flow.h
index a2d0daa..3076f7f 100644
--- a/WebCore/khtml/rendering/render_flow.h
+++ b/WebCore/khtml/rendering/render_flow.h
@@ -56,16 +56,22 @@ public:
 
     static RenderFlow* createAnonymousFlow(DOM::DocumentImpl* doc, RenderStyle* style);
 
+    void extractLineBox(InlineFlowBox* lineBox);
+    void attachLineBox(InlineFlowBox* lineBox);
+    void removeLineBox(InlineFlowBox* lineBox);
     void deleteLineBoxes();
     virtual void detach();
 
+    virtual void dirtyLinesFromChangedChild(RenderObject* child);
+    
     virtual short lineHeight(bool firstLine, bool isRootLineBox=false) const;
     
     InlineFlowBox* firstLineBox() const { return m_firstLineBox; }
     InlineFlowBox* lastLineBox() const { return m_lastLineBox; }
 
-    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
-
+    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun=false);
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox = false);
+    
     void paintLineBoxBackgroundBorder(PaintInfo& i, int _tx, int _ty);
     void paintLineBoxDecorations(PaintInfo& i, int _tx, int _ty);
 
diff --git a/WebCore/khtml/rendering/render_line.cpp b/WebCore/khtml/rendering/render_line.cpp
index fc3ce0f..fdce20b 100644
--- a/WebCore/khtml/rendering/render_line.cpp
+++ b/WebCore/khtml/rendering/render_line.cpp
@@ -90,6 +90,66 @@ long InlineBox::caretMaxOffset() const
     return 1; 
 }
 
+void InlineBox::dirtyLineBoxes()
+{
+    markDirty();
+    for (InlineFlowBox* curr = parent(); curr && !curr->isDirty(); curr = curr->parent())
+        curr->markDirty();
+}
+
+void InlineBox::deleteLine(RenderArena* arena)
+{
+    detach(arena);
+}
+
+void InlineBox::extractLine()
+{
+    m_extracted = true;
+    m_object->setInlineBoxWrapper(0);
+}
+
+void InlineBox::attachLine()
+{
+    m_extracted = false;
+    m_object->setInlineBoxWrapper(this);
+}
+
+void InlineBox::adjustVerticalPosition(int delta)
+{
+    m_y += delta;
+    if (m_object->isReplaced() || m_object->isBR())
+        m_object->setPos(m_object->xPos(), m_object->yPos() + delta);
+}
+
+RootInlineBox* InlineBox::root()
+{ 
+    if (m_parent)
+        return m_parent->root(); 
+    return static_cast<RootInlineBox*>(this);
+}
+
+bool InlineBox::nextOnLineExists() const
+{
+    if (!parent())
+        return false;
+    
+    if (nextOnLine())
+        return true;
+    
+    return parent()->nextOnLineExists();
+}
+
+bool InlineBox::prevOnLineExists() const
+{
+    if (!parent())
+        return false;
+    
+    if (prevOnLine())
+        return true;
+    
+    return parent()->prevOnLineExists();
+}
+
 int InlineFlowBox::marginLeft()
 {
     if (!includeLeftEdge())
@@ -136,6 +196,12 @@ int InlineFlowBox::getFlowSpacingWidth()
 
 void InlineFlowBox::removeChild(InlineBox* child)
 {
+    if (!m_dirty)
+        dirtyLineBoxes();
+
+    if (!child->nextOnLineExists())
+        child->root()->childRemoved(child);
+
     if (child == m_firstChild)
         m_firstChild = child->nextOnLine();
     if (child == m_lastChild)
@@ -146,26 +212,41 @@ void InlineFlowBox::removeChild(InlineBox* child)
         child->prevOnLine()->setNextOnLine(child->nextOnLine());
 }
 
-bool InlineFlowBox::nextOnLineExists()
+void InlineFlowBox::deleteLine(RenderArena* arena)
 {
-    if (!parent())
-        return false;
-
-    if (nextOnLine())
-        return true;
-
-    return parent()->nextOnLineExists();
+    InlineBox* child = m_firstChild;
+    InlineBox* next = 0;
+    while (child) {
+        next = child->nextOnLine();
+        child->deleteLine(arena);
+        child = next;
+    }
+    
+    static_cast<RenderFlow*>(m_object)->removeLineBox(this);
+    detach(arena);
 }
 
-bool InlineFlowBox::prevOnLineExists()
+void InlineFlowBox::extractLine()
 {
-    if (!parent())
-        return false;
+    if (!m_extracted)
+        static_cast<RenderFlow*>(m_object)->extractLineBox(this);
+    for (InlineBox* child = m_firstChild; child; child = child->nextOnLine())
+        child->extractLine();
+}
 
-    if (prevOnLine())
-        return true;
+void InlineFlowBox::attachLine()
+{
+    if (m_extracted)
+        static_cast<RenderFlow*>(m_object)->attachLineBox(this);
+    for (InlineBox* child = m_firstChild; child; child = child->nextOnLine())
+        child->attachLine();
+}
 
-    return parent()->prevOnLineExists();
+void InlineFlowBox::adjustVerticalPosition(int delta)
+{
+    InlineRunBox::adjustVerticalPosition(delta);
+    for (InlineBox* child = m_firstChild; child; child = child->nextOnLine())
+        child->adjustVerticalPosition(delta);
 }
 
 bool InlineFlowBox::onEndChain(RenderObject* endObject)
@@ -316,7 +397,7 @@ void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
     
     computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
 
-    if (maxAscent + maxDescent < QMAX(maxPositionTop, maxPositionBottom))
+    if (maxAscent + maxDescent < kMax(maxPositionTop, maxPositionBottom))
         adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
 
     int maxHeight = maxAscent + maxDescent;
@@ -351,7 +432,7 @@ void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
                     maxAscent = curr->height() - maxDescent;
             }
 
-            if ( maxAscent + maxDescent >= QMAX( maxPositionTop, maxPositionBottom ) )
+            if (maxAscent + maxDescent >= kMax(maxPositionTop, maxPositionBottom))
                 break;
         }
 
@@ -631,3 +712,24 @@ void InlineFlowBox::paintDecorations(RenderObject::PaintInfo& i, int _tx, int _t
 #endif
     }
 }
+
+void RootInlineBox::adjustVerticalPosition(int delta)
+{
+    InlineFlowBox::adjustVerticalPosition(delta);
+    m_topOverflow += delta;
+    m_bottomOverflow += delta;
+    m_blockHeight += delta;
+}
+
+void RootInlineBox::childRemoved(InlineBox* box)
+{
+    if (box->object() == m_lineBreakObj)
+        setLineBreakInfo(0,0);
+
+    RootInlineBox* prev = prevRootBox();
+    if (prev && prev->lineBreakObj() == box->object()) {
+        prev->setLineBreakInfo(0,0);
+        prev->markDirty();
+    }
+}
+
diff --git a/WebCore/khtml/rendering/render_line.h b/WebCore/khtml/rendering/render_line.h
index abadd9b..5cc07a5 100644
--- a/WebCore/khtml/rendering/render_line.h
+++ b/WebCore/khtml/rendering/render_line.h
@@ -27,7 +27,8 @@
 namespace khtml {
 
 class InlineFlowBox;
-
+class RootInlineBox;
+    
 // InlineBox represents a rectangle that occurs on a line.  It corresponds to
 // some RenderObject (i.e., it represents a portion of that RenderObject).
 class InlineBox
@@ -35,7 +36,7 @@ class InlineBox
 public:
     InlineBox(RenderObject* obj)
     :m_object(obj), m_x(0), m_y(0), m_width(0), m_height(0), m_baseline(0),
-     m_firstLine(false), m_constructed(false)
+     m_firstLine(false), m_constructed(false), m_dirty(false), m_extracted(false)
     {
         m_next = 0;
         m_prev = 0;
@@ -46,6 +47,12 @@ public:
 
     void detach(RenderArena* renderArena);
 
+    virtual void deleteLine(RenderArena* arena);
+    virtual void extractLine();
+    virtual void attachLine();
+
+    virtual void adjustVerticalPosition(int delta);
+
     // Overloaded new operator.
     void* operator new(size_t sz, RenderArena* renderArena) throw();
 
@@ -69,7 +76,8 @@ public:
         if (m_next)
             m_next->setConstructed();
     }
-
+    void setExtracted(bool b = true) { m_extracted = b; }
+    
     void setFirstLineStyleBit(bool f) { m_firstLine = f; }
     bool isFirstLineStyle() const { return m_firstLine; }
 
@@ -79,12 +87,16 @@ public:
     InlineBox* prevOnLine() const { return m_prev; }
     void setNextOnLine(InlineBox* next) { m_next = next; }
     void setPrevOnLine(InlineBox* prev) { m_prev = prev; }
+    bool nextOnLineExists() const;
+    bool prevOnLineExists() const;
     
-    RenderObject* object() { return m_object; }
+    RenderObject* object() const { return m_object; }
 
-    InlineFlowBox* parent() { return m_parent; }
+    InlineFlowBox* parent() const { return m_parent; }
     void setParent(InlineFlowBox* par) { m_parent = par; }
 
+    RootInlineBox* root();
+    
     void setWidth(short w) { m_width = w; }
     short width() { return m_width; }
 
@@ -108,6 +120,11 @@ public:
     virtual long caretMinOffset() const;
     virtual long caretMaxOffset() const;
     
+    bool isDirty() const { return m_dirty; }
+    void markDirty(bool dirty=true) { m_dirty = dirty; }
+
+    void dirtyLineBoxes();
+    
 public: // FIXME: Would like to make this protected, but methods are accessing these
         // members over in the part.
     RenderObject* m_object;
@@ -120,6 +137,8 @@ public: // FIXME: Would like to make this protected, but methods are accessing t
     
     bool m_firstLine : 1;
     bool m_constructed : 1;
+    bool m_dirty : 1;
+    bool m_extracted : 1;
 
     InlineBox* m_next; // The next element on the same line as us.
     InlineBox* m_prev; // The previous element on the same line as us.
@@ -164,6 +183,9 @@ public:
 
     virtual bool isInlineFlowBox() { return true; }
 
+    InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
+    InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); }
+    
     InlineBox* firstChild() { return m_firstChild; }
     InlineBox* lastChild() { return m_lastChild; }
     
@@ -186,6 +208,11 @@ public:
             m_hasTextChildren = true;
     }
 
+    virtual void deleteLine(RenderArena* arena);
+    virtual void extractLine();
+    virtual void attachLine();
+    virtual void adjustVerticalPosition(int delta);
+
     virtual void paintBackgroundAndBorder(RenderObject::PaintInfo& i, int _tx, int _ty, int xOffsetOnLine);
     virtual void paintDecorations(RenderObject::PaintInfo& i, int _tx, int _ty);
     
@@ -209,8 +236,6 @@ public:
     // Helper functions used during line construction and placement.
     void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject);
     int getFlowSpacingWidth();
-    bool nextOnLineExists();
-    bool prevOnLineExists();
     bool onEndChain(RenderObject* endObject);
     int placeBoxesHorizontally(int x);
     void verticallyAlignBoxes(int& heightOfBlock);
@@ -238,19 +263,51 @@ class RootInlineBox : public InlineFlowBox
 {
 public:
     RootInlineBox(RenderObject* obj)
-    :InlineFlowBox(obj)
-    {
-        m_topOverflow = m_bottomOverflow = 0;
-    }
+    : InlineFlowBox(obj), m_topOverflow(0), m_bottomOverflow(0), m_lineBreakObj(0), m_lineBreakPos(0), 
+      m_blockHeight(0), m_endsWithBreak(false)
+    {}
+    
+    RootInlineBox* nextRootBox() { return static_cast<RootInlineBox*>(m_nextLine); }
+    RootInlineBox* prevRootBox() { return static_cast<RootInlineBox*>(m_prevLine); }
+    
+    virtual void adjustVerticalPosition(int delta);
     
     virtual bool isRootInlineBox() { return true; }
     virtual int topOverflow() { return m_topOverflow; }
     virtual int bottomOverflow() { return m_bottomOverflow; }
     virtual void setOverflowPositions(int top, int bottom) { m_topOverflow = top; m_bottomOverflow = bottom; }
 
+    void setLineBreakInfo(RenderObject* obj, uint breakPos)
+    { m_lineBreakObj = obj; m_lineBreakPos = breakPos; }
+    void setLineBreakPos(int p) { m_lineBreakPos = p; }
+
+    void setBlockHeight(int h) { m_blockHeight = h; }
+    void setEndsWithBreak(bool b) { m_endsWithBreak = b; }
+    
+    int blockHeight() const { return m_blockHeight; }
+    bool endsWithBreak() const { return m_endsWithBreak; }
+    RenderObject* lineBreakObj() const { return m_lineBreakObj; }
+    uint lineBreakPos() const { return m_lineBreakPos; }
+
+    void childRemoved(InlineBox* box);
+
 protected:
+    // Normally we are only as tall as the style on our block dictates, but we might have content
+    // that spills out above the height of our font (e.g, a tall image), or something that extends further
+    // below our line (e.g., a child whose font has a huge descent).
     int m_topOverflow;
     int m_bottomOverflow;
+
+    // Where this line ended.  The exact object and the position within that object are stored so that
+    // we can create a BidiIterator beginning just after the end of this line.
+    RenderObject* m_lineBreakObj;
+    uint m_lineBreakPos;
+    
+    // The height of the block at the end of this line.  This is where the next line starts.
+    int m_blockHeight;
+    
+    // Whether the line ends with a <br>.
+    bool m_endsWithBreak;
 };
 
 }; //namespace
diff --git a/WebCore/khtml/rendering/render_object.cpp b/WebCore/khtml/rendering/render_object.cpp
index 2af72e5..c6c1b31 100644
--- a/WebCore/khtml/rendering/render_object.cpp
+++ b/WebCore/khtml/rendering/render_object.cpp
@@ -1154,21 +1154,23 @@ void RenderObject::repaintRectangle(const QRect& r, bool immediate)
     c->repaintViewRectangle(absRect, immediate);
 }
 
-void RenderObject::repaintAfterLayoutIfNeeded(const QRect& oldBounds, const QRect& oldFullBounds)
+bool RenderObject::repaintAfterLayoutIfNeeded(const QRect& oldBounds, const QRect& oldFullBounds)
 {
     QRect newBounds, newFullBounds;
     getAbsoluteRepaintRectIncludingFloats(newBounds, newFullBounds);
     if (newBounds != oldBounds || selfNeedsLayout()) {
         RenderObject* c = canvas();
         if (!c || !c->isCanvas())
-            return;
+            return false;
         RenderCanvas* canvasObj = static_cast<RenderCanvas*>(c);
         if (canvasObj->printingMode())
-            return; // Don't repaint if we're printing.
+            return false; // Don't repaint if we're printing.
         canvasObj->repaintViewRectangle(oldFullBounds);
         if (newBounds != oldBounds)
             canvasObj->repaintViewRectangle(newFullBounds);
+        return true;
     }
+    return false;
 }
 
 void RenderObject::repaintDuringLayoutIfMoved(int x, int y)
@@ -1189,10 +1191,8 @@ void RenderObject::repaintObjectsBeforeLayout()
     if (!needsLayout() || isText())
         return;
     
-    // FIXME: For now we just always repaint blocks with inline children, regardless of whether
-    // they're really dirty or not.
     bool blockWithInlineChildren = (isRenderBlock() && !isTable() && normalChildNeedsLayout() && childrenInline());
-    if (selfNeedsLayout() || blockWithInlineChildren) {
+    if (selfNeedsLayout()) {
         repaint();
         if (blockWithInlineChildren)
             return;
@@ -1242,6 +1242,10 @@ void RenderObject::computeAbsoluteRepaintRect(QRect& r, bool f)
         return parent()->computeAbsoluteRepaintRect(r, f);
 }
 
+void RenderObject::dirtyLinesFromChangedChild(RenderObject* child)
+{
+}
+
 #ifndef NDEBUG
 
 QString RenderObject::information() const
@@ -1995,19 +1999,28 @@ void RenderObject::removeLeftoverAnonymousBoxes()
 {
 }
 
-InlineBox* RenderObject::createInlineBox(bool,bool isRootLineBox)
+InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
 {
     KHTMLAssert(!isRootLineBox);
     return new (renderArena()) InlineBox(this);
 }
 
+void RenderObject::dirtyLineBoxes(bool, bool)
+{
+}
+
 InlineBox* RenderObject::inlineBoxWrapper() const
 {
     return 0;
 }
 
+void RenderObject::setInlineBoxWrapper(InlineBox* b)
+{
+}
+
 void RenderObject::deleteLineBoxWrapper()
-{}
+{
+}
 
 RenderStyle* RenderObject::style(bool firstLine) const {
     RenderStyle *s = m_style;
diff --git a/WebCore/khtml/rendering/render_object.h b/WebCore/khtml/rendering/render_object.h
index 0881baf..83f291f 100644
--- a/WebCore/khtml/rendering/render_object.h
+++ b/WebCore/khtml/rendering/render_object.h
@@ -322,12 +322,14 @@ public:
 
     void scheduleRelayout();
     
-    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
+    virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox, bool isOnlyRun=false);
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootLineBox=false);
     
     // For inline replaced elements, this function returns the inline box that owns us.  Enables
     // the replaced RenderObject to quickly determine what line it is contained on and to easily
     // iterate over structures on the line.
     virtual InlineBox* inlineBoxWrapper() const;
+    virtual void setInlineBoxWrapper(InlineBox* b);
     void deleteLineBoxWrapper();
     
     // for discussion of lineHeight see CSS2 spec
@@ -454,11 +456,22 @@ public:
         bool m_active;
     };
 
+    // Used to signal a specific subrect within an object that must be repainted after
+    // layout is complete.
+    struct RepaintInfo {
+        RenderObject* m_object;
+        QRect m_repaintRect;
+    
+        RepaintInfo(RenderObject* o, const QRect& r) :m_object(o), m_repaintRect(r) {}
+    };
+    
     FindSelectionResult checkSelectionPoint(int x, int y, int tx, int ty, DOM::NodeImpl*&, int& offset);
     virtual FindSelectionResult checkSelectionPointIgnoringContinuations(int x, int y, int tx, int ty, DOM::NodeImpl*&, int& offset);
     virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
                              HitTestAction hitTestAction = HitTestAll, bool inside=false);
     
+    virtual void dirtyLinesFromChangedChild(RenderObject* child);
+    
     // set the style of the object.
     virtual void setStyle(RenderStyle *style);
 
@@ -611,7 +624,7 @@ public:
     void repaintRectangle(const QRect& r, bool immediate = false);
     
     // Repaint only if our old bounds and new bounds are different.
-    virtual void repaintAfterLayoutIfNeeded(const QRect& oldBounds, const QRect& oldFullBounds);
+    bool repaintAfterLayoutIfNeeded(const QRect& oldBounds, const QRect& oldFullBounds);
 
     // Repaint only if the object moved.
     virtual void repaintDuringLayoutIfMoved(int oldX, int oldY);
diff --git a/WebCore/khtml/rendering/render_table.cpp b/WebCore/khtml/rendering/render_table.cpp
index 5bb51b7..432c3bd 100644
--- a/WebCore/khtml/rendering/render_table.cpp
+++ b/WebCore/khtml/rendering/render_table.cpp
@@ -1367,7 +1367,7 @@ int RenderTableSection::layoutRows( int toAdd )
             // If the cell moved, we have to repaint it as well as any floating/positioned
             // descendants.  An exception is if we need a layout.  In this case, we know we're going to
             // repaint ourselves (and the cell) anyway.
-            if (!table()->selfNeedsLayout() && checkForRepaintDuringLayout())
+            if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
                 cell->repaintDuringLayoutIfMoved(oldCellX, oldCellY);
         }
     }
diff --git a/WebCore/khtml/rendering/render_text.cpp b/WebCore/khtml/rendering/render_text.cpp
index ca32c83..6bde190 100644
--- a/WebCore/khtml/rendering/render_text.cpp
+++ b/WebCore/khtml/rendering/render_text.cpp
@@ -71,6 +71,28 @@ void InlineTextBox::operator delete(void* ptr, size_t sz)
     *(size_t *)ptr = sz;
 }
 
+void InlineTextBox::deleteLine(RenderArena* arena)
+{
+    static_cast<RenderText*>(m_object)->removeTextBox(this);
+    detach(arena);
+}
+
+void InlineTextBox::extractLine()
+{
+    if (m_extracted)
+        return;
+
+    static_cast<RenderText*>(m_object)->extractTextBox(this);
+}
+
+void InlineTextBox::attachLine()
+{
+    if (!m_extracted)
+        return;
+    
+    static_cast<RenderText*>(m_object)->attachTextBox(this);
+}
+
 void InlineTextBox::paintSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos)
 {
     if(startPos > m_len) return;
@@ -237,7 +259,7 @@ FindSelectionResult InlineTextBox::checkSelectionPoint(int _x, int _y, int _tx,
 // -------------------------------------------------------------------------------------
 
 RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
-    : RenderObject(node)
+    : RenderObject(node), m_linesDirty(false)
 {
     // init RenderObject attributes
     setRenderText();   // our object inherits from RenderText
@@ -297,13 +319,56 @@ RenderText::~RenderText()
 void RenderText::detach()
 {
     if (!documentBeingDestroyed()) {
-        for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
-            box->remove();
+        if (firstTextBox())
+            for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+                box->remove();
+        else if (parent() && isBR())
+            parent()->dirtyLinesFromChangedChild(this);
     }
     deleteTextBoxes();
     RenderObject::detach();
 }
 
+void RenderText::extractTextBox(InlineTextBox* box)
+{
+    m_lastTextBox = box->prevTextBox();
+    if (box == m_firstTextBox)
+        m_firstTextBox = 0;
+    if (box->prevTextBox())
+        box->prevTextBox()->setNextLineBox(0);
+    box->setPreviousLineBox(0);
+    for (InlineRunBox* curr = box; curr; curr = curr->nextLineBox())
+        curr->setExtracted();
+}
+
+void RenderText::attachTextBox(InlineTextBox* box)
+{
+    if (m_lastTextBox) {
+        m_lastTextBox->setNextLineBox(box);
+        box->setPreviousLineBox(m_lastTextBox);
+    }
+    else
+        m_firstTextBox = box;
+    InlineTextBox* last = box;
+    for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox()) {
+        curr->setExtracted(false);
+        last = curr;
+    }
+    m_lastTextBox = last;
+}
+
+void RenderText::removeTextBox(InlineTextBox* box)
+{
+    if (box == m_firstTextBox)
+        m_firstTextBox = box->nextTextBox();
+    if (box == m_lastTextBox)
+        m_lastTextBox = box->prevTextBox();
+    if (box->nextTextBox())
+        box->nextTextBox()->setPreviousLineBox(box->prevTextBox());
+    if (box->prevTextBox())
+        box->prevTextBox()->setNextLineBox(box->nextTextBox());
+}
+
 void RenderText::deleteTextBoxes()
 {
     if (firstTextBox()) {
@@ -1116,14 +1181,64 @@ const QFont &RenderText::font()
     return style()->font();
 }
 
+void RenderText::setTextWithOffset(DOMStringImpl *text, uint offset, uint len, bool force)
+{
+    uint oldLen = str ? str->l : 0;
+    uint newLen = text ? text->l : 0;
+    uint delta = newLen - oldLen;
+    uint end = len ? offset+len-1 : offset;
+
+    RootInlineBox* firstRootBox = 0;
+    RootInlineBox* lastRootBox = 0;
+    
+    // Dirty all text boxes that include characters in between offset and offset+len.
+    for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
+        // Text run is entirely before the affected range.
+        if (curr->end() < offset)
+            continue;
+        
+        // Text run is entirely after the affected range.
+        if (curr->start() > end) {
+            curr->offsetRun(delta);
+            RootInlineBox* root = curr->root();
+            if (!firstRootBox)
+                firstRootBox = root;
+            lastRootBox = root;
+        }
+        else if (curr->end() >= offset && curr->end() <= end)
+            curr->dirtyLineBoxes(); // Text run overlaps with the left end of the affected range.
+        else if (curr->start() <= offset && curr->end() >= end)
+            curr->dirtyLineBoxes(); // Text run subsumes the affected range.
+        else if (curr->start() <= end && curr->end() >= end)
+            curr->dirtyLineBoxes(); // Text run overlaps with right end of the affected range.
+    }
+    
+    // Now we have to walk all of the clean lines and adjust their cached line break information
+    // to reflect our updated offsets.
+    if (lastRootBox)
+        lastRootBox = lastRootBox->nextRootBox();
+    if (firstRootBox) {
+        RootInlineBox* prev = firstRootBox->prevRootBox();
+        if (prev)
+            firstRootBox = prev;
+    }
+    for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) {
+        if (curr->lineBreakObj() == this && curr->lineBreakPos() >= end)
+            curr->setLineBreakPos(curr->lineBreakPos()+delta);
+    }
+    
+    m_linesDirty = true;
+    setText(text, force);
+}
+
 void RenderText::setText(DOMStringImpl *text, bool force)
 {
-#if APPLE_CHANGES
     if (!text)
         return;
-#endif
-    if( !force && str == text ) return;
-    if(str) str->deref();
+    if (!force && str == text)
+        return;
+    if (str)
+        str->deref();
 
     str = text;
     if (str) {
@@ -1143,6 +1258,7 @@ void RenderText::setText(DOMStringImpl *text, bool force)
 #if APPLE_CHANGES
     cacheWidths();
 #endif
+
     // ### what should happen if we change the text of a
     // RenderBR object ?
     KHTMLAssert(!isBR() || (str->l == 1 && (*str->s) == '\n'));
@@ -1178,7 +1294,18 @@ short RenderText::baselinePosition( bool firstLine, bool ) const
         ( lineHeight( firstLine ) - fm.height() ) / 2;
 }
 
-InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox)
+void RenderText::dirtyLineBoxes(bool fullLayout, bool)
+{
+    if (fullLayout)
+        deleteTextBoxes();
+    else if (!m_linesDirty) {
+        for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+            box->dirtyLineBoxes();
+    }
+    m_linesDirty = false;
+}
+
+InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox, bool)
 {
     KHTMLAssert(!isRootLineBox);
     InlineTextBox* textBox = new (renderArena()) InlineTextBox(this);
diff --git a/WebCore/khtml/rendering/render_text.h b/WebCore/khtml/rendering/render_text.h
index 3fd9b90..02fc1a6 100644
--- a/WebCore/khtml/rendering/render_text.h
+++ b/WebCore/khtml/rendering/render_text.h
@@ -56,8 +56,17 @@ public:
     InlineTextBox* nextTextBox() const { return static_cast<InlineTextBox*>(nextLineBox()); }
     InlineTextBox* prevTextBox() const { return static_cast<InlineTextBox*>(prevLineBox()); }
     
+    uint start() const { return m_start; }
+    uint end() const { return m_len ? m_start+m_len-1 : m_start; }
+
+    void offsetRun(int d) { m_start += d; }
+
     void detach(RenderArena* arena);
     
+    virtual void deleteLine(RenderArena* arena);
+    virtual void extractLine();
+    virtual void attachLine();
+
     // Overloaded new operator.  Derived classes must override operator new
     // in order to allocate out of the RenderArena.
     void* operator new(size_t sz, RenderArena* renderArena) throw();    
@@ -118,13 +127,17 @@ public:
     
     virtual void paint(PaintInfo& i, int tx, int ty);
 
+    void extractTextBox(InlineTextBox* textBox);
+    void attachTextBox(InlineTextBox* textBox);
+    void removeTextBox(InlineTextBox* textBox);
     void deleteTextBoxes();
     virtual void detach();
     
     DOM::DOMString data() const { return str; }
     DOM::DOMStringImpl *string() const { return str; }
 
-    virtual InlineBox* createInlineBox(bool,bool);
+    virtual InlineBox* createInlineBox(bool,bool, bool isOnlyRun = false);
+    virtual void dirtyLineBoxes(bool fullLayout, bool isRootInlineBox = false);
     
     virtual void layout() {assert(false);}
 
@@ -176,6 +189,7 @@ public:
     bool isFixedWidthFont() const;
 
     void setText(DOM::DOMStringImpl *text, bool force=false);
+    void setTextWithOffset(DOM::DOMStringImpl *text, uint offset, uint len, bool force=false);
 
     virtual SelectionState selectionState() const {return m_selectionState;}
     virtual void setSelectionState(SelectionState s) {m_selectionState = s; }
@@ -230,7 +244,12 @@ protected: // members
     bool m_hasBeginWS : 1; // Whether or not we begin with WS (only true if we aren't pre)
     bool m_hasEndWS : 1; // Whether or not we end with WS (only true if we aren't pre)
     
-    // 19 bits left
+    bool m_linesDirty : 1; // This bit indicates that the text run has already dirtied specific
+                           // line boxes, and this hint will enable layoutInlineChildren to avoid
+                           // just dirtying everything when character data is modified (e.g., appended/inserted
+                           // or removed).
+
+    // 22 bits left
 #if APPLE_CHANGES
     mutable bool m_allAsciiChecked:1;
     mutable bool m_allAscii:1;
diff --git a/WebCore/khtml/xml/dom_nodeimpl.cpp b/WebCore/khtml/xml/dom_nodeimpl.cpp
index 8d1a67c..56d8dcb 100644
--- a/WebCore/khtml/xml/dom_nodeimpl.cpp
+++ b/WebCore/khtml/xml/dom_nodeimpl.cpp
@@ -1586,6 +1586,8 @@ void NodeBaseImpl::removeChildren()
         next = n->nextSibling();
         if (n->attached())
 	    n->detach();
+        if (n->inDocument())
+            n->removedFromDocument();
         n->setPreviousSibling(0);
         n->setNextSibling(0);
         n->setParent(0);
@@ -1771,6 +1773,20 @@ void NodeBaseImpl::detach()
     NodeImpl::detach();
 }
 
+void NodeBaseImpl::insertedIntoDocument()
+{
+    NodeImpl::insertedIntoDocument();
+    for (NodeImpl *child = _first; child; child = child->nextSibling())
+        child->insertedIntoDocument();
+}
+
+void NodeBaseImpl::removedFromDocument()
+{
+    NodeImpl::removedFromDocument();
+    for (NodeImpl *child = _first; child; child = child->nextSibling())
+        child->removedFromDocument();
+}
+
 void NodeBaseImpl::cloneChildNodes(NodeImpl *clone)
 {
     int exceptioncode = 0;
diff --git a/WebCore/khtml/xml/dom_nodeimpl.h b/WebCore/khtml/xml/dom_nodeimpl.h
index f97bc04..ed8b8f7 100644
--- a/WebCore/khtml/xml/dom_nodeimpl.h
+++ b/WebCore/khtml/xml/dom_nodeimpl.h
@@ -481,6 +481,9 @@ public:
     virtual unsigned long childNodeCount();
     virtual NodeImpl *childNode(unsigned long index);
 
+    virtual void insertedIntoDocument();
+    virtual void removedFromDocument();
+    
     // check for being (grand-..)father:
     bool checkNoOwner( NodeImpl *other, int &exceptioncode );
 
diff --git a/WebCore/khtml/xml/dom_textimpl.cpp b/WebCore/khtml/xml/dom_textimpl.cpp
index 4f7a9ab..19bd751 100644
--- a/WebCore/khtml/xml/dom_textimpl.cpp
+++ b/WebCore/khtml/xml/dom_textimpl.cpp
@@ -73,8 +73,7 @@ void CharacterDataImpl::setData( const DOMString &_data, int &exceptioncode )
     if(str) str->ref();
     if (m_render)
       (static_cast<RenderText*>(m_render))->setText(str);
-    setChanged(true);
-
+    
     dispatchModifiedEvent(oldStr);
     if(oldStr) oldStr->deref();
 }
@@ -109,9 +108,8 @@ void CharacterDataImpl::appendData( const DOMString &arg, int &exceptioncode )
     str->ref();
     str->append(arg.impl);
     if (m_render)
-      (static_cast<RenderText*>(m_render))->setText(str);
-    setChanged(true);
-
+      (static_cast<RenderText*>(m_render))->setTextWithOffset(str, oldStr->l, 0);
+    
     dispatchModifiedEvent(oldStr);
     oldStr->deref();
 }
@@ -128,9 +126,8 @@ void CharacterDataImpl::insertData( const unsigned long offset, const DOMString
     str->ref();
     str->insert(arg.impl, offset);
     if (m_render)
-      (static_cast<RenderText*>(m_render))->setText(str);
-    setChanged(true);
-
+      (static_cast<RenderText*>(m_render))->setTextWithOffset(str, offset, 0);
+    
     dispatchModifiedEvent(oldStr);
     oldStr->deref();
 }
@@ -147,9 +144,8 @@ void CharacterDataImpl::deleteData( const unsigned long offset, const unsigned l
     str->ref();
     str->remove(offset,count);
     if (m_render)
-      (static_cast<RenderText*>(m_render))->setText(str);
-    setChanged(true);
-
+      (static_cast<RenderText*>(m_render))->setTextWithOffset(str, offset, count);
+    
     dispatchModifiedEvent(oldStr);
     oldStr->deref();
 }
@@ -173,9 +169,8 @@ void CharacterDataImpl::replaceData( const unsigned long offset, const unsigned
     str->remove(offset,realCount);
     str->insert(arg.impl, offset);
     if (m_render)
-      (static_cast<RenderText*>(m_render))->setText(str);
-    setChanged(true);
-
+      (static_cast<RenderText*>(m_render))->setTextWithOffset(str, offset, count);
+    
     dispatchModifiedEvent(oldStr);
     oldStr->deref();
 }
@@ -356,7 +351,6 @@ TextImpl *TextImpl::splitText( const unsigned long offset, int &exceptioncode )
 
     if (m_render)
         (static_cast<RenderText*>(m_render))->setText(str);
-    setChanged(true);
     return newText;
 }
 
diff --git a/WebCore/kwq/KWQRenderTreeDebug.cpp b/WebCore/kwq/KWQRenderTreeDebug.cpp
index 2efd96f..9444208 100644
--- a/WebCore/kwq/KWQRenderTreeDebug.cpp
+++ b/WebCore/kwq/KWQRenderTreeDebug.cpp
@@ -234,7 +234,7 @@ static void write(QTextStream &ts, const RenderObject &o, int indent = 0)
     
     ts << o << "\n";
     
-    if (o.isText()) {
+    if (o.isText() && !o.isBR()) {
         const RenderText &text = static_cast<const RenderText &>(o);
         for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) {
             writeIndent(ts, indent+1);

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list