webengine/osswebengine/WebCore/rendering/RenderContainer.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /**
       
     2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
       
     3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
       
     4  *           (C) 2000 Dirk Mueller (mueller@kde.org)
       
     5  *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
       
     6  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
       
     7  * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
       
     8  *
       
     9  * This library is free software; you can redistribute it and/or
       
    10  * modify it under the terms of the GNU Library General Public
       
    11  * License as published by the Free Software Foundation; either
       
    12  * version 2 of the License, or (at your option) any later version.
       
    13  *
       
    14  * This library is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    17  * Library General Public License for more details.
       
    18  *
       
    19  * You should have received a copy of the GNU Library General Public License
       
    20  * along with this library; see the file COPYING.LIB.  If not, write to
       
    21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    22  * Boston, MA 02110-1301, USA.
       
    23  *
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "RenderContainer.h"
       
    28 
       
    29 #include "AXObjectCache.h"
       
    30 #include "Document.h"
       
    31 #include "RenderCounter.h"
       
    32 #include "RenderImage.h"
       
    33 #include "RenderLayer.h"
       
    34 #include "RenderListItem.h"
       
    35 #include "RenderTable.h"
       
    36 #include "RenderTextFragment.h"
       
    37 #include "RenderView.h"
       
    38 #include "htmlediting.h"
       
    39 
       
    40 namespace WebCore {
       
    41 
       
    42 RenderContainer::RenderContainer(Node* node)
       
    43     : RenderBox(node)
       
    44     , m_firstChild(0)
       
    45     , m_lastChild(0)
       
    46 {
       
    47 }
       
    48 
       
    49 RenderContainer::~RenderContainer()
       
    50 {
       
    51 }
       
    52 
       
    53 void RenderContainer::destroy()
       
    54 {
       
    55     destroyLeftoverChildren();
       
    56     RenderBox::destroy();
       
    57 }
       
    58 
       
    59 void RenderContainer::destroyLeftoverChildren()
       
    60 {
       
    61     while (m_firstChild) {
       
    62         if (m_firstChild->isListMarker() || (m_firstChild->style()->styleType() == RenderStyle::FIRST_LETTER && !m_firstChild->isText()))
       
    63             m_firstChild->remove();  // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
       
    64         else {
       
    65         // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
       
    66             if (m_firstChild->element())
       
    67                 m_firstChild->element()->setRenderer(0);
       
    68             m_firstChild->destroy();
       
    69         }
       
    70     }
       
    71 }
       
    72 
       
    73 bool RenderContainer::canHaveChildren() const
       
    74 {
       
    75     return true;
       
    76 }
       
    77 
       
    78 static void updateListMarkerNumbers(RenderObject* child)
       
    79 {
       
    80     for (RenderObject* r = child; r; r = r->nextSibling())
       
    81         if (r->isListItem())
       
    82             static_cast<RenderListItem*>(r)->updateValue();
       
    83 }
       
    84 
       
    85 void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
       
    86 {
       
    87     bool needsTable = false;
       
    88 
       
    89     if (newChild->isListItem())
       
    90         updateListMarkerNumbers(beforeChild ? beforeChild : m_lastChild);
       
    91     else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
       
    92         needsTable = !isTable();
       
    93     else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
       
    94         needsTable = !isTable();
       
    95     else if (newChild->isTableSection())
       
    96         needsTable = !isTable();
       
    97     else if (newChild->isTableRow())
       
    98         needsTable = !isTableSection();
       
    99     else if (newChild->isTableCell()) {
       
   100         needsTable = !isTableRow();
       
   101         // I'm not 100% sure this is the best way to fix this, but without this
       
   102         // change we recurse infinitely when trying to render the CSS2 test page:
       
   103         // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
       
   104         // See Radar 2925291.
       
   105         if (needsTable && isTableCell() && !m_firstChild && !newChild->isTableCell())
       
   106             needsTable = false;
       
   107     }
       
   108 
       
   109     if (needsTable) {
       
   110         RenderTable *table;
       
   111         if(!beforeChild)
       
   112             beforeChild = m_lastChild;
       
   113         if(beforeChild && beforeChild->isAnonymous() && beforeChild->isTable())
       
   114             table = static_cast<RenderTable*>(beforeChild);
       
   115         else {
       
   116             table = new (renderArena()) RenderTable(document() /* is anonymous */);
       
   117             RenderStyle *newStyle = new (renderArena()) RenderStyle;
       
   118             newStyle->inheritFrom(style());
       
   119             newStyle->setDisplay(TABLE);
       
   120             table->setStyle(newStyle);
       
   121             addChild(table, beforeChild);
       
   122         }
       
   123         table->addChild(newChild);
       
   124     } else {
       
   125         // just add it...
       
   126         insertChildNode(newChild, beforeChild);
       
   127     }
       
   128     
       
   129     if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
       
   130         RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
       
   131         if (textToTransform)
       
   132             static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
       
   133     }
       
   134 }
       
   135 
       
   136 RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
       
   137 {
       
   138     ASSERT(oldChild->parent() == this);
       
   139 
       
   140     // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
       
   141     // that a positioned child got yanked).  We also repaint, so that the area exposed when the child
       
   142     // disappears gets repainted properly.
       
   143     if (!documentBeingDestroyed() && fullRemove) {
       
   144         oldChild->setNeedsLayoutAndPrefWidthsRecalc();
       
   145         oldChild->repaint();
       
   146     }
       
   147         
       
   148     // If we have a line box wrapper, delete it.
       
   149     oldChild->deleteLineBoxWrapper();
       
   150 
       
   151     if (!documentBeingDestroyed() && fullRemove) {
       
   152         // if we remove visible child from an invisible parent, we don't know the layer visibility any more
       
   153         RenderLayer* layer = 0;
       
   154         if (m_style->visibility() != VISIBLE && oldChild->style()->visibility() == VISIBLE && !oldChild->hasLayer()) {
       
   155             layer = enclosingLayer();
       
   156             layer->dirtyVisibleContentStatus();
       
   157         }
       
   158 
       
   159          // Keep our layer hierarchy updated.
       
   160         if (oldChild->firstChild() || oldChild->hasLayer()) {
       
   161             if (!layer) layer = enclosingLayer();            
       
   162             oldChild->removeLayers(layer);
       
   163         }
       
   164         
       
   165         // renumber ordered lists
       
   166         if (oldChild->isListItem())
       
   167             updateListMarkerNumbers(oldChild->nextSibling());
       
   168         
       
   169         if (oldChild->isPositioned() && childrenInline())
       
   170             dirtyLinesFromChangedChild(oldChild);
       
   171     }
       
   172     
       
   173     // If oldChild is the start or end of the selection, then clear the selection to
       
   174     // avoid problems of invalid pointers.
       
   175     // FIXME: The SelectionController should be responsible for this when it
       
   176     // is notified of DOM mutations.
       
   177     if (!documentBeingDestroyed() && oldChild->isSelectionBorder())
       
   178         view()->clearSelection();
       
   179 
       
   180     // remove the child
       
   181     if (oldChild->previousSibling())
       
   182         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
       
   183     if (oldChild->nextSibling())
       
   184         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
       
   185 
       
   186     if (m_firstChild == oldChild)
       
   187         m_firstChild = oldChild->nextSibling();
       
   188     if (m_lastChild == oldChild)
       
   189         m_lastChild = oldChild->previousSibling();
       
   190 
       
   191     oldChild->setPreviousSibling(0);
       
   192     oldChild->setNextSibling(0);
       
   193     oldChild->setParent(0);
       
   194 
       
   195     if (AXObjectCache::accessibilityEnabled())
       
   196         document()->axObjectCache()->childrenChanged(this);
       
   197 
       
   198     return oldChild;
       
   199 }
       
   200 
       
   201 void RenderContainer::removeChild(RenderObject* oldChild)
       
   202 {
       
   203     // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
       
   204     // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
       
   205     // layout anyway).
       
   206     oldChild->removeFromObjectLists();
       
   207     
       
   208     removeChildNode(oldChild);
       
   209 }
       
   210 
       
   211 RenderObject* RenderContainer::beforeAfterContainer(RenderStyle::PseudoId type)
       
   212 {
       
   213     if (type == RenderStyle::BEFORE) {
       
   214         RenderObject* first = this;
       
   215         do {
       
   216             // Skip list markers.
       
   217             first = first->firstChild();
       
   218             while (first && first->isListMarker())
       
   219                 first = first->nextSibling();
       
   220         } while (first && first->isAnonymous() && first->style()->styleType() == RenderStyle::NOPSEUDO);
       
   221         if (first && first->style()->styleType() != type)
       
   222             return 0;
       
   223         return first;
       
   224     }
       
   225     if (type == RenderStyle::AFTER) {
       
   226         RenderObject* last = this;
       
   227         do {
       
   228             last = last->lastChild();
       
   229         } while (last && last->isAnonymous() && last->style()->styleType() == RenderStyle::NOPSEUDO && !last->isListMarker());
       
   230         if (last && last->style()->styleType() != type)
       
   231             return 0;
       
   232         return last;
       
   233     }
       
   234 
       
   235     ASSERT_NOT_REACHED();
       
   236     return 0;
       
   237 }
       
   238 
       
   239 void RenderContainer::updateBeforeAfterContent(RenderStyle::PseudoId type)
       
   240 {
       
   241     // If this is an anonymous wrapper, then the parent applies its own pseudo-element style to it.
       
   242     if (parent() && parent()->createsAnonymousWrapper())
       
   243         return;
       
   244     updateBeforeAfterContentForContainer(type, this);
       
   245 }
       
   246 
       
   247 void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId type, RenderContainer* styledObject)
       
   248 {
       
   249     // In CSS2, before/after pseudo-content cannot nest.  Check this first.
       
   250     if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER)
       
   251         return;
       
   252     
       
   253     RenderStyle* pseudoElementStyle = styledObject->getPseudoStyle(type);
       
   254     RenderObject* child = beforeAfterContainer(type);
       
   255 
       
   256     // Whether or not we currently have generated content attached.
       
   257     bool oldContentPresent = child;
       
   258 
       
   259     // Whether or not we now want generated content.  
       
   260     bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE;
       
   261 
       
   262     // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate
       
   263     // :after content and not :before content.
       
   264     if (newContentWanted && type == RenderStyle::BEFORE && isInlineContinuation())
       
   265         newContentWanted = false;
       
   266 
       
   267     // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object,
       
   268     // then we don't generate the :after content.
       
   269     if (newContentWanted && type == RenderStyle::AFTER && isRenderInline() && continuation())
       
   270         newContentWanted = false;
       
   271     
       
   272     // If we don't want generated content any longer, or if we have generated content, but it's no longer
       
   273     // identical to the new content data we want to build render objects for, then we nuke all
       
   274     // of the old generated content.
       
   275     if (!newContentWanted || (oldContentPresent && !child->style()->contentDataEquivalent(pseudoElementStyle))) {
       
   276         // Nuke the child. 
       
   277         if (child && child->style()->styleType() == type) {
       
   278             oldContentPresent = false;
       
   279             child->destroy();
       
   280             child = (type == RenderStyle::BEFORE) ? m_firstChild : m_lastChild;
       
   281         }
       
   282     }
       
   283 
       
   284     // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we
       
   285     // have no generated content and can now return.
       
   286     if (!newContentWanted)
       
   287         return;
       
   288 
       
   289     if (isInlineFlow() && !pseudoElementStyle->isDisplayInlineType() && pseudoElementStyle->floating() == FNONE &&
       
   290         !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition))
       
   291         // According to the CSS2 spec (the end of section 12.1), the only allowed
       
   292         // display values for the pseudo style are NONE and INLINE for inline flows.
       
   293         // FIXME: CSS2.1 lifted this restriction, but block display types will crash.
       
   294         // For now we at least relax the restriction to allow all inline types like inline-block
       
   295         // and inline-table.
       
   296         pseudoElementStyle->setDisplay(INLINE);
       
   297 
       
   298     if (oldContentPresent) {
       
   299         if (child && child->style()->styleType() == type) {
       
   300             // We have generated content present still.  We want to walk this content and update our
       
   301             // style information with the new pseudo-element style.
       
   302             child->setStyle(pseudoElementStyle);
       
   303 
       
   304             // Note that if we ever support additional types of generated content (which should be way off
       
   305             // in the future), this code will need to be patched.
       
   306             for (RenderObject* genChild = child->firstChild(); genChild; genChild = genChild->nextSibling()) {
       
   307                 if (genChild->isText())
       
   308                     // Generated text content is a child whose style also needs to be set to the pseudo-element style.
       
   309                     genChild->setStyle(pseudoElementStyle);
       
   310                 else if (genChild->isImage()) {
       
   311                     // Images get an empty style that inherits from the pseudo.
       
   312                     RenderStyle* style = new (renderArena()) RenderStyle;
       
   313                     style->inheritFrom(pseudoElementStyle);
       
   314                     genChild->setStyle(style);
       
   315                 } else
       
   316                     // Must be a first-letter container. updateFirstLetter() will take care of it.
       
   317                     ASSERT(genChild->style()->styleType() == RenderStyle::FIRST_LETTER);
       
   318             }
       
   319         }
       
   320         return; // We've updated the generated content. That's all we needed to do.
       
   321     }
       
   322     
       
   323     RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? firstChild() : 0;
       
   324 
       
   325     // Generated content consists of a single container that houses multiple children (specified
       
   326     // by the content property).  This generated content container gets the pseudo-element style set on it.
       
   327     RenderObject* generatedContentContainer = 0;
       
   328     
       
   329     // Walk our list of generated content and create render objects for each.
       
   330     for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->m_next) {
       
   331         RenderObject* renderer = 0;
       
   332         switch (content->m_type) {
       
   333             case CONTENT_NONE:
       
   334                 break;
       
   335             case CONTENT_TEXT:
       
   336                 renderer = new (renderArena()) RenderTextFragment(document() /* anonymous object */, content->m_content.m_text);
       
   337                 renderer->setStyle(pseudoElementStyle);
       
   338                 break;
       
   339             case CONTENT_OBJECT:
       
   340                 if (CachedResource* resource = content->m_content.m_object)
       
   341                     if (resource->type() == CachedResource::ImageResource) {
       
   342                         RenderImage* image = new (renderArena()) RenderImage(document()); // anonymous object
       
   343                         RenderStyle* style = new (renderArena()) RenderStyle;
       
   344                         style->inheritFrom(pseudoElementStyle);
       
   345                         image->setStyle(style);
       
   346                         image->setCachedImage(static_cast<CachedImage*>(resource));
       
   347                         image->setIsAnonymousImage(true);
       
   348                         renderer = image;
       
   349                     }
       
   350                 break;
       
   351             case CONTENT_COUNTER:
       
   352                 renderer = new (renderArena()) RenderCounter(document(), *content->m_content.m_counter);
       
   353                 renderer->setStyle(pseudoElementStyle);
       
   354                 break;
       
   355         }
       
   356 
       
   357         if (renderer) {
       
   358             if (!generatedContentContainer) {
       
   359                 // Make a generated box that might be any display type now that we are able to drill down into children
       
   360                 // to find the original content properly.
       
   361                 generatedContentContainer = RenderObject::createObject(document(), pseudoElementStyle);
       
   362                 generatedContentContainer->setStyle(pseudoElementStyle);
       
   363             }
       
   364             generatedContentContainer->addChild(renderer);
       
   365         }
       
   366     }
       
   367 
       
   368     // Add the pseudo after we've installed all our content so that addChild will be able to find the text
       
   369     // inside the inline for e.g., first-letter styling.
       
   370     if (generatedContentContainer)
       
   371         addChild(generatedContentContainer, insertBefore);
       
   372 }
       
   373 
       
   374 bool RenderContainer::isAfterContent(RenderObject* child) const
       
   375 {
       
   376     if (!child)
       
   377         return false;
       
   378     if (child->style()->styleType() != RenderStyle::AFTER)
       
   379         return false;
       
   380     // Text nodes don't have their own styles, so ignore the style on a text node.
       
   381     if (child->isText() && !child->isBR())
       
   382         return false;
       
   383     return true;
       
   384 }
       
   385 
       
   386 void RenderContainer::appendChildNode(RenderObject* newChild, bool fullAppend)
       
   387 {
       
   388     ASSERT(newChild->parent() == 0);
       
   389     ASSERT(!isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
       
   390 
       
   391     newChild->setParent(this);
       
   392     RenderObject* lChild = m_lastChild;
       
   393 
       
   394     if (lChild) {
       
   395         newChild->setPreviousSibling(lChild);
       
   396         lChild->setNextSibling(newChild);
       
   397     } else
       
   398         m_firstChild = newChild;
       
   399 
       
   400     m_lastChild = newChild;
       
   401     
       
   402     if (fullAppend) {
       
   403         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
       
   404         // and don't have a layer attached to ourselves.
       
   405         RenderLayer* layer = 0;
       
   406         if (newChild->firstChild() || newChild->hasLayer()) {
       
   407             layer = enclosingLayer();
       
   408             newChild->addLayers(layer, newChild);
       
   409         }
       
   410 
       
   411         // if the new child is visible but this object was not, tell the layer it has some visible content
       
   412         // that needs to be drawn and layer visibility optimization can't be used
       
   413         if (style()->visibility() != VISIBLE && newChild->style()->visibility() == VISIBLE && !newChild->hasLayer()) {
       
   414             if (!layer)
       
   415                 layer = enclosingLayer();
       
   416             if (layer)
       
   417                 layer->setHasVisibleContent(true);
       
   418         }
       
   419         
       
   420         if (!newChild->isFloatingOrPositioned() && childrenInline())
       
   421             dirtyLinesFromChangedChild(newChild);
       
   422     }
       
   423 
       
   424     newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
       
   425     if (!normalChildNeedsLayout())
       
   426         setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
       
   427     
       
   428     if (AXObjectCache::accessibilityEnabled())
       
   429         document()->axObjectCache()->childrenChanged(this);
       
   430 }
       
   431 
       
   432 void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild, bool fullInsert)
       
   433 {
       
   434     if (!beforeChild) {
       
   435         appendChildNode(child);
       
   436         return;
       
   437     }
       
   438 
       
   439     ASSERT(!child->parent());
       
   440     while (beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock())
       
   441         beforeChild = beforeChild->parent();
       
   442     ASSERT(beforeChild->parent() == this);
       
   443 
       
   444     ASSERT(!isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
       
   445 
       
   446     if (beforeChild == m_firstChild)
       
   447         m_firstChild = child;
       
   448 
       
   449     RenderObject* prev = beforeChild->previousSibling();
       
   450     child->setNextSibling(beforeChild);
       
   451     beforeChild->setPreviousSibling(child);
       
   452     if(prev) prev->setNextSibling(child);
       
   453     child->setPreviousSibling(prev);
       
   454 
       
   455     child->setParent(this);
       
   456     
       
   457     if (fullInsert) {
       
   458         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
       
   459         // and don't have a layer attached to ourselves.
       
   460         RenderLayer* layer = 0;
       
   461         if (child->firstChild() || child->hasLayer()) {
       
   462             layer = enclosingLayer();
       
   463             child->addLayers(layer, child);
       
   464         }
       
   465 
       
   466         // if the new child is visible but this object was not, tell the layer it has some visible content
       
   467         // that needs to be drawn and layer visibility optimization can't be used
       
   468         if (style()->visibility() != VISIBLE && child->style()->visibility() == VISIBLE && !child->hasLayer()) {
       
   469             if (!layer)
       
   470                 layer = enclosingLayer();
       
   471             if (layer)
       
   472                 layer->setHasVisibleContent(true);
       
   473         }
       
   474 
       
   475         
       
   476         if (!child->isFloating() && childrenInline())
       
   477             dirtyLinesFromChangedChild(child);
       
   478     }
       
   479 
       
   480     child->setNeedsLayoutAndPrefWidthsRecalc();
       
   481     if (!normalChildNeedsLayout())
       
   482         setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
       
   483     
       
   484     if (AXObjectCache::accessibilityEnabled())
       
   485         document()->axObjectCache()->childrenChanged(this);
       
   486 }
       
   487 
       
   488 void RenderContainer::layout()
       
   489 {
       
   490     ASSERT(needsLayout());
       
   491 
       
   492     view()->pushLayoutState(this, IntSize(m_x, m_y));
       
   493 
       
   494     RenderObject* child = m_firstChild;
       
   495     while (child) {
       
   496         child->layoutIfNeeded();
       
   497         ASSERT(child->isRenderInline() || !child->needsLayout());
       
   498         child = child->nextSibling();
       
   499     }
       
   500 
       
   501     view()->popLayoutState();
       
   502     setNeedsLayout(false);
       
   503 }
       
   504 
       
   505 void RenderContainer::removeLeftoverAnonymousBlock(RenderBlock* child)
       
   506 {
       
   507     ASSERT(child->isAnonymousBlock());
       
   508     ASSERT(!child->childrenInline());
       
   509     
       
   510     if (child->continuation()) 
       
   511         return;
       
   512     
       
   513     RenderObject* firstAnChild = child->firstChild();
       
   514     RenderObject* lastAnChild = child->lastChild();
       
   515     if (firstAnChild) {
       
   516         RenderObject* o = firstAnChild;
       
   517         while(o) {
       
   518             o->setParent(this);
       
   519             o = o->nextSibling();
       
   520         }
       
   521         firstAnChild->setPreviousSibling(child->previousSibling());
       
   522         lastAnChild->setNextSibling(child->nextSibling());
       
   523         if (child->previousSibling())
       
   524             child->previousSibling()->setNextSibling(firstAnChild);
       
   525         if (child->nextSibling())
       
   526             child->nextSibling()->setPreviousSibling(lastAnChild);
       
   527     } else {
       
   528         if (child->previousSibling())
       
   529             child->previousSibling()->setNextSibling(child->nextSibling());
       
   530         if (child->nextSibling())
       
   531             child->nextSibling()->setPreviousSibling(child->previousSibling());
       
   532     }
       
   533     if (child == m_firstChild)
       
   534         m_firstChild = firstAnChild;
       
   535     if (child == m_lastChild)
       
   536         m_lastChild = lastAnChild;
       
   537     child->setParent(0);
       
   538     child->setPreviousSibling(0);
       
   539     child->setNextSibling(0);
       
   540     if (!child->isText()) {
       
   541         RenderContainer *c = static_cast<RenderContainer*>(child);
       
   542         c->m_firstChild = 0;
       
   543         c->m_next = 0;
       
   544     }
       
   545     child->destroy();
       
   546 }
       
   547 
       
   548 VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
       
   549 {
       
   550     // no children...return this render object's element, if there is one, and offset 0
       
   551     if (!m_firstChild)
       
   552         return VisiblePosition(element(), 0, DOWNSTREAM);
       
   553         
       
   554     if (isTable() && element()) {
       
   555         int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
       
   556         int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();
       
   557         
       
   558         if (x < 0 || x > right || y < 0 || y > bottom) {
       
   559             if (x <= right / 2)
       
   560                 return VisiblePosition(Position(element(), 0));
       
   561             else
       
   562                 return VisiblePosition(Position(element(), maxDeepOffset(element())));
       
   563         }
       
   564     }
       
   565 
       
   566     // Pass off to the closest child.
       
   567     int minDist = INT_MAX;
       
   568     RenderObject* closestRenderer = 0;
       
   569     int newX = x;
       
   570     int newY = y;
       
   571     if (isTableRow()) {
       
   572         newX += xPos();
       
   573         newY += yPos();
       
   574     }
       
   575     for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) {
       
   576         if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow() 
       
   577             || renderer->style()->visibility() != VISIBLE)
       
   578             continue;
       
   579         
       
   580         int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->yPos());
       
   581         int bottom = top + renderer->contentHeight();
       
   582         int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->xPos());
       
   583         int right = left + renderer->contentWidth();
       
   584         
       
   585         if (x <= right && x >= left && y <= top && y >= bottom) {
       
   586             if (renderer->isTableRow())
       
   587                 return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos());
       
   588             return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos());
       
   589         }
       
   590 
       
   591         // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
       
   592         // and use a different compare depending on which piece (x, y) is in.
       
   593         IntPoint cmp;
       
   594         if (x > right) {
       
   595             if (y < top)
       
   596                 cmp = IntPoint(right, top);
       
   597             else if (y > bottom)
       
   598                 cmp = IntPoint(right, bottom);
       
   599             else
       
   600                 cmp = IntPoint(right, y);
       
   601         } else if (x < left) {
       
   602             if (y < top)
       
   603                 cmp = IntPoint(left, top);
       
   604             else if (y > bottom)
       
   605                 cmp = IntPoint(left, bottom);
       
   606             else
       
   607                 cmp = IntPoint(left, y);
       
   608         } else {
       
   609             if (y < top)
       
   610                 cmp = IntPoint(x, top);
       
   611             else
       
   612                 cmp = IntPoint(x, bottom);
       
   613         }
       
   614         
       
   615         int x1minusx2 = cmp.x() - x;
       
   616         int y1minusy2 = cmp.y() - y;
       
   617         
       
   618         int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
       
   619         if (dist < minDist) {
       
   620             closestRenderer = renderer;
       
   621             minDist = dist;
       
   622         }
       
   623     }
       
   624     
       
   625     if (closestRenderer)
       
   626         return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos());
       
   627     
       
   628     return VisiblePosition(element(), 0, DOWNSTREAM);
       
   629 }
       
   630 
       
   631 void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end)
       
   632 {
       
   633     if (!m_firstChild && (isInline() || isAnonymousBlock())) {
       
   634         int x, y;
       
   635         absolutePositionForContent(x, y);
       
   636         absoluteRects(rects, x, y);
       
   637         return;
       
   638     }
       
   639 
       
   640     if (!m_firstChild)
       
   641         return;
       
   642 
       
   643     unsigned offset = start;
       
   644     for (RenderObject* child = childAt(start); child && offset < end; child = child->nextSibling(), ++offset) {
       
   645         if (child->isText() || child->isInline() || child->isAnonymousBlock()) {
       
   646             int x, y;
       
   647             child->absolutePositionForContent(x, y);
       
   648             child->absoluteRects(rects, x, y);
       
   649         }
       
   650     }
       
   651 }
       
   652 
       
   653 #undef DEBUG_LAYOUT
       
   654 
       
   655 } // namespace WebCore