[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 06:59:12 UTC 2009


The following commit has been merged in the debian/unstable branch:
commit 33f8d493f350dc23213996921ca2efdb08dfa0d9
Author: hyatt <hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Nov 12 21:44:52 2002 +0000

    	This patch lands a rewrite of whitespace-handling in the
    	layout engine and adds support for the CSS2 white-space
    	property.
    
    	It also includes a rewrite of inlines' min/max width
    	calculations (for both flow inlines and raw text).
    
    	A problem with <form> margins has been fixed (this is a
    	regression I caused with my collapsing margin checkin).
    
            * WebCore.pbproj/project.pbxproj:
            * khtml/css/html4.css:
            * khtml/html/dtd.cpp:
            (DOM::checkChild):
            * khtml/html/html_baseimpl.cpp:
            (HTMLBodyElementImpl::attach):
            (HTMLFrameElementImpl::attach):
            (HTMLFrameSetElementImpl::attach):
            (HTMLHtmlElementImpl::attach):
            (HTMLIFrameElementImpl::attach):
            * khtml/html/html_formimpl.cpp:
            (HTMLFormElementImpl::HTMLFormElementImpl):
            (HTMLInputElementImpl::attach):
            (HTMLSelectElementImpl::attach):
            (HTMLTextAreaElementImpl::attach):
            * khtml/html/html_formimpl.h:
            * khtml/html/html_imageimpl.cpp:
            (HTMLImageElementImpl::attach):
            * khtml/html/html_inlineimpl.cpp:
            (HTMLBRElementImpl::attach):
            * khtml/html/html_objectimpl.cpp:
            (HTMLAppletElementImpl::attach):
            (HTMLEmbedElementImpl::attach):
            (HTMLObjectElementImpl::attach):
            * khtml/html/htmlparser.cpp:
            (KHTMLParser::reset):
            (KHTMLParser::parseToken):
            (KHTMLParser::insertNode):
            (KHTMLParser::popBlock):
            (KHTMLParser::popOneBlock):
            * khtml/html/htmlparser.h:
            * khtml/html/htmltokenizer.cpp:
            (HTMLTokenizer::addPending):
            (HTMLTokenizer::write):
            * khtml/misc/arena.cpp: Added.
            (CeilingLog2):
            (InitArenaPool):
            (ArenaAllocate):
            (ArenaGrow):
            (FreeArenaList):
            (ArenaRelease):
            (FreeArenaPool):
            (FinishArenaPool):
            (ArenaFinish):
            * khtml/misc/arena.h: Added.
            * khtml/rendering/bidi.cpp:
            (BidiIterator::detach):
            (throw):
            (BidiIterator::operator delete):
            (appendRunsForObject):
            (appendRun):
            (RenderFlow::bidiReorderLine):
            (deleteMidpoints):
            (RenderFlow::layoutInlineChildren):
            (RenderFlow::findNextLineBreak):
            * khtml/rendering/bidi.h:
            * khtml/rendering/render_arena.cpp: Added.
            (RenderArena::RenderArena):
            (RenderArena::~RenderArena):
            (RenderArena::allocate):
            (RenderArena::free):
            * khtml/rendering/render_arena.h: Added.
            * khtml/rendering/render_box.cpp:
            (RenderBox::setStyle):
            (RenderBox::~RenderBox):
            (RenderBox::detach):
            * khtml/rendering/render_box.h:
            * khtml/rendering/render_br.cpp:
            (RenderBR::RenderBR):
            * khtml/rendering/render_container.cpp:
            (RenderContainer::~RenderContainer):
            (RenderContainer::detach):
            * khtml/rendering/render_container.h:
            * khtml/rendering/render_flow.cpp:
            (RenderFlow::setStyle):
            (RenderFlow::layout):
            (RenderFlow::calcInlineMinMaxWidth):
            (RenderFlow::calcBlockMinMaxWidth):
            (RenderFlow::calcMinMaxWidth):
            (RenderFlow::addChild):
            (RenderFlow::makeChildrenNonInline):
            * khtml/rendering/render_flow.h:
            * khtml/rendering/render_html.cpp:
            (RenderHtml::RenderHtml):
            * khtml/rendering/render_layer.cpp:
            (RenderLayer::~RenderLayer):
            (throw):
            (RenderLayer::operator delete):
            (RenderLayer::detach):
            (RenderLayer::paint):
            (RenderLayer::nodeAtPoint):
            (RenderLayer::constructZTree):
            (RenderLayer::RenderLayerElement::operator delete):
            (RenderLayer::RenderLayerElement::detach):
            (RenderLayer::RenderZTreeNode::operator delete):
            (RenderLayer::RenderZTreeNode::detach):
            * khtml/rendering/render_layer.h:
            * khtml/rendering/render_list.cpp:
            (RenderListItem::setStyle):
            * khtml/rendering/render_object.cpp:
            (throw):
            (RenderObject::operator delete):
            (RenderObject::createObject):
            (RenderObject::renderArena):
            (RenderObject::detach):
            * khtml/rendering/render_object.h:
            * khtml/rendering/render_replaced.cpp:
            (RenderWidget::detach):
            * khtml/rendering/render_replaced.h:
            * khtml/rendering/render_root.cpp:
            (RenderRoot::RenderRoot):
            * khtml/rendering/render_table.cpp:
            (RenderTable::addChild):
            (RenderTable::calcWidth):
            (RenderTable::setCellWidths):
            (RenderTableSection::addChild):
            (RenderTableRow::addChild):
            * khtml/rendering/render_text.cpp:
            (TextSlave::detach):
            (throw):
            (TextSlave::operator delete):
            (TextSlaveArray::TextSlaveArray):
            (RenderText::RenderText):
            (RenderText::~RenderText):
            (RenderText::detach):
            (RenderText::deleteSlaves):
            (RenderText::trimmedMinMaxWidth):
            (RenderText::calcMinMaxWidth):
            (RenderText::position):
            * khtml/rendering/render_text.h:
            * khtml/xml/dom_docimpl.cpp:
            (DocumentImpl::DocumentImpl):
            (DocumentImpl::~DocumentImpl):
            (DocumentImpl::attach):
            (DocumentImpl::detach):
            * khtml/xml/dom_docimpl.h:
            * khtml/xml/dom_nodeimpl.cpp:
            (NodeImpl::detach):
            (NodeImpl::isReadOnly):
            (NodeImpl::previousRenderer):
            * khtml/xml/dom_nodeimpl.h:
            * khtml/xml/dom_stringimpl.cpp:
            * khtml/xml/dom_stringimpl.h:
            * khtml/xml/dom_textimpl.cpp:
            (CharacterDataImpl::containsOnlyWhitespace):
            (TextImpl::attach):
            * khtml/xml/dom_textimpl.h:
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@2635 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog-2002-12-03 b/WebCore/ChangeLog-2002-12-03
index 47e20bd..247d964 100644
--- a/WebCore/ChangeLog-2002-12-03
+++ b/WebCore/ChangeLog-2002-12-03
@@ -1,3 +1,163 @@
+2002-11-12  David Hyatt  <hyatt at apple.com>
+
+	This patch lands a rewrite of whitespace-handling in the
+	layout engine and adds support for the CSS2 white-space
+	property.  
+
+	It also includes a rewrite of inlines' min/max width 
+	calculations (for both flow inlines and raw text).
+
+	A problem with <form> margins has been fixed (this is a
+	regression I caused with my collapsing margin checkin).
+
+        * WebCore.pbproj/project.pbxproj:
+        * khtml/css/html4.css:
+        * khtml/html/dtd.cpp:
+        (DOM::checkChild):
+        * khtml/html/html_baseimpl.cpp:
+        (HTMLBodyElementImpl::attach):
+        (HTMLFrameElementImpl::attach):
+        (HTMLFrameSetElementImpl::attach):
+        (HTMLHtmlElementImpl::attach):
+        (HTMLIFrameElementImpl::attach):
+        * khtml/html/html_formimpl.cpp:
+        (HTMLFormElementImpl::HTMLFormElementImpl):
+        (HTMLInputElementImpl::attach):
+        (HTMLSelectElementImpl::attach):
+        (HTMLTextAreaElementImpl::attach):
+        * khtml/html/html_formimpl.h:
+        * khtml/html/html_imageimpl.cpp:
+        (HTMLImageElementImpl::attach):
+        * khtml/html/html_inlineimpl.cpp:
+        (HTMLBRElementImpl::attach):
+        * khtml/html/html_objectimpl.cpp:
+        (HTMLAppletElementImpl::attach):
+        (HTMLEmbedElementImpl::attach):
+        (HTMLObjectElementImpl::attach):
+        * khtml/html/htmlparser.cpp:
+        (KHTMLParser::reset):
+        (KHTMLParser::parseToken):
+        (KHTMLParser::insertNode):
+        (KHTMLParser::popBlock):
+        (KHTMLParser::popOneBlock):
+        * khtml/html/htmlparser.h:
+        * khtml/html/htmltokenizer.cpp:
+        (HTMLTokenizer::addPending):
+        (HTMLTokenizer::write):
+        * khtml/misc/arena.cpp: Added.
+        (CeilingLog2):
+        (InitArenaPool):
+        (ArenaAllocate):
+        (ArenaGrow):
+        (FreeArenaList):
+        (ArenaRelease):
+        (FreeArenaPool):
+        (FinishArenaPool):
+        (ArenaFinish):
+        * khtml/misc/arena.h: Added.
+        * khtml/rendering/bidi.cpp:
+        (BidiIterator::detach):
+        (throw):
+        (BidiIterator::operator delete):
+        (appendRunsForObject):
+        (appendRun):
+        (RenderFlow::bidiReorderLine):
+        (deleteMidpoints):
+        (RenderFlow::layoutInlineChildren):
+        (RenderFlow::findNextLineBreak):
+        * khtml/rendering/bidi.h:
+        * khtml/rendering/render_arena.cpp: Added.
+        (RenderArena::RenderArena):
+        (RenderArena::~RenderArena):
+        (RenderArena::allocate):
+        (RenderArena::free):
+        * khtml/rendering/render_arena.h: Added.
+        * khtml/rendering/render_box.cpp:
+        (RenderBox::setStyle):
+        (RenderBox::~RenderBox):
+        (RenderBox::detach):
+        * khtml/rendering/render_box.h:
+        * khtml/rendering/render_br.cpp:
+        (RenderBR::RenderBR):
+        * khtml/rendering/render_container.cpp:
+        (RenderContainer::~RenderContainer):
+        (RenderContainer::detach):
+        * khtml/rendering/render_container.h:
+        * khtml/rendering/render_flow.cpp:
+        (RenderFlow::setStyle):
+        (RenderFlow::layout):
+        (RenderFlow::calcInlineMinMaxWidth):
+        (RenderFlow::calcBlockMinMaxWidth):
+        (RenderFlow::calcMinMaxWidth):
+        (RenderFlow::addChild):
+        (RenderFlow::makeChildrenNonInline):
+        * khtml/rendering/render_flow.h:
+        * khtml/rendering/render_html.cpp:
+        (RenderHtml::RenderHtml):
+        * khtml/rendering/render_layer.cpp:
+        (RenderLayer::~RenderLayer):
+        (throw):
+        (RenderLayer::operator delete):
+        (RenderLayer::detach):
+        (RenderLayer::paint):
+        (RenderLayer::nodeAtPoint):
+        (RenderLayer::constructZTree):
+        (RenderLayer::RenderLayerElement::operator delete):
+        (RenderLayer::RenderLayerElement::detach):
+        (RenderLayer::RenderZTreeNode::operator delete):
+        (RenderLayer::RenderZTreeNode::detach):
+        * khtml/rendering/render_layer.h:
+        * khtml/rendering/render_list.cpp:
+        (RenderListItem::setStyle):
+        * khtml/rendering/render_object.cpp:
+        (throw):
+        (RenderObject::operator delete):
+        (RenderObject::createObject):
+        (RenderObject::renderArena):
+        (RenderObject::detach):
+        * khtml/rendering/render_object.h:
+        * khtml/rendering/render_replaced.cpp:
+        (RenderWidget::detach):
+        * khtml/rendering/render_replaced.h:
+        * khtml/rendering/render_root.cpp:
+        (RenderRoot::RenderRoot):
+        * khtml/rendering/render_table.cpp:
+        (RenderTable::addChild):
+        (RenderTable::calcWidth):
+        (RenderTable::setCellWidths):
+        (RenderTableSection::addChild):
+        (RenderTableRow::addChild):
+        * khtml/rendering/render_text.cpp:
+        (TextSlave::detach):
+        (throw):
+        (TextSlave::operator delete):
+        (TextSlaveArray::TextSlaveArray):
+        (RenderText::RenderText):
+        (RenderText::~RenderText):
+        (RenderText::detach):
+        (RenderText::deleteSlaves):
+        (RenderText::trimmedMinMaxWidth):
+        (RenderText::calcMinMaxWidth):
+        (RenderText::position):
+        * khtml/rendering/render_text.h:
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::DocumentImpl):
+        (DocumentImpl::~DocumentImpl):
+        (DocumentImpl::attach):
+        (DocumentImpl::detach):
+        * khtml/xml/dom_docimpl.h:
+        * khtml/xml/dom_nodeimpl.cpp:
+        (NodeImpl::detach):
+        (NodeImpl::isReadOnly):
+        (NodeImpl::previousRenderer):
+        * khtml/xml/dom_nodeimpl.h:
+        * khtml/xml/dom_stringimpl.cpp:
+        * khtml/xml/dom_stringimpl.h:
+        * khtml/xml/dom_textimpl.cpp:
+        (CharacterDataImpl::containsOnlyWhitespace):
+        (TextImpl::attach):
+        * khtml/xml/dom_textimpl.h:
+
 2002-11-12  Darin Adler  <darin at apple.com>
 
 	- fixed 3094819 -- Crash in -[KWQObjectTimerTarget timerFired]
