summaryrefslogtreecommitdiffstats
path: root/khtml/rendering/render_container.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khtml/rendering/render_container.cpp')
-rw-r--r--khtml/rendering/render_container.cpp597
1 files changed, 0 insertions, 597 deletions
diff --git a/khtml/rendering/render_container.cpp b/khtml/rendering/render_container.cpp
deleted file mode 100644
index 69f987477..000000000
--- a/khtml/rendering/render_container.cpp
+++ /dev/null
@@ -1,597 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2001-2003 Lars Knoll (knoll@kde.org)
- * (C) 2001 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2002-2003 Apple Computer, Inc.
- *
- * 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., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-//#define DEBUG_LAYOUT
-
-#include "rendering/render_container.h"
-#include "rendering/render_table.h"
-#include "rendering/render_text.h"
-#include "rendering/render_image.h"
-#include "rendering/render_canvas.h"
-#include "rendering/render_generated.h"
-#include "rendering/render_inline.h"
-#include "xml/dom_docimpl.h"
-#include "css/css_valueimpl.h"
-
-#include <kdebug.h>
-#include <assert.h>
-
-using namespace khtml;
-
-RenderContainer::RenderContainer(DOM::NodeImpl* node)
- : RenderObject(node)
-{
- m_first = 0;
- m_last = 0;
-}
-
-void RenderContainer::detach()
-{
- if (continuation())
- continuation()->detach();
-
- // We simulate removeNode calls for all our children
- // and set parent to 0 to avoid removeNode from being called.
- // First call removeLayers and removeFromObjectLists since they assume
- // a valid render-tree
- for(RenderObject* n = m_first; n; n = n->nextSibling() ) {
- n->removeLayers(enclosingLayer());
- n->removeFromObjectLists();
- }
-
- RenderObject* next;
- for(RenderObject* n = m_first; n; n = next ) {
- n->setParent(0);
- next = n->nextSibling();
- n->detach();
- }
- m_first = 0;
- m_last = 0;
-
- RenderObject::detach();
-}
-
-void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << this << ": " << renderName() << "(RenderObject)::addChild( " << newChild << ": " <<
- newChild->renderName() << ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
-#endif
- // protect ourselves from deletion
- setDoNotDelete(true);
-
- bool needsTable = false;
-
- if(!newChild->isText() && !newChild->isReplaced()) {
- switch(newChild->style()->display()) {
- case INLINE:
- case BLOCK:
- case LIST_ITEM:
- case RUN_IN:
- case COMPACT:
- case INLINE_BLOCK:
- case TABLE:
- case INLINE_TABLE:
- break;
- case TABLE_COLUMN:
- if ( isTableCol() )
- break;
- // nobreak
- case TABLE_COLUMN_GROUP:
- case TABLE_CAPTION:
- case TABLE_ROW_GROUP:
- case TABLE_HEADER_GROUP:
- case TABLE_FOOTER_GROUP:
-
- //kdDebug( 6040 ) << "adding section" << endl;
- if ( !isTable() )
- needsTable = true;
- break;
- case TABLE_ROW:
- //kdDebug( 6040 ) << "adding row" << endl;
- if ( !isTableSection() )
- needsTable = true;
- break;
- case TABLE_CELL:
- //kdDebug( 6040 ) << "adding cell" << endl;
- if ( !isTableRow() )
- needsTable = true;
- // I'm not 100% sure this is the best way to fix this, but without this
- // change we recurse infinitely when trying to render the CSS2 test page:
- // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
- if ( isTableCell() && !firstChild() && !newChild->isTableCell() )
- needsTable = false;
-
- break;
- case NONE:
- // RenderHtml and some others can have display:none
- // KHTMLAssert(false);
- break;
- }
- }
-
- if ( needsTable ) {
- RenderTable *table;
- RenderObject *last = beforeChild ? beforeChild->previousSibling() : lastChild();
- if ( last && last->isTable() && last->isAnonymous() ) {
- table = static_cast<RenderTable *>(last);
- } else {
- //kdDebug( 6040 ) << "creating anonymous table, before=" << beforeChild << endl;
- table = new (renderArena()) RenderTable(document() /* is anonymous */);
- RenderStyle *newStyle = new RenderStyle();
- newStyle->inheritFrom(style());
- newStyle->setDisplay( TABLE );
- newStyle->setFlowAroundFloats( true );
- table->setParent( this ); // so it finds the arena
- table->setStyle(newStyle);
- table->setParent( 0 );
- addChild(table, beforeChild);
- }
- table->addChild(newChild);
- } else {
- // just add it...
- insertChildNode(newChild, beforeChild);
- }
-
- if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
- DOM::DOMStringImpl* textToTransform = static_cast<RenderText*>(newChild)->originalString();
- if (textToTransform)
- static_cast<RenderText*>(newChild)->setText(textToTransform, true);
- }
- newChild->attach();
-
- setDoNotDelete(false);
-}
-
-RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild)
-{
- KHTMLAssert(oldChild->parent() == this);
-
- // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
- // that a positioned child got yanked). We also repaint, so that the area exposed when the child
- // disappears gets repainted properly.
- if ( document()->renderer() ) {
- oldChild->setNeedsLayoutAndMinMaxRecalc();
- oldChild->repaint();
-
- // Keep our layer hierarchy updated.
- oldChild->removeLayers(enclosingLayer());
- // remove the child from any special layout lists
- oldChild->removeFromObjectLists();
-
- // if oldChild is the start or end of the selection, then clear
- // the selection to avoid problems of invalid pointers
-
- // ### This is not the "proper" solution... ideally the selection
- // ### should be maintained based on DOM Nodes and a Range, which
- // ### gets adjusted appropriately when nodes are deleted/inserted
- // ### near etc. But this at least prevents crashes caused when
- // ### the start or end of the selection is deleted and then
- // ### accessed when the user next selects something.
-
- if (oldChild->isSelectionBorder()) {
- RenderObject *root = oldChild;
- while (root->parent())
- root = root->parent();
- if (root->isCanvas()) {
- static_cast<RenderCanvas*>(root)->clearSelection();
- }
- }
- }
-
- // remove the child from the render-tree
- if (oldChild->previousSibling())
- oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
- if (oldChild->nextSibling())
- oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
-
- if (m_first == oldChild)
- m_first = oldChild->nextSibling();
- if (m_last == oldChild)
- m_last = oldChild->previousSibling();
-
- oldChild->setPreviousSibling(0);
- oldChild->setNextSibling(0);
- oldChild->setParent(0);
-
- return oldChild;
-}
-
-void RenderContainer::setStyle(RenderStyle* _style)
-{
- RenderObject::setStyle(_style);
-
- // If we are a pseudo-container we need to restyle the children
- if (style()->isGenerated())
- {
- // ### we could save this call when the change only affected
- // non inherited properties
- RenderStyle *pseudoStyle = new RenderStyle();
- pseudoStyle->inheritFrom(style());
- pseudoStyle->ref();
- RenderObject *child = firstChild();
- while (child != 0)
- {
- child->setStyle(pseudoStyle);
- child = child->nextSibling();
- }
- pseudoStyle->deref();
- }
-}
-
-void RenderContainer::updatePseudoChildren()
-{
- // In CSS2, before/after pseudo-content cannot nest. Check this first.
- // Remove when CSS 3 Generated Content becomes Candidate Recommendation
- if (style()->styleType() == RenderStyle::BEFORE
- || style()->styleType() == RenderStyle::AFTER)
- return;
-
- updatePseudoChild(RenderStyle::BEFORE);
- updatePseudoChild(RenderStyle::AFTER);
- // updatePseudoChild(RenderStyle::MARKER, marker());
-}
-
-void RenderContainer::updatePseudoChild(RenderStyle::PseudoId type)
-{
- // The head manages generated content for its continuations
- if (isInlineContinuation()) return;
-
- RenderStyle* pseudo = style()->getPseudoStyle(type);
-
- RenderObject* child = pseudoContainer(type);
-
- // Whether or not we currently have generated content attached.
- bool oldContentPresent = child && (child->style()->styleType() == type);
-
- // Whether or not we now want generated content.
- bool newContentWanted = pseudo && pseudo->display() != NONE;
-
- // No generated content
- if (!oldContentPresent && !newContentWanted)
- return;
-
- bool movedContent = (type == RenderStyle::AFTER && isRenderInline() && continuation());
-
- // Whether or not we want the same old content.
- bool sameOldContent = oldContentPresent && newContentWanted && !movedContent
- && (child->style()->contentDataEquivalent(pseudo));
-
- // No change in content, update style
- if( sameOldContent ) {
- child->setStyle(pseudo);
- return;
- }
-
- // If we don't want generated content any longer, or if we have generated content,
- // but it's no longer identical to the new content data we want to build
- // render objects for, then we nuke all of the old generated content.
- if (oldContentPresent && (!newContentWanted || !sameOldContent))
- {
- // The child needs to be removed.
- oldContentPresent = false;
- child->detach();
- child = 0;
- }
-
- // If we have no pseudo-style or if the pseudo's display type is NONE, then we
- // have no generated content and can now return.
- if (!newContentWanted)
- return;
-
- // Generated content consists of a single container that houses multiple children (specified
- // by the content property). This pseudo container gets the pseudo style set on it.
- RenderContainer* pseudoContainer = 0;
- pseudoContainer = RenderFlow::createFlow(element(), pseudo, renderArena());
- pseudoContainer->setIsAnonymous( true );
- pseudoContainer->createGeneratedContent();
-
- // Only add the container if it had content
- if (pseudoContainer->firstChild()) {
- addPseudoContainer(pseudoContainer);
- pseudoContainer->close();
- }
-}
-
-void RenderContainer::createGeneratedContent()
-{
- RenderStyle* pseudo = style();
- RenderStyle* style = new RenderStyle();
- style->ref();
- style->inheritFrom(pseudo);
-
- // Now walk our list of generated content and create render objects for every type
- // we encounter.
- for (ContentData* contentData = pseudo->contentData();
- contentData; contentData = contentData->_nextContent)
- {
- if (contentData->_contentType == CONTENT_TEXT)
- {
- RenderText* t = new (renderArena()) RenderText( node(), 0);
- t->setIsAnonymous( true );
- t->setStyle(style);
- t->setText(contentData->contentText());
- addChild(t);
- }
- else if (contentData->_contentType == CONTENT_OBJECT)
- {
- RenderImage* img = new (renderArena()) RenderImage(node());
- img->setIsAnonymous( true );
- img->setStyle(style);
- img->setContentObject(contentData->contentObject());
- addChild(img);
- }
- else if (contentData->_contentType == CONTENT_COUNTER)
- {
- // really a counter or just a glyph?
- EListStyleType type = (EListStyleType)contentData->contentCounter()->listStyle();
- RenderObject *t = 0;
- if (isListStyleCounted(type)) {
- t = new (renderArena()) RenderCounter( node(), contentData->contentCounter() );
- }
- else {
- t = new (renderArena()) RenderGlyph( node(), type );
- }
- t->setIsAnonymous( true );
- t->setStyle(style);
- addChild(t);
- }
- else if (contentData->_contentType == CONTENT_QUOTE)
- {
- RenderQuote* t = new (renderArena()) RenderQuote( node(), contentData->contentQuote() );
- t->setIsAnonymous( true );
- t->setStyle(style);
- addChild(t);
- }
- }
- style->deref();
-}
-
-RenderContainer* RenderContainer::pseudoContainer(RenderStyle::PseudoId type) const
-{
- RenderObject *child = 0;
- switch (type) {
- case RenderStyle::AFTER:
- child = lastChild();
- break;
- case RenderStyle::BEFORE:
- child = firstChild();
- break;
- case RenderStyle::REPLACED:
- child = lastChild();
- if (child && child->style()->styleType() == RenderStyle::AFTER)
- child = child->previousSibling();
- break;
- default:
- child = 0;
- }
-
- if (child && child->style()->styleType() == type) {
- assert(child->isRenderBlock() || child->isRenderInline());
- return static_cast<RenderContainer*>(child);
- }
- if (type == RenderStyle::AFTER) {
- // check continuations
- if (continuation())
- return continuation()->pseudoContainer(type);
- }
- if (child && child->isAnonymousBlock())
- return static_cast<RenderBlock*>(child)->pseudoContainer(type);
- return 0;
-}
-
-void RenderContainer::addPseudoContainer(RenderObject* child)
-{
- RenderStyle::PseudoId type = child->style()->styleType();
- switch (type) {
- case RenderStyle::AFTER: {
- RenderObject *o = this;
- while (o->continuation()) o = o->continuation();
-
- // Coalesce inlines
- if (child->style()->display() == INLINE && o->lastChild() && o->lastChild()->isAnonymousBlock()) {
- o->lastChild()->addChild(child, 0);
- } else
- o->addChild(child, 0);
- break;
- }
- case RenderStyle::BEFORE:
- // Coalesce inlines
- if (child->style()->display() == INLINE && firstChild() && firstChild()->isAnonymousBlock()) {
- firstChild()->addChild(child, firstChild()->firstChild());
- } else
- addChild(child, firstChild());
- break;
- case RenderStyle::REPLACED:
- addChild(child, pseudoContainer(RenderStyle::AFTER));
- break;
- default:
- break;
- }
-}
-
-void RenderContainer::updateReplacedContent()
-{
- // Only for normal elements
- if (!style() || style()->styleType() != RenderStyle::NOPSEUDO)
- return;
-
- // delete old generated content
- RenderContainer *container = pseudoContainer(RenderStyle::REPLACED);
- if (container) {
- container->detach();
- }
-
- if (style()->useNormalContent()) return;
-
- // create generated content
- RenderStyle* pseudo = style()->getPseudoStyle(RenderStyle::REPLACED);
- if (!pseudo) {
- pseudo = new RenderStyle();
- pseudo->inheritFrom(style());
- pseudo->setStyleType(RenderStyle::REPLACED);
- }
- if (pseudo->useNormalContent())
- pseudo->setContentData(style()->contentData());
-
- container = RenderFlow::createFlow(node(), pseudo, renderArena());
- container->setIsAnonymous( true );
- container->createGeneratedContent();
-
- addChild(container, pseudoContainer(RenderStyle::AFTER));
-}
-
-void RenderContainer::appendChildNode(RenderObject* newChild)
-{
- KHTMLAssert(newChild->parent() == 0);
-
- newChild->setParent(this);
- RenderObject* lChild = lastChild();
-
- if(lChild)
- {
- newChild->setPreviousSibling(lChild);
- lChild->setNextSibling(newChild);
- }
- else
- setFirstChild(newChild);
-
- setLastChild(newChild);
-
- // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
- // and don't have a layer attached to ourselves.
- if (newChild->firstChild() || newChild->layer()) {
- RenderLayer* layer = enclosingLayer();
- newChild->addLayers(layer, newChild);
- }
-
- newChild->setNeedsLayoutAndMinMaxRecalc(); // Goes up the containing block hierarchy.
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-}
-
-void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild)
-{
- if(!beforeChild) {
- appendChildNode(child);
- return;
- }
-
- KHTMLAssert(!child->parent());
- while ( beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock() )
- beforeChild = beforeChild->parent();
- KHTMLAssert(beforeChild->parent() == this);
-
- if(beforeChild == firstChild())
- setFirstChild(child);
-
- RenderObject* prev = beforeChild->previousSibling();
- child->setNextSibling(beforeChild);
- beforeChild->setPreviousSibling(child);
- if(prev) prev->setNextSibling(child);
- child->setPreviousSibling(prev);
- child->setParent(this);
-
- // Keep our layer hierarchy updated.
- RenderLayer* layer = enclosingLayer();
- child->addLayers(layer, child);
-
- child->setNeedsLayoutAndMinMaxRecalc();
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-}
-
-
-void RenderContainer::layout()
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
- const bool pagedMode = canvas()->pagedMode();
- RenderObject *child = firstChild();
- while( child ) {
- if (pagedMode) child->setNeedsLayout(true);
- child->layoutIfNeeded();
- if (child->containsPageBreak()) setContainsPageBreak(true);
- if (child->needsPageClear()) setNeedsPageClear(true);
- child = child->nextSibling();
- }
- setNeedsLayout(false);
-}
-
-void RenderContainer::removeLeftoverAnonymousBoxes()
-{
- // we have to go over all child nodes and remove anonymous boxes, that do _not_
- // have inline children to keep the tree flat
- RenderObject *child = firstChild();
- while( child ) {
- RenderObject *next = child->nextSibling();
-
- if ( child->isRenderBlock() && child->isAnonymousBlock() && !child->continuation() &&
- !child->childrenInline() && !child->isTableCell() && !child->doNotDelete()) {
- RenderObject *firstAnChild = child->firstChild();
- RenderObject *lastAnChild = child->lastChild();
- if ( firstAnChild ) {
- RenderObject *o = firstAnChild;
- while( o ) {
- o->setParent( this );
- o = o->nextSibling();
- }
- firstAnChild->setPreviousSibling( child->previousSibling() );
- lastAnChild->setNextSibling( child->nextSibling() );
- if ( child->previousSibling() )
- child->previousSibling()->setNextSibling( firstAnChild );
- if ( child->nextSibling() )
- child->nextSibling()->setPreviousSibling( lastAnChild );
- if ( child == firstChild() )
- m_first = firstAnChild;
- if ( child == lastChild() )
- m_last = lastAnChild;
- } else {
- if ( child->previousSibling() )
- child->previousSibling()->setNextSibling( child->nextSibling() );
- if ( child->nextSibling() )
- child->nextSibling()->setPreviousSibling( child->previousSibling() );
- if ( child == firstChild() )
- m_first = child->nextSibling();
- if ( child == lastChild() )
- m_last = child->previousSibling();
- }
- child->setParent( 0 );
- child->setPreviousSibling( 0 );
- child->setNextSibling( 0 );
- if ( !child->isText() ) {
- RenderContainer *c = static_cast<RenderContainer *>(child);
- c->m_first = 0;
- c->m_next = 0;
- }
- child->detach();
- }
- child = next;
- }
- if ( parent() )
- parent()->removeLeftoverAnonymousBoxes();
-}
-
-#undef DEBUG_LAYOUT