diff --git a/WebCore/ChangeLog-2003-10-25 b/WebCore/ChangeLog-2003-10-25
index 47e20bd..247d964 100644
--- a/WebCore/ChangeLog-2003-10-25
+++ b/WebCore/ChangeLog-2003-10-25
@@ -1,3 +1,163 @@
+2002-11-12  David Hyatt  <hyatt at apple.com>
+
+	This patch lands a rewrite of whitespace-handling in the
+	layout engine and adds support for the CSS2 white-space
+	property.  
+
+	It also includes a rewrite of inlines' min/max width 
+	calculations (for both flow inlines and raw text).
+
+	A problem with <form> margins has been fixed (this is a
+	regression I caused with my collapsing margin checkin).
+
+        * WebCore.pbproj/project.pbxproj:
+        * khtml/css/html4.css:
+        * khtml/html/dtd.cpp:
+        (DOM::checkChild):
+        * khtml/html/html_baseimpl.cpp:
+        (HTMLBodyElementImpl::attach):
+        (HTMLFrameElementImpl::attach):
+        (HTMLFrameSetElementImpl::attach):
+        (HTMLHtmlElementImpl::attach):
+        (HTMLIFrameElementImpl::attach):
+        * khtml/html/html_formimpl.cpp:
+        (HTMLFormElementImpl::HTMLFormElementImpl):
+        (HTMLInputElementImpl::attach):
+        (HTMLSelectElementImpl::attach):
+        (HTMLTextAreaElementImpl::attach):
+        * khtml/html/html_formimpl.h:
+        * khtml/html/html_imageimpl.cpp:
+        (HTMLImageElementImpl::attach):
+        * khtml/html/html_inlineimpl.cpp:
+        (HTMLBRElementImpl::attach):
+        * khtml/html/html_objectimpl.cpp:
+        (HTMLAppletElementImpl::attach):
+        (HTMLEmbedElementImpl::attach):
+        (HTMLObjectElementImpl::attach):
+        * khtml/html/htmlparser.cpp:
+        (KHTMLParser::reset):
+        (KHTMLParser::parseToken):
+        (KHTMLParser::insertNode):
+        (KHTMLParser::popBlock):
+        (KHTMLParser::popOneBlock):
+        * khtml/html/htmlparser.h:
+        * khtml/html/htmltokenizer.cpp:
+        (HTMLTokenizer::addPending):
+        (HTMLTokenizer::write):
+        * khtml/misc/arena.cpp: Added.
+        (CeilingLog2):
+        (InitArenaPool):
+        (ArenaAllocate):
+        (ArenaGrow):
+        (FreeArenaList):
+        (ArenaRelease):
+        (FreeArenaPool):
+        (FinishArenaPool):
+        (ArenaFinish):
+        * khtml/misc/arena.h: Added.
+        * khtml/rendering/bidi.cpp:
+        (BidiIterator::detach):
+        (throw):
+        (BidiIterator::operator delete):
+        (appendRunsForObject):
+        (appendRun):
+        (RenderFlow::bidiReorderLine):
+        (deleteMidpoints):
+        (RenderFlow::layoutInlineChildren):
+        (RenderFlow::findNextLineBreak):
+        * khtml/rendering/bidi.h:
+        * khtml/rendering/render_arena.cpp: Added.
+        (RenderArena::RenderArena):
+        (RenderArena::~RenderArena):
+        (RenderArena::allocate):
+        (RenderArena::free):
+        * khtml/rendering/render_arena.h: Added.
+        * khtml/rendering/render_box.cpp:
+        (RenderBox::setStyle):
+        (RenderBox::~RenderBox):
+        (RenderBox::detach):
+        * khtml/rendering/render_box.h:
+        * khtml/rendering/render_br.cpp:
+        (RenderBR::RenderBR):
+        * khtml/rendering/render_container.cpp:
+        (RenderContainer::~RenderContainer):
+        (RenderContainer::detach):
+        * khtml/rendering/render_container.h:
+        * khtml/rendering/render_flow.cpp:
+        (RenderFlow::setStyle):
+        (RenderFlow::layout):
+        (RenderFlow::calcInlineMinMaxWidth):
+        (RenderFlow::calcBlockMinMaxWidth):
+        (RenderFlow::calcMinMaxWidth):
+        (RenderFlow::addChild):
+        (RenderFlow::makeChildrenNonInline):
+        * khtml/rendering/render_flow.h:
+        * khtml/rendering/render_html.cpp:
+        (RenderHtml::RenderHtml):
+        * khtml/rendering/render_layer.cpp:
+        (RenderLayer::~RenderLayer):
+        (throw):
+        (RenderLayer::operator delete):
+        (RenderLayer::detach):
+        (RenderLayer::paint):
+        (RenderLayer::nodeAtPoint):
+        (RenderLayer::constructZTree):
+        (RenderLayer::RenderLayerElement::operator delete):
+        (RenderLayer::RenderLayerElement::detach):
+        (RenderLayer::RenderZTreeNode::operator delete):
+        (RenderLayer::RenderZTreeNode::detach):
+        * khtml/rendering/render_layer.h:
+        * khtml/rendering/render_list.cpp:
+        (RenderListItem::setStyle):
+        * khtml/rendering/render_object.cpp:
+        (throw):
+        (RenderObject::operator delete):
+        (RenderObject::createObject):
+        (RenderObject::renderArena):
+        (RenderObject::detach):
+        * khtml/rendering/render_object.h:
+        * khtml/rendering/render_replaced.cpp:
+        (RenderWidget::detach):
+        * khtml/rendering/render_replaced.h:
+        * khtml/rendering/render_root.cpp:
+        (RenderRoot::RenderRoot):
+        * khtml/rendering/render_table.cpp:
+        (RenderTable::addChild):
+        (RenderTable::calcWidth):
+        (RenderTable::setCellWidths):
+        (RenderTableSection::addChild):
+        (RenderTableRow::addChild):
+        * khtml/rendering/render_text.cpp:
+        (TextSlave::detach):
+        (throw):
+        (TextSlave::operator delete):
+        (TextSlaveArray::TextSlaveArray):
+        (RenderText::RenderText):
+        (RenderText::~RenderText):
+        (RenderText::detach):
+        (RenderText::deleteSlaves):
+        (RenderText::trimmedMinMaxWidth):
+        (RenderText::calcMinMaxWidth):
+        (RenderText::position):
+        * khtml/rendering/render_text.h:
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::DocumentImpl):
+        (DocumentImpl::~DocumentImpl):
+        (DocumentImpl::attach):
+        (DocumentImpl::detach):
+        * khtml/xml/dom_docimpl.h:
+        * khtml/xml/dom_nodeimpl.cpp:
+        (NodeImpl::detach):
+        (NodeImpl::isReadOnly):
+        (NodeImpl::previousRenderer):
+        * khtml/xml/dom_nodeimpl.h:
+        * khtml/xml/dom_stringimpl.cpp:
+        * khtml/xml/dom_stringimpl.h:
+        * khtml/xml/dom_textimpl.cpp:
+        (CharacterDataImpl::containsOnlyWhitespace):
+        (TextImpl::attach):
+        * khtml/xml/dom_textimpl.h:
+
 2002-11-12  Darin Adler  <darin at apple.com>
 
 	- fixed 3094819 -- Crash in -[KWQObjectTimerTarget timerFired]
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index 47e20bd..247d964 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,163 @@
+2002-11-12  David Hyatt  <hyatt at apple.com>
+
+	This patch lands a rewrite of whitespace-handling in the
+	layout engine and adds support for the CSS2 white-space
+	property.  
+
+	It also includes a rewrite of inlines' min/max width 
+	calculations (for both flow inlines and raw text).
+
+	A problem with <form> margins has been fixed (this is a
+	regression I caused with my collapsing margin checkin).
+
+        * WebCore.pbproj/project.pbxproj:
+        * khtml/css/html4.css:
+        * khtml/html/dtd.cpp:
+        (DOM::checkChild):
+        * khtml/html/html_baseimpl.cpp:
+        (HTMLBodyElementImpl::attach):
+        (HTMLFrameElementImpl::attach):
+        (HTMLFrameSetElementImpl::attach):
+        (HTMLHtmlElementImpl::attach):
+        (HTMLIFrameElementImpl::attach):
+        * khtml/html/html_formimpl.cpp:
+        (HTMLFormElementImpl::HTMLFormElementImpl):
+        (HTMLInputElementImpl::attach):
+        (HTMLSelectElementImpl::attach):
+        (HTMLTextAreaElementImpl::attach):
+        * khtml/html/html_formimpl.h:
+        * khtml/html/html_imageimpl.cpp:
+        (HTMLImageElementImpl::attach):
+        * khtml/html/html_inlineimpl.cpp:
+        (HTMLBRElementImpl::attach):
+        * khtml/html/html_objectimpl.cpp:
+        (HTMLAppletElementImpl::attach):
+        (HTMLEmbedElementImpl::attach):
+        (HTMLObjectElementImpl::attach):
+        * khtml/html/htmlparser.cpp:
+        (KHTMLParser::reset):
+        (KHTMLParser::parseToken):
+        (KHTMLParser::insertNode):
+        (KHTMLParser::popBlock):
+        (KHTMLParser::popOneBlock):
+        * khtml/html/htmlparser.h:
+        * khtml/html/htmltokenizer.cpp:
+        (HTMLTokenizer::addPending):
+        (HTMLTokenizer::write):
+        * khtml/misc/arena.cpp: Added.
+        (CeilingLog2):
+        (InitArenaPool):
+        (ArenaAllocate):
+        (ArenaGrow):
+        (FreeArenaList):
+        (ArenaRelease):
+        (FreeArenaPool):
+        (FinishArenaPool):
+        (ArenaFinish):
+        * khtml/misc/arena.h: Added.
+        * khtml/rendering/bidi.cpp:
+        (BidiIterator::detach):
+        (throw):
+        (BidiIterator::operator delete):
+        (appendRunsForObject):
+        (appendRun):
+        (RenderFlow::bidiReorderLine):
+        (deleteMidpoints):
+        (RenderFlow::layoutInlineChildren):
+        (RenderFlow::findNextLineBreak):
+        * khtml/rendering/bidi.h:
+        * khtml/rendering/render_arena.cpp: Added.
+        (RenderArena::RenderArena):
+        (RenderArena::~RenderArena):
+        (RenderArena::allocate):
+        (RenderArena::free):
+        * khtml/rendering/render_arena.h: Added.
+        * khtml/rendering/render_box.cpp:
+        (RenderBox::setStyle):
+        (RenderBox::~RenderBox):
+        (RenderBox::detach):
+        * khtml/rendering/render_box.h:
+        * khtml/rendering/render_br.cpp:
+        (RenderBR::RenderBR):
+        * khtml/rendering/render_container.cpp:
+        (RenderContainer::~RenderContainer):
+        (RenderContainer::detach):
+        * khtml/rendering/render_container.h:
+        * khtml/rendering/render_flow.cpp:
+        (RenderFlow::setStyle):
+        (RenderFlow::layout):
+        (RenderFlow::calcInlineMinMaxWidth):
+        (RenderFlow::calcBlockMinMaxWidth):
+        (RenderFlow::calcMinMaxWidth):
+        (RenderFlow::addChild):
+        (RenderFlow::makeChildrenNonInline):
+        * khtml/rendering/render_flow.h:
+        * khtml/rendering/render_html.cpp:
+        (RenderHtml::RenderHtml):
+        * khtml/rendering/render_layer.cpp:
+        (RenderLayer::~RenderLayer):
+        (throw):
+        (RenderLayer::operator delete):
+        (RenderLayer::detach):
+        (RenderLayer::paint):
+        (RenderLayer::nodeAtPoint):
+        (RenderLayer::constructZTree):
+        (RenderLayer::RenderLayerElement::operator delete):
+        (RenderLayer::RenderLayerElement::detach):
+        (RenderLayer::RenderZTreeNode::operator delete):
+        (RenderLayer::RenderZTreeNode::detach):
+        * khtml/rendering/render_layer.h:
+        * khtml/rendering/render_list.cpp:
+        (RenderListItem::setStyle):
+        * khtml/rendering/render_object.cpp:
+        (throw):
+        (RenderObject::operator delete):
+        (RenderObject::createObject):
+        (RenderObject::renderArena):
+        (RenderObject::detach):
+        * khtml/rendering/render_object.h:
+        * khtml/rendering/render_replaced.cpp:
+        (RenderWidget::detach):
+        * khtml/rendering/render_replaced.h:
+        * khtml/rendering/render_root.cpp:
+        (RenderRoot::RenderRoot):
+        * khtml/rendering/render_table.cpp:
+        (RenderTable::addChild):
+        (RenderTable::calcWidth):
+        (RenderTable::setCellWidths):
+        (RenderTableSection::addChild):
+        (RenderTableRow::addChild):
+        * khtml/rendering/render_text.cpp:
+        (TextSlave::detach):
+        (throw):
+        (TextSlave::operator delete):
+        (TextSlaveArray::TextSlaveArray):
+        (RenderText::RenderText):
+        (RenderText::~RenderText):
+        (RenderText::detach):
+        (RenderText::deleteSlaves):
+        (RenderText::trimmedMinMaxWidth):
+        (RenderText::calcMinMaxWidth):
+        (RenderText::position):
+        * khtml/rendering/render_text.h:
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::DocumentImpl):
+        (DocumentImpl::~DocumentImpl):
+        (DocumentImpl::attach):
+        (DocumentImpl::detach):
+        * khtml/xml/dom_docimpl.h:
+        * khtml/xml/dom_nodeimpl.cpp:
+        (NodeImpl::detach):
+        (NodeImpl::isReadOnly):
+        (NodeImpl::previousRenderer):
+        * khtml/xml/dom_nodeimpl.h:
+        * khtml/xml/dom_stringimpl.cpp:
+        * khtml/xml/dom_stringimpl.h:
+        * khtml/xml/dom_textimpl.cpp:
+        (CharacterDataImpl::containsOnlyWhitespace):
+        (TextImpl::attach):
+        * khtml/xml/dom_textimpl.h:
+
 2002-11-12  Darin Adler  <darin at apple.com>
 
 	- fixed 3094819 -- Crash in -[KWQObjectTimerTarget timerFired]
diff --git a/WebCore/WebCore.pbproj/project.pbxproj b/WebCore/WebCore.pbproj/project.pbxproj
index fec0c5d..2d604e9 100644
--- a/WebCore/WebCore.pbproj/project.pbxproj
+++ b/WebCore/WebCore.pbproj/project.pbxproj
@@ -473,6 +473,8 @@
 				93386B92037045B3008635CE,
 				517FA6B30370BD6100CA2D3A,
 				931C8A180380288B008635CE,
+				BC7294FA03804B3C00A80166,
+				BC7294FE03804B5600A80166,
 			);
 			isa = PBXHeadersBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -705,6 +707,8 @@
 				93386B93037045B3008635CE,
 				517FA6B70370C7ED00CA2D3A,
 				931C8A190380288B008635CE,
+				BC7294F903804B3C00A80166,
+				BC7294FD03804B5600A80166,
 			);
 			isa = PBXSourcesBuildPhase;
 			runOnlyForDeploymentPostprocessing = 0;
@@ -981,6 +985,64 @@
 //932
 //933
 //934
+//BC0
+//BC1
+//BC2
+//BC3
+//BC4
+		BC7294F703804B3C00A80166 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = arena.cpp;
+			refType = 4;
+		};
+		BC7294F803804B3C00A80166 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = arena.h;
+			refType = 4;
+		};
+		BC7294F903804B3C00A80166 = {
+			fileRef = BC7294F703804B3C00A80166;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		BC7294FA03804B3C00A80166 = {
+			fileRef = BC7294F803804B3C00A80166;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		BC7294FB03804B5600A80166 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = render_arena.cpp;
+			refType = 4;
+		};
+		BC7294FC03804B5600A80166 = {
+			fileEncoding = 30;
+			isa = PBXFileReference;
+			path = render_arena.h;
+			refType = 4;
+		};
+		BC7294FD03804B5600A80166 = {
+			fileRef = BC7294FB03804B5600A80166;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+		BC7294FE03804B5600A80166 = {
+			fileRef = BC7294FC03804B5600A80166;
+			isa = PBXBuildFile;
+			settings = {
+			};
+		};
+//BC0
+//BC1
+//BC2
+//BC3
+//BC4
 //F50
 //F51
 //F52
@@ -3149,6 +3211,8 @@
 				F523D28702DE43D7018635CA,
 				F523D28802DE43D7018635CA,
 				F523D28902DE43D7018635CA,
+				BC7294F703804B3C00A80166,
+				BC7294F803804B3C00A80166,
 			);
 			isa = PBXGroup;
 			path = misc;
@@ -3699,6 +3763,8 @@
 				F523D2C402DE4438018635CA,
 				F523D2C702DE4438018635CA,
 				F523D2C602DE4438018635CA,
+				BC7294FB03804B5600A80166,
+				BC7294FC03804B5600A80166,
 			);
 			isa = PBXGroup;
 			path = rendering;
diff --git a/WebCore/khtml/css/html4.css b/WebCore/khtml/css/html4.css
index 3fc497b..2d1b85a 100644
--- a/WebCore/khtml/css/html4.css
+++ b/WebCore/khtml/css/html4.css
@@ -54,7 +54,7 @@ script {
 @media screen {
 	body {
 		display: block;
-		margin: 10px;
+		margin: 8px;
 	}
 }
 
@@ -353,16 +353,6 @@ OL OL {
 	margin-bottom: auto; 
 }
 
-LI > P { 
-	margin-top: auto; 
-	margin-bottom: auto;
-}
-      
-LI > DIV { 
-	margin-top: auto; 
-	margin-bottom: auto;
-}
-
 /*
  * form elements
  */
@@ -397,6 +387,10 @@ INPUT, TEXTAREA {
 	margin: 3px;
 }
 
+input[type="image"] {
+    margin: 0px;
+}
+
 INPUT[type="hidden"] {
 	display: none; 
 }
diff --git a/WebCore/khtml/html/dtd.cpp b/WebCore/khtml/html/dtd.cpp
index 671f784..fdf7e8d 100644
--- a/WebCore/khtml/html/dtd.cpp
+++ b/WebCore/khtml/html/dtd.cpp
@@ -308,6 +308,7 @@ static const ushort tag_list_0[] = {
 };
 
 static const ushort tag_list_1[] = {
+    ID_TEXT,
     ID_P,
     ID_H1,
     ID_H2,
@@ -334,7 +335,6 @@ static const ushort tag_list_1[] = {
     ID_TABLE,
     ID_FIELDSET,
     ID_ADDRESS,
-    ID_TEXT,
     ID_TT,
     ID_I,
     ID_B,
@@ -393,6 +393,7 @@ static const ushort tag_list_2[] = {
 };
 
 static const ushort tag_list_3[] = {
+    ID_TEXT,
     ID_P,
     ID_H1,
     ID_H2,
@@ -428,6 +429,7 @@ static const ushort tag_list_3[] = {
 };
 
 static const ushort tag_list_4[] = {
+    ID_TEXT,
     ID_PARAM,
     ID_P,
     ID_H1,
@@ -503,6 +505,7 @@ static const ushort tag_list_4[] = {
 };
 
 static const ushort tag_list_6[] = {
+    ID_TEXT,
     ID_DT,
     ID_DD,
     ID_COMMENT,
@@ -510,6 +513,7 @@ static const ushort tag_list_6[] = {
 };
 
 static const ushort tag_list_7[] = {
+    ID_TEXT,
     ID_OPTGROUP,
     ID_OPTION,
     ID_COMMENT,
@@ -532,6 +536,7 @@ static const ushort tag_list_10[] = {
 };
 
 static const ushort tag_list_11[] = {
+    ID_TEXT,
     ID_SCRIPT,
     ID_STYLE,
     ID_META,
@@ -726,6 +731,8 @@ bool DOM::checkChild(ushort tagID, ushort childID)
         case ID_THEAD:
         case ID_TFOOT:
         case ID_TBODY:
+        case ID_TEXT:
+        case ID_COMMENT:
             return true;
         default:
             return false;
@@ -734,11 +741,11 @@ bool DOM::checkChild(ushort tagID, ushort childID)
     case ID_TFOOT:
     case ID_TBODY:
         // THEAD: TR +
-        if(childID == ID_TR) return true;
+        if(childID == ID_TR || childID == ID_TEXT || childID == ID_COMMENT) return true;
         return false;
     case ID_COLGROUP:
         // COLGROUP: COL *
-        if(childID == ID_COL) return true;
+        if(childID == ID_COL || childID == ID_TEXT || childID == ID_COMMENT) return true;
         return false;
     case ID_TR:
         // TR: _9 +
diff --git a/WebCore/khtml/html/html_baseimpl.cpp b/WebCore/khtml/html/html_baseimpl.cpp
index ba9484d..a7be8c5 100644
--- a/WebCore/khtml/html/html_baseimpl.cpp
+++ b/WebCore/khtml/html/html_baseimpl.cpp
@@ -193,7 +193,7 @@ void HTMLBodyElementImpl::attach()
     RenderStyle* style = getDocument()->styleSelector()->styleForElement(this);
     style->ref();
     if (style->display() != NONE) {
-        m_render = new RenderBody(this);
+        m_render = new (getDocument()->renderArena()) RenderBody(this);
         m_render->setStyle(style);
         parentNode()->renderer()->addChild(m_render, nextRenderer());
     }
@@ -311,7 +311,7 @@ void HTMLFrameElementImpl::attach()
         }
 
     if (!selfreference)  {
-        m_render = new RenderFrame(this);
+        m_render = new (getDocument()->renderArena()) RenderFrame(this);
         m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
         parentNode()->renderer()->addChild(m_render, nextRenderer());
     }
@@ -477,7 +477,7 @@ void HTMLFrameSetElementImpl::attach()
     assert(parentNode()->renderer());
 
     // ignore display: none
-    m_render = new RenderFrameSet(this);
+    m_render = new (getDocument()->renderArena()) RenderFrameSet(this);
     m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
     parentNode()->renderer()->addChild(m_render, nextRenderer());
 
@@ -535,7 +535,7 @@ void HTMLHtmlElementImpl::attach()
     assert(parentNode());
     assert(parentNode()->renderer());
 
-    m_render = new RenderHtml(this);
+    m_render = new (getDocument()->renderArena()) RenderHtml(this);
     m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
     parentNode()->renderer()->addChild(m_render, nextRenderer());
 
@@ -623,7 +623,7 @@ void HTMLIFrameElementImpl::attach()
     _style->ref();
     if (!selfreference && !(w->part()->onlyLocalReferences() && u.protocol() != "file") &&
         parentNode()->renderer() && _style->display() != NONE) {
-        m_render = new RenderPartObject(this);
+        m_render = new (getDocument()->renderArena()) RenderPartObject(this);
         m_render->setStyle(_style);
         parentNode()->renderer()->addChild(m_render, nextRenderer());
     }
diff --git a/WebCore/khtml/html/html_formimpl.cpp b/WebCore/khtml/html/html_formimpl.cpp
index 7a6396f..cf77981 100644
--- a/WebCore/khtml/html/html_formimpl.cpp
+++ b/WebCore/khtml/html/html_formimpl.cpp
@@ -74,6 +74,7 @@ HTMLFormElementImpl::HTMLFormElementImpl(DocumentPtr *doc)
     m_enctype = "application/x-www-form-urlencoded";
     m_boundary = "----------0xKhTmLbOuNdArY";
     m_acceptcharset = "UNKNOWN";
+    m_malformed = false;
 }
 
 HTMLFormElementImpl::~HTMLFormElementImpl()
@@ -1076,18 +1077,19 @@ void HTMLInputElementImpl::attach()
     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
     _style->ref();
     if (parentNode()->renderer() && _style->display() != NONE) {
+        RenderArena* arena = getDocument()->renderArena();
         switch(m_type)
         {
         case TEXT:
         case PASSWORD:
-        case ISINDEX:      m_render = new RenderLineEdit(this);   break;
-        case CHECKBOX:  m_render = new RenderCheckBox(this); break;
-        case RADIO:        m_render = new RenderRadioButton(this); break;
-        case SUBMIT:      m_render = new RenderSubmitButton(this); break;
-        case IMAGE:       m_render =  new RenderImageButton(this); break;
-        case RESET:      m_render = new RenderResetButton(this);   break;
-        case FILE:         m_render =  new RenderFileButton(this);    break;
-        case BUTTON:  m_render = new RenderPushButton(this);
+        case ISINDEX:      m_render = new (arena) RenderLineEdit(this);   break;
+        case CHECKBOX:  m_render = new (arena) RenderCheckBox(this); break;
+        case RADIO:        m_render = new (arena) RenderRadioButton(this); break;
+        case SUBMIT:      m_render = new (arena) RenderSubmitButton(this); break;
+        case IMAGE:       m_render =  new (arena) RenderImageButton(this); break;
+        case RESET:      m_render = new (arena) RenderResetButton(this);   break;
+        case FILE:         m_render =  new (arena) RenderFileButton(this);    break;
+        case BUTTON:  m_render = new (arena) RenderPushButton(this);
         case HIDDEN:   break;
         }
     }
@@ -1697,7 +1699,7 @@ void HTMLSelectElementImpl::attach()
     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
     _style->ref();
     if (parentNode()->renderer() && _style->display() != NONE) {
-        m_render = new RenderSelect(this);
+        m_render = new (getDocument()->renderArena()) RenderSelect(this);
         m_render->setStyle(_style);
     }
 
@@ -2188,7 +2190,7 @@ void HTMLTextAreaElementImpl::attach()
     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
     _style->ref();
     if (parentNode()->renderer() && _style->display() != NONE) {
-        m_render = new RenderTextArea(this);
+        m_render = new (getDocument()->renderArena()) RenderTextArea(this);
         m_render->setStyle(_style);
     }
 
diff --git a/WebCore/khtml/html/html_formimpl.h b/WebCore/khtml/html/html_formimpl.h
index 4b75c53..a49b059 100644
--- a/WebCore/khtml/html/html_formimpl.h
+++ b/WebCore/khtml/html/html_formimpl.h
@@ -90,6 +90,9 @@ public:
     void submit();
     void reset();
 
+    void setMalformed(bool malformed) { m_malformed = malformed; }
+    virtual bool isMalformed() { return m_malformed; }
+    
     static void i18nData();
 
     friend class HTMLFormElement;
@@ -108,6 +111,7 @@ public:
     bool m_insubmit : 1;
     bool m_doingsubmit : 1;
     bool m_inreset : 1;
+    bool m_malformed : 1;
 };
 
 // -------------------------------------------------------------------------
diff --git a/WebCore/khtml/html/html_imageimpl.cpp b/WebCore/khtml/html/html_imageimpl.cpp
index f937d14..ad330e1 100644
--- a/WebCore/khtml/html/html_imageimpl.cpp
+++ b/WebCore/khtml/html/html_imageimpl.cpp
@@ -171,7 +171,7 @@ void HTMLImageElementImpl::attach()
     RenderStyle* _style = getDocument()->styleSelector()->styleForElement(this);
     _style->ref();
     if (parentNode()->renderer() && _style->display() != NONE) {
-        m_render = new RenderImage(this);
+        m_render = new (getDocument()->renderArena()) RenderImage(this);
         m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
         parentNode()->renderer()->addChild(m_render, nextRenderer());
         m_render->updateFromElement();
diff --git a/WebCore/khtml/html/html_inlineimpl.cpp b/WebCore/khtml/html/html_inlineimpl.cpp
index fd7f984..42c2374 100644
--- a/WebCore/khtml/html/html_inlineimpl.cpp
+++ b/WebCore/khtml/html/html_inlineimpl.cpp
@@ -212,7 +212,7 @@ void HTMLBRElementImpl::attach()
     assert(parentNode());
 
     if (parentNode()->renderer()) {
-        m_render = new RenderBR(this);
+        m_render = new (getDocument()->renderArena()) RenderBR(this);
         m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
         parentNode()->renderer()->addChild(m_render, nextRenderer());
     }
diff --git a/WebCore/khtml/html/html_objectimpl.cpp b/WebCore/khtml/html/html_objectimpl.cpp
index b77572e..6c244eb 100644
--- a/WebCore/khtml/html/html_objectimpl.cpp
+++ b/WebCore/khtml/html/html_objectimpl.cpp
@@ -116,12 +116,12 @@ void HTMLAppletElementImpl::attach()
 	    args.insert( "archive", archive.string() );
 
 	args.insert( "baseURL", getDocument()->baseURL() );
-        m_render = new RenderApplet(this, args);
+        m_render = new (getDocument()->renderArena()) RenderApplet(this, args);
     }
     else
         // ### remove me. we should never show an empty applet, instead
         // render the alternative content given by the webpage
-        m_render = new RenderEmptyApplet(this);
+        m_render = new (getDocument()->renderArena()) RenderEmptyApplet(this);
 #endif
 
     if (m_render) {
@@ -246,7 +246,7 @@ void HTMLEmbedElementImpl::attach()
         KHTMLView* w = getDocument()->view();
         if (w->part()->pluginsEnabled()) {
             if (parentNode()->id() != ID_OBJECT)
-                m_render = new RenderPartObject(this);
+                m_render = new (getDocument()->renderArena()) RenderPartObject(this);
         }
 
         if (m_render) {
@@ -355,7 +355,7 @@ void HTMLObjectElementImpl::attach()
     // render tree construction caused by stylesheet loads. -dwh
     if (loadplugin && parentNode()->renderer()) {
         needWidgetUpdate = false;
-        m_render = new RenderPartObject(this);
+        m_render = new (getDocument()->renderArena()) RenderPartObject(this);
         m_render->setStyle(getDocument()->styleSelector()->styleForElement(this));
         parentNode()->renderer()->addChild(m_render, nextRenderer());
     }
diff --git a/WebCore/khtml/html/htmlparser.cpp b/WebCore/khtml/html/htmlparser.cpp
index ef7cfde..30540aa 100644
--- a/WebCore/khtml/html/htmlparser.cpp
+++ b/WebCore/khtml/html/htmlparser.cpp
@@ -174,8 +174,7 @@ void KHTMLParser::reset()
     haveFrameSet = false;
     haveContent = false;
     inSelect = false;
-    m_inline = false;
-
+    
     form = 0;
     map = 0;
     head = 0;
@@ -209,7 +208,7 @@ void KHTMLParser::parseToken(Token *t)
 #ifdef PARSER_DEBUG
     kdDebug( 6035 ) << "\n\n==> parser: processing token " << getTagName(t->id).string() << "(" << t->id << ")"
                     << " current = " << getTagName(current->id()).string() << "(" << current->id() << ")" << endl;
-    kdDebug(6035) << "inline=" << m_inline << " inBody=" << inBody << " haveFrameSet=" << haveFrameSet << endl;
+    kdDebug(6035) << " inBody=" << inBody << " haveFrameSet=" << haveFrameSet << endl;
 #endif
 
     // holy shit. apparently some sites use </br> instead of <br>
@@ -225,7 +224,10 @@ void KHTMLParser::parseToken(Token *t)
 
     // ignore spaces, if we're not inside a paragraph or other inline code
     if( t->id == ID_TEXT && t->text ) {
-        if(inBody && !skipMode() && t->text->l > 2) haveContent = true;
+        if(inBody && !skipMode() && current->id() != ID_STYLE 
+            && current->id() != ID_TITLE && current->id() != ID_SCRIPT &&
+            !t->text->containsOnlyWhitespace()) 
+            haveContent = true;
 #ifdef PARSER_DEBUG
         kdDebug(6035) << "length="<< t->text->l << " text='" << QConstString(t->text->s, t->text->l).string() << "'" << endl;
 #endif
@@ -331,8 +333,6 @@ bool KHTMLParser::insertNode(NodeImpl *n, bool flat)
                     n->renderer()->setBlockBidi();
             }
 #endif
-            //_inline = current->isInline();
-            if(current->isInline()) m_inline = true;
         }
         else {
 #if SPEED_DEBUG < 2
@@ -1199,6 +1199,12 @@ void KHTMLParser::popBlock( int _id )
         }
         else
         {
+            if (Elem->id == ID_FORM && form)
+                // A <form> is being closed prematurely (and this is
+                // malformed HTML).  Set an attribute on the form to clear out its
+                // bottom margin.
+                form->setMalformed(true);
+            
             popOneBlock();
             Elem = blockStack;
         }
@@ -1230,10 +1236,6 @@ void KHTMLParser::popOneBlock()
     removeForbidden(Elem->id, forbiddenTag);
 
     blockStack = Elem->next;
-    // we only set inline to false, if the element we close is a block level element.
-    // This helps getting cases as <p><b>bla</b> <b>bla</b> right.
-    if(!current->isInline())
-        m_inline = false;
     current = Elem->node;
 
     delete Elem;
diff --git a/WebCore/khtml/html/htmlparser.h b/WebCore/khtml/html/htmlparser.h
index dbb8193..c68fdb3 100644
--- a/WebCore/khtml/html/htmlparser.h
+++ b/WebCore/khtml/html/htmlparser.h
@@ -84,7 +84,7 @@ public:
     void reset();
 
     bool skipMode() const { return (discard_until != 0); }
-    bool noSpaces() const { return (!m_inline  || !inBody); }
+    bool noSpaces() const { return !inBody; }
     bool selectMode() const { return inSelect; }
 
     DOM::HTMLDocumentImpl *doc() const { return static_cast<DOM::HTMLDocumentImpl *>(document->document()); }
@@ -160,7 +160,6 @@ protected:
     bool inBody;
     bool haveContent;
     bool haveFrameSet;
-    bool m_inline;
     bool end;
     bool haveKonqBlock;
     bool inSelect;
diff --git a/WebCore/khtml/html/htmltokenizer.cpp b/WebCore/khtml/html/htmltokenizer.cpp
index 23584f6..e672556 100644
--- a/WebCore/khtml/html/htmltokenizer.cpp
+++ b/WebCore/khtml/html/htmltokenizer.cpp
@@ -1274,7 +1274,7 @@ void HTMLTokenizer::addPending()
             assert(0);
         }
     }
-    else if ( pre )
+    else
     {
         int p;
 
@@ -1308,11 +1308,7 @@ void HTMLTokenizer::addPending()
             break;
         }
     }
-    else
-    {
-        *dest++ = ' ';
-    }
-
+    
     pending = NonePending;
 }
 
@@ -1434,20 +1430,19 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
 
             if ( pending ) {
                 // pre context always gets its spaces/linefeeds
-                if ( pre )
+                if ( pre || (!parser->selectMode() &&
+                             (!parser->noSpaces() || dest > buffer ))) {
                     addPending();
-                // only add in existing inline context or if
-                // we just started one, i.e. we're about to insert real text
-                else if ( !parser->selectMode() &&
-                          ( !parser->noSpaces() || dest > buffer )) {
-                    addPending();
-                    discard = AllDiscard;
+                    discard = AllDiscard; // So we discard the first LF after the open tag.
                 }
                 // just forget it
                 else
                     pending = NonePending;
             }
 
+            if (cc == '/' && discard == AllDiscard)
+                discard = NoneDiscard; // A close tag. No need to discard LF.
+                    
             processToken();
 
             cBufferPos = 0;
@@ -1469,38 +1464,38 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
         }
         else if (( cc == '\n' ) || ( cc == '\r' ))
         {
-            if ( pre || textarea)
+	    if (select)
             {
-                if (discard == LFDiscard || discard == AllDiscard)
+                if (discard == LFDiscard)
                 {
                     // Ignore this LF
                     discard = NoneDiscard; // We have discarded 1 LF
                 }
-                else
+                else if(discard == AllDiscard)
                 {
-                    // Process this LF
-                    if (pending)
-                        addPending();
-                    pending = LFPending;
+                }
+                else
+                 {
+                     // Process this LF
+                    if (pending == NonePending)
+                         pending = LFPending;
                 }
             }
-            else
-            {
-                if (discard == LFDiscard)
+            else {
+                if (discard == LFDiscard || discard == AllDiscard)
                 {
                     // Ignore this LF
                     discard = NoneDiscard; // We have discarded 1 LF
                 }
-                else if(discard == AllDiscard)
-                {
-                }
                 else
                 {
                     // Process this LF
-                    if (pending == NonePending)
-                        pending = LFPending;
+                    if (pending)
+                        addPending();
+                    pending = LFPending;
                 }
             }
+            
             /* Check for MS-DOS CRLF sequence */
             if (cc == '\r')
             {
@@ -1510,8 +1505,19 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
         }
         else if (( cc == ' ' ) || ( cc == '\t' ))
         {
-            if ( pre || textarea)
-            {
+	    if (select) {
+                if(discard == SpaceDiscard)
+                    discard = NoneDiscard;
+                 else if(discard == AllDiscard)
+                 { }
+                 else
+                     pending = SpacePending;
+            
+            }
+            else {
+                if (discard == AllDiscard)
+                    discard = NoneDiscard;
+            
                 if (pending)
                     addPending();
                 if (cc == ' ')
@@ -1519,15 +1525,7 @@ void HTMLTokenizer::write( const QString &str, bool appendData )
                 else
                     pending = TabPending;
             }
-            else
-            {
-                if(discard == SpaceDiscard)
-                    discard = NoneDiscard;
-                else if(discard == AllDiscard)
-                { }
-                else
-                    pending = SpacePending;
-            }
+            
             ++src;
         }
         else
diff --git a/WebCore/khtml/misc/arena.cpp b/WebCore/khtml/misc/arena.cpp
new file mode 100644
index 0000000..013624f
--- /dev/null
+++ b/WebCore/khtml/misc/arena.cpp
@@ -0,0 +1,246 @@
+/* This is a direct port of Gecko's PLArena code.  It is based on lifetime-based fast allocation, 	 inspired by much prior art, including
+  "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
+  David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "arena.h"
+
+//#define DEBUG_ARENA_MALLOC
+#ifdef DEBUG_ARENA_MALLOC
+static int i = 0;
+#endif
+
+#define FREELIST_MAX 30
+static Arena *arena_freelist;
+static int freelist_count = 0;
+
+#define ARENA_DEFAULT_ALIGN  sizeof(double)
+#define BIT(n)				 ((unsigned int)1 << (n))
+#define BITMASK(n) 		  	 (BIT(n) - 1)
+#define CEILING_LOG2(_log2,_n)   \
+      unsigned int j_ = (unsigned int)(_n);   \
+      (_log2) = 0;                    \
+      if ((j_) & ((j_)-1))            \
+      (_log2) += 1;               \
+      if ((j_) >> 16)                 \
+      (_log2) += 16, (j_) >>= 16; \
+      if ((j_) >> 8)                  \
+      (_log2) += 8, (j_) >>= 8;   \
+      if ((j_) >> 4)                  \
+      (_log2) += 4, (j_) >>= 4;   \
+      if ((j_) >> 2)                  \
+      (_log2) += 2, (j_) >>= 2;   \
+      if ((j_) >> 1)                  \
+      (_log2) += 1;
+
+int CeilingLog2(unsigned int i) {
+    int log2;
+    CEILING_LOG2(log2,i);
+    return log2;
+}
+
+void InitArenaPool(ArenaPool *pool, const char *name, 
+                   unsigned int size, unsigned int align)
+{
+     if (align == 0)
+         align = ARENA_DEFAULT_ALIGN;
+     pool->mask = BITMASK(CeilingLog2(align));
+     pool->first.next = NULL;
+     pool->first.base = pool->first.avail = pool->first.limit =
+         (uword)ARENA_ALIGN(pool, &pool->first + 1);
+     pool->current = &pool->first;
+     pool->arenasize = size;                                  
+}
+
+
+/*
+ ** ArenaAllocate() -- allocate space from an arena pool
+ ** 
+ ** Description: ArenaAllocate() allocates space from an arena
+ ** pool. 
+ **
+ ** First try to satisfy the request from arenas starting at
+ ** pool->current.
+ **
+ ** If there is not enough space in the arena pool->current, try
+ ** to claim an arena, on a first fit basis, from the global
+ ** freelist (arena_freelist).
+ ** 
+ ** If no arena in arena_freelist is suitable, then try to
+ ** allocate a new arena from the heap.
+ **
+ ** Returns: pointer to allocated space or NULL
+ ** 
+ */
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb)
+{
+    Arena *a;   
+    char *rp;     /* returned pointer */
+
+    assert((nb & pool->mask) == 0);
+    
+    nb = (uword)ARENA_ALIGN(pool, nb); /* force alignment */
+
+    /* attempt to allocate from arenas at pool->current */
+    {
+        a = pool->current;
+        do {
+            if ( a->avail +nb <= a->limit )  {
+                pool->current = a;
+                rp = (char *)a->avail;
+                a->avail += nb;
+                return rp;
+            }
+        } while( NULL != (a = a->next) );
+    }
+
+    /* attempt to allocate from arena_freelist */
+    {
+        Arena *p; /* previous pointer, for unlinking from freelist */
+
+        for ( a = p = arena_freelist; a != NULL ; p = a, a = a->next ) {
+            if ( a->base +nb <= a->limit )  {
+                if ( p == arena_freelist )
+                    arena_freelist = a->next;
+                else
+                    p->next = a->next;
+                a->avail = a->base;
+                rp = (char *)a->avail;
+                a->avail += nb;
+                /* the newly allocated arena is linked after pool->current 
+                 *  and becomes pool->current */
+                a->next = pool->current->next;
+                pool->current->next = a;
+                pool->current = a;
+                if ( 0 == pool->first.next )
+                    pool->first.next = a;
+                freelist_count--;
+                return(rp);
+            }
+        }
+    }
+
+    /* attempt to allocate from the heap */ 
+    {  
+        unsigned int sz = MAX(pool->arenasize, nb);
+        sz += sizeof *a + pool->mask;  /* header and alignment slop */
+#ifdef DEBUG_ARENA_MALLOC
+        i++;
+        printf("Malloc: %d\n", i);
+#endif
+        a = (Arena*)malloc(sz);
+        if (a)  {
+            a->limit = (uword)a + sz;
+            a->base = a->avail = (uword)ARENA_ALIGN(pool, a + 1);
+            rp = (char *)a->avail;
+            a->avail += nb;
+            /* the newly allocated arena is linked after pool->current 
+            *  and becomes pool->current */
+            a->next = pool->current->next;
+            pool->current->next = a;
+            pool->current = a;
+            if ( !pool->first.next )
+                pool->first.next = a;
+            return(rp);
+       }
+    }
+
+    /* we got to here, and there's no memory to allocate */
+    return(0);
+} /* --- end ArenaAllocate() --- */
+
+void* ArenaGrow(ArenaPool *pool, void *p, unsigned int size, unsigned int incr)
+{
+    void *newp;
+ 
+    ARENA_ALLOCATE(newp, pool, size + incr);
+    if (newp)
+        memcpy(newp, p, size);
+    return newp;
+}
+
+/*
+ * Free tail arenas linked after head, which may not be the true list head.
+ * Reset pool->current to point to head in case it pointed at a tail arena.
+ */
+static void FreeArenaList(ArenaPool *pool, Arena *head, bool reallyFree)
+{
+    Arena **ap, *a;
+
+    ap = &head->next;
+    a = *ap;
+    if (!a)
+        return;
+
+#ifdef DEBUG
+    do {
+        assert(a->base <= a->avail && a->avail <= a->limit);
+        a->avail = a->base;
+        CLEAR_UNUSED(a);
+    } while ((a = a->next) != 0);
+    a = *ap;
+#endif
+
+    if (freelist_count >= FREELIST_MAX)
+        reallyFree = true;
+        
+    if (reallyFree) {
+        do {
+            *ap = a->next;
+            CLEAR_ARENA(a);
+#ifdef DEBUG_ARENA_MALLOC
+            if (a) {
+                i--;
+                printf("Free: %d\n", i);
+            }
+#endif
+            free(a); a = 0;
+        } while ((a = *ap) != 0);
+    } else {
+        /* Insert the whole arena chain at the front of the freelist. */
+        do {
+            ap = &(*ap)->next;
+            freelist_count++;
+        } while (*ap);
+        *ap = arena_freelist;
+        arena_freelist = a;
+        head->next = 0;
+    }
+    pool->current = head;
+}
+
+void ArenaRelease(ArenaPool *pool, char *mark)
+{
+    Arena *a;
+
+    for (a = pool->first.next; a; a = a->next) {
+        if (UPTRDIFF(mark, a->base) < UPTRDIFF(a->avail, a->base)) {
+            a->avail = (uword)ARENA_ALIGN(pool, mark);
+            FreeArenaList(pool, a, false);
+            return;
+        }
+    }
+}
+
+void FreeArenaPool(ArenaPool *pool)
+{
+    FreeArenaList(pool, &pool->first, false);
+}
+
+void FinishArenaPool(ArenaPool *pool)
+{
+    FreeArenaList(pool, &pool->first, true);
+}
+
+void ArenaFinish(void)
+{
+    Arena *a, *next;
+
+    for (a = arena_freelist; a; a = next) {
+        next = a->next;
+        free(a); a = 0;
+    }
+    arena_freelist = NULL;
+}
diff --git a/WebCore/khtml/misc/arena.h b/WebCore/khtml/misc/arena.h
new file mode 100644
index 0000000..d20f5b0
--- /dev/null
+++ b/WebCore/khtml/misc/arena.h
@@ -0,0 +1,91 @@
+#ifndef ARENA_H
+#define ARENA_H
+
+// This code is a more-or-less direct port of the PLArena code found in the NSPR (the runtime
+// used by Gecko).  This version is not thread safe.  It sacrifices thread safety for speed
+// (no lock overhead when allocing out of the arena). -dwh
+
+#define ARENA_ALIGN_MASK 3
+
+typedef unsigned long uword;
+
+struct Arena {
+    Arena* next; 	// next arena
+    uword base;		// aligned base address
+    uword limit;	// end of arena (1+last byte)
+    uword avail;	// points to next available byte in arena
+};
+
+struct ArenaPool {
+    Arena first;	// first arena in pool list.
+    Arena* current; // current arena.
+    unsigned int arenasize;
+    uword mask; 	// Mask (power-of-2 - 1)
+};
+
+void InitArenaPool(ArenaPool *pool, const char *name, 
+                   unsigned int size, unsigned int align);
+void FinishArenaPool(ArenaPool *pool);
+void FreeArenaPool(ArenaPool *pool);
+void* ArenaAllocate(ArenaPool *pool, unsigned int nb);
+
+#define ARENA_ALIGN(pool, n) (((uword)(n) + ARENA_ALIGN_MASK) & ~ARENA_ALIGN_MASK)
+#define INIT_ARENA_POOL(pool, name, size) \
+        InitArenaPool(pool, name, size, ARENA_ALIGN_MASK + 1)
+
+#define ARENA_ALLOCATE(p, pool, nb) \
+        Arena *_a = (pool)->current; \
+        unsigned int _nb = ARENA_ALIGN(pool, nb); \
+        uword _p = _a->avail; \
+        uword _q = _p + _nb; \
+        if (_q > _a->limit) \
+            _p = (uword)ArenaAllocate(pool, _nb); \
+        else \
+            _a->avail = _q; \
+        p = (void *)_p;
+
+#define ARENA_GROW(p, pool, size, incr) \
+        Arena *_a = (pool)->current; \
+        unsigned int _incr = ARENA_ALIGN(pool, incr); \
+        uword _p = _a->avail; \
+        uword _q = _p + _incr; \
+        if (_p == (uword)(p) + ARENA_ALIGN(pool, size) && \
+            _q <= _a->limit) { \
+            _a->avail = _q; \
+        } else { \
+            p = ArenaGrow(pool, p, size, incr); \
+        }
+
+#define ARENA_MARK(pool) ((void *) (pool)->current->avail)
+#define UPTRDIFF(p,q) ((uword)(p) - (uword)(q))     
+
+#ifdef DEBUG
+#define FREE_PATTERN 0xDA
+#define CLEAR_UNUSED(a) (assert((a)->avail <= (a)->limit), \
+                           memset((void*)(a)->avail, FREE_PATTERN, \
+                            (a)->limit - (a)->avail))
+#define CLEAR_ARENA(a)  memset((void*)(a), FREE_PATTERN, \
+                            (a)->limit - (PRUword)(a))
+#else
+#define CLEAR_UNUSED(a)
+#define CLEAR_ARENA(a)
+#endif
+
+#define ARENA_RELEASE(pool, mark) \
+         char *_m = (char *)(mark); \
+         Arena *_a = (pool)->current; \
+         if (UPTRDIFF(_m, _a->base) <= UPTRDIFF(_a->avail, _a->base)) { \
+             _a->avail = (uword)ARENA_ALIGN(pool, _m); \
+             CLEAR_UNUSED(_a); \
+         } else { \
+             ArenaRelease(pool, _m); \
+         }
+
+#define ARENA_DESTROY(pool, a, pnext) \
+         if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
+         *(pnext) = (a)->next; \
+         CLEAR_ARENA(a); \
+         free(a); \
+         (a) = 0;
+
+#endif ARENA_H
diff --git a/WebCore/khtml/rendering/bidi.cpp b/WebCore/khtml/rendering/bidi.cpp
index 04a0d06..4fa5b47 100644
--- a/WebCore/khtml/rendering/bidi.cpp
+++ b/WebCore/khtml/rendering/bidi.cpp
@@ -23,6 +23,9 @@
 #include "break_lines.h"
 #include "render_flow.h"
 #include "render_text.h"
+#include "render_arena.h"
+#include "xml/dom_docimpl.h"
+
 using namespace khtml;
 
 #include "kdebug.h"
@@ -40,6 +43,9 @@ static BidiIterator current;
 static BidiContext *context;
 static BidiStatus status;
 static QPtrList<BidiRun> *sruns = 0;
+static QPtrList<BidiIterator> *smidpoints = 0;
+static bool betweenMidpoints = false;
+static bool isLineEmpty = true;
 static QChar::Direction dir;
 static bool adjustEmbeddding = false;
 static bool emptyRun = true;
@@ -48,6 +54,25 @@ static int numSpaces;
 static void embed( QChar::Direction d );
 static void appendRun();
 
+void BidiIterator::detach(RenderArena* renderArena)
+{
+    delete this;
+    
+    // Now perform the destroy.
+    size_t* sz = (size_t*)this;
+    renderArena->free(*sz, (void*)this);
+}
+
+void* BidiIterator::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void BidiIterator::operator delete(void* ptr, size_t sz) {
+    size_t* szPtr = (size_t*)ptr;
+    *szPtr = sz;
+}
+
 // ---------------------------------------------------------------------
 
 /* a small helper class used internally to resolve Bidi embedding levels.
@@ -224,6 +249,36 @@ inline QChar::Direction BidiIterator::direction() const
 
 // -------------------------------------------------------------------------------------------------
 
+static void appendRunsForObject(int start, int end, RenderObject* obj)
+{
+    BidiIterator* nextMidpoint = (smidpoints && smidpoints->count()) ? smidpoints->at(0) : 0;
+    if (betweenMidpoints) {
+        if (!(nextMidpoint && nextMidpoint->obj == obj))
+            return;
+        // This is a new start point. Stop ignoring objects and 
+        // adjust our start.
+        betweenMidpoints = false;
+        start = nextMidpoint->pos;
+        smidpoints->removeFirst(); // Delete the midpoint.
+        if (start < end)
+            return appendRunsForObject(start, end, obj);
+    }
+    else {
+        if (!smidpoints || !nextMidpoint || (obj != nextMidpoint->obj)) {
+            sruns->append( new BidiRun(start, end, obj, context, dir) );
+            return;
+        }
+        
+        // An end midpoint has been encounted within our object.  We
+        // need to go ahead and append a run with our endpoint.
+        sruns->append( new BidiRun(start, nextMidpoint->pos+1, obj, context, dir) );
+        betweenMidpoints = true;
+        int nextPos = nextMidpoint->pos+1;
+        smidpoints->removeFirst();
+        return appendRunsForObject(nextPos, end, obj);
+    }
+}
+
 static void appendRun()
 {
     if ( emptyRun ) return;
@@ -237,18 +292,12 @@ static void appendRun()
     int start = sor.pos;
     RenderObject *obj = sor.obj;
     while( obj && obj != eor.obj ) {
-        if(!obj->isHidden()) {
-            //kdDebug(6041) << "appendRun: "<< start << "/" << obj->length() <<endl;
-            sruns->append( new BidiRun(start, obj->length(), obj, context, dir) );
-        }
+        appendRunsForObject(start, obj->length(), obj);        
         start = 0;
         obj = Bidinext( sor.par, obj );
     }
-    if( obj && !obj->isHidden()) {
-        //kdDebug(6041) << "appendRun: "<< start << "/" << eor.pos <<endl;
-        sruns->append( new BidiRun(start, eor.pos + 1, obj, context, dir) );
-    }
-
+    appendRunsForObject(start, eor.pos+1, obj);
+    
     ++eor;
     sor = eor;
     dir = QChar::DirON;
@@ -332,10 +381,10 @@ static void embed( QChar::Direction d )
 void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &end)
 {
     if ( start == end ) {
-	if ( start.current() == '\n' ) {
-	    m_height += lineHeight( firstLine );
-	}
-	return;
+        if ( start.current() == '\n' ) {
+            m_height += lineHeight( firstLine );
+        }
+        return;
     }
 #if BIDI_DEBUG > 1
     kdDebug(6041) << "reordering Line from " << start.obj << "/" << start.pos << " to " << end.obj << "/" << end.pos << endl;
@@ -358,16 +407,16 @@ void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &
     while( 1 ) {
 
         QChar::Direction dirCurrent;
-        if(atEnd ) {
+        if (atEnd) {
             //kdDebug(6041) << "atEnd" << endl;
             BidiContext *c = context;
-	    if ( current.atEnd())
-		while ( c->parent )
-		    c = c->parent;
+            if ( current.atEnd())
+                while ( c->parent )
+                    c = c->parent;
             dirCurrent = c->dir;
         } else {
             dirCurrent = current.direction();
-	}
+        }
 
 #ifndef QT_NO_UNICODETABLES
 
@@ -383,9 +432,9 @@ void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &
         case QChar::DirRLO:
         case QChar::DirLRO:
         case QChar::DirPDF:
-	    eor = last;
-	    embed( dirCurrent );
-	    break;
+            eor = last;
+            embed( dirCurrent );
+            break;
 
             // strong types
         case QChar::DirL:
@@ -918,6 +967,20 @@ void RenderFlow::bidiReorderLine(const BidiIterator &start, const BidiIterator &
 }
 
 
+static void deleteMidpoints(RenderArena* arena, QPtrList<BidiIterator>* midpoints)
+{
+    if (!midpoints)
+        return;
+        
+    unsigned int len = midpoints->count();
+    for(unsigned int i=0; i < len; i++) {
+        BidiIterator* s = midpoints->at(i);
+        if (s)
+            s->detach(arena);
+        midpoints->remove(i);
+    }
+}
+
 void RenderFlow::layoutInlineChildren()
 {
     invalidateVerticalPositions();
@@ -937,6 +1000,7 @@ void RenderFlow::layoutInlineChildren()
         m_height += paddingTop();
         toAdd += paddingBottom();
     }
+    
     if(firstChild()) {
         // layout replaced elements
         RenderObject *o = first( this );
@@ -967,35 +1031,48 @@ void RenderFlow::layoutInlineChildren()
         startEmbed->ref();
 
         context = startEmbed;
-	adjustEmbeddding = true;
+        adjustEmbeddding = true;
         BidiIterator start(this);
-	adjustEmbeddding = false;
+        adjustEmbeddding = false;
         BidiIterator end(this);
 
         firstLine = true;
+        
+        if (!smidpoints) {
+            smidpoints = new QPtrList<BidiIterator>;
+            smidpoints->setAutoDelete(false);
+        }
+                
         while( !end.atEnd() ) {
             start = end;
-
-            end = findNextLineBreak(start);
+            betweenMidpoints = false;
+            isLineEmpty = true;
+            end = findNextLineBreak(start, *smidpoints);
             if( start.atEnd() ) break;
-	    bidiReorderLine(start, end);
-
-            if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) {
-		adjustEmbeddding = true;
-                ++end;
-		adjustEmbeddding = false;
-	    } else if(m_pre && end.current() == QChar('\n') ) {
-		adjustEmbeddding = true;
-                ++end;
-		adjustEmbeddding = false;
+            if (!isLineEmpty) {
+                bidiReorderLine(start, end);
+    
+                if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) {
+                    adjustEmbeddding = true;
+                    ++end;
+                    adjustEmbeddding = false;
+                } else if(m_pre && end.current() == QChar('\n') ) {
+                    adjustEmbeddding = true;
+                    ++end;
+                    adjustEmbeddding = false;
+                }
+    
+                newLine();
             }
-
-            newLine();
             firstLine = false;
+            deleteMidpoints(renderArena(), smidpoints);
         }
         startEmbed->deref();
         //embed->deref();
     }
+    
+    deleteMidpoints(renderArena(), smidpoints);
+    
     m_height += toAdd;
 
     // in case we have a float on the last line, it might not be positioned up to now.
@@ -1008,7 +1085,7 @@ void RenderFlow::layoutInlineChildren()
     //kdDebug(6040) << "height = " << m_height <<endl;
 }
 
-BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
+BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start, QPtrList<BidiIterator>& midpoints)
 {
     int width = lineWidth(m_height);
     int w = 0;
@@ -1018,42 +1095,55 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
     kdDebug(6041) << "sol: " << start.obj << " " << start.pos << endl;
 #endif
 
-
     // eliminate spaces at beginning of line
     if(!m_pre) {
-	// remove leading spaces
-	while(!start.atEnd() &&
+        // remove leading spaces
+        while(!start.atEnd() &&
 #ifndef QT_NO_UNICODETABLES
-	      ( start.direction() == QChar::DirWS || start.obj->isSpecial() )
+            ( start.direction() == QChar::DirWS || start.obj->isSpecial() )
 #else
-	      ( start.current() == ' ' || start.obj->isSpecial() )
+            ( start.current() == ' ' || start.obj->isSpecial() )
 #endif
-	      ) {
-		if( start.obj->isSpecial() ) {
-		    RenderObject *o = start.obj;
-		    // add to special objects...
-		    if(o->isFloating()) {
-			insertSpecialObject(o);
-			// check if it fits in the current line.
-			// If it does, position it now, otherwise, position
-			// it after moving to next line (in newLine() func)
-			if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
-			    positionNewFloats();
-			    width = lineWidth(m_height);
-			}
-		    } else if(o->isPositioned()) {
-			static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
-		    }
-		}
-
-		adjustEmbeddding = true;
-		++start;
-		adjustEmbeddding = false;
-	}
+            ) {
+            if( start.obj->isSpecial() ) {
+                RenderObject *o = start.obj;
+                // add to special objects...
+                if(o->isFloating()) {
+                    insertSpecialObject(o);
+                    // check if it fits in the current line.
+                    // If it does, position it now, otherwise, position
+                    // it after moving to next line (in newLine() func)
+                    if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
+                        positionNewFloats();
+                        width = lineWidth(m_height);
+                    }
+                } else if(o->isPositioned()) {
+                    static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
+                }
+            }
+    
+            adjustEmbeddding = true;
+            ++start;
+            adjustEmbeddding = false;
+        }
     }
     if ( start.atEnd() )
         return start;
 
+    // This variable is used only if whitespace isn't set to PRE, and it tells us whether
+    // or not we are currently ignoring whitespace.
+    bool ignoringSpaces = false;
+    
+    // This variable tracks whether the very last character we saw was a space.  We use
+    // this to detect when we encounter a second space so we know we have to terminate
+    // a run.
+    bool sawSpace = false;
+    RenderObject* trailingSpaceObject = 0;
+    
+    // The pos of the last whitespace char we saw, not to be confused with the lastSpace
+    // variable below, which is really the last breakable char.
+    int lastSpacePos = 0;
+    
     BidiIterator lBreak = start;
 
     RenderObject *o = start.obj;
@@ -1068,6 +1158,13 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
             if( w + tmpW <= width ) {
                 lBreak.obj = o;
                 lBreak.pos = 0;
+             
+                // 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. -dwh
+                isLineEmpty = false;
+                trailingSpaceObject = 0;
+                
                 //check the clear status
                 EClear clear = o->style()->clear();
                 if(clear != CNONE) {
@@ -1078,109 +1175,171 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
         }
         if( o->isSpecial() ) {
             // add to special objects...
-	    if(o->isFloating()) {
-		insertSpecialObject(o);
-		// check if it fits in the current line.
-		// If it does, position it now, otherwise, position
-		// it after moving to next line (in newLine() func)
-		if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
-		    positionNewFloats();
-		    width = lineWidth(m_height);
-		}
-	    } else if(o->isPositioned()) {
-		static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
-	    }
+            if(o->isFloating()) {
+                insertSpecialObject(o);
+                // check if it fits in the current line.
+                // If it does, position it now, otherwise, position
+                // it after moving to next line (in newLine() func)
+                if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
+                    positionNewFloats();
+                    width = lineWidth(m_height);
+                }
+            } else if(o->isPositioned()) {
+                static_cast<RenderFlow*>(o->containingBlock())->insertSpecialObject(o);
+            }
         } else if ( o->isReplaced() ) {
             tmpW += o->width()+o->marginLeft()+o->marginRight();
+            if (ignoringSpaces) {
+                BidiIterator* startMid = new (o->renderArena()) BidiIterator();
+                startMid->obj = o;
+                startMid->pos = 0;
+                midpoints.append(startMid);
+            }
+            isLineEmpty = false;
+            ignoringSpaces = false;
+            sawSpace = false;
+            lastSpacePos = 0;
+            trailingSpaceObject = 0;
         } else if ( o->isText() ) {
-	    RenderText *t = static_cast<RenderText *>(o);
-	    int strlen = t->stringLength();
-	    int len = strlen - pos;
-	    QChar *str = t->text();
-#if 0
-	    if ( ( !firstLine || !t->firstLine() ) && !t->hasReturn() && t->maxWidth() + w + tmpW < width ) {
-		// the rest of the object fits completely
-// 		kdDebug() << "RenderFlow::findNextLineBreak object fits completely, max=" << t->maxWidth()
-// 			  << " width =" << w << " avail = " << width <<" tmp=" << tmpW << endl;
-		//search backwards for last possible linebreak
-		int lastSpace = strlen-1;
-		while( lastSpace >= pos && !isBreakable( str, lastSpace, strlen ) )
-		    lastSpace--;
-		lastSpace++;
-		if ( lastSpace > pos ) {
-		    w += tmpW + t->width( pos, lastSpace-pos, firstLine);
-		    tmpW = 0;
-		    lBreak.obj = o;
-		    lBreak.pos = lastSpace;
-		}
-		tmpW += t->width( lastSpace, strlen-lastSpace, firstLine);
-// 		kdDebug() << "--> width=" << t->width( pos, strlen-pos, firstLine)
-// 			  <<" first=" << t->width( pos, lastSpace-pos, firstLine)
-// 			  <<" end=" << t->width( lastSpace, strlen-lastSpace, firstLine)
-// 			  << endl;
-	    } else {
-#endif
-            if (style()->whiteSpace() == NOWRAP || t->style()->whiteSpace() == NOWRAP ) {
-                tmpW += t->maxWidth();
-                pos = len;
-                len = 0;
-            } else {
-                const Font *f = t->htmlFont( firstLine );
-                // proportional font, needs a bit more work.
-                int lastSpace = pos;
-                bool isPre = style()->whiteSpace() == PRE;
-                while(len) {
-                    if( (isPre && str[pos] == '\n') ||
-                        (!isPre && isBreakable( str, pos, strlen ) ) ) {
-		    tmpW += t->width(lastSpace, pos - lastSpace, f);
+            RenderText *t = static_cast<RenderText *>(o);
+            int strlen = t->stringLength();
+            int len = strlen - pos;
+            QChar *str = t->text();
+
+            const Font *f = t->htmlFont( firstLine );
+            // proportional font, needs a bit more work.
+            int lastSpace = pos;
+            bool isPre = o->style()->whiteSpace() == PRE;
+            //QChar space[1]; space[0] = ' ';
+            //int spaceWidth = f->width(space, 1, 0);
+            while(len) {
+                //XXXdwh This is wrong. Still mutating the DOM
+                // string for newlines... will fix in second stage.
+                if (!isPre && str[pos] == '\n')
+                    str[pos] = ' ';
+                    
+                bool oldSawSpace = sawSpace;
+                sawSpace = (str[pos].direction() == QChar::DirWS);
+                    
+                if (isPre || !sawSpace)
+                    isLineEmpty = false;
+                    
+                if( (isPre && str[pos] == '\n') ||
+                    (!isPre && isBreakable( str, pos, strlen ) ) ) {
+                    
+                    if (ignoringSpaces) {
+                        if (!sawSpace) {
+                            // Stop ignoring spaces and begin at this
+                            // new point.
+                            BidiIterator* startMid = new (o->renderArena()) BidiIterator();
+                            startMid->obj = o;
+                            startMid->pos = pos;
+                            midpoints.append(startMid);
+                        }
+                        else {
+                            // Just keep ignoring these spaces.
+                            pos++;
+                            len--;
+                            continue;
+                        }
+                    }
+                    else {
+                        if (sawSpace && !oldSawSpace)
+                            lastSpacePos = pos;
+                        tmpW += t->width(lastSpace, pos - lastSpace, f);
+                    }
+                    
 #ifdef DEBUG_LINEBREAKS
-		    kdDebug(6041) << "found space at " << pos << " in string '" << QString( str, strlen ).latin1() << "' adding " << tmpW << " new width = " << w << endl;
+                    kdDebug(6041) << "found space at " << pos << " in string '" << QString( str, strlen ).latin1() << "' adding " << tmpW << " new width = " << w << endl;
 #endif
-		    if ( !isPre && w + tmpW > width && w == 0 ) {
-			int fb = floatBottom();
-			int newLineWidth = lineWidth(fb);
-			if(!w && m_height < fb && width < newLineWidth) {
-			    m_height = fb;
-			    width = newLineWidth;
+                    if ( !isPre && w + tmpW > width && w == 0 ) {
+                        int fb = floatBottom();
+                        int newLineWidth = lineWidth(fb);
+                        if(!w && m_height < fb && width < newLineWidth) {
+                            m_height = fb;
+                            width = newLineWidth;
 #ifdef DEBUG_LINEBREAKS
-			    kdDebug() << "RenderFlow::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
+                            kdDebug() << "RenderFlow::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
 #endif
-			}
-		    }
-		    if ( !isPre && w + tmpW > width )
-			goto end;
-
-		    lBreak.obj = o;
-		    lBreak.pos = pos;
+                        }
+                    }
+        
+                    if ( !isPre && w + tmpW > width )
+                        goto end;
 
-		    if( *(str+pos) == '\n' ) {
+                    lBreak.obj = o;
+                    lBreak.pos = pos;
+    
+                    if( *(str+pos) == '\n' && isPre) {
 #ifdef DEBUG_LINEBREAKS
-			kdDebug(6041) << "forced break sol: " << start.obj << " " << start.pos << "   end: " << lBreak.obj << " " << lBreak.pos << "   width=" << w << endl;
+                        kdDebug(6041) << "forced break sol: " << start.obj << " " << start.pos << "   end: " << lBreak.obj << " " << lBreak.pos << "   width=" << w << endl;
 #endif
-			return lBreak;
-		    }
-		    w += tmpW;
-		    tmpW = 0;
-		    lastSpace = pos;
-		}
-		pos++;
-		len--;
-	    }
-            // IMPORTANT: pos is > length here!
-            tmpW += t->width(lastSpace, pos - lastSpace, f);
-            }
-#if 0
+                        return lBreak;
+                    }
+                    
+                    w += tmpW;
+                    tmpW = 0;
+                    lastSpace = pos;
+                    
+                    if (!ignoringSpaces && !isPre) {
+                        // If we encounter a newline, or if we encounter a
+                        // second space, we need to go ahead and break up this
+                        // run and enter a mode where we start collapsing spaces.
+                        if (sawSpace && oldSawSpace)
+                            ignoringSpaces = true;
+                        
+                        if (ignoringSpaces) {
+                            // We just entered a mode where we are ignoring
+                            // spaces. Create a midpoint to terminate the run
+                            // before the second space. 
+                            BidiIterator* endMid = new (o->renderArena()) BidiIterator();
+                            if (trailingSpaceObject) {
+                                endMid->obj = trailingSpaceObject;
+                            }
+                            else
+                                endMid->obj = o;
+                            endMid->pos = lastSpacePos;
+                            midpoints.append(endMid);
+                            lastSpace = pos;
+                        }
+                    }
+                }
+                else if (ignoringSpaces) {
+                    // Stop ignoring spaces and begin at this
+                    // new point.
+                    ignoringSpaces = false;
+                    lastSpacePos = 0;
+                    lastSpace = pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
+                    BidiIterator* startMid = new (o->renderArena()) BidiIterator();
+                    startMid->obj = o;
+                    startMid->pos = pos;
+                    midpoints.append(startMid);
+                }
+                
+                if (!isPre && sawSpace && !ignoringSpaces)
+                    trailingSpaceObject = o;
+                else if (isPre || !sawSpace)
+                    trailingSpaceObject = 0;
+                    
+                pos++;
+                len--;
             }
-#endif
+            
+            // IMPORTANT: pos is > length here!
+            if (!ignoringSpaces)
+                tmpW += t->width(lastSpace, pos - lastSpace, f);
         } else
             KHTMLAssert( false );
 
         if( w + tmpW > width+1 && style()->whiteSpace() != NOWRAP && o->style()->whiteSpace() != NOWRAP ) {
             //kdDebug() << " too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
-	    //kdDebug() << "start=" << start.obj << " current=" << o << endl;
+            //kdDebug() << "start=" << start.obj << " current=" << o << endl;
             // if we have floats, try to get below them.
+            if (sawSpace && !ignoringSpaces && o->style()->whiteSpace() != PRE)
+                trailingSpaceObject = 0;
+                
             int fb = floatBottom();
-	    int newLineWidth = lineWidth(fb);
+            int newLineWidth = lineWidth(fb);
             if( !w && m_height < fb && width < newLineWidth ) {
                 m_height = fb;
                 width = newLineWidth;
@@ -1188,10 +1347,10 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
                 kdDebug() << "RenderFlow::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
 #endif
             }
-	    if( !w && w + tmpW > width+1 && (o != start.obj || (unsigned) pos != start.pos) ) {
-		// getting below floats wasn't enough...
-		//kdDebug() << "still too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
-		lBreak.obj = o;
+            if( !w && w + tmpW > width+1 && (o != start.obj || (unsigned) pos != start.pos) ) {
+                // getting below floats wasn't enough...
+                //kdDebug() << "still too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
+                lBreak.obj = o;
                 if(last != o) {
                     //kdDebug() << " using last " << last << endl;
                     //lBreak.obj = last;
@@ -1233,35 +1392,53 @@ BidiIterator RenderFlow::findNextLineBreak(BidiIterator &start)
                 lBreak.pos = last->length();
             }
         } else if( lBreak.obj ) {
-	    if( last != o ) {
-		// better break between object boundaries than in the middle of a word
-		lBreak.obj = o;
-		lBreak.pos = 0;
-	    } else {
-		int w = 0;
-		if( lBreak.obj->isText() )
-		    w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
-		else
-		    w += lBreak.obj->width();
-		while( lBreak.obj && w < width ) {
-		    ++lBreak;
-		    if( !lBreak.obj ) break;
-		    if( lBreak.obj->isText() )
-			w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
-		    else
-			w += lBreak.obj->width();
-		}
-	    }
+            if( last != o ) {
+                // better break between object boundaries than in the middle of a word
+                lBreak.obj = o;
+                lBreak.pos = 0;
+            } else {
+                int w = 0;
+                if( lBreak.obj->isText() )
+                    w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
+                else
+                    w += lBreak.obj->width();
+                while( lBreak.obj && w < width ) {
+                    ++lBreak;
+                    if( !lBreak.obj ) break;
+                    if( lBreak.obj->isText() )
+                    w += static_cast<RenderText *>(lBreak.obj)->width(lBreak.pos, 1);
+                    else
+                    w += lBreak.obj->width();
+                }
+            }
         }
     }
 
     // make sure we consume at least one char/object.
     if( lBreak == start )
         ++lBreak;
-
+    
 #ifdef DEBUG_LINEBREAKS
     kdDebug(6041) << "regular break sol: " << start.obj << " " << start.pos << "   end: " << lBreak.obj << " " << lBreak.pos << "   width=" << w << endl;
 #endif
+
+    if (trailingSpaceObject) {
+        // This object is either going to be part of the last midpoint, or it is going
+        // to be the actual endpoint.  In both cases we just decrease our pos by 1 level to
+        // exclude the space, allowing it to - in effect - collapse into the newline.
+        int count = midpoints.count();
+        if (count%2==1) {
+            BidiIterator* lastEndPoint = midpoints.at(count-1);
+            lastEndPoint->pos--;
+        }
+        //else if (lBreak.pos > 0)
+        //    lBreak.pos--;
+        else if (lBreak.obj == 0 && trailingSpaceObject->isText()) {
+            lBreak.obj = trailingSpaceObject;
+            lBreak.pos = static_cast<RenderText *>(trailingSpaceObject)->length() - 1;
+        }
+    }
+    
     return lBreak;
 }
 
diff --git a/WebCore/khtml/rendering/bidi.h b/WebCore/khtml/rendering/bidi.h
index 954e519..67a2da4 100644
--- a/WebCore/khtml/rendering/bidi.h
+++ b/WebCore/khtml/rendering/bidi.h
@@ -24,6 +24,8 @@
 
 #include <qstring.h>
 
+class RenderArena;
+
 namespace khtml {
     class RenderFlow;
     class RenderObject;
@@ -100,6 +102,20 @@ namespace khtml {
 	const QChar &current() const;
 	QChar::Direction direction() const;
 
+    void detach(RenderArena* renderArena);
+    
+    // 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();    
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void* ptr, size_t sz);
+        
+private:
+    // The normal operator new is disallowed.
+    void* operator new(size_t sz) throw() { assert(false); return 0; };
+
+public:
 	RenderFlow *par;
 	RenderObject *obj;
 	unsigned int pos;
diff --git a/WebCore/khtml/rendering/render_arena.cpp b/WebCore/khtml/rendering/render_arena.cpp
new file mode 100644
index 0000000..aa38ce8
--- /dev/null
+++ b/WebCore/khtml/rendering/render_arena.cpp
@@ -0,0 +1,87 @@
+/*
+ * This file contains the implementation of an arena allocation system for use by
+ * render objects and temporaries allocated during layout and style resolution
+ * of render objects.  It is a direct port of Gecko's 
+ * FrameArena code (frame = render_object in Gecko).
+ *
+ * Copyright (C) 2002 (hyatt at apple.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include "render_arena.h"
+
+RenderArena::RenderArena(unsigned int arenaSize)
+{
+    // Initialize the arena pool
+    INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize);
+
+    // Zero out the recyclers array
+    memset(m_recyclers, 0, sizeof(m_recyclers));
+}
+
+RenderArena::~RenderArena()
+{
+    // Free the arena in the pool and finish using it
+    FreeArenaPool(&m_pool);
+}
+
+void* RenderArena::allocate(size_t size)
+{
+    void* result = 0;
+
+    // Ensure we have correct alignment for pointers.  Important for Tru64
+    size = ROUNDUP(size, sizeof(void*));
+
+    // Check recyclers first
+    if (size < gMaxRecycledSize) {
+        const int   index = size >> 2;
+    
+        result = m_recyclers[index];
+        if (result) {
+            // Need to move to the next object
+            void* next = *((void**)result);
+            m_recyclers[index] = next;
+        }
+    }
+    
+    if (!result) {
+        // Allocate a new chunk from the arena
+        ARENA_ALLOCATE(result, &m_pool, size);
+    }
+
+    return result;
+}
+
+void RenderArena::free(size_t size, void* ptr)
+{
+#ifdef DEBUG
+    // Mark the memory with 0xdd in DEBUG builds so that there will be
+    // problems if someone tries to access memory that they've freed.
+    memset(ptr, 0xdd, size);
+#endif
+
+    // Ensure we have correct alignment for pointers.  Important for Tru64
+    size = ROUNDUP(size, sizeof(void*));
+
+    // See if it's a size that we recycle
+    if (size < gMaxRecycledSize) {
+        const int   index = size >> 2;
+        void*       currentTop = m_recyclers[index];
+        m_recyclers[index] = ptr;
+        *((void**)ptr) = currentTop;
+    }
+}
diff --git a/WebCore/khtml/rendering/render_arena.h b/WebCore/khtml/rendering/render_arena.h
new file mode 100644
index 0000000..7fb72b5
--- /dev/null
+++ b/WebCore/khtml/rendering/render_arena.h
@@ -0,0 +1,52 @@
+#ifndef RENDERARENA_H
+#define RENDERARENA_H
+
+/*
+ * This file contains the implementation of an arena allocation system for use by
+ * render objects and temporaries allocated during layout and style resolution
+ * of render objects.  It is a direct port of Gecko's 
+ * FrameArena code (frame = render_object in Gecko).
+ *
+ * Copyright (C) 2002 (hyatt at apple.com)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+#include "arena.h"
+
+static const size_t gMaxRecycledSize = 400;
+#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
+
+class RenderArena {
+public:
+   RenderArena(unsigned int arenaSize = 4096);
+    ~RenderArena();
+
+  // Memory management functions
+  void* allocate(size_t size);
+  void  free(size_t size, void* ptr);
+
+private:
+  // Underlying arena pool
+  ArenaPool m_pool;
+
+  // The recycler array is sparse with the indices being multiples of 4,
+  // i.e., 0, 4, 8, 12, 16, 20, ...
+  void*       m_recyclers[gMaxRecycledSize >> 2];
+};
+
+#endif
+
diff --git a/WebCore/khtml/rendering/render_box.cpp b/WebCore/khtml/rendering/render_box.cpp
index 70732d0..e85a5c0 100644
--- a/WebCore/khtml/rendering/render_box.cpp
+++ b/WebCore/khtml/rendering/render_box.cpp
@@ -30,9 +30,11 @@
 #include "rendering/render_replaced.h"
 #include "rendering/render_root.h"
 #include "rendering/render_table.h"
+#include "render_arena.h"
 
 #include "misc/htmlhashes.h"
 #include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
 
 #include <khtmlview.h>
 #include <kdebug.h>
@@ -83,13 +85,22 @@ void RenderBox::setStyle(RenderStyle *_style)
     }
     
     if ((isPositioned() || isRelPositioned() || (isFloating() && !isListMarker())) && !m_layer)
-        m_layer = new RenderLayer(this);
+        m_layer = new (element()->getDocument()->renderArena()) RenderLayer(this);
 }
 
 RenderBox::~RenderBox()
 {
     //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;
-    delete m_layer;
+}
+
+void RenderBox::detach(RenderArena* renderArena)
+{
+    RenderLayer* layer = m_layer;
+    
+    RenderContainer::detach(renderArena);
+    
+    if (layer)
+        layer->detach(renderArena);
 }
 
 short RenderBox::contentWidth() const
diff --git a/WebCore/khtml/rendering/render_box.h b/WebCore/khtml/rendering/render_box.h
index 213c3a3..472bb93 100644
--- a/WebCore/khtml/rendering/render_box.h
+++ b/WebCore/khtml/rendering/render_box.h
@@ -49,6 +49,8 @@ public:
 
     virtual void close();
 
+    virtual void detach(RenderArena* renderArena);
+    
     virtual short minWidth() const { return m_minWidth; }
     virtual short maxWidth() const { return m_maxWidth; }
 
diff --git a/WebCore/khtml/rendering/render_br.cpp b/WebCore/khtml/rendering/render_br.cpp
index 67e570a..4cccfbe 100644
--- a/WebCore/khtml/rendering/render_br.cpp
+++ b/WebCore/khtml/rendering/render_br.cpp
@@ -27,7 +27,6 @@ using namespace khtml;
 RenderBR::RenderBR(DOM::NodeImpl* node)
     : RenderText(node, new DOM::DOMStringImpl(QChar('\n')))
 {
-    m_hasReturn = true;
 }
 
 RenderBR::~RenderBR()
diff --git a/WebCore/khtml/rendering/render_container.cpp b/WebCore/khtml/rendering/render_container.cpp
index dd5ae87..fcbdfed 100644
--- a/WebCore/khtml/rendering/render_container.cpp
+++ b/WebCore/khtml/rendering/render_container.cpp
@@ -45,15 +45,21 @@ RenderContainer::RenderContainer(DOM::NodeImpl* node)
 
 RenderContainer::~RenderContainer()
 {
+}
+
+void RenderContainer::detach(RenderArena* renderArena)
+{
     RenderObject* next;
     for(RenderObject* n = m_first; n; n = next ) {
         n->removeFromSpecialObjects();
         n->setParent(0);
         next = n->nextSibling();
-        n->detach();
+        n->detach(renderArena);
     }
     m_first = 0;
     m_last = 0;
+
+    RenderObject::detach(renderArena);
 }
 
 void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
diff --git a/WebCore/khtml/rendering/render_container.h b/WebCore/khtml/rendering/render_container.h
index 14d1d43..68eb913 100644
--- a/WebCore/khtml/rendering/render_container.h
+++ b/WebCore/khtml/rendering/render_container.h
@@ -43,6 +43,8 @@ public:
     virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
     virtual void removeChild(RenderObject *oldChild);
 
+    virtual void detach(RenderArena* renderArena);
+    
     virtual RenderObject* removeChildNode(RenderObject* child);
     virtual void appendChildNode(RenderObject* child);
     virtual void insertChildNode(RenderObject* child, RenderObject* before);
diff --git a/WebCore/khtml/rendering/render_flow.cpp b/WebCore/khtml/rendering/render_flow.cpp
index 6c85d68..d7eea84 100644
--- a/WebCore/khtml/rendering/render_flow.cpp
+++ b/WebCore/khtml/rendering/render_flow.cpp
@@ -36,6 +36,8 @@
 #include "rendering/render_root.h"
 #include "xml/dom_nodeimpl.h"
 #include "xml/dom_docimpl.h"
+#include "html/html_formimpl.h"
+
 #include "khtmlview.h"
 #include "htmltags.h"
 
@@ -68,7 +70,7 @@ void RenderFlow::setStyle(RenderStyle *_style)
         setInline(false);
     
     if ((isPositioned() || isRelPositioned() || style()->overflow()==OHIDDEN) && !m_layer)
-        m_layer = new RenderLayer(this);
+        m_layer = new (renderArena()) RenderLayer(this);
     
     if(isFloating() || !style()->display() == INLINE)
         setInline(false);
@@ -245,6 +247,11 @@ void RenderFlow::layout()
             
         m_topMarginQuirk = style()->marginTop().quirk;
         m_bottomMarginQuirk = style()->marginBottom().quirk;
+        
+        if (element() && element()->id() == ID_FORM && element()->isMalformed())
+            // See if this form is malformed (i.e., unclosed). If so, don't give the form
+            // a bottom margin.
+            m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
     }
     
     // A quirk that has become an unfortunate standard.  Positioned elements, floating elements
@@ -1223,181 +1230,285 @@ static inline RenderObject *next(RenderObject *par, RenderObject *current)
     return next;
 }
 
-
-void RenderFlow::calcMinMaxWidth()
+void RenderFlow::calcInlineMinMaxWidth()
 {
-    KHTMLAssert( !minMaxKnown() );
-
-#ifdef DEBUG_LAYOUT
-    kdDebug( 6040 ) << renderName() << "(RenderBox)::calcMinMaxWidth() this=" << this << endl;
-#endif
-
-    m_minWidth = 0;
-    m_maxWidth = 0;
-
-    if (isInline()) {
-	setMinMaxKnown();
-        return;
-    }
-
+    int inlineMax=0;
+    int inlineMin=0;
+    
     int cw = containingBlock()->contentWidth();
 
-    // non breaking space
-    const QChar nbsp = 0xa0;
-
     RenderObject *child = firstChild();
     RenderObject *prevchild = 0;
-    if(childrenInline())
+    
+    // If we are at the start of a line, we want to ignore all white-space.
+    // Also strip spaces if we previously had text that ended in a trailing space.
+    bool stripFrontSpaces = true;
+    RenderObject* trailingSpaceChild = 0;
+    
+    while(child != 0)
     {
-        int inlineMax=0;
-        int currentMin=0;
-        int inlineMin=0;
-        bool noBreak=false;
-	bool prevWasText = false;
-
-        while(child != 0)
+        // positioned children don't affect the minmaxwidth
+        if (child->isPositioned())
         {
-            // positioned children don't affect the minmaxwidth
-            if (child->isPositioned())
-            {
-                child = next(this, child);
-                continue;
-            }
+            child = next(this, child);
+            continue;
+        }
 
-            if( !child->isBR() )
-            {
-                RenderStyle* cstyle = child->style();
+        if( !child->isBR() )
+        {
+            // Step One: determine whether or not we need to go ahead and
+            // terminate our current line.  Each discrete chunk can become
+            // the new min-width, if it is the widest chunk seen so far, and
+            // it can also become the max-width.  
+            
+            // Children fall into three categories:
+            // (1) An inline flow object.  These objects always have a min/max of 0,
+            // and are included in the iteration solely so that their margins can
+            // be added in.  XXXdwh Just adding in the margins is totally bogus, since
+            // a <span> could wrap to multiple lines.  Technically the left margin should
+            // be considered part of the first descendant's start, and the right margin
+            // should be considered part of the last descendant's end.  Leave this alone
+            // for now, but fix later.
+            //
+            // (2) An inline non-text non-flow object, e.g., an inline replaced element.
+            // These objects can always be on a line by themselves, so in this situation
+            // we need to go ahead and break the current line, and then add in our own
+            // margins and min/max width on its own line, and then terminate the line.
+            //
+            // (3) A text object.  Text runs can have breakable characters at the start,
+            // the middle or the end.  They may also lose whitespace off the front if
+            // we're already ignoring whitespace.  In order to compute accurate min-width
+            // information, we need three pieces of information.  
+            // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
+            // starts with whitespace.
+            // (b) the min-width of the last non-breakable run. Should be 0 if the text string
+            // ends with whitespace.
+            // (c) the min/max width of the string (trimmed for whitespace).
+            //
+            // If the text string starts with whitespace, then we need to go ahead and 
+            // terminate our current line (unless we're already in a whitespace stripping
+            // mode.
+            //
+            // If the text string has a breakable character in the middle, but didn't start
+            // with whitespace, then we add the width of the first non-breakable run and
+            // then end the current line.  We then need to use the intermediate min/max width
+            // values (if any of them are larger than our current min/max).  We then look at
+            // the width of the last non-breakable run and use that to start a new line
+            // (unless we end in whitespace).
+            RenderStyle* cstyle = child->style();
+            short childMin = 0;
+            short childMax = 0;
+            
+            if (!child->isText()) {
+                // Case (1) and (2).  Inline replaced and inline flow elements.  Both
+                // add in their margins to their min/max values.
                 int margins = 0;
-		LengthType type = cstyle->marginLeft().type;
+                LengthType type = cstyle->marginLeft().type;
                 if ( type != Variable )
                     margins += (type == Fixed ? cstyle->marginLeft().value : child->marginLeft());
-		type = cstyle->marginRight().type;
+                type = cstyle->marginRight().type;
                 if ( type != Variable )
                     margins += (type == Fixed ? cstyle->marginRight().value : child->marginRight());
-                int childMin = child->minWidth() + margins;
-                int childMax = child->maxWidth() + margins;
-                if (child->isText() && static_cast<RenderText *>(child)->length() > 0)
-                {
-
-                    int ti = cstyle->textIndent().minWidth(cw);
-                    childMin+=ti;
-                    childMax+=ti;
-
-                    bool hasNbsp=false;
-                    RenderText* t = static_cast<RenderText *>(child);
-                    if (t->data()[0] == nbsp) //inline starts with nbsp
-                    {
-                        currentMin += childMin;
-                        inlineMax += childMax;
-                        hasNbsp = true;
+                childMin += margins;
+                childMax += margins;
+            }
+            
+            if (!(child->isInline() && child->isFlow()) && !child->isText()) {
+                // Case (2). Inline replaced elements.
+                // Go ahead and terminate the current line as far as
+                // minwidth is concerned.
+                childMin += child->minWidth();
+                childMax += child->maxWidth();
+                
+                if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+                inlineMin = 0;
+                
+                // Add our width to the max.
+                inlineMax += childMax;
+                
+                // Now check our line.
+                inlineMin = childMin;
+                if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+                
+                // Now start a new line.
+                inlineMin = 0;
+                
+                // We are no longer stripping whitespace at the start of
+                // a line.
+                if (!child->isFloating())
+                    stripFrontSpaces = false;
+                trailingSpaceChild = 0;
+            }
+            else if (child->isText())
+            {
+                // Case (3). Text. 
+                RenderText* t = static_cast<RenderText *>(child);
+                
+                // Determine if we have a breakable character.  Pass in
+                // whether or not we should ignore any spaces at the front
+                // of the string.  If those are going to be stripped out,
+                // then they shouldn't be considered in the breakable char
+                // check.
+                bool hasBreakableChar, hasBreak;
+                short beginMin, endMin;
+                bool beginWS, endWS;
+                short beginMax, endMax;
+                t->trimmedMinMaxWidth(beginMin, beginWS, endMin, endWS, hasBreakableChar,
+                                      hasBreak, beginMax, endMax,
+                                      childMin, childMax, stripFrontSpaces);
+                if (stripFrontSpaces)
+                    trailingSpaceChild = child;
+                else
+                    trailingSpaceChild = 0;
+
+                // Add in text-indent.
+                int ti = cstyle->textIndent().minWidth(cw);
+                childMin+=ti; beginMin += ti;
+                childMax+=ti; beginMax += ti;
+
+                // If we have no breakable characters at all,
+                // then this is the easy case. We add ourselves to the current
+                // min and max and continue.
+                if (!hasBreakableChar) {
+                    inlineMin += childMin;
+                    inlineMax += childMax;
+                }
+                else {
+                    // We have a breakable character.  Now we need to know if
+                    // we start and end with whitespace.
+                    if (beginWS) {
+                        // Go ahead and end the current line.
+                        if(m_minWidth < inlineMin) m_minWidth = inlineMin;
                     }
-                    if (hasNbsp && t->data()[t->length()-1]==nbsp )
-                    {                           //inline starts and ends with nbsp
-                        noBreak=true;
+                    else {
+                        inlineMin += beginMin;
+                        if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+                        childMin -= ti;
                     }
-                    else if (t->data()[t->length()-1] == nbsp && t->data()[0] != ' ')
-                    {                           //inline only ends with nbsp
-                        if(currentMin < childMin) currentMin = childMin;
-                        inlineMax += childMax;
-                        noBreak = true;
-                        hasNbsp = true;
+                    
+                    inlineMin = childMin;
+                    
+                    if (endWS) {
+                        // We end in whitespace, which means we can go ahead
+                        // and end our current line.
+                        if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+                        inlineMin = 0;
                     }
-                    if ( t->hasBreakableChar() )
-                        noBreak = false;
-                    prevWasText = true;
-                    if (hasNbsp)
-                    {
-                        if(inlineMin < currentMin) inlineMin = currentMin;
-                        prevchild = child;
-                        child = next(this, child);
-                        hasNbsp = false;
-                        continue;
+                    else {
+                        if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+                        inlineMin = endMin;
                     }
-                }
-		prevWasText = false;
-                if (noBreak ||
-                        (prevchild && prevchild->isFloating() && child->isFloating()))
-                {
-                    currentMin += childMin;
-                    if(inlineMin < currentMin) inlineMin = currentMin;
+                        
                     inlineMax += childMax;
-                    noBreak = false;
                 }
-                else
-                {
-                    currentMin = childMin;
-                    if(inlineMin < currentMin) inlineMin = currentMin;
-                    inlineMax += childMax;
-                }
-
             }
-            else
-            {
-                if(m_minWidth < inlineMin) m_minWidth = inlineMin;
-                if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
-                inlineMin = currentMin = inlineMax = 0;
-            }
-	    prevWasText = false;
-            prevchild = child;
-            child = next(this, child);
         }
-        if(m_minWidth < inlineMin) m_minWidth = inlineMin;
-        if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
+        else
+        {             
+            if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+            if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
+            inlineMin = inlineMax = 0;
+            stripFrontSpaces = true;
+            trailingSpaceChild = 0;
+        }
+        
+        prevchild = child;
+        child = next(this, child);
+    }
+    
+    if (trailingSpaceChild && trailingSpaceChild->isText() && !m_pre) {
+        // Collapse away the trailing space at the end of a block. 
+        RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
+        const Font *f = t->htmlFont( false );
+        QChar space[1]; space[0] = ' ';
+        int spaceWidth = f->width(space, 1, 0);
+        inlineMax -= spaceWidth;
+        if (inlineMin > inlineMax)
+            inlineMin = inlineMax;
+    }
+
+    if(m_minWidth < inlineMin) m_minWidth = inlineMin;
+    if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
 //         kdDebug( 6040 ) << "m_minWidth=" << m_minWidth
 // 			<< " m_maxWidth=" << m_maxWidth << endl;
-    }
-    else
+}
+
+void RenderFlow::calcBlockMinMaxWidth()
+{
+    RenderObject *child = firstChild();
+    while(child != 0)
     {
-        while(child != 0)
+        // positioned children don't affect the minmaxwidth
+        if (child->isPositioned())
         {
-            // positioned children don't affect the minmaxwidth
-            if (child->isPositioned())
-            {
-                child = child->nextSibling();
-                continue;
-            }
+            child = child->nextSibling();
+            continue;
+        }
 
-            int margin=0;
-            //  auto margins don't affect minwidth
+        int margin=0;
+        //  auto margins don't affect minwidth
 
-            Length ml = child->style()->marginLeft();
-            Length mr = child->style()->marginRight();
+        Length ml = child->style()->marginLeft();
+        Length mr = child->style()->marginRight();
 
-            if (style()->textAlign() == KONQ_CENTER)
-            {
-                if (ml.type==Fixed) margin+=ml.value;
-                if (mr.type==Fixed) margin+=mr.value;
-            }
-            else
+        if (style()->textAlign() == KONQ_CENTER)
+        {
+            if (ml.type==Fixed) margin+=ml.value;
+            if (mr.type==Fixed) margin+=mr.value;
+        }
+        else
+        {
+            if (!(ml.type==Variable) && !(mr.type==Variable))
             {
-                if (!(ml.type==Variable) && !(mr.type==Variable))
+                if (!(child->style()->width().type==Variable))
                 {
-                    if (!(child->style()->width().type==Variable))
-                    {
-                        if (child->style()->direction()==LTR)
-                            margin = child->marginLeft();
-                        else
-                            margin = child->marginRight();
-                    }
+                    if (child->style()->direction()==LTR)
+                        margin = child->marginLeft();
                     else
-                        margin = child->marginLeft()+child->marginRight();
-
+                        margin = child->marginRight();
                 }
-                else if (!(ml.type == Variable))
-                    margin = child->marginLeft();
-                else if (!(mr.type == Variable))
-                    margin = child->marginRight();
+                else
+                    margin = child->marginLeft()+child->marginRight();
+
             }
+            else if (!(ml.type == Variable))
+                margin = child->marginLeft();
+            else if (!(mr.type == Variable))
+                margin = child->marginRight();
+        }
 
-            if (margin<0) margin=0;
+        if (margin<0) margin=0;
 
-            int w = child->minWidth() + margin;
-            if(m_minWidth < w) m_minWidth = w;
-            w = child->maxWidth() + margin;
-            if(m_maxWidth < w) m_maxWidth = w;
-            child = child->nextSibling();
-        }
+        int w = child->minWidth() + margin;
+        if(m_minWidth < w) m_minWidth = w;
+        w = child->maxWidth() + margin;
+        if(m_maxWidth < w) m_maxWidth = w;
+        child = child->nextSibling();
     }
+}
+
+void RenderFlow::calcMinMaxWidth()
+{
+    KHTMLAssert( !minMaxKnown() );
+
+#ifdef DEBUG_LAYOUT
+    kdDebug( 6040 ) << renderName() << "(RenderBox)::calcMinMaxWidth() this=" << this << endl;
+#endif
+
+    m_minWidth = 0;
+    m_maxWidth = 0;
+
+    if (isInline()) {
+        // Irrelevant, since some enclosing block will actually flow our children.
+        setMinMaxKnown();
+        return;
+    }
+
+    if (childrenInline())
+        calcInlineMinMaxWidth();
+    else
+        calcBlockMinMaxWidth();
+        
     if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
 
     if (style()->width().isFixed())
@@ -1494,15 +1605,13 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
 	    newChild->setBlockBidi();
 
     RenderStyle* pseudoStyle=0;
-    if ( !isInline() && ( !firstChild() || firstChild() == beforeChild )
-        && ( pseudoStyle=style()->getPseudoStyle(RenderStyle::FIRST_LETTER) ) )
+    if (!isInline() && (!firstChild() || firstChild() == beforeChild) && newChild->isText())
     {
-        if (newChild->isText()) {
-            RenderText* newTextChild = static_cast<RenderText*>(newChild);
+        RenderText* newTextChild = static_cast<RenderText*>(newChild);
+        //kdDebug( 6040 ) << "first letter" << endl;
 
-            //kdDebug( 6040 ) << "first letter" << endl;
-    
-            RenderFlow* firstLetter = new RenderFlow(0 /* anonymous box */);
+        if ( (pseudoStyle=style()->getPseudoStyle(RenderStyle::FIRST_LETTER)) ) {
+            RenderFlow* firstLetter = new (renderArena()) RenderFlow(0 /* anonymous box */);
             pseudoStyle->setDisplay( INLINE );
             firstLetter->setStyle(pseudoStyle);
     
@@ -1519,7 +1628,7 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
                 //kdDebug( 6040 ) << "letter= '" << DOMString(oldText->substring(0,length)).string() << "'" << endl;
                 newTextChild->setText(oldText->substring(length,oldText->l-length));
     
-                RenderText* letter = new RenderText(0 /* anonymous object */, oldText->substring(0,length));
+                RenderText* letter = new (renderArena()) RenderText(0 /* anonymous object */, oldText->substring(0,length));
                 RenderStyle* newStyle = new RenderStyle();
                 newStyle->inheritFrom(pseudoStyle);
                 letter->setStyle(newStyle);
@@ -1568,7 +1677,7 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
             }
 
             removeChildNode(anonBox);
-            anonBox->detach(); // does necessary cleanup & deletes anonBox
+            anonBox->detach(renderArena()); // does necessary cleanup & deletes anonBox
 
             KHTMLAssert(beforeChild->parent() == this);
         }
@@ -1631,7 +1740,7 @@ void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
             newStyle->inheritFrom(style());
             newStyle->setDisplay(BLOCK);
 
-            RenderFlow *newBox = new RenderFlow(0 /* anonymous box */);
+            RenderFlow *newBox = new (element()->getDocument()->renderArena()) RenderFlow(0 /* anonymous box */);
             newBox->setStyle(newStyle);
             newBox->setIsAnonymousBox(true);
 
@@ -1710,7 +1819,7 @@ void RenderFlow::makeChildrenNonInline(RenderObject *box2Start)
             newStyle->inheritFrom(style());
             newStyle->setDisplay(BLOCK);
 
-            RenderFlow *box = new RenderFlow(0 /* anonymous box */);
+            RenderFlow *box = new (renderArena()) RenderFlow(0 /* anonymous box */);
             box->setStyle(newStyle);
             box->setIsAnonymousBox(true);
             // ### the children have a wrong style!!!
diff --git a/WebCore/khtml/rendering/render_flow.h b/WebCore/khtml/rendering/render_flow.h
index aa94341..e52a619 100644
--- a/WebCore/khtml/rendering/render_flow.h
+++ b/WebCore/khtml/rendering/render_flow.h
@@ -122,7 +122,9 @@ public:
     void positionNewFloats();
     void clearFloats();
     virtual void calcMinMaxWidth();
-
+    void calcInlineMinMaxWidth();
+    void calcBlockMinMaxWidth();
+    
     virtual bool containsSpecial() { return specialObjects!=0; }
     virtual bool hasOverhangingFloats() { return floatBottom() > m_height; }
 
@@ -130,7 +132,7 @@ public:
 
     // implementation of the following functions is in bidi.cpp
     void bidiReorderLine(const BidiIterator &start, const BidiIterator &end);
-    BidiIterator findNextLineBreak(BidiIterator &start);
+    BidiIterator findNextLineBreak(BidiIterator &start, QPtrList<BidiIterator>& midpoints);
 
     virtual bool isSelfCollapsingBlock() const { return m_height == 0; }
     virtual bool isTopMarginQuirk() const { return m_topMarginQuirk; }
diff --git a/WebCore/khtml/rendering/render_html.cpp b/WebCore/khtml/rendering/render_html.cpp
index 31db5e3..882814f 100644
--- a/WebCore/khtml/rendering/render_html.cpp
+++ b/WebCore/khtml/rendering/render_html.cpp
@@ -22,6 +22,7 @@
 #include "rendering/render_html.h"
 #include "rendering/render_root.h"
 #include "html/html_elementimpl.h"
+#include "xml/dom_docimpl.h"
 
 #include "khtmlview.h"
 
@@ -32,7 +33,7 @@ using namespace khtml;
 RenderHtml::RenderHtml(DOM::HTMLElementImpl* node)
     : RenderFlow(node)
 {
-    m_layer = new RenderLayer(this);
+    m_layer = new (node->getDocument()->renderArena()) RenderLayer(this);
 }
 
 RenderHtml::~RenderHtml()
diff --git a/WebCore/khtml/rendering/render_layer.cpp b/WebCore/khtml/rendering/render_layer.cpp
index ce626de..4adc9b8 100644
--- a/WebCore/khtml/rendering/render_layer.cpp
+++ b/WebCore/khtml/rendering/render_layer.cpp
@@ -25,6 +25,8 @@
 #include <assert.h>
 #include "khtmlview.h"
 #include "render_box.h"
+#include "render_arena.h"
+#include "xml/dom_docimpl.h"
 
 using namespace DOM;
 using namespace khtml;
@@ -47,6 +49,7 @@ RenderLayer::~RenderLayer()
 {
     // Child layers will be deleted by their corresponding render objects, so
     // our destructor doesn't have to do anything.
+    m_parent = m_previous = m_next = m_first = m_last = 0;
 }
 
 void RenderLayer::updateLayerPosition()
@@ -82,6 +85,26 @@ RenderLayer::enclosingPositionedAncestor()
     return curr;
 }
 
+void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void RenderLayer::operator delete(void* ptr, size_t sz) {
+    size_t* szPtr = (size_t*)ptr;
+    *szPtr = sz;
+}
+
+void RenderLayer::detach(RenderArena* renderArena)
+{
+    delete this;
+    
+    
+    // Now perform the destroy.
+    size_t* sz = (size_t*)this;
+    renderArena->free(*sz, (void*)this);
+}
+
 void RenderLayer::addChild(RenderLayer *child)
 {
     if (!firstChild()) {
@@ -202,7 +225,7 @@ RenderLayer::paint(QPainter *p, int x, int y, int w, int h)
     if (currRect != paintRect)
         p->restore(); // Pop the clip.
         
-    delete node;
+    node->detach(renderer()->element()->getDocument()->renderArena());
 }
 
 bool
@@ -234,7 +257,7 @@ RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
         if (inside)
             break;
     }
-    delete node;
+    node->detach(renderer()->element()->getDocument()->renderArena());
 
     return inside;
 }
@@ -244,6 +267,9 @@ RenderLayer::constructZTree(QRect damageRect,
                             RenderLayer* rootLayer,
                             bool eventProcessing)
 {
+    // The arena we use for allocating our temporary ztree elements.
+    RenderArena* renderArena = renderer()->element()->getDocument()->renderArena();
+    
     // This variable stores the result we will hand back.
     RenderLayer::RenderZTreeNode* returnNode = 0;
     
@@ -266,7 +292,7 @@ RenderLayer::constructZTree(QRect damageRect,
     convertToLayerCoords(rootLayer, x, y);
     QRect layerBounds(x, y, width(), height());
      
-    returnNode = new RenderLayer::RenderZTreeNode(this);
+    returnNode = new (renderArena) RenderZTreeNode(this);
 
     // If we establish a clip rect, then we want to intersect that rect
     // with the damage rect to form a new damage rect.
@@ -309,10 +335,10 @@ RenderLayer::constructZTree(QRect damageRect,
         (eventProcessing && layerBounds.contains(damageRect.x(),
 						 damageRect.y())) ||
         (!eventProcessing && layerBounds.intersects(damageRect))) {
-        RenderLayerElement* layerElt = new RenderLayerElement(this, layerBounds, 
+        RenderLayerElement* layerElt = new (renderArena) RenderLayerElement(this, layerBounds, 
                                                               damageRect, x, y);
         if (returnNode->child) {
-            RenderZTreeNode* leaf = new RenderZTreeNode(layerElt);
+            RenderZTreeNode* leaf = new (renderArena) RenderZTreeNode(layerElt);
             leaf->next = returnNode->child;
             returnNode->child = leaf;
             
@@ -338,7 +364,7 @@ RenderLayer::constructZTree(QRect damageRect,
             // children.
             if (returnNode->layerElement) {
                 RenderZTreeNode* leaf = returnNode;
-                returnNode = new RenderLayer::RenderZTreeNode(this);
+                returnNode = new (renderArena) RenderZTreeNode(this);
                 returnNode->child = leaf;
             }
             
@@ -470,3 +496,55 @@ void RenderLayer::RenderZTreeNode::constructLayerList(QPtrVector<RenderLayerElem
         elt->zindex = explicitZIndex;
     }
 }
+
+void* RenderLayer::RenderLayerElement::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    void* result = renderArena->allocate(sz);
+    if (result)
+        memset(result, 0, sz);
+    return result;
+}
+
+void RenderLayer::RenderLayerElement::operator delete(void* ptr, size_t sz) {
+    size_t* szPtr = (size_t*)ptr;
+    *szPtr = sz;
+}
+
+void RenderLayer::RenderLayerElement::detach(RenderArena* renderArena)
+{
+    delete this;
+    
+    // Now perform the destroy.
+    size_t* sz = (size_t*)this;
+    renderArena->free(*sz, (void*)this);
+}
+
+void* RenderLayer::RenderZTreeNode::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    void* result = renderArena->allocate(sz);
+    if (result)
+        memset(result, 0, sz);
+    return result;
+}
+
+void RenderLayer::RenderZTreeNode::operator delete(void* ptr, size_t sz) {
+    size_t* szPtr = (size_t*)ptr;
+    *szPtr = sz;
+}
+
+void RenderLayer::RenderZTreeNode::detach(RenderArena* renderArena)
+{
+    if (next)
+        next->detach(renderArena); 
+    if (child)
+        child->detach(renderArena);
+    if (layerElement)
+        layerElement->detach(renderArena);
+
+    delete this;
+    
+    // Now perform the destroy.
+    size_t* sz = (size_t*)this;
+    renderArena->free(*sz, (void*)this);
+}
+
diff --git a/WebCore/khtml/rendering/render_layer.h b/WebCore/khtml/rendering/render_layer.h
index 111e352..626ef3c 100644
--- a/WebCore/khtml/rendering/render_layer.h
+++ b/WebCore/khtml/rendering/render_layer.h
@@ -98,6 +98,19 @@ public:
     void paint(QPainter *p, int x, int y, int w, int h);
     bool nodeAtPoint(RenderObject::NodeInfo& info, int x, int y);
     
+    void detach(RenderArena* renderArena);
+    
+     // 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();    
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void* ptr, size_t sz);
+        
+private:
+    // The normal operator new is disallowed on all render objects.
+    void* operator new(size_t sz) throw() { assert(false); return 0; };
+
 public:
     // Z-Index Implementation Notes
     //
@@ -133,6 +146,18 @@ public:
       RenderLayerElement(RenderLayer* l, const QRect& rect, const QRect& clip, int xpos, int ypos)
           :layer(l), absBounds(rect), clipRect(clip), zindex(l->zIndex()), zauto(l->hasAutoZIndex()),
           x(xpos), y(ypos) {}
+          
+      void detach(RenderArena* renderArena);
+    
+      // 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();    
+
+      // Overridden to prevent the normal delete from being called.
+      void operator delete(void* ptr, size_t sz);
+        
+      // The normal operator new is disallowed.
+      void* operator new(size_t sz) throw() { assert(false); return 0; };
     };
 
     // The list of layer elements is built through a recursive examination
@@ -165,11 +190,22 @@ public:
       RenderZTreeNode(RenderLayerElement* layerElt)
           :layer(layerElt->layer), next(0), child(0), layerElement(layerElt) {}
       
-      ~RenderZTreeNode() { delete next; delete child; delete layerElement; }
+      ~RenderZTreeNode() {}
 
       void constructLayerList(QPtrVector<RenderLayerElement>* mergeTmpBuffer,
                               QPtrVector<RenderLayerElement>* finalBuffer);
       
+      void detach(RenderArena* renderArena);
+          
+      // 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();    
+
+      // Overridden to prevent the normal delete from being called.
+      void operator delete(void* ptr, size_t sz);
+        
+      // The normal operator new is disallowed.
+      void* operator new(size_t sz) throw() { assert(false); return 0; };
     };
       
 private:
diff --git a/WebCore/khtml/rendering/render_list.cpp b/WebCore/khtml/rendering/render_list.cpp
index 330aa46..a90b2ef 100644
--- a/WebCore/khtml/rendering/render_list.cpp
+++ b/WebCore/khtml/rendering/render_list.cpp
@@ -24,6 +24,8 @@
 #include "render_list.h"
 #include "rendering/render_root.h"
 
+#include "xml/dom_docimpl.h"
+
 #include <qpainter.h>
 
 #include "misc/helper.h"
@@ -143,11 +145,11 @@ void RenderListItem::setStyle(RenderStyle *_style)
 
     if(!m_marker && style()->listStyleType() != LNONE) {
 
-        m_marker = new RenderListMarker();
+        m_marker = new (element()->getDocument()->renderArena()) RenderListMarker();
         m_marker->setStyle(newStyle);
         insertChildNode( m_marker, firstChild() );
     } else if ( m_marker && style()->listStyleType() == LNONE) {
-        m_marker->detach();
+        m_marker->detach(element()->getDocument()->renderArena());
         m_marker = 0;
     }
     else if ( m_marker ) {
diff --git a/WebCore/khtml/rendering/render_object.cpp b/WebCore/khtml/rendering/render_object.cpp
index 19e9b54..7837d7b 100644
--- a/WebCore/khtml/rendering/render_object.cpp
+++ b/WebCore/khtml/rendering/render_object.cpp
@@ -32,14 +32,26 @@
 #include <kdebug.h>
 #include <qpainter.h>
 #include "khtmlview.h"
+#include "render_arena.h"
 
 #include <assert.h>
 using namespace DOM;
 using namespace khtml;
 
+void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void RenderObject::operator delete(void* ptr, size_t sz) {
+    size_t* szPtr = (size_t*)ptr;
+    *szPtr = sz;
+}
+
 RenderObject *RenderObject::createObject(DOM::NodeImpl* node,  RenderStyle* style)
 {
     RenderObject *o = 0;
+    RenderArena* arena = node->getDocument()->renderArena();
     switch(style->display())
     {
     case NONE:
@@ -52,12 +64,12 @@ RenderObject *RenderObject::createObject(DOM::NodeImpl* node,  RenderStyle* styl
         // to suffice. -dwh
         if (style->display() == BLOCK && node->id() == ID_TD &&
             node->getDocument()->parseMode() != DocumentImpl::Strict)
-            o = new RenderTableCell(node);
+            o = new (arena) RenderTableCell(node);
         else
-            o = new RenderFlow(node);
+            o = new (arena) RenderFlow(node);
         break;
     case LIST_ITEM:
-        o = new RenderListItem(node);
+        o = new (arena) RenderListItem(node);
         break;
     case RUN_IN:
     case COMPACT:
@@ -67,32 +79,31 @@ RenderObject *RenderObject::createObject(DOM::NodeImpl* node,  RenderStyle* styl
     case INLINE_TABLE:
         // ### set inline/block right
         //kdDebug( 6040 ) << "creating RenderTable" << endl;
-        o = new RenderTable(node);
+        o = new (arena) RenderTable(node);
         break;
     case TABLE_ROW_GROUP:
     case TABLE_HEADER_GROUP:
     case TABLE_FOOTER_GROUP:
-        o = new RenderTableSection(node);
+        o = new (arena) RenderTableSection(node);
         break;
     case TABLE_ROW:
-        o = new RenderTableRow(node);
+        o = new (arena) RenderTableRow(node);
         break;
     case TABLE_COLUMN_GROUP:
     case TABLE_COLUMN:
-        o = new RenderTableCol(node);
+        o = new (arena) RenderTableCol(node);
         break;
     case TABLE_CELL:
-        o = new RenderTableCell(node);
+        o = new (arena) RenderTableCell(node);
         break;
     case TABLE_CAPTION:
-        o = new RenderTableCaption(node);
+        o = new (arena) RenderTableCaption(node);
         break;
     }
     if(o) o->setStyle(style);
     return o;
 }
 
-
 RenderObject::RenderObject(DOM::NodeImpl* node)
     : CachedObjectClient(),
 m_style( 0 ),
@@ -864,11 +875,31 @@ void RenderObject::removeFromSpecialObjects()
     }
 }
 
-void RenderObject::detach()
+RenderArena* RenderObject::renderArena() {
+    DOM::NodeImpl* elt = element();
+    RenderObject* current = parent();
+    while (!elt && current) {
+        elt = current->element();
+        current = current->parent();
+    }
+    if (!elt)
+        return 0;
+    return elt->getDocument()->renderArena();
+}
+
+
+void RenderObject::detach(RenderArena* renderArena)
 {
     remove();
+    
+    m_next = m_previous = 0;
+    
     // by default no refcounting
     delete this;
+    
+    // Now perform the destroy.
+    size_t* sz = (size_t*)this;
+    renderArena->free(*sz, (void*)this);
 }
 
 FindSelectionResult RenderObject::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset )
diff --git a/WebCore/khtml/rendering/render_object.h b/WebCore/khtml/rendering/render_object.h
index 39b722a..fd61bee 100644
--- a/WebCore/khtml/rendering/render_object.h
+++ b/WebCore/khtml/rendering/render_object.h
@@ -37,6 +37,7 @@ class QPainter;
 class QTextStream;
 class CSSStyle;
 class KHTMLView;
+class RenderArena;
 
 #ifndef NDEBUG
 #define KHTMLAssert( x ) if( !(x) ) { \
@@ -121,6 +122,20 @@ public:
 
     static RenderObject *createObject(DOM::NodeImpl* node, RenderStyle* style);
 
+    // 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();    
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void* ptr, size_t sz);
+        
+private:
+    // The normal operator new is disallowed on all render objects.
+    void* operator new(size_t sz) throw() { assert(false); return 0; };
+    
+public:
+    RenderArena* renderArena();
+    
     // some helper functions...
     virtual bool childrenInline() const { return false; }
     virtual bool isRendered() const { return false; }
@@ -404,7 +419,7 @@ public:
 
     virtual short minWidth() const { return 0; }
     virtual short maxWidth() const { return 0; }
-
+        
     RenderStyle* style() const { return m_style; }
     RenderStyle* style( bool firstLine ) const {
 	RenderStyle *s = m_style;
@@ -464,7 +479,7 @@ public:
     virtual void calcVerticalMargins() {}
     void removeFromSpecialObjects();
 
-    virtual void detach();
+    virtual void detach(RenderArena* renderArena);
 
     const QFont &font(bool firstLine) const {
 	return style( firstLine )->font();
diff --git a/WebCore/khtml/rendering/render_replaced.cpp b/WebCore/khtml/rendering/render_replaced.cpp
index 29ca898..e1e4f27 100644
--- a/WebCore/khtml/rendering/render_replaced.cpp
+++ b/WebCore/khtml/rendering/render_replaced.cpp
@@ -23,6 +23,8 @@
 #include "render_replaced.h"
 #include "render_root.h"
 
+#include "render_arena.h"
+
 #include <assert.h>
 #include <qwidget.h>
 #include <qpainter.h>
@@ -120,7 +122,7 @@ RenderWidget::RenderWidget(DOM::NodeImpl* node)
     ref();
 }
 
-void RenderWidget::detach()
+void RenderWidget::detach(RenderArena* renderArena)
 {
     remove();
 
@@ -131,6 +133,7 @@ void RenderWidget::detach()
         m_widget->removeEventFilter( this );
         m_widget->setMouseTracking( false );
     }
+    
     deref();
 }
 
diff --git a/WebCore/khtml/rendering/render_replaced.h b/WebCore/khtml/rendering/render_replaced.h
index 356adc8..ee6ee02 100644
--- a/WebCore/khtml/rendering/render_replaced.h
+++ b/WebCore/khtml/rendering/render_replaced.h
@@ -74,7 +74,7 @@ public:
 
     virtual bool isWidget() const { return true; };
 
-    virtual void detach();
+    virtual void detach(RenderArena* renderArena);
     virtual void layout( );
 
     QWidget *widget() const { return m_widget; }
diff --git a/WebCore/khtml/rendering/render_root.cpp b/WebCore/khtml/rendering/render_root.cpp
index cdb7645..52fa062 100644
--- a/WebCore/khtml/rendering/render_root.cpp
+++ b/WebCore/khtml/rendering/render_root.cpp
@@ -20,6 +20,7 @@
  */
 #include "rendering/render_root.h"
 #include "render_layer.h"
+#include "xml/dom_docimpl.h"
 
 #include "khtmlview.h"
 #include <kdebug.h>
@@ -62,7 +63,7 @@ RenderRoot::RenderRoot(DOM::NodeImpl* node, KHTMLView *view)
     m_selectionEndPos = -1;
 
     // Create a new root layer for our layer hierarchy.
-    m_layer = new RenderLayer(this);
+    m_layer = new (node->getDocument()->renderArena()) RenderLayer(this);
 }
 
 RenderRoot::~RenderRoot()
diff --git a/WebCore/khtml/rendering/render_table.cpp b/WebCore/khtml/rendering/render_table.cpp
index e131172..63c9815 100644
--- a/WebCore/khtml/rendering/render_table.cpp
+++ b/WebCore/khtml/rendering/render_table.cpp
@@ -31,6 +31,7 @@
 #include "rendering/render_table.h"
 #include "html/html_tableimpl.h"
 #include "misc/htmltags.h"
+#include "xml/dom_docimpl.h"
 
 #include <kglobal.h>
 
@@ -211,7 +212,7 @@ void RenderTable::addChild(RenderObject *child, RenderObject *beforeChild)
 		return;
 	    } else {
 //          kdDebug( 6040 ) << "creating anonymous table section" << endl;
-		o = new RenderTableSection(0 /* anonymous */);
+		o = new (renderArena()) RenderTableSection(0 /* anonymous */);
 		RenderStyle *newStyle = new RenderStyle();
 		newStyle->inheritFrom(style());
 		newStyle->setDisplay(TABLE_ROW_GROUP);
@@ -1010,17 +1011,15 @@ void RenderTable::calcWidth()
         calcAbsoluteHorizontal();
     }
 
-    int borderWidth = borderLeft() + borderRight();
     RenderObject *cb = containingBlock();
-    int availableWidth = cb->contentWidth() - borderWidth;
-
+    int availableWidth = cb->contentWidth();
 
     LengthType widthType = style()->width().type;
     if(widthType > Relative) {
-	// Percent or fixed table
+        // Percent or fixed table
         m_width = style()->width().minWidth( availableWidth );
         if(m_minWidth > m_width) m_width = m_minWidth;
-	//kdDebug( 6040 ) << "1 width=" << m_width << " minWidth=" << m_minWidth << " availableWidth=" << availableWidth << " " << endl;
+        //kdDebug( 6040 ) << "1 width=" << m_width << " minWidth=" << m_minWidth << " availableWidth=" << availableWidth << " " << endl;
     } else if (hasPercent) {
         m_width = KMIN(short( availableWidth ),m_maxWidth);
 //        kdDebug( 6040 ) << "width=" << m_width << " maxPercent=" << maxPercent << " maxVar=" << maxVar << " " << endl;
@@ -1030,7 +1029,7 @@ void RenderTable::calcWidth()
 
     // restrict width to what we really have in case we flow around floats
     if ( style()->flowAroundFloats() && cb->isFlow() )
-	m_width = QMIN( static_cast<RenderFlow *>(cb)->lineWidth( m_y ) - borderWidth, m_width );
+	m_width = QMIN( static_cast<RenderFlow *>(cb)->lineWidth( m_y ), m_width );
 
     m_width = KMAX (m_width, m_minWidth);
 
@@ -1056,8 +1055,6 @@ void RenderTable::calcWidth()
             calcFinalColMax(c, col);
         }
     }
-
-    m_width += borderWidth;
 }
 
 void RenderTable::calcColWidth(void)
@@ -1601,7 +1598,7 @@ void RenderTable::setCellWidths()
         {
             if ( ( indx = c-cell->colSpan()+1) < 0 )
                 indx = 0;
-            int w = columnPos[c+1] - columnPos[ indx ] - spacing ; //- padding*2;
+            int w = columnPos[c+1] - columnPos[ indx ] - spacing; //- padding*2;
 
 #ifdef TABLE_DEBUG
             kdDebug( 6040 ) << "0x" << this << ": setting width " << r << "/" << indx << "-" << c << " (0x" << cell << "): " << w << " " << endl;
@@ -1895,7 +1892,7 @@ void RenderTableSection::addChild(RenderObject *child, RenderObject *beforeChild
 		return;
 	    } else {
 		kdDebug( 6040 ) << "creating anonymous table row" << endl;
-		row = new RenderTableRow(0 /* anonymous table */);
+		row = new (renderArena()) RenderTableRow(0 /* anonymous table */);
 		RenderStyle *newStyle = new RenderStyle();
 		newStyle->inheritFrom(style());
 		newStyle->setDisplay(TABLE_ROW);
@@ -1986,7 +1983,7 @@ void RenderTableRow::addChild(RenderObject *child, RenderObject *beforeChild)
 		return;
 	    } else {
 //          kdDebug( 6040 ) << "creating anonymous table cell" << endl;
-		cell = new RenderTableCell(0 /* anonymous object */);
+		cell = new (renderArena()) RenderTableCell(0 /* anonymous object */);
 		RenderStyle *newStyle = new RenderStyle();
 		newStyle->inheritFrom(style());
 		newStyle->setDisplay(TABLE_CELL);
diff --git a/WebCore/khtml/rendering/render_text.cpp b/WebCore/khtml/rendering/render_text.cpp
index 6885b6f..da74115 100644
--- a/WebCore/khtml/rendering/render_text.cpp
+++ b/WebCore/khtml/rendering/render_text.cpp
@@ -28,6 +28,8 @@
 #include "rendering/render_root.h"
 #include "rendering/break_lines.h"
 #include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "render_arena.h"
 
 #include "misc/loader.h"
 
@@ -38,6 +40,25 @@
 using namespace khtml;
 using namespace DOM;
 
+void TextSlave::detach(RenderArena* renderArena)
+{
+    delete this;
+    
+    // Now perform the destroy.
+    size_t* sz = (size_t*)this;
+    renderArena->free(*sz, (void*)this);
+}
+
+void* TextSlave::operator new(size_t sz, RenderArena* renderArena) throw()
+{
+    return renderArena->allocate(sz);
+}
+
+void TextSlave::operator delete(void* ptr, size_t sz) {
+    size_t* szPtr = (size_t*)ptr;
+    *szPtr = sz;
+}
+
 void TextSlave::printSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos)
 {
     if(startPos > m_len) return;
@@ -226,7 +247,7 @@ FindSelectionResult TextSlave::checkSelectionPoint(int _x, int _y, int _tx, int
 
 TextSlaveArray::TextSlaveArray()
 {
-    setAutoDelete(true);
+    setAutoDelete(false);
 }
 
 int TextSlaveArray::compareItems( Item d1, Item d2 )
@@ -289,7 +310,6 @@ RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
     KHTMLAssert(!str || !str->l || str->s);
 
     m_selectionState = SelectionNone;
-    m_hasReturn = true;
 
 #ifdef DEBUG_LAYOUT
     QConstString cstr(str->s, str->l);
@@ -315,20 +335,30 @@ void RenderText::setStyle(RenderStyle *_style)
 
 RenderText::~RenderText()
 {
-    deleteSlaves();
     if(str) str->deref();
 }
 
+void RenderText::detach(RenderArena* renderArena)
+{
+    deleteSlaves();
+    RenderObject::detach(renderArena);
+}
+
 void RenderText::deleteSlaves()
 {
     // this is a slight variant of QArray::clear().
     // We don't delete the array itself here because its
     // likely to be used in the same size later again, saves
     // us resize() calls
+    RenderArena* arena = element()->getDocument()->renderArena();
     unsigned int len = m_lines.size();
-    for(unsigned int i=0; i < len; i++)
+    for(unsigned int i=0; i < len; i++) {
+        TextSlave* s = m_lines.at(i);
+        if (s)
+            s->detach(arena);
         m_lines.remove(i);
-
+    }
+    
     KHTMLAssert(m_lines.count() == 0);
 }
 
@@ -704,62 +734,145 @@ void RenderText::print( QPainter *p, int x, int y, int w, int h,
     printObject(p, x, y, w, h, tx, ty);
 }
 
+void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS, 
+                                    short& endMinW, bool& endWS,
+                                    bool& hasBreakableChar, bool& hasBreak,
+                                    short& beginMaxW, short& endMaxW,
+                                    short& minW, short& maxW, bool& stripFrontSpaces)
+{
+    int len = str->l;
+    bool isPre = style()->whiteSpace() == PRE;
+    if (isPre)
+        stripFrontSpaces = false;
+    
+    minW = m_minWidth;
+    maxW = m_maxWidth;
+    beginWS = stripFrontSpaces ? false : m_hasBeginWS;
+    // Handle the case where all space got stripped.
+    endWS = stripFrontSpaces && len > 0 && str->containsOnlyWhitespace() ? false : m_hasEndWS;
+    
+    beginMinW = m_beginMinWidth;
+    endMinW = m_endMinWidth;
+    
+    hasBreakableChar = m_hasBreakableChar;
+    hasBreak = false; // XXXdwh will need to make this work eventually.
+                      // m_hasBreak;
+    
+    if (len == 0)
+        return;
+        
+    if (stripFrontSpaces && str->s[0].direction() == QChar::DirWS) {
+        const Font *f = htmlFont( false );
+        QChar space[1]; space[0] = ' ';
+        int spaceWidth = f->width(space, 1, 0);
+        maxW -= spaceWidth;
+    }
+    
+    stripFrontSpaces = !isPre && endWS;
+    
+    if (style()->whiteSpace() == NOWRAP)
+        minW = maxW;
+    else if (minW > maxW)
+        minW = maxW;
+
+    // Compute our max widths by scanning the string for newlines.
+    if (hasBreak) {
+        // XXXdwh this will only be an issue for white-space: pre inlines and
+        // not for the <pre> element itself.
+    }
+}
+
 void RenderText::calcMinMaxWidth()
 {
     KHTMLAssert( !minMaxKnown() );
 
     // ### calc Min and Max width...
-    m_minWidth = 0;
+    m_minWidth = m_beginMinWidth = m_endMinWidth = 0;
     m_maxWidth = 0;
 
+    if (isBR())
+        return;
+        
     int currMinWidth = 0;
     int currMaxWidth = 0;
-    m_hasReturn = false;
-    m_hasBreakableChar = false;
-
+    m_hasBreakableChar = m_hasBreak = m_hasBeginWS = m_hasEndWS = false;
+    
     // ### not 100% correct for first-line
     const Font *f = htmlFont( false );
     int len = str->l;
-    if ( len == 1 && str->s->latin1() == '\n' )
-	m_hasReturn = true;
+    bool ignoringSpaces = false;
+    bool isSpace = false;
+    bool isPre = style()->whiteSpace() == PRE;
+    bool firstWord = true;
     for(int i = 0; i < len; i++)
     {
+        // XXXdwh Wrong in the first stage.  Will stop mutating newlines
+        // in a second stage.
+        if (str->s[i] == '\n') {
+            if (isPre)
+                m_hasBreak = true;
+            else
+                str->s[i] = ' ';
+        }
+        
+        bool oldSpace = isSpace;
+        isSpace = str->s[i].direction() == QChar::DirWS;
+        
+        if (isSpace && i == 0)
+            m_hasBeginWS = true;
+        if (isSpace && i == len-1)
+            m_hasEndWS = true;
+            
+        if (!ignoringSpaces && !isPre && oldSpace && isSpace)
+            ignoringSpaces = true;
+        
+        if (ignoringSpaces && !isSpace)
+            ignoringSpaces = false;
+            
+        if (ignoringSpaces)
+            continue;
+        
         int wordlen = 0;
         while( i+wordlen < len && !(isBreakable( str->s, i+wordlen, str->l )) )
             wordlen++;
+            
         if (wordlen)
         {
             int w = f->width(str->s, str->l, i, wordlen);
             currMinWidth += w;
             currMaxWidth += w;
+            if (firstWord) {
+                firstWord = false;
+                m_beginMinWidth = w;
+            }
+            m_endMinWidth = w;
+            
+            if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
+            currMinWidth = 0;
+                
+            i += wordlen-1;
         }
-        if(i+wordlen < len)
-        {
-	    m_hasBreakableChar = true;
-            if ( (*(str->s+i+wordlen)).latin1() == '\n' )
+        else {
+            // Nowrap can never be broken, so don't bother setting the
+            // breakable character boolean.
+            if (style()->whiteSpace() != NOWRAP)
+                m_hasBreakableChar = true;
+
+            if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
+            currMinWidth = 0;
+                
+            if (str->s[i] == '\n')
             {
-		m_hasReturn = true;
-                if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
-                currMinWidth = 0;
                 if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
                 currMaxWidth = 0;
             }
             else
             {
-                if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
-                currMinWidth = 0;
                 currMaxWidth += f->width( str->s, str->l, i + wordlen );
             }
-            /* else if( c == '-')
-            {
-                currMinWidth += minus_width;
-                if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
-                currMinWidth = 0;
-                currMaxWidth += minus_width;
-            }*/
         }
-        i += wordlen;
     }
+    
     if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
     if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
 
@@ -870,7 +983,8 @@ short RenderText::baselinePosition( bool firstLine ) const
 void RenderText::position(int x, int y, int from, int len, int width, bool reverse, bool firstLine, int spaceAdd)
 {
     // ### should not be needed!!!
-    assert(!(len == 0 || (str->l && len == 1 && *(str->s+from) == '\n') ));
+    if (len == 0 || (str->l && len == 1 && *(str->s+from) == '\n'))
+        return;
 
     reverse = reverse && !style()->visuallyOrdered();
 
@@ -890,7 +1004,7 @@ void RenderText::position(int x, int y, int from, int len, int width, bool rever
     qDebug("setting slave text to *%s*, len=%d, w)=%d" , cstr.string().latin1(), len, width );//" << y << ")" << " height=" << lineHeight(false) << " fontHeight=" << metrics(false).height() << " ascent =" << metrics(false).ascent() << endl;
 #endif
 
-    TextSlave *s = new TextSlave(x, y, from, len,
+    TextSlave *s = new (element()->getDocument()->renderArena()) TextSlave(x, y, from, len,
                                  baselinePosition( firstLine ),
                                  width+spaceAdd, reverse, spaceAdd, firstLine);
 
diff --git a/WebCore/khtml/rendering/render_text.h b/WebCore/khtml/rendering/render_text.h
index cc9f0b9..8c68873 100644
--- a/WebCore/khtml/rendering/render_text.h
+++ b/WebCore/khtml/rendering/render_text.h
@@ -56,6 +56,22 @@ public:
         m_firstLine = firstLine;
         m_toAdd = toAdd;
     }
+    
+    void detach(RenderArena* renderArena);
+    
+    // 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();    
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void* ptr, size_t sz);
+        
+private:
+    // The normal operator new is disallowed.
+    void* operator new(size_t sz) throw() { assert(false); return 0; };
+
+public:
+
     void printDecoration( QPainter *pt, RenderText* p, int _tx, int _ty, int decoration, bool begin, bool end);
     void printBoxDecorations(QPainter *p, RenderStyle* style, RenderText *parent, int _tx, int _ty, bool begin, bool end);
     void printSelection(const Font *f, RenderText *text, QPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos);
@@ -123,7 +139,8 @@ public:
                         int tx, int ty);
 
     void deleteSlaves();
-
+    virtual void detach(RenderArena* renderArena);
+    
     DOM::DOMString data() const { return str; }
     DOM::DOMStringImpl *string() const { return str; }
 
@@ -153,7 +170,12 @@ public:
     virtual void calcMinMaxWidth();
     virtual short minWidth() const { return m_minWidth; }
     virtual short maxWidth() const { return m_maxWidth; }
-
+    virtual void trimmedMinMaxWidth(short& beginMinW, bool& beginWS, 
+                                    short& endMinW, bool& endWS,
+                                    bool& hasBreakableChar, bool& hasBreak,
+                                    short& beginMaxW, short& endMaxW,
+                                    short& minW, short& maxW, bool& stripFrontSpaces);
+    
     // returns the minimum x position of all slaves relative to the parent.
     // defaults to 0.
     int minXPos() const;
@@ -161,8 +183,6 @@ public:
     virtual int xPos() const;
     virtual int yPos() const;
 
-    bool hasReturn() const { return m_hasReturn; }
-
     virtual const QFont &font();
     virtual short verticalPositionHint( bool firstLine ) const;
 
@@ -183,7 +203,6 @@ public:
 
     virtual void repaint();
 
-    bool hasBreakableChar() const { return m_hasBreakableChar; }
     const QFontMetrics &metrics(bool firstLine) const;
     const Font *htmlFont(bool firstLine) const;
 
@@ -210,11 +229,15 @@ protected: // members
     short m_lineHeight;
     short m_minWidth;
     short m_maxWidth;
-
+    short m_beginMinWidth;
+    short m_endMinWidth;
+    
     SelectionState m_selectionState : 3 ;
-    bool m_hasReturn : 1;
-    bool m_hasBreakableChar : 1;
-
+    bool m_hasBreakableChar : 1; // Whether or not we can be broken into multiple lines.
+    bool m_hasBreak : 1; // Whether or not we have a hard break (e.g., <pre> with '\n').
+    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
 };
 
diff --git a/WebCore/khtml/xml/dom_docimpl.cpp b/WebCore/khtml/xml/dom_docimpl.cpp
index 39a0c9e..6542952 100644
--- a/WebCore/khtml/xml/dom_docimpl.cpp
+++ b/WebCore/khtml/xml/dom_docimpl.cpp
@@ -43,6 +43,7 @@
 
 #include "rendering/render_root.h"
 #include "rendering/render_replaced.h"
+#include "render_arena.h"
 
 #include "khtmlview.h"
 #include "khtml_part.h"
@@ -233,7 +234,8 @@ DocumentImpl::DocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
     m_paintDeviceMetrics = 0;
 
     m_view = v;
-
+    m_renderArena = 0;
+    
     if ( v ) {
         m_docLoader = new DocLoader(v->part(), this );
         setPaintDevice( m_view );
@@ -322,6 +324,8 @@ DocumentImpl::~DocumentImpl()
     m_styleSheets->deref();
     if (m_focusNode)
         m_focusNode->deref();
+        
+    delete m_renderArena;
 }
 
 
@@ -981,8 +985,11 @@ void DocumentImpl::attach()
     if ( m_view )
         setPaintDevice( m_view );
 
+    if (!m_renderArena)
+        m_renderArena = new RenderArena();
+    
     // Create the rendering tree
-    m_render = new RenderRoot(this, m_view);
+    m_render = new (m_renderArena) RenderRoot(this, m_view);
     m_styleSelector->computeFontSizes(paintDeviceMetrics(), m_view ? m_view->part()->zoomFactor() : 100);
     recalcStyle( Force );
 
@@ -1003,9 +1010,12 @@ void DocumentImpl::detach()
     NodeBaseImpl::detach();
 
     if ( render )
-        render->detach();
+        render->detach(m_renderArena);
 
     m_view = 0;
+    
+    delete m_renderArena;
+    m_renderArena = 0;
 }
 
 void DocumentImpl::setVisuallyOrdered()
diff --git a/WebCore/khtml/xml/dom_docimpl.h b/WebCore/khtml/xml/dom_docimpl.h
index 2753123..b9eaced 100644
--- a/WebCore/khtml/xml/dom_docimpl.h
+++ b/WebCore/khtml/xml/dom_docimpl.h
@@ -44,6 +44,7 @@ class QPaintDevice;
 class QPaintDeviceMetrics;
 class KHTMLView;
 class Tokenizer;
+class RenderArena;
 
 namespace khtml {
     class CSSStyleSelector;
@@ -226,6 +227,8 @@ public:
     virtual void attach();
     virtual void detach();
 
+    RenderArena* renderArena() { return m_renderArena; }
+    
     // to get visually ordered hebrew and arabic pages right
     void setVisuallyOrdered();
 
@@ -479,6 +482,8 @@ protected:
     bool m_inStyleRecalc;
     
     DOMString m_title;
+    
+    RenderArena* m_renderArena;
 };
 
 class DocumentFragmentImpl : public NodeBaseImpl
diff --git a/WebCore/khtml/xml/dom_nodeimpl.cpp b/WebCore/khtml/xml/dom_nodeimpl.cpp
index 4729e68..8034e9b 100644
--- a/WebCore/khtml/xml/dom_nodeimpl.cpp
+++ b/WebCore/khtml/xml/dom_nodeimpl.cpp
@@ -949,7 +949,7 @@ void NodeImpl::detach()
 //    assert(m_attached);
 
     if ( m_render )
-        m_render->detach();
+        m_render->detach(getDocument()->renderArena());
 
     m_render = 0;
     m_attached = false;
@@ -996,6 +996,15 @@ bool NodeImpl::isReadOnly()
     return false;
 }
 
+RenderObject * NodeImpl::previousRenderer()
+{
+    for (NodeImpl *n = previousSibling(); n; n = n->previousSibling()) {
+        if (n->renderer())
+            return n->renderer();
+    }
+    return 0;
+}
+
 RenderObject * NodeImpl::nextRenderer()
 {
     for (NodeImpl *n = nextSibling(); n; n = n->nextSibling()) {
diff --git a/WebCore/khtml/xml/dom_nodeimpl.h b/WebCore/khtml/xml/dom_nodeimpl.h
index 841ac78..f031142 100644
--- a/WebCore/khtml/xml/dom_nodeimpl.h
+++ b/WebCore/khtml/xml/dom_nodeimpl.h
@@ -104,7 +104,10 @@ public:
     virtual bool isTextNode() const { return false; }
     virtual bool isDocumentNode() const { return false; }
     virtual bool isXMLElementNode() const { return false; }
-
+    
+    virtual bool isMalformed() { return false; }
+    virtual bool containsOnlyWhitespace() const { return false; }
+    
     // helper functions not being part of the DOM
     // Attention: they assume that the caller did the consistency checking!
     void setPreviousSibling(NodeImpl *previous) { m_previous = previous; }
@@ -262,6 +265,7 @@ public:
 
     khtml::RenderObject *renderer() const { return m_render; }
     khtml::RenderObject *nextRenderer();
+    khtml::RenderObject *previousRenderer();
 
     void checkSetPrefix(const DOMString &_prefix, int &exceptioncode);
     void checkAddChild(NodeImpl *newChild, int &exceptioncode);
diff --git a/WebCore/khtml/xml/dom_stringimpl.cpp b/WebCore/khtml/xml/dom_stringimpl.cpp
index b003883..881228d 100644
--- a/WebCore/khtml/xml/dom_stringimpl.cpp
+++ b/WebCore/khtml/xml/dom_stringimpl.cpp
@@ -128,6 +128,21 @@ DOMStringImpl *DOMStringImpl::split(uint pos)
   return str;
 }
 
+bool DOMStringImpl::containsOnlyWhitespace() const
+{
+  if (!s)
+    return true;
+    
+  unsigned int i;
+  QChar tab('\t');
+  QChar ret('\r');
+  QChar lf('\n');
+  for (i = 0; i < l; i++)
+    if (s[i].direction() != QChar::DirWS && s[i] != tab && s[i] != ret && s[i] != lf)
+	    return false;
+  return true;
+}
+    
 DOMStringImpl *DOMStringImpl::substring(uint pos, uint len)
 {
   if( pos >=l ) return new DOMStringImpl();
diff --git a/WebCore/khtml/xml/dom_stringimpl.h b/WebCore/khtml/xml/dom_stringimpl.h
index 903208e..b949025 100644
--- a/WebCore/khtml/xml/dom_stringimpl.h
+++ b/WebCore/khtml/xml/dom_stringimpl.h
@@ -76,7 +76,9 @@ public:
 	{ return *(s+pos); }
 
     khtml::Length toLength() const;
-
+    
+    bool containsOnlyWhitespace() const;
+    
     // ignores trailing garbage, unlike QString
     int toInt(bool* ok=0) const {
         int len = l;
diff --git a/WebCore/khtml/xml/dom_textimpl.cpp b/WebCore/khtml/xml/dom_textimpl.cpp
index 9843840..0423d4a 100644
--- a/WebCore/khtml/xml/dom_textimpl.cpp
+++ b/WebCore/khtml/xml/dom_textimpl.cpp
@@ -184,6 +184,13 @@ DOMString CharacterDataImpl::nodeValue() const
     return str;
 }
 
+bool CharacterDataImpl::containsOnlyWhitespace() const
+{
+    if (str)
+        return str->containsOnlyWhitespace();
+    return true;
+}
+
 void CharacterDataImpl::setNodeValue( const DOMString &_nodeValue, int &exceptioncode )
 {
     // NO_MODIFICATION_ALLOWED_ERR: taken care of by setData()
@@ -357,8 +364,29 @@ void TextImpl::attach()
 
     ElementImpl* element = static_cast<ElementImpl*>(parentNode());
     if (!m_render && element->renderer()) {
-        khtml::RenderStyle* _style = element->renderer()->style();
-        m_render = new RenderText(this, str);
+        RenderObject* par = element->renderer();
+        khtml::RenderStyle* _style = par->style();
+        bool onlyWS = containsOnlyWhitespace();
+        if (onlyWS) {
+            if (par->isTable() || par->isTableRow() || par->isTableSection())
+                return CharacterDataImpl::attach();
+        
+            if (!par->isInline() && _style->whiteSpace() != PRE) {
+                RenderObject* prevRender = previousRenderer();
+                if (par->isFlow() && !par->childrenInline() && 
+                    (!prevRender || !prevRender->isInline()))
+                    return CharacterDataImpl::attach();
+                
+                RenderObject* nextRender = nextRenderer();
+                if ((!par->firstChild() || 
+                    nextRender == par->firstChild()))
+                    // Whitespace at the start of a block just goes away.  Don't even
+                    // make a render object for this text.
+                    return CharacterDataImpl::attach();
+            }
+        }
+
+        m_render = new (getDocument()->renderArena()) RenderText(this, str);
         m_render->setStyle(_style);
         parentNode()->renderer()->addChild(m_render, nextRenderer());
     }
diff --git a/WebCore/khtml/xml/dom_textimpl.h b/WebCore/khtml/xml/dom_textimpl.h
index 9255477..35da605 100644
--- a/WebCore/khtml/xml/dom_textimpl.h
+++ b/WebCore/khtml/xml/dom_textimpl.h
@@ -52,6 +52,8 @@ public:
     virtual void deleteData ( const unsigned long offset, const unsigned long count, int &exceptioncode );
     virtual void replaceData ( const unsigned long offset, const unsigned long count, const DOMString &arg, int &exceptioncode );
 
+    virtual bool containsOnlyWhitespace() const;
+    
     // DOM methods overridden from  parent classes
 
     virtual DOMString nodeValue() const;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list