cd8f6546b2c78d64164a5d558b5dc7d331cd016e
[WebKit-https.git] / WebCore / rendering / RenderBlock.cpp
1 /*
2  * This file is part of the render object implementation for KHTML.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include "config.h"
25 #include "RenderBlock.h"
26
27 #include "Document.h"
28 #include "Element.h"
29 #include "Frame.h"
30 #include "GraphicsContext.h"
31 #include "InlineTextBox.h"
32 #include "RenderTableCell.h"
33 #include "RenderTextFragment.h"
34 #include "SelectionController.h"
35 #include "HTMLNames.h"
36 #include "RenderView.h"
37 #include "RenderTheme.h"
38 #include "KWQTextStream.h"
39
40 using namespace std;
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45
46 // Our MarginInfo state used when laying out block children.
47 RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
48 {
49     // Whether or not we can collapse our own margins with our children.  We don't do this
50     // if we had any border/padding (obviously), if we're the root or HTML elements, or if
51     // we're positioned, floating, a table cell.
52     m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isPositioned() &&
53         !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable();
54
55     m_canCollapseTopWithChildren = m_canCollapseWithChildren && (top == 0) && block->style()->marginTopCollapse() != MSEPARATE;
56
57     // If any height other than auto is specified in CSS, then we don't collapse our bottom
58     // margins with our children's margins.  To do otherwise would be to risk odd visual
59     // effects when the children overflow out of the parent block and yet still collapse
60     // with it.  We also don't collapse if we have any bottom border/padding.
61     m_canCollapseBottomWithChildren = m_canCollapseWithChildren && (bottom == 0) &&
62         (block->style()->height().isAuto() && block->style()->height().value() == 0) && block->style()->marginBottomCollapse() != MSEPARATE;
63     
64     m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginTopCollapse() == MDISCARD || 
65         block->style()->marginBottomCollapse() == MDISCARD;
66
67     m_atTopOfBlock = true;
68     m_atBottomOfBlock = false;
69
70     m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;
71     m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;
72
73     m_selfCollapsingBlockClearedFloat = false;
74     
75     m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;
76 }
77
78 // -------------------------------------------------------------------------------------------------------
79
80 RenderBlock::RenderBlock(WebCore::Node* node)
81 :RenderFlow(node)
82 {
83     m_childrenInline = true;
84     m_floatingObjects = 0;
85     m_positionedObjects = 0;
86     m_firstLine = false;
87     m_hasMarkupTruncation = false;
88     m_selectionState = SelectionNone;
89     m_clearStatus = CNONE;
90     m_maxTopPosMargin = m_maxTopNegMargin = m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
91     m_topMarginQuirk = m_bottomMarginQuirk = false;
92     m_overflowHeight = m_overflowWidth = 0;
93     m_overflowLeft = m_overflowTop = 0;
94     m_tabWidth = -1;
95 }
96
97 RenderBlock::~RenderBlock()
98 {
99     delete m_floatingObjects;
100     delete m_positionedObjects;
101 }
102
103 void RenderBlock::setStyle(RenderStyle* _style)
104 {
105     setReplaced(_style->isDisplayReplacedType());
106
107     RenderFlow::setStyle(_style);
108
109     // ### we could save this call when the change only affected
110     // non inherited properties
111     RenderObject *child = firstChild();
112     while (child != 0)
113     {   
114         if (child->isAnonymousBlock())
115         {
116             RenderStyle* newStyle = new (renderArena()) RenderStyle();
117             newStyle->inheritFrom(style());
118             newStyle->setDisplay(BLOCK);
119             child->setStyle(newStyle);
120         }
121         child = child->nextSibling();
122     }
123
124     m_lineHeight = -1;
125     m_tabWidth = -1;
126
127     // Update pseudos for :before and :after now.
128     RenderObject* first = firstChild();
129     while (first && first->isListMarker()) first = first->nextSibling();
130     updatePseudoChild(RenderStyle::BEFORE, first);
131     updatePseudoChild(RenderStyle::AFTER, lastChild());
132 }
133
134 void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
135 {
136     // Make sure we don't append things after :after-generated content if we have it.
137     if (!beforeChild && lastChild() && lastChild()->style()->styleType() == RenderStyle::AFTER)
138         beforeChild = lastChild();
139     
140     bool madeBoxesNonInline = false;
141
142     // If the requested beforeChild is not one of our children, then this is most likely because
143     // there is an anonymous block box within this object that contains the beforeChild. So
144     // just insert the child into the anonymous block box instead of here.
145     if (beforeChild && beforeChild->parent() != this) {
146
147         KHTMLAssert(beforeChild->parent());
148         KHTMLAssert(beforeChild->parent()->isAnonymousBlock());
149
150         if (newChild->isInline()) {
151             beforeChild->parent()->addChild(newChild,beforeChild);
152             return;
153         }
154         else if (beforeChild->parent()->firstChild() != beforeChild)
155             return beforeChild->parent()->addChild(newChild, beforeChild);
156         else
157             return addChildToFlow(newChild, beforeChild->parent());
158     }
159
160     // A block has to either have all of its children inline, or all of its children as blocks.
161     // So, if our children are currently inline and a block child has to be inserted, we move all our
162     // inline children into anonymous block boxes
163     if ( m_childrenInline && !newChild->isInline() && !newChild->isFloatingOrPositioned() )
164     {
165         // This is a block with inline content. Wrap the inline content in anonymous blocks.
166         makeChildrenNonInline(beforeChild);
167         madeBoxesNonInline = true;
168         
169         if (beforeChild && beforeChild->parent() != this) {
170             beforeChild = beforeChild->parent();
171             KHTMLAssert(beforeChild->isAnonymousBlock());
172             KHTMLAssert(beforeChild->parent() == this);
173         }
174     }
175     else if (!m_childrenInline && !newChild->isFloatingOrPositioned())
176     {
177         // If we're inserting an inline child but all of our children are blocks, then we have to make sure
178         // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
179         // a new one is created and inserted into our list of children in the appropriate position.
180         if (newChild->isInline()) {
181             if (beforeChild) {
182                 if (beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousBlock()) {
183                     beforeChild->previousSibling()->addChild(newChild);
184                     return;
185                 }
186             }
187             else {
188                 if (m_last && m_last->isAnonymousBlock()) {
189                     m_last->addChild(newChild);
190                     return;
191                 }
192             }
193
194             // no suitable existing anonymous box - create a new one
195             RenderBlock* newBox = createAnonymousBlock();
196             RenderContainer::addChild(newBox,beforeChild);
197             newBox->addChild(newChild);
198             return;
199         }
200     }
201
202     RenderContainer::addChild(newChild,beforeChild);
203     // ### care about aligned stuff
204
205     if ( madeBoxesNonInline )
206         removeLeftoverAnonymousBoxes();
207 }
208
209 static void getInlineRun(RenderObject* start, RenderObject* boundary,
210                          RenderObject*& inlineRunStart,
211                          RenderObject*& inlineRunEnd)
212 {
213     // Beginning at |start| we find the largest contiguous run of inlines that
214     // we can.  We denote the run with start and end points, |inlineRunStart|
215     // and |inlineRunEnd|.  Note that these two values may be the same if
216     // we encounter only one inline.
217     //
218     // We skip any non-inlines we encounter as long as we haven't found any
219     // inlines yet.
220     //
221     // |boundary| indicates a non-inclusive boundary point.  Regardless of whether |boundary|
222     // is inline or not, we will not include it in a run with inlines before it.  It's as though we encountered
223     // a non-inline.
224     
225     // Start by skipping as many non-inlines as we can.
226     RenderObject * curr = start;
227     bool sawInline;
228     do {
229         while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
230             curr = curr->nextSibling();
231         
232         inlineRunStart = inlineRunEnd = curr;
233         
234         if (!curr)
235             return; // No more inline children to be found.
236         
237         sawInline = curr->isInline();
238         
239         curr = curr->nextSibling();
240         while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != boundary)) {
241             inlineRunEnd = curr;
242             if (curr->isInline())
243                 sawInline = true;
244             curr = curr->nextSibling();
245         }
246     } while (!sawInline);
247 }
248
249 void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
250 {    
251     // makeChildrenNonInline takes a block whose children are *all* inline and it
252     // makes sure that inline children are coalesced under anonymous
253     // blocks.  If |insertionPoint| is defined, then it represents the insertion point for
254     // the new block child that is causing us to have to wrap all the inlines.  This
255     // means that we cannot coalesce inlines before |insertionPoint| with inlines following
256     // |insertionPoint|, because the new child is going to be inserted in between the inlines,
257     // splitting them.
258     KHTMLAssert(isInlineBlockOrInlineTable() || !isInline());
259     KHTMLAssert(!insertionPoint || insertionPoint->parent() == this);
260
261     m_childrenInline = false;
262
263     RenderObject *child = firstChild();
264
265     while (child) {
266         RenderObject *inlineRunStart, *inlineRunEnd;
267         getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
268
269         if (!inlineRunStart)
270             break;
271
272         child = inlineRunEnd->nextSibling();
273
274         RenderBlock* box = createAnonymousBlock();
275         insertChildNode(box, inlineRunStart);
276         RenderObject* o = inlineRunStart;
277         while(o != inlineRunEnd)
278         {
279             RenderObject* no = o;
280             o = no->nextSibling();
281             box->appendChildNode(removeChildNode(no));
282         }
283         box->appendChildNode(removeChildNode(inlineRunEnd));
284     }
285
286 #ifndef NDEBUG
287     for (RenderObject *c = firstChild(); c; c = c->nextSibling())
288         KHTMLAssert(!c->isInline());
289 #endif
290 }
291
292 void RenderBlock::removeChild(RenderObject *oldChild)
293 {
294     // If this child is a block, and if our previous and next siblings are
295     // both anonymous blocks with inline content, then we can go ahead and
296     // fold the inline content back together.
297     RenderObject* prev = oldChild->previousSibling();
298     RenderObject* next = oldChild->nextSibling();
299     bool canDeleteAnonymousBlocks = !documentBeingDestroyed() && !isInline() && !oldChild->isInline() && 
300                                     !oldChild->continuation() && 
301                                     (!prev || (prev->isAnonymousBlock() && prev->childrenInline())) &&
302                                     (!next || (next->isAnonymousBlock() && next->childrenInline()));
303     if (canDeleteAnonymousBlocks && prev && next) {
304         // Take all the children out of the |next| block and put them in
305         // the |prev| block.
306         prev->setNeedsLayoutAndMinMaxRecalc();
307         RenderObject* o = next->firstChild();
308         while (o) {
309             RenderObject* no = o;
310             o = no->nextSibling();
311             prev->appendChildNode(next->removeChildNode(no));
312             no->setNeedsLayoutAndMinMaxRecalc();
313         }
314         // Nuke the now-empty block.
315         next->destroy();
316     }
317
318     RenderFlow::removeChild(oldChild);
319
320     RenderObject* child = prev ? prev : next;
321     if (canDeleteAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling()) {
322         // The removal has knocked us down to containing only a single anonymous
323         // box.  We can go ahead and pull the content right back up into our
324         // box.
325         setNeedsLayoutAndMinMaxRecalc();
326         RenderObject* anonBlock = removeChildNode(child);
327         m_childrenInline = true;
328         RenderObject* o = anonBlock->firstChild();
329         while (o) {
330             RenderObject* no = o;
331             o = no->nextSibling();
332             appendChildNode(anonBlock->removeChildNode(no));
333             no->setNeedsLayoutAndMinMaxRecalc();
334         }
335
336         // Nuke the now-empty block.
337         anonBlock->destroy();
338     }
339 }
340
341 int RenderBlock::overflowHeight(bool includeInterior) const
342 {
343     return (!includeInterior && hasOverflowClip()) ? m_height : m_overflowHeight;
344 }
345
346 int RenderBlock::overflowWidth(bool includeInterior) const
347 {
348     return (!includeInterior && hasOverflowClip()) ? m_width : m_overflowWidth;
349 }
350 int RenderBlock::overflowLeft(bool includeInterior) const
351 {
352     return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowLeft;
353 }
354
355 int RenderBlock::overflowTop(bool includeInterior) const
356 {
357     return (!includeInterior && hasOverflowClip()) ? 0 : m_overflowTop;
358 }
359
360 IntRect RenderBlock::overflowRect(bool includeInterior) const
361 {
362     if (!includeInterior && hasOverflowClip())
363         return borderBox();
364     int l = overflowLeft(includeInterior);
365     int t = min(overflowTop(includeInterior), -borderTopExtra());
366     return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height() + borderBottomExtra()) - t);
367 }
368
369 bool RenderBlock::isSelfCollapsingBlock() const
370 {
371     // We are not self-collapsing if we
372     // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
373     // (b) are a table,
374     // (c) have border/padding,
375     // (d) have a min-height
376     // (e) have specified that one of our margins can't collapse using a CSS extension
377     if (m_height > 0 ||
378         isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 ||
379         style()->minHeight().value() > 0 || 
380         style()->marginTopCollapse() == MSEPARATE || style()->marginBottomCollapse() == MSEPARATE)
381         return false;
382
383     bool hasAutoHeight = style()->height().isAuto();
384     if (style()->height().isPercent() && !style()->htmlHacks()) {
385         hasAutoHeight = true;
386         for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
387             if (cb->style()->height().isFixed() || cb->isTableCell())
388                 hasAutoHeight = false;
389         }
390     }
391
392     // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
393     // on whether we have content that is all self-collapsing or not.
394     if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().value() == 0)) {
395         // If the block has inline children, see if we generated any line boxes.  If we have any
396         // line boxes, then we can't be self-collapsing, since we have content.
397         if (childrenInline())
398             return !firstLineBox();
399         
400         // Whether or not we collapse is dependent on whether all our normal flow children
401         // are also self-collapsing.
402         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
403             if (child->isFloatingOrPositioned())
404                 continue;
405             if (!child->isSelfCollapsingBlock())
406                 return false;
407         }
408         return true;
409     }
410     return false;
411 }
412
413 void RenderBlock::layout()
414 {
415     // Table cells call layoutBlock directly, so don't add any logic here.  Put code into
416     // layoutBlock().
417     layoutBlock(false);
418 }
419
420 void RenderBlock::layoutBlock(bool relayoutChildren)
421 {
422     KHTMLAssert(needsLayout());
423     KHTMLAssert(minMaxKnown());
424
425     if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
426         return;                                      // cause us to come in here.  Just bail.
427
428     if (!relayoutChildren && posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {
429         // All we have to is lay out our positioned objects.
430         layoutPositionedObjects(relayoutChildren || isRoot());
431         if (hasOverflowClip())
432             m_layer->updateScrollInfoAfterLayout();
433         setNeedsLayout(false);
434         return;
435     }
436     
437     IntRect oldBounds, oldFullBounds;
438     bool checkForRepaint = checkForRepaintDuringLayout();
439     if (checkForRepaint)
440         getAbsoluteRepaintRectIncludingFloats(oldBounds, oldFullBounds);
441
442     int oldWidth = m_width;
443     
444     calcWidth();
445     m_overflowWidth = m_width;
446
447     if (oldWidth != m_width)
448         relayoutChildren = true;
449
450     clearFloats();
451
452     int previousHeight = m_height;
453     m_height = 0;
454     m_overflowHeight = 0;
455     m_clearStatus = CNONE;
456
457     // We use four values, maxTopPos, maxPosNeg, maxBottomPos, and maxBottomNeg, to track
458     // our current maximal positive and negative margins.  These values are used when we
459     // are collapsed with adjacent blocks, so for example, if you have block A and B
460     // collapsing together, then you'd take the maximal positive margin from both A and B
461     // and subtract it from the maximal negative margin from both A and B to get the
462     // true collapsed margin.  This algorithm is recursive, so when we finish layout()
463     // our block knows its current maximal positive/negative values.
464     //
465     // Start out by setting our margin values to our current margins.  Table cells have
466     // no margins, so we don't fill in the values for table cells.
467     if (!isTableCell()) {
468         initMaxMarginValues();
469
470         m_topMarginQuirk = style()->marginTop().quirk();
471         m_bottomMarginQuirk = style()->marginBottom().quirk();
472
473         if (element() && element()->hasTagName(formTag) && element()->isMalformed())
474             // See if this form is malformed (i.e., unclosed). If so, don't give the form
475             // a bottom margin.
476             m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
477     }
478
479     // For overflow:scroll blocks, ensure we have both scrollbars in place always.
480     if (scrollsOverflow()) {
481         if (style()->overflowX() == OSCROLL)
482             m_layer->setHasHorizontalScrollbar(true);
483         if (style()->overflowY() == OSCROLL)
484             m_layer->setHasVerticalScrollbar(true);
485     }
486
487     IntRect repaintRect;
488     if (childrenInline())
489         repaintRect = layoutInlineChildren(relayoutChildren);
490     else
491         layoutBlockChildren(relayoutChildren);
492
493     // Expand our intrinsic height to encompass floats.
494     int toAdd = borderBottom() + paddingBottom();
495     if (includeHorizontalScrollbarSize())
496         toAdd += m_layer->horizontalScrollbarHeight();
497     if (floatBottom() > (m_height - toAdd) && (isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() ||
498                                     (parent() && parent()->isFlexibleBox())))
499         m_height = floatBottom() + toAdd;
500            
501     int oldHeight = m_height;
502     calcHeight();
503     if (oldHeight != m_height) {
504         // If the block got expanded in size, then increase our overflowheight to match.
505         if (m_overflowHeight > m_height)
506             m_overflowHeight -= paddingBottom() + borderBottom();
507         if (m_overflowHeight < m_height)
508             m_overflowHeight = m_height;
509     }
510     if (previousHeight != m_height)
511         relayoutChildren = true;
512
513     if (isTableCell()) {
514         // Table cells need to grow to accommodate both overhanging floats and
515         // blocks that have overflowed content.
516         // Check for an overhanging float first.
517         // FIXME: This needs to look at the last flow, not the last child.
518         if (lastChild() && lastChild()->hasOverhangingFloats()) {
519             KHTMLAssert(lastChild()->isRenderBlock());
520             m_height = lastChild()->yPos() + static_cast<RenderBlock*>(lastChild())->floatBottom();
521             m_height += borderBottom() + paddingBottom();
522         }
523
524         if (m_overflowHeight > m_height && !hasOverflowClip())
525             m_height = m_overflowHeight + borderBottom() + paddingBottom();
526     }
527
528     if (hasOverhangingFloats() && ((isFloating() && style()->height().isAuto()) || isTableCell())) {
529         m_height = floatBottom();
530         m_height += borderBottom() + paddingBottom();
531     }
532
533     layoutPositionedObjects(relayoutChildren || isRoot());
534
535     positionListMarker();
536
537     // Always ensure our overflow width/height are at least as large as our width/height.
538     m_overflowWidth = max(m_overflowWidth, m_width);
539     m_overflowHeight = max(m_overflowHeight, m_height);
540
541     // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
542     // we overflow or not.
543     if (hasOverflowClip())
544         m_layer->updateScrollInfoAfterLayout();
545
546     // Repaint with our new bounds if they are different from our old bounds.
547     bool didFullRepaint = false;
548     if (checkForRepaint)
549         didFullRepaint = repaintAfterLayoutIfNeeded(oldBounds, oldFullBounds);
550     if (!didFullRepaint && !repaintRect.isEmpty()) {
551         RenderView* v = view();
552         if (v && v->frameView()) {
553             repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
554             v->frameView()->addRepaintInfo(this, repaintRect); // We need to do a partial repaint of our content.
555         }
556     }
557     setNeedsLayout(false);
558 }
559
560 void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo)
561 {
562     if (child->hasStaticX()) {
563         if (style()->direction() == LTR)
564             child->setStaticX(borderLeft() + paddingLeft());
565         else
566             child->setStaticX(borderRight() + paddingRight());
567     }
568
569     if (child->hasStaticY()) {
570         int y = m_height;
571         if (!marginInfo.canCollapseWithTop()) {
572             child->calcVerticalMargins();
573             int marginTop = child->marginTop();
574             int collapsedTopPos = marginInfo.posMargin();
575             int collapsedTopNeg = marginInfo.negMargin();
576             if (marginTop > 0) {
577                 if (marginTop > collapsedTopPos)
578                     collapsedTopPos = marginTop;
579             } else {
580                 if (-marginTop > collapsedTopNeg)
581                     collapsedTopNeg = -marginTop;
582             }
583             y += (collapsedTopPos - collapsedTopNeg) - marginTop;
584         }
585         child->setStaticY(y);
586     }
587 }
588
589 void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
590 {
591     // The float should be positioned taking into account the bottom margin
592     // of the previous flow.  We add that margin into the height, get the
593     // float positioned properly, and then subtract the margin out of the
594     // height again.  In the case of self-collapsing blocks, we always just
595     // use the top margins, since the self-collapsing block collapsed its
596     // own bottom margin into its top margin.
597     //
598     // Note also that the previous flow may collapse its margin into the top of
599     // our block.  If this is the case, then we do not add the margin in to our
600     // height when computing the position of the float.   This condition can be tested
601     // for by simply calling canCollapseWithTop.  See
602     // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
603     // an example of this scenario.
604     int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
605     m_height += marginOffset;
606     positionNewFloats();
607     m_height -= marginOffset;
608 }
609
610 RenderObject* RenderBlock::handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled)
611 {
612     // Handle positioned children first.
613     RenderObject* next = handlePositionedChild(child, marginInfo, handled);
614     if (handled) return next;
615     
616     // Handle floating children next.
617     next = handleFloatingChild(child, marginInfo, handled);
618     if (handled) return next;
619
620     // See if we have a compact element.  If we do, then try to tuck the compact element into the margin space of the next block.
621     next = handleCompactChild(child, compactInfo, handled);
622     if (handled) return next;
623
624     // Finally, see if we have a run-in element.
625     return handleRunInChild(child, handled);
626 }
627
628
629 RenderObject* RenderBlock::handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
630 {
631     if (child->isPositioned()) {
632         handled = true;
633         child->containingBlock()->insertPositionedObject(child);
634         adjustPositionedBlock(child, marginInfo);
635         return child->nextSibling();
636     }
637
638     return 0;
639 }
640
641 RenderObject* RenderBlock::handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
642 {
643     if (child->isFloating()) {
644         handled = true;
645         insertFloatingObject(child);
646         adjustFloatingBlock(marginInfo);
647         return child->nextSibling();
648     }
649     
650     return 0;
651 }
652
653 RenderObject* RenderBlock::handleCompactChild(RenderObject* child, CompactInfo& compactInfo, bool& handled)
654 {
655     // FIXME: We only deal with one compact at a time.  It is unclear what should be
656     // done if multiple contiguous compacts are encountered.  For now we assume that
657     // compact A followed by another compact B should simply be treated as block A.
658     if (child->isCompact() && !compactInfo.compact() && (child->childrenInline() || child->isReplaced())) {
659         // Get the next non-positioned/non-floating RenderBlock.
660         RenderObject* next = child->nextSibling();
661         RenderObject* curr = next;
662         while (curr && curr->isFloatingOrPositioned())
663             curr = curr->nextSibling();
664         if (curr && curr->isRenderBlock() && !curr->isCompact() && !curr->isRunIn()) {
665             curr->calcWidth(); // So that horizontal margins are correct.
666                                
667             child->setInline(true); // Need to compute the margins/width for the child as though it is an inline, so that it won't try to puff up the margins to
668                                     // fill the containing block width.
669             child->calcWidth();
670             int childMargins = child->marginLeft() + child->marginRight();
671             int margin = style()->direction() == LTR ? curr->marginLeft() : curr->marginRight();
672             if (margin >= (childMargins + child->maxWidth())) {
673                 // The compact will fit in the margin.
674                 handled = true;
675                 compactInfo.set(child, curr);
676                 child->setPos(0,0); // This position will be updated to reflect the compact's
677                                     // desired position and the line box for the compact will
678                                     // pick that position up.
679                 
680                 // Remove the child.
681                 RenderObject* next = child->nextSibling();
682                 removeChildNode(child);
683                 
684                 // Now insert the child under |curr|.
685                 curr->insertChildNode(child, curr->firstChild());
686                 return next;
687             }
688             else
689                 child->setInline(false); // We didn't fit, so we remain a block-level element.
690         }
691     }
692     return 0;
693 }
694
695 void RenderBlock::insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
696 {
697     if (compactInfo.matches(child)) {
698         // We have a compact child to squeeze in.
699         RenderObject* compactChild = compactInfo.compact();
700         int compactXPos = borderLeft() + paddingLeft() + compactChild->marginLeft();
701         if (style()->direction() == RTL) {
702             compactChild->calcWidth(); // have to do this because of the capped maxwidth
703             compactXPos = width() - borderRight() - paddingRight() - marginRight() -
704                 compactChild->width() - compactChild->marginRight();
705         }
706         compactXPos -= child->xPos(); // Put compactXPos into the child's coordinate space.
707         compactChild->setPos(compactXPos, compactChild->yPos()); // Set the x position.
708         compactInfo.clear();
709     }
710 }
711
712 RenderObject* RenderBlock::handleRunInChild(RenderObject* child, bool& handled)
713 {
714     // See if we have a run-in element with inline children.  If the
715     // children aren't inline, then just treat the run-in as a normal
716     // block.
717     if (child->isRunIn() && (child->childrenInline() || child->isReplaced())) {
718         // Get the next non-positioned/non-floating RenderBlock.
719         RenderObject* curr = child->nextSibling();
720         while (curr && curr->isFloatingOrPositioned())
721             curr = curr->nextSibling();
722         if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) {
723             // The block acts like an inline, so just null out its
724             // position.
725             handled = true;
726             child->setInline(true);
727             child->setPos(0,0);
728             
729             // Remove the child.
730             RenderObject* next = child->nextSibling();
731             removeChildNode(child);
732             
733             // Now insert the child under |curr|.
734             curr->insertChildNode(child, curr->firstChild());
735             return next;
736         }
737     }
738     return 0;
739 }
740
741 void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate)
742 {
743     // Get our max pos and neg top margins.
744     int posTop = child->maxTopMargin(true);
745     int negTop = child->maxTopMargin(false);
746
747     // For self-collapsing blocks, collapse our bottom margins into our
748     // top to get new posTop and negTop values.
749     if (child->isSelfCollapsingBlock()) {
750         posTop = max(posTop, child->maxBottomMargin(true));
751         negTop = max(negTop, child->maxBottomMargin(false));
752     }
753     
754     // See if the top margin is quirky. We only care if this child has
755     // margins that will collapse with us.
756     bool topQuirk = child->isTopMarginQuirk() || style()->marginTopCollapse() == MDISCARD;
757
758     if (marginInfo.canCollapseWithTop()) {
759         // This child is collapsing with the top of the
760         // block.  If it has larger margin values, then we need to update
761         // our own maximal values.
762         if (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk) {
763             m_maxTopPosMargin = max(posTop, m_maxTopPosMargin);
764             m_maxTopNegMargin = max(negTop, m_maxTopNegMargin);
765         }
766
767         // The minute any of the margins involved isn't a quirk, don't
768         // collapse it away, even if the margin is smaller (www.webreference.com
769         // has an example of this, a <dt> with 0.8em author-specified inside
770         // a <dl> inside a <td>.
771         if (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) {
772             m_topMarginQuirk = false;
773             marginInfo.setDeterminedTopQuirk(true);
774         }
775
776         if (!marginInfo.determinedTopQuirk() && topQuirk && marginTop() == 0)
777             // We have no top margin and our top child has a quirky margin.
778             // We will pick up this quirky margin and pass it through.
779             // This deals with the <td><div><p> case.
780             // Don't do this for a block that split two inlines though.  You do
781             // still apply margins in this case.
782             m_topMarginQuirk = true;
783     }
784
785     if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))
786         marginInfo.setTopQuirk(topQuirk);
787
788     int ypos = m_height;
789     if (child->isSelfCollapsingBlock()) {
790         // This child has no height.  We need to compute our
791         // position before we collapse the child's margins together,
792         // so that we can get an accurate position for the zero-height block.
793         int collapsedTopPos = max(marginInfo.posMargin(), child->maxTopMargin(true));
794         int collapsedTopNeg = max(marginInfo.negMargin(), child->maxTopMargin(false));
795         marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
796         
797         // Now collapse the child's margins together, which means examining our
798         // bottom margin values as well. 
799         marginInfo.setPosMarginIfLarger(child->maxBottomMargin(true));
800         marginInfo.setNegMarginIfLarger(child->maxBottomMargin(false));
801
802         if (!marginInfo.canCollapseWithTop())
803             // We need to make sure that the position of the self-collapsing block
804             // is correct, since it could have overflowing content
805             // that needs to be positioned correctly (e.g., a block that
806             // had a specified height of 0 but that actually had subcontent).
807             ypos = m_height + collapsedTopPos - collapsedTopNeg;
808     }
809     else {
810         if (child->style()->marginTopCollapse() == MSEPARATE) {
811             m_height += marginInfo.margin() + child->marginTop();
812             ypos = m_height;
813         }
814         else if (!marginInfo.atTopOfBlock() ||
815             (!marginInfo.canCollapseTopWithChildren()
816              && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) {
817             // We're collapsing with a previous sibling's margins and not
818             // with the top of the block.
819             m_height += max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop);
820             ypos = m_height;
821         }
822
823         marginInfo.setPosMargin(child->maxBottomMargin(true));
824         marginInfo.setNegMargin(child->maxBottomMargin(false));
825
826         if (marginInfo.margin())
827             marginInfo.setBottomQuirk(child->isBottomMarginQuirk() || style()->marginBottomCollapse() == MDISCARD);
828
829         marginInfo.setSelfCollapsingBlockClearedFloat(false);
830     }
831
832     child->setPos(child->xPos(), ypos);
833     if (ypos != yPosEstimate) {
834         if (child->style()->width().isPercent() && child->usesLineWidth())
835             // The child's width is a percentage of the line width.
836             // When the child shifts to clear an item, its width can
837             // change (because it has more available line width).
838             // So go ahead and mark the item as dirty.
839             child->setChildNeedsLayout(true);
840
841         if (!child->avoidsFloats() && child->containsFloats())
842             child->markAllDescendantsWithFloatsForLayout();
843
844         // Our guess was wrong. Make the child lay itself out again.
845         child->layoutIfNeeded();
846     }
847 }
848
849 void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin)
850 {
851     int heightIncrease = getClearDelta(child);
852     if (heightIncrease) {
853         // The child needs to be lowered.  Move the child so that it just clears the float.
854         child->setPos(child->xPos(), child->yPos() + heightIncrease);
855
856         // Increase our height by the amount we had to clear.
857         if (!child->isSelfCollapsingBlock())
858             m_height += heightIncrease;
859         else {
860             // For self-collapsing blocks that clear, they may end up collapsing
861             // into the bottom of the parent block.  We simulate this behavior by
862             // setting our positive margin value to compensate for the clear.
863             marginInfo.setPosMargin(max(0, child->yPos() - m_height));
864             marginInfo.setNegMargin(0);
865             marginInfo.setSelfCollapsingBlockClearedFloat(true);
866         }
867         
868         if (marginInfo.canCollapseWithTop()) {
869             // We can no longer collapse with the top of the block since a clear
870             // occurred.  The empty blocks collapse into the cleared block.
871             // FIXME: This isn't quite correct.  Need clarification for what to do
872             // if the height the cleared block is offset by is smaller than the
873             // margins involved.
874             m_maxTopPosMargin = oldTopPosMargin;
875             m_maxTopNegMargin = oldTopNegMargin;
876             marginInfo.setAtTopOfBlock(false);
877         }
878
879         // If our value of clear caused us to be repositioned vertically to be
880         // underneath a float, we might have to do another layout to take into account
881         // the extra space we now have available.
882         if (child->style()->width().isPercent() && child->usesLineWidth())
883             // The child's width is a percentage of the line width.
884             // When the child shifts to clear an item, its width can
885             // change (because it has more available line width).
886             // So go ahead and mark the item as dirty.
887             child->setChildNeedsLayout(true);
888         if (!child->avoidsFloats() && child->containsFloats())
889             child->markAllDescendantsWithFloatsForLayout();
890         child->layoutIfNeeded();
891     }
892 }
893
894 int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo& marginInfo)
895 {
896     // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
897     // relayout if there are intruding floats.
898     int yPosEstimate = m_height;
899     if (!marginInfo.canCollapseWithTop()) {
900         int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();
901         yPosEstimate += max(marginInfo.margin(), childMarginTop);
902     }
903     return yPosEstimate;
904 }
905
906 void RenderBlock::determineHorizontalPosition(RenderObject* child)
907 {
908     if (style()->direction() == LTR) {
909         int xPos = borderLeft() + paddingLeft();
910         
911         // Add in our left margin.
912         int chPos = xPos + child->marginLeft();
913         
914         // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats.  They need
915         // to shift over as necessary to dodge any floats that might get in the way.
916         if (child->avoidsFloats()) {
917             int leftOff = leftOffset(m_height);
918             if (style()->textAlign() != KHTML_CENTER && child->style()->marginLeft().type() != Auto) {
919                 if (child->marginLeft() < 0)
920                     leftOff += child->marginLeft();
921                 chPos = max(chPos, leftOff); // Let the float sit in the child's margin if it can fit.
922             }
923             else if (leftOff != xPos) {
924                 // The object is shifting right. The object might be centered, so we need to
925                 // recalculate our horizontal margins. Note that the containing block content
926                 // width computation will take into account the delta between |leftOff| and |xPos|
927                 // so that we can just pass the content width in directly to the |calcHorizontalMargins|
928                 // function.
929                 static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
930                 chPos = leftOff + child->marginLeft();
931             }
932         }
933         child->setPos(chPos, child->yPos());
934     } else {
935         int xPos = m_width - borderRight() - paddingRight() - (includeVerticalScrollbarSize() ? m_layer->verticalScrollbarWidth() : 0);
936         int chPos = xPos - (child->width() + child->marginRight());
937         if (child->avoidsFloats()) {
938             int rightOff = rightOffset(m_height);
939             if (style()->textAlign() != KHTML_CENTER && child->style()->marginRight().type() != Auto) {
940                 if (child->marginRight() < 0)
941                     rightOff -= child->marginRight();
942                 chPos = min(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit.
943             } else if (rightOff != xPos) {
944                 // The object is shifting left. The object might be centered, so we need to
945                 // recalculate our horizontal margins. Note that the containing block content
946                 // width computation will take into account the delta between |rightOff| and |xPos|
947                 // so that we can just pass the content width in directly to the |calcHorizontalMargins|
948                 // function.
949                 static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
950                 chPos = rightOff - child->marginRight() - child->width();
951             }
952         }
953         child->setPos(chPos, child->yPos());
954     }
955 }
956
957 void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
958 {
959     if (marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()) {
960         // Update our max pos/neg bottom margins, since we collapsed our bottom margins
961         // with our children.
962         m_maxBottomPosMargin = max(m_maxBottomPosMargin, marginInfo.posMargin());
963         m_maxBottomNegMargin = max(m_maxBottomNegMargin, marginInfo.negMargin());
964
965         if (!marginInfo.bottomQuirk())
966             m_bottomMarginQuirk = false;
967
968         if (marginInfo.bottomQuirk() && marginBottom() == 0)
969             // We have no bottom margin and our last child has a quirky margin.
970             // We will pick up this quirky margin and pass it through.
971             // This deals with the <td><div><p> case.
972             m_bottomMarginQuirk = true;
973     }
974 }
975
976 void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
977 {
978      // If our last flow was a self-collapsing block that cleared a float, then we don't
979     // collapse it with the bottom of the block.
980     if (!marginInfo.selfCollapsingBlockClearedFloat())
981         marginInfo.setAtBottomOfBlock(true);
982
983     // If we can't collapse with children then go ahead and add in the bottom margin.
984     if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()
985         && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk()))
986         m_height += marginInfo.margin();
987         
988     // Now add in our bottom border/padding.
989     m_height += bottom;
990
991     // Negative margins can cause our height to shrink below our minimal height (border/padding).
992     // If this happens, ensure that the computed height is increased to the minimal height.
993     m_height = max(m_height, top + bottom);
994
995     // Always make sure our overflow height is at least our height.
996     m_overflowHeight = max(m_height, m_overflowHeight);
997
998     // Update our bottom collapsed margin info.
999     setCollapsedBottomMargin(marginInfo);
1000 }
1001
1002 void RenderBlock::layoutBlockChildren(bool relayoutChildren)
1003 {
1004     int top = borderTop() + paddingTop();
1005     int bottom = borderBottom() + paddingBottom() + (includeHorizontalScrollbarSize() ? m_layer->horizontalScrollbarHeight() : 0);
1006
1007     m_height = m_overflowHeight = top;
1008
1009     // The margin struct caches all our current margin collapsing state.  The compact struct caches state when we encounter compacts,
1010     MarginInfo marginInfo(this, top, bottom);
1011     CompactInfo compactInfo;
1012
1013     // Fieldsets need to find their legend and position it inside the border of the object.
1014     // The legend then gets skipped during normal layout.
1015     RenderObject* legend = layoutLegend(relayoutChildren);
1016
1017     RenderObject* child = firstChild();
1018     while (child) {
1019         if (legend == child) {
1020             child = child->nextSibling();
1021             continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
1022         }
1023
1024         int oldTopPosMargin = m_maxTopPosMargin;
1025         int oldTopNegMargin = m_maxTopNegMargin;
1026
1027         // Make sure we layout children if they need it.
1028         // FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
1029         // an auto value.  Add a method to determine this, so that we can avoid the relayout.
1030         if (relayoutChildren || (child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent()))
1031             child->setChildNeedsLayout(true);
1032
1033         // Handle the four types of special elements first.  These include positioned content, floating content, compacts and
1034         // run-ins.  When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
1035         bool handled = false;
1036         RenderObject* next = handleSpecialChild(child, marginInfo, compactInfo, handled);
1037         if (handled) { child = next; continue; }
1038
1039         // The child is a normal flow object.  Compute its vertical margins now.
1040         child->calcVerticalMargins();
1041
1042         // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
1043         if (child->style()->marginTopCollapse() == MSEPARATE) {
1044             marginInfo.setAtTopOfBlock(false);
1045             marginInfo.clearMargin();
1046         }
1047
1048         // Try to guess our correct y position.  In most cases this guess will
1049         // be correct.  Only if we're wrong (when we compute the real y position)
1050         // will we have to potentially relayout.
1051         int yPosEstimate = estimateVerticalPosition(child, marginInfo);
1052         
1053         // If an element might be affected by the presence of floats, then always mark it for
1054         // layout.
1055         if (!child->avoidsFloats() || child->usesLineWidth()) {
1056             int fb = floatBottom();
1057             if (fb > m_height || fb > yPosEstimate)
1058                 child->setChildNeedsLayout(true);
1059         }
1060
1061         // Cache our old position so that we can dirty the proper repaint rects if the child moves.
1062         int oldChildX = child->xPos();
1063         int oldChildY = child->yPos();
1064         
1065         // Go ahead and position the child as though it didn't collapse with the top.
1066         child->setPos(child->xPos(), yPosEstimate);
1067         if (yPosEstimate != oldChildY && !child->avoidsFloats() && child->containsFloats())
1068             child->markAllDescendantsWithFloatsForLayout();
1069         child->layoutIfNeeded();
1070
1071         // Now determine the correct ypos based off examination of collapsing margin
1072         // values.
1073         collapseMargins(child, marginInfo, yPosEstimate);
1074         int postCollapseChildY = child->yPos();
1075
1076         // Now check for clear.
1077         clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin);
1078
1079         // We are no longer at the top of the block if we encounter a non-empty child.  
1080         // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
1081         if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
1082             marginInfo.setAtTopOfBlock(false);
1083
1084         // Now place the child in the correct horizontal position
1085         determineHorizontalPosition(child);
1086
1087         // Update our top overflow in case the child spills out the top of the block.
1088         m_overflowTop = min(m_overflowTop, child->yPos() + child->overflowTop(false));
1089         
1090         // Update our height now that the child has been placed in the correct position.
1091         m_height += child->height();
1092         if (child->style()->marginBottomCollapse() == MSEPARATE) {
1093             m_height += child->marginBottom();
1094             marginInfo.clearMargin();
1095         }
1096         int overflowDelta = child->overflowHeight(false) - child->height();
1097         if (m_height + overflowDelta > m_overflowHeight)
1098             m_overflowHeight = m_height + overflowDelta;
1099
1100         // If the child has overhanging floats that intrude into following siblings (or possibly out
1101         // of this block), then the parent gets notified of the floats now.
1102         addOverhangingFloats(static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos());
1103
1104         // See if this child has made our overflow need to grow.
1105         m_overflowWidth = max(child->xPos() + child->overflowWidth(false), m_overflowWidth);
1106         m_overflowLeft = min(child->xPos() + child->overflowLeft(false), m_overflowLeft);
1107         
1108         // Insert our compact into the block margin if we have one.
1109         insertCompactIfNeeded(child, compactInfo);
1110
1111         // If the child moved, we have to repaint it as well as any floating/positioned
1112         // descendants.  An exception is if we need a layout.  In this case, we know we're going to
1113         // repaint ourselves (and the child) anyway.
1114         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout()) {
1115             int finalChildX = child->xPos();
1116             int finalChildY = child->yPos();
1117             if (finalChildX != oldChildX || finalChildY != oldChildY)
1118                 child->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
1119             else if (finalChildY != yPosEstimate || finalChildY != postCollapseChildY) {
1120                 // The child's repaints during layout were done before it reached its final position,
1121                 // so they were wrong.
1122                 child->repaint();
1123                 child->repaintFloatingDescendants();
1124             }
1125         }
1126
1127         child = child->nextSibling();
1128     }
1129
1130     // Now do the handling of the bottom of the block, adding in our bottom border/padding and
1131     // determining the correct collapsed bottom margin information.
1132     handleBottomOfBlock(top, bottom, marginInfo);
1133
1134     // Finished. Clear the dirty layout bits.
1135     setNeedsLayout(false);
1136 }
1137
1138 void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
1139 {
1140     if (m_positionedObjects) {
1141         RenderObject* r;
1142         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
1143         for ( ; (r = it.current()); ++it ) {
1144             // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
1145             // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
1146             // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
1147             // positioned explicitly) this should not incur a performance penalty.
1148             if (relayoutChildren || (r->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()))
1149                 r->setChildNeedsLayout(true);
1150             r->layoutIfNeeded();
1151         }
1152     }
1153 }
1154
1155 void RenderBlock::markPositionedObjectsForLayout()
1156 {
1157     if (m_positionedObjects) {
1158         RenderObject* r;
1159         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
1160         for (; (r = it.current()); ++it)
1161             r->setChildNeedsLayout(true);
1162     }
1163 }
1164
1165 void RenderBlock::getAbsoluteRepaintRectIncludingFloats(IntRect& bounds, IntRect& fullBounds)
1166 {
1167     bounds = fullBounds = getAbsoluteRepaintRect();
1168
1169     // Include any overhanging floats (if we know we're the one to paint them).
1170     // We null-check m_floatingObjects here to catch any cases where m_height ends up negative
1171     // for some reason.  I think I've caught all those cases, but this way we stay robust and don't
1172     // crash.
1173     if (hasOverhangingFloats() && m_floatingObjects) {
1174         FloatingObject* r;
1175         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1176         for ( ; (r = it.current()); ++it) {
1177             // Only repaint the object if our noPaint flag isn't set and if it isn't in
1178             // its own layer.
1179             if (!r->noPaint && !r->node->layer()) {
1180                 IntRect childRect, childFullRect;
1181                 r->node->getAbsoluteRepaintRectIncludingFloats(childRect, childFullRect);
1182                 fullBounds.unite(childFullRect);
1183             }
1184         }
1185     }
1186 }
1187
1188 void RenderBlock::repaintFloatingDescendants()
1189 {
1190     // Repaint any overhanging floats (if we know we're the one to paint them).
1191     if (hasOverhangingFloats()) {
1192         // We think that we must be in a bad state if m_floatingObjects is nil at this point, so 
1193         // we assert on Debug builds and nil-check Release builds.
1194         ASSERT(m_floatingObjects);
1195         if (!m_floatingObjects)
1196             return;
1197         
1198         FloatingObject* r;
1199         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1200         for ( ; (r = it.current()); ++it) {
1201             // Only repaint the object if our noPaint flag isn't set and if it isn't in
1202             // its own layer.
1203             if (!r->noPaint && !r->node->layer()) {                
1204                 r->node->repaint();
1205                 r->node->repaintFloatingDescendants();
1206             }
1207         }
1208     }
1209 }
1210
1211 void RenderBlock::repaintObjectsBeforeLayout()
1212 {
1213     RenderFlow::repaintObjectsBeforeLayout();
1214     if (!needsLayout())
1215         return;
1216
1217     // Walk our positioned objects.
1218     if (m_positionedObjects) {
1219         RenderObject* r;
1220         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
1221         for ( ; (r = it.current()); ++it )
1222             r->repaintObjectsBeforeLayout();
1223     }
1224 }
1225
1226 void RenderBlock::paint(PaintInfo& i, int _tx, int _ty)
1227 {
1228     _tx += m_x;
1229     _ty += m_y;
1230
1231     // Check if we need to do anything at all.
1232     if (!isInlineFlow() && !isRoot()) {
1233         IntRect overflowBox = overflowRect(false);
1234         overflowBox.inflate(maximalOutlineSize(i.phase));
1235         overflowBox.move(_tx, _ty);
1236         bool intersectsOverflowBox = overflowBox.intersects(i.r);
1237         if (!intersectsOverflowBox) {
1238             // Check floats next.
1239             if (i.phase != PaintPhaseFloat)
1240                 return;
1241             IntRect floatBox = floatRect();
1242             floatBox.inflate(maximalOutlineSize(i.phase));
1243             floatBox.move(_tx, _ty);
1244             if (!floatBox.intersects(i.r))
1245                 return;
1246         }
1247     }
1248
1249     return paintObject(i, _tx, _ty);
1250 }
1251
1252 void RenderBlock::paintChildren(PaintInfo& i, int _tx, int _ty)
1253 {
1254     PaintPhase newPhase = (i.phase == PaintPhaseChildOutlines) ? PaintPhaseOutline : i.phase;
1255     newPhase = (newPhase == PaintPhaseChildBlockBackgrounds) ? PaintPhaseChildBlockBackground : newPhase;
1256     
1257     // We don't paint our own background, but we do let the kids paint their backgrounds.
1258     PaintInfo paintInfo(i);
1259     paintInfo.phase = newPhase;
1260     bool isPrinting = document()->printing();
1261
1262     for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {        
1263         // Check for page-break-before: always, and if it's set, break and bail.
1264         if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
1265             inRootBlockContext() && (_ty + child->yPos()) > i.r.y() && 
1266             (_ty + child->yPos()) < i.r.bottom()) {
1267             view()->setBestTruncatedAt(_ty + child->yPos(), this, true);
1268             return;
1269         }
1270         
1271         if (!child->layer() && !child->isFloating())
1272             child->paint(paintInfo, _tx, _ty);
1273         
1274         // Check for page-break-after: always, and if it's set, break and bail.
1275         if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS && 
1276             inRootBlockContext() && (_ty + child->yPos() + child->height()) > i.r.y() && 
1277             (_ty + child->yPos() + child->height()) < i.r.bottom()) {
1278             view()->setBestTruncatedAt(_ty + child->yPos() + child->height() + child->collapsedMarginBottom(), this, true);
1279             return;
1280         }
1281     }
1282 }
1283
1284 void RenderBlock::paintCaret(PaintInfo& i, CaretType type)
1285 {
1286     const SelectionController &s = type == CursorCaret ? document()->frame()->selection() : document()->frame()->dragCaret();
1287     Node *caretNode = s.start().node();
1288     RenderObject *renderer = caretNode ? caretNode->renderer() : 0;
1289     if (renderer && (renderer == this || renderer->containingBlock() == this) && caretNode && caretNode->isContentEditable()) {
1290         if (type == CursorCaret) {
1291             document()->frame()->paintCaret(i.p, i.r);
1292         } else {
1293             document()->frame()->paintDragCaret(i.p, i.r);
1294         }
1295     }
1296 }
1297
1298 void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
1299 {
1300     PaintPhase paintPhase = i.phase;
1301
1302     // If we're a repositioned run-in or a compact, don't paint background/borders.
1303     bool inlineFlow = isInlineFlow();
1304
1305     // 1. paint background, borders etc
1306     if (!inlineFlow &&
1307         (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) &&
1308         shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE) {
1309         paintBoxDecorations(i, _tx, _ty);
1310     }
1311
1312     // We're done.  We don't bother painting any children.
1313     if (paintPhase == PaintPhaseBlockBackground)
1314         return;
1315
1316     // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s
1317     int scrolledX = _tx;
1318     int scrolledY = _ty;
1319     if (hasOverflowClip())
1320         m_layer->subtractScrollOffset(scrolledX, scrolledY);
1321
1322     // 2. paint contents
1323     if (paintPhase != PaintPhaseSelfOutline) {
1324         if (childrenInline())
1325             paintLines(i, scrolledX, scrolledY);
1326         else
1327             paintChildren(i, scrolledX, scrolledY);
1328     }
1329     
1330     // 3. paint selection
1331     bool isPrinting = document()->printing();
1332     if (!inlineFlow && !isPrinting)
1333         paintSelection(i, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
1334
1335     // 4. paint floats.
1336     if (!inlineFlow && (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection))
1337         paintFloats(i, scrolledX, scrolledY, paintPhase == PaintPhaseSelection);
1338
1339     // 5. paint outline.
1340     if (!inlineFlow && (paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) 
1341         && style()->outlineWidth() && style()->visibility() == VISIBLE)
1342         paintOutline(i.p, _tx, _ty, width(), height(), style());
1343
1344     // 6. paint caret.
1345     // If the caret's node's render object's containing block is this block, and the paint action is PaintPhaseForeground,
1346     // then paint the caret.
1347     if (!inlineFlow && paintPhase == PaintPhaseForeground) {        
1348         paintCaret(i, CursorCaret);
1349         paintCaret(i, DragCaret);
1350     }
1351
1352 #ifdef BOX_DEBUG
1353     if ( style() && style()->visibility() == VISIBLE ) {
1354         if(isAnonymous())
1355             outlineBox(i.p, _tx, _ty, "green");
1356         if(isFloating())
1357             outlineBox(i.p, _tx, _ty, "yellow");
1358         else
1359             outlineBox(i.p, _tx, _ty);
1360     }
1361 #endif
1362 }
1363
1364 void RenderBlock::paintFloats(PaintInfo& i, int _tx, int _ty, bool paintSelection)
1365 {
1366     if (!m_floatingObjects)
1367         return;
1368
1369     FloatingObject* r;
1370     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1371     for ( ; (r = it.current()); ++it) {
1372         // Only paint the object if our noPaint flag isn't set.
1373         if (!r->noPaint && !r->node->layer()) {
1374             PaintInfo info(i);
1375             info.phase = paintSelection ? PaintPhaseSelection : PaintPhaseBlockBackground;
1376             int tx = _tx + r->left - r->node->xPos() + r->node->marginLeft();
1377             int ty = _ty + r->startY - r->node->yPos() + r->node->marginTop();
1378             r->node->paint(info, tx, ty);
1379             if (!paintSelection) {
1380                 info.phase = PaintPhaseChildBlockBackgrounds;
1381                 r->node->paint(info, tx, ty);
1382                 info.phase = PaintPhaseFloat;
1383                 r->node->paint(info, tx, ty);
1384                 info.phase = PaintPhaseForeground;
1385                 r->node->paint(info, tx, ty);
1386                 info.phase = PaintPhaseOutline;
1387                 r->node->paint(info, tx, ty);
1388             }
1389         }
1390     }
1391 }
1392
1393 void RenderBlock::paintEllipsisBoxes(PaintInfo& i, int _tx, int _ty)
1394 {
1395     if (!shouldPaintWithinRoot(i) || !firstLineBox())
1396         return;
1397
1398     if (style()->visibility() == VISIBLE && i.phase == PaintPhaseForeground) {
1399         // We can check the first box and last box and avoid painting if we don't
1400         // intersect.
1401         int yPos = _ty + firstLineBox()->yPos();;
1402         int h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
1403         if (yPos >= i.r.bottom() || yPos + h <= i.r.y())
1404             return;
1405
1406         // See if our boxes intersect with the dirty rect.  If so, then we paint
1407         // them.  Note that boxes can easily overlap, so we can't make any assumptions
1408         // based off positions of our first line box or our last line box.
1409         for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
1410             yPos = _ty + curr->yPos();
1411             h = curr->height();
1412             if (curr->ellipsisBox() && yPos < i.r.bottom() && yPos + h > i.r.y())
1413                 curr->paintEllipsisBox(i, _tx, _ty);
1414         }
1415     }
1416 }
1417
1418 void RenderBlock::setSelectionState(SelectionState s)
1419 {
1420     if (selectionState() == s)
1421         return;
1422     
1423     if (s == SelectionInside && selectionState() != SelectionNone)
1424         return;
1425
1426     if ((s == SelectionStart && selectionState() == SelectionEnd) ||
1427         (s == SelectionEnd && selectionState() == SelectionStart))
1428         m_selectionState = SelectionBoth;
1429     else
1430         m_selectionState = s;
1431     
1432     RenderBlock* cb = containingBlock();
1433     if (cb && !cb->isRenderView())
1434         cb->setSelectionState(s);
1435 }
1436
1437 bool RenderBlock::shouldPaintSelectionGaps() const
1438 {
1439     return m_selectionState != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
1440 }
1441
1442 bool RenderBlock::isSelectionRoot() const
1443 {
1444     if (!element())
1445         return false;
1446         
1447     // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
1448     if (isTable())
1449         return false;
1450         
1451     if (isBody() || isRoot() || hasOverflowClip() || isRelPositioned() ||
1452         isFloatingOrPositioned() || isTableCell() || isInlineBlockOrInlineTable())
1453         return true;
1454     
1455     if (view() && view()->selectionStart()) {
1456         Node* startElement = view()->selectionStart()->element();
1457         if (startElement && startElement->rootEditableElement() == element())
1458             return true;
1459     }
1460     
1461     return false;
1462 }
1463
1464 GapRects RenderBlock::selectionGapRects()
1465 {
1466     if (!shouldPaintSelectionGaps())
1467         return GapRects();
1468
1469     int tx, ty;
1470     absolutePositionForContent(tx, ty);
1471     
1472     int lastTop = -borderTopExtra();
1473     int lastLeft = leftSelectionOffset(this, lastTop);
1474     int lastRight = rightSelectionOffset(this, lastTop);
1475     
1476     return fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight);
1477 }
1478
1479 void RenderBlock::paintSelection(PaintInfo& i, int tx, int ty)
1480 {
1481     if (shouldPaintSelectionGaps() && i.phase == PaintPhaseForeground) {
1482         int lastTop = -borderTopExtra();
1483         int lastLeft = leftSelectionOffset(this, lastTop);
1484         int lastRight = rightSelectionOffset(this, lastTop);
1485         fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &i);
1486     }
1487 }
1488
1489 GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, int& lastTop, int& lastLeft, int& lastRight, 
1490                                         const PaintInfo* i)
1491 {
1492     // FIXME: overflow: auto/scroll regions need more math here, since painting in the border box is different from painting in the padding box (one is scrolled, the other is
1493     // fixed).
1494     GapRects result;
1495     if (!isBlockFlow())
1496         return result;
1497
1498     if (childrenInline())
1499         result = fillInlineSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, i);
1500     else
1501         result = fillBlockSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, i);
1502         
1503     // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
1504     if (rootBlock == this && (m_selectionState != SelectionBoth && m_selectionState != SelectionEnd))
1505         result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height() + borderBottomExtra(),
1506                                                     rootBlock, blockX, blockY, i));
1507     return result;
1508 }
1509
1510 GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, 
1511                                               int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* i)
1512 {
1513     GapRects result;
1514     
1515     RenderObject* selStart = view()->selectionStart();
1516     // If there is no selection, don't try to get the selection's containing block. 
1517     // If we do, we'll crash.
1518     bool containsStart = (selStart && (selStart == this || selStart->containingBlock() == this));
1519
1520     if (!firstLineBox()) {
1521         if (containsStart) {
1522             // Go ahead and update our lastY to be the bottom of the block.  <hr>s or empty blocks with height can trip this
1523             // case.
1524             lastTop = (ty - blockY) + height();
1525             lastLeft = leftSelectionOffset(rootBlock, height());
1526             lastRight = rightSelectionOffset(rootBlock, height());
1527         }
1528         return result;
1529     }
1530
1531     RootInlineBox* lastSelectedLine = 0;
1532     RootInlineBox* curr;
1533     for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox());
1534
1535     // Now paint the gaps for the lines.
1536     for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
1537         int selTop =  curr->selectionTop();
1538         int selHeight = curr->selectionHeight();
1539
1540         if (!containsStart && !lastSelectedLine &&
1541             selectionState() != SelectionStart && selectionState() != SelectionBoth)
1542             result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + selTop,
1543                                                         rootBlock, blockX, blockY, i));
1544
1545         if (!i || ty + selTop < i->r.bottom() && ty + selTop + selHeight > i->r.y())
1546             result.unite(curr->fillLineSelectionGap(selTop, selHeight, rootBlock, blockX, blockY, tx, ty, i));
1547
1548         lastSelectedLine = curr;
1549     }
1550
1551     if (containsStart && !lastSelectedLine)
1552         // Selection must start just after our last line.
1553         lastSelectedLine = lastRootBox();
1554
1555     if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
1556         // Go ahead and update our lastY to be the bottom of the last selected line.
1557         lastTop = (ty - blockY) + lastSelectedLine->bottomOverflow();
1558         lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
1559         lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
1560     }
1561     return result;
1562 }
1563
1564 GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, int& lastTop, int& lastLeft, int& lastRight,
1565                                           const PaintInfo* i)
1566 {
1567     GapRects result;
1568     
1569     // Go ahead and jump right to the first block child that contains some selected objects.
1570     RenderObject* curr;
1571     for (curr = firstChild(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSibling());
1572     
1573     for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSibling()) {
1574         SelectionState childState = curr->selectionState();
1575         if (childState == SelectionBoth || childState == SelectionEnd)
1576             sawSelectionEnd = true;
1577
1578         if (curr->isFloatingOrPositioned())
1579             continue; // We must be a normal flow object in order to even be considered.
1580         
1581         if (curr->isRelPositioned() && curr->layer()) {
1582             // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
1583             // Just disregard it completely.
1584             int x = 0;
1585             int y = 0;
1586             curr->layer()->relativePositionOffset(x, y);
1587             if (x || y)
1588                 continue;
1589         }
1590
1591         bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
1592         bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
1593         if (fillBlockGaps) {
1594             // We need to fill the vertical gap above this object.
1595             if (childState == SelectionEnd || childState == SelectionInside)
1596                 // Fill the gap above the object.
1597                 result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, 
1598                                                             ty + curr->yPos(), rootBlock, blockX, blockY, i));
1599
1600             // Only fill side gaps for objects that paint their own selection if we know for sure the selection is going to extend all the way *past*
1601             // our object.  We know this if the selection did not end inside our object.
1602             if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
1603                 childState = SelectionNone;
1604
1605             // Fill side gaps on this object based off its state.
1606             bool leftGap, rightGap;
1607             getHorizontalSelectionGapInfo(childState, leftGap, rightGap);
1608             
1609             if (leftGap)
1610                 result.uniteLeft(fillLeftSelectionGap(this, curr->xPos(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, i));
1611             if (rightGap)
1612                 result.uniteRight(fillRightSelectionGap(this, curr->xPos() + curr->width(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, i));
1613
1614             // Update lastTop to be just underneath the object.  lastLeft and lastRight extend as far as
1615             // they can without bumping into floating or positioned objects.  Ideally they will go right up
1616             // to the border of the root selection block.
1617             lastTop = (ty - blockY) + (curr->yPos() + curr->height());
1618             lastLeft = leftSelectionOffset(rootBlock, curr->yPos() + curr->height());
1619             lastRight = rightSelectionOffset(rootBlock, curr->yPos() + curr->height());
1620         }
1621         else if (childState != SelectionNone)
1622             // We must be a block that has some selected object inside it.  Go ahead and recur.
1623             result.unite(static_cast<RenderBlock*>(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->xPos(), ty + curr->yPos(), 
1624                                                                             lastTop, lastLeft, lastRight, i));
1625     }
1626     return result;
1627 }
1628
1629 IntRect RenderBlock::fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height,
1630                                                 const PaintInfo* i)
1631 {
1632     if (width <= 0 || height <= 0)
1633         return IntRect();
1634     IntRect gapRect(xPos, yPos, width, height);
1635     if (i)
1636         i->p->fillRect(gapRect, selObj->selectionBackgroundColor());
1637     return gapRect;
1638 }
1639
1640 IntRect RenderBlock::fillVerticalSelectionGap(int lastTop, int lastLeft, int lastRight,
1641                                               int bottomY, RenderBlock* rootBlock, int blockX, int blockY,
1642                                               const PaintInfo* i)
1643 {
1644     int top = blockY + lastTop;
1645     int height = bottomY - top;
1646     if (height <= 0)
1647         return IntRect();
1648         
1649     // Get the selection offsets for the bottom of the gap
1650     int left = blockX + max(lastLeft, leftSelectionOffset(rootBlock, bottomY));
1651     int right = blockX + min(lastRight, rightSelectionOffset(rootBlock, bottomY));
1652     int width = right - left;
1653     if (width <= 0)
1654         return IntRect();
1655
1656     IntRect gapRect(left, top, width, height);
1657     if (i)
1658         i->p->fillRect(gapRect, selectionBackgroundColor());
1659     return gapRect;
1660 }
1661
1662 IntRect RenderBlock::fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const PaintInfo* i)
1663 {
1664     int top = yPos + ty;
1665     int left = blockX + max(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height));
1666     int width = tx + xPos - left;
1667     if (width <= 0)
1668         return IntRect();
1669
1670     IntRect gapRect(left, top, width, height);
1671     if (i)
1672         i->p->fillRect(gapRect, selObj->selectionBackgroundColor());
1673     return gapRect;
1674 }
1675
1676 IntRect RenderBlock::fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const PaintInfo* i)
1677 {
1678     int left = xPos + tx;
1679     int top = yPos + ty;
1680     int right = blockX + min(rightSelectionOffset(rootBlock, yPos), rightSelectionOffset(rootBlock, yPos + height));
1681     int width = right - left;
1682     if (width <= 0)
1683         return IntRect();
1684
1685     IntRect gapRect(left, top, width, height);
1686     if (i)
1687         i->p->fillRect(gapRect, selObj->selectionBackgroundColor());
1688     return gapRect;
1689 }
1690
1691 void RenderBlock::getHorizontalSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
1692 {
1693     bool ltr = style()->direction() == LTR;
1694     leftGap = (state == RenderObject::SelectionInside) ||
1695               (state == RenderObject::SelectionEnd && ltr) ||
1696               (state == RenderObject::SelectionStart && !ltr);
1697     rightGap = (state == RenderObject::SelectionInside) ||
1698                (state == RenderObject::SelectionStart && ltr) ||
1699                (state == RenderObject::SelectionEnd && !ltr);
1700 }
1701
1702 int RenderBlock::leftSelectionOffset(RenderBlock* rootBlock, int y)
1703 {
1704     int left = leftOffset(y);
1705     if (left == borderLeft() + paddingLeft()) {
1706         if (rootBlock != this)
1707             // The border can potentially be further extended by our containingBlock().
1708             return containingBlock()->leftSelectionOffset(rootBlock, y + yPos());
1709         return 0;
1710     }
1711     else {
1712         RenderBlock* cb = this;
1713         while (cb != rootBlock) {
1714             left += cb->xPos();
1715             cb = cb->containingBlock();
1716         }
1717     }
1718     
1719     return left;
1720 }
1721
1722 int RenderBlock::rightSelectionOffset(RenderBlock* rootBlock, int y)
1723 {
1724     int right = rightOffset(y);
1725     if (right == (contentWidth() + (borderLeft() + paddingLeft()))) {
1726         if (rootBlock != this)
1727             // The border can potentially be further extended by our containingBlock().
1728             return containingBlock()->rightSelectionOffset(rootBlock, y + yPos());
1729         return width();
1730     }
1731     else {
1732         RenderBlock* cb = this;
1733         while (cb != rootBlock) {
1734             right += cb->xPos();
1735             cb = cb->containingBlock();
1736         }
1737     }
1738     return right;
1739 }
1740
1741 void RenderBlock::insertPositionedObject(RenderObject *o)
1742 {
1743     // Create the list of special objects if we don't aleady have one
1744     if (!m_positionedObjects) {
1745         m_positionedObjects = new DeprecatedPtrList<RenderObject>;
1746         m_positionedObjects->setAutoDelete(false);
1747     }
1748     else {
1749         // Don't insert the object again if it's already in the list
1750         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
1751         RenderObject* f;
1752         while ( (f = it.current()) ) {
1753             if (f == o) return;
1754             ++it;
1755         }
1756     }
1757
1758     m_positionedObjects->append(o);
1759 }
1760
1761 void RenderBlock::removePositionedObject(RenderObject *o)
1762 {
1763     if (m_positionedObjects) {
1764         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
1765         while (it.current()) {
1766             if (it.current() == o) {
1767                 m_positionedObjects->removeRef(it.current());
1768                 return;
1769             }
1770             ++it;
1771         }
1772     }
1773 }
1774
1775 void RenderBlock::removePositionedObjects(RenderBlock* o)
1776 {
1777     if (!m_positionedObjects)
1778         return;
1779     
1780     DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
1781     while (it.current()) {
1782         if (!o || it.current()->hasAncestor(o)) {
1783             if (o)
1784                 it.current()->setChildNeedsLayout(true, false);
1785             m_positionedObjects->removeRef(it.current());
1786         } else
1787             ++it;
1788     }
1789 }
1790
1791 void RenderBlock::insertFloatingObject(RenderObject *o)
1792 {
1793     // Create the list of special objects if we don't aleady have one
1794     if (!m_floatingObjects) {
1795         m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
1796         m_floatingObjects->setAutoDelete(true);
1797     }
1798     else {
1799         // Don't insert the object again if it's already in the list
1800         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1801         FloatingObject* f;
1802         while ( (f = it.current()) ) {
1803             if (f->node == o) return;
1804             ++it;
1805         }
1806     }
1807
1808     // Create the special object entry & append it to the list
1809
1810     FloatingObject *newObj;
1811     if (o->isFloating()) {
1812         // floating object
1813         o->layoutIfNeeded();
1814
1815         if(o->style()->floating() == FLEFT)
1816             newObj = new FloatingObject(FloatingObject::FloatLeft);
1817         else
1818             newObj = new FloatingObject(FloatingObject::FloatRight);
1819
1820         newObj->startY = -1;
1821         newObj->endY = -1;
1822         newObj->width = o->width() + o->marginLeft() + o->marginRight();
1823         newObj->noPaint = o->layer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
1824     }
1825     else {
1826         // We should never get here, as insertFloatingObject() should only ever be called with floating
1827         // objects.
1828         KHTMLAssert(false);
1829         newObj = 0; // keep gcc's uninitialized variable warnings happy
1830     }
1831
1832     newObj->node = o;
1833
1834     m_floatingObjects->append(newObj);
1835 }
1836
1837 void RenderBlock::removeFloatingObject(RenderObject *o)
1838 {
1839     if (m_floatingObjects) {
1840         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1841         while (it.current()) {
1842             if (it.current()->node == o)
1843                 m_floatingObjects->removeRef(it.current());
1844             ++it;
1845         }
1846     }
1847 }
1848
1849 void RenderBlock::setPaintsFloatingObject(RenderObject* o, bool b)
1850 {
1851     if (!m_floatingObjects)
1852         return;
1853     
1854     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1855     while (it.current()) {
1856         if (it.current()->node == o) {
1857             it.current()->noPaint = !b;
1858             setChildNeedsLayout(true);
1859             return;
1860         }
1861         ++it;
1862     }
1863 }
1864
1865 void RenderBlock::positionNewFloats()
1866 {
1867     if(!m_floatingObjects) return;
1868     FloatingObject *f = m_floatingObjects->last();
1869     if(!f || f->startY != -1) return;
1870     FloatingObject *lastFloat;
1871     while(1)
1872     {
1873         lastFloat = m_floatingObjects->getPrev();
1874         if (!lastFloat || lastFloat->startY != -1)
1875             break;        
1876         f = m_floatingObjects->prev();
1877     }
1878
1879
1880     int y = m_height;
1881
1882
1883     // the float can not start above the y position of the last positioned float.
1884     if(lastFloat && lastFloat->startY > y)
1885         y = lastFloat->startY;
1886
1887     while(f)
1888     {
1889         //skip elements copied from elsewhere and positioned elements
1890         if (f->node->containingBlock()!=this)
1891         {
1892             f = m_floatingObjects->next();
1893             continue;
1894         }
1895
1896         RenderObject *o = f->node;
1897         int _height = o->height() + o->marginTop() + o->marginBottom();
1898
1899         int ro = rightOffset(); // Constant part of right offset.
1900         int lo = leftOffset(); // Constat part of left offset.
1901         int fwidth = f->width; // The width we look for.
1902         if (ro - lo < fwidth)
1903             fwidth = ro - lo; // Never look for more than what will be available.
1904         
1905         int oldChildX = o->xPos();
1906         int oldChildY = o->yPos();
1907         
1908         if ( o->style()->clear() & CLEFT )
1909             y = max( leftBottom(), y );
1910         if ( o->style()->clear() & CRIGHT )
1911             y = max( rightBottom(), y );
1912
1913         if (o->style()->floating() == FLEFT)
1914         {
1915             int heightRemainingLeft = 1;
1916             int heightRemainingRight = 1;
1917             int fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
1918             while (rightRelOffset(y,ro, false, &heightRemainingRight)-fx < fwidth)
1919             {
1920                 y += min( heightRemainingLeft, heightRemainingRight );
1921                 fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
1922             }
1923             if (fx<0) fx=0;
1924             f->left = fx;
1925             o->setPos(fx + o->marginLeft(), y + o->marginTop());
1926         }
1927         else
1928         {
1929             int heightRemainingLeft = 1;
1930             int heightRemainingRight = 1;
1931             int fx = rightRelOffset(y,ro, false, &heightRemainingRight);
1932             while (fx - leftRelOffset(y,lo, false, &heightRemainingLeft) < fwidth)
1933             {
1934                 y += min(heightRemainingLeft, heightRemainingRight);
1935                 fx = rightRelOffset(y,ro, false, &heightRemainingRight);
1936             }
1937             if (fx<f->width) fx=f->width;
1938             f->left = fx - f->width;
1939             o->setPos(fx - o->marginRight() - o->width(), y + o->marginTop());
1940         }
1941         f->startY = y;
1942         f->endY = f->startY + _height;
1943
1944         // If the child moved, we have to repaint it.
1945         if (o->checkForRepaintDuringLayout())
1946             o->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
1947
1948         f = m_floatingObjects->next();
1949     }
1950 }
1951
1952 void RenderBlock::newLine()
1953 {
1954     positionNewFloats();
1955     // set y position
1956     int newY = 0;
1957     switch(m_clearStatus)
1958     {
1959         case CLEFT:
1960             newY = leftBottom();
1961             break;
1962         case CRIGHT:
1963             newY = rightBottom();
1964             break;
1965         case CBOTH:
1966             newY = floatBottom();
1967         default:
1968             break;
1969     }
1970     if (m_height < newY)
1971         m_height = newY;
1972     m_clearStatus = CNONE;
1973 }
1974
1975 int
1976 RenderBlock::leftOffset() const
1977 {
1978     return borderLeft()+paddingLeft();
1979 }
1980
1981 int
1982 RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent,
1983                            int *heightRemaining ) const
1984 {
1985     int left = fixedOffset;
1986     if (m_floatingObjects) {
1987         if ( heightRemaining ) *heightRemaining = 1;
1988         FloatingObject* r;
1989         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
1990         for ( ; (r = it.current()); ++it )
1991         {
1992             //kdDebug( 6040 ) <<(void *)this << " left: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
1993             if (r->startY <= y && r->endY > y &&
1994                 r->type() == FloatingObject::FloatLeft &&
1995                 r->left + r->width > left) {
1996                 left = r->left + r->width;
1997                 if ( heightRemaining ) *heightRemaining = r->endY - y;
1998             }
1999         }
2000     }
2001
2002     if (applyTextIndent && m_firstLine && style()->direction() == LTR) {
2003         int cw=0;
2004         if (style()->textIndent().isPercent())
2005             cw = containingBlock()->contentWidth();
2006         left += style()->textIndent().calcMinValue(cw);
2007     }
2008
2009     //kdDebug( 6040 ) << "leftOffset(" << y << ") = " << left << endl;
2010     return left;
2011 }
2012
2013 int
2014 RenderBlock::rightOffset() const
2015 {
2016     int right = m_width - borderRight() - paddingRight();
2017     if (includeVerticalScrollbarSize())
2018         right -= m_layer->verticalScrollbarWidth();
2019     return right;
2020 }
2021
2022 int
2023 RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent,
2024                             int *heightRemaining ) const
2025 {
2026     int right = fixedOffset;
2027
2028     if (m_floatingObjects) {
2029         if (heightRemaining) *heightRemaining = 1;
2030         FloatingObject* r;
2031         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2032         for ( ; (r = it.current()); ++it )
2033         {
2034             //kdDebug( 6040 ) << "right: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
2035             if (r->startY <= y && r->endY > y &&
2036                 r->type() == FloatingObject::FloatRight &&
2037                 r->left < right) {
2038                 right = r->left;
2039                 if ( heightRemaining ) *heightRemaining = r->endY - y;
2040             }
2041         }
2042     }
2043     
2044     if (applyTextIndent && m_firstLine && style()->direction() == RTL) {
2045         int cw=0;
2046         if (style()->textIndent().isPercent())
2047             cw = containingBlock()->contentWidth();
2048         right -= style()->textIndent().calcMinValue(cw);
2049     }
2050     
2051     //kdDebug( 6040 ) << "rightOffset(" << y << ") = " << right << endl;
2052     return right;
2053 }
2054
2055 int
2056 RenderBlock::lineWidth(int y) const
2057 {
2058     //kdDebug( 6040 ) << "lineWidth(" << y << ")=" << rightOffset(y) - leftOffset(y) << endl;
2059     int result = rightOffset(y) - leftOffset(y);
2060     return (result < 0) ? 0 : result;
2061 }
2062
2063 int
2064 RenderBlock::nearestFloatBottom(int height) const
2065 {
2066     if (!m_floatingObjects) return 0;
2067     int bottom = 0;
2068     FloatingObject* r;
2069     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2070     for ( ; (r = it.current()); ++it )
2071         if (r->endY>height && (r->endY<bottom || bottom==0))
2072             bottom=r->endY;
2073     return max(bottom, height);
2074 }
2075
2076 int
2077 RenderBlock::floatBottom() const
2078 {
2079     if (!m_floatingObjects) return 0;
2080     int bottom=0;
2081     FloatingObject* r;
2082     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2083     for ( ; (r = it.current()); ++it )
2084         if (r->endY>bottom)
2085             bottom=r->endY;
2086     return bottom;
2087 }
2088
2089 IntRect RenderBlock::floatRect() const
2090 {
2091     IntRect result(borderBox());
2092     if (!m_floatingObjects || hasOverflowClip())
2093         return result;
2094     FloatingObject* r;
2095     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2096     for (; (r = it.current()); ++it) {
2097         if (!r->noPaint && !r->node->layer()) {
2098             IntRect childRect = unionRect(r->node->floatRect(), r->node->overflowRect());
2099             childRect.move(r->left + r->node->marginLeft(), r->startY + r->node->marginTop());
2100             result.unite(childRect);
2101         }
2102     }
2103
2104     return result;
2105 }
2106
2107 int
2108 RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
2109 {
2110     int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf);
2111     if (!includeOverflowInterior && hasOverflowClip())
2112         return bottom;
2113     if (includeSelf && m_overflowHeight > bottom)
2114         bottom = m_overflowHeight;
2115     
2116     if (m_floatingObjects) {
2117         FloatingObject* r;
2118         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2119         for ( ; (r = it.current()); ++it ) {
2120             if (!r->noPaint || r->node->layer()) {
2121                 int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false);
2122                 bottom = max(bottom, lp);
2123             }
2124         }
2125     }
2126
2127     // Fixed positioned objects do not scroll and thus should not constitute
2128     // part of the lowest position.
2129     if (m_positionedObjects && !isRenderView()) {
2130         RenderObject* r;
2131         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
2132         for ( ; (r = it.current()); ++it ) {
2133             int lp = r->yPos() + r->lowestPosition(false);
2134             bottom = max(bottom, lp);
2135         }
2136     }
2137
2138     if (!includeSelf && lastLineBox()) {
2139         int lp = lastLineBox()->yPos() + lastLineBox()->height();
2140         bottom = max(bottom, lp);
2141     }
2142     
2143     return bottom;
2144 }
2145
2146 int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
2147 {
2148     int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf);
2149     if (!includeOverflowInterior && hasOverflowClip())
2150         return right;
2151     if (includeSelf && m_overflowWidth > right)
2152         right = m_overflowWidth;
2153     
2154     if (m_floatingObjects) {
2155         FloatingObject* r;
2156         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2157         for ( ; (r = it.current()); ++it ) {
2158             if (!r->noPaint || r->node->layer()) {
2159                 int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false);
2160                 right = max(right, rp);
2161             }
2162         }
2163     }
2164
2165     if (m_positionedObjects && !isRenderView()) {
2166         RenderObject* r;
2167         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
2168         for ( ; (r = it.current()); ++it ) {
2169             int rp = r->xPos() + r->rightmostPosition(false);
2170             right = max(right, rp);
2171         }
2172     }
2173
2174     if (!includeSelf && firstLineBox()) {
2175         for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
2176             int rp = currBox->xPos() + currBox->width();
2177             // If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
2178             // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
2179             if (node()->isContentEditable() && node() == node()->rootEditableElement() && style()->direction() == LTR)
2180                 rp += 1;
2181             right = max(right, rp);
2182         }
2183     }
2184     
2185     return right;
2186 }
2187
2188 int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
2189 {
2190     int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf);
2191     if (!includeOverflowInterior && hasOverflowClip())
2192         return left;
2193     if (includeSelf && m_overflowLeft < left)
2194         left = m_overflowLeft;
2195     
2196     if (m_floatingObjects) {
2197         FloatingObject* r;
2198         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2199         for ( ; (r = it.current()); ++it ) {
2200             if (!r->noPaint || r->node->layer()) {
2201                 int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false);
2202                 left = min(left, lp);
2203             }
2204         }
2205     }
2206     
2207     if (m_positionedObjects && !isRenderView()) {
2208         RenderObject* r;
2209         DeprecatedPtrListIterator<RenderObject> it(*m_positionedObjects);
2210         for ( ; (r = it.current()); ++it ) {
2211             int lp = r->xPos() + r->leftmostPosition(false);
2212             left = min(left, lp);
2213         }
2214     }
2215     
2216     if (!includeSelf && firstLineBox()) {
2217         for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
2218             left = min(left, (int)currBox->xPos());
2219     }
2220     
2221     return left;
2222 }
2223
2224 int
2225 RenderBlock::leftBottom()
2226 {
2227     if (!m_floatingObjects) return 0;
2228     int bottom=0;
2229     FloatingObject* r;
2230     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2231     for ( ; (r = it.current()); ++it )
2232         if (r->endY > bottom && r->type() == FloatingObject::FloatLeft)
2233             bottom=r->endY;
2234
2235     return bottom;
2236 }
2237
2238 int
2239 RenderBlock::rightBottom()
2240 {
2241     if (!m_floatingObjects) return 0;
2242     int bottom=0;
2243     FloatingObject* r;
2244     DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2245     for ( ; (r = it.current()); ++it )
2246         if (r->endY>bottom && r->type() == FloatingObject::FloatRight)
2247             bottom=r->endY;
2248
2249     return bottom;
2250 }
2251
2252 void
2253 RenderBlock::clearFloats()
2254 {
2255     if (m_floatingObjects)
2256         m_floatingObjects->clear();
2257
2258     // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
2259     if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell())
2260         return;
2261     
2262     // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
2263     // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
2264     // to avoid floats.
2265     bool parentHasFloats = false;
2266     RenderObject *prev = previousSibling();
2267     while (prev && (!prev->isRenderBlock() || prev->avoidsFloats() || prev->isFloatingOrPositioned())) {
2268         if (prev->isFloating())
2269             parentHasFloats = true;
2270          prev = prev->previousSibling();
2271     }
2272
2273     // First add in floats from the parent.
2274     int offset = m_y;
2275     if (parentHasFloats)
2276         addIntrudingFloats(static_cast<RenderBlock *>(parent()),
2277                            parent()->borderLeft() + parent()->paddingLeft(), offset);
2278
2279     int xoffset = 0;
2280     if (prev)
2281         offset -= prev->yPos();
2282     else {
2283         prev = parent();
2284         xoffset += prev->borderLeft() + prev->paddingLeft();
2285     }
2286     //kdDebug() << "RenderBlock::clearFloats found previous "<< (void *)this << " prev=" << (void *)prev<< endl;
2287
2288     // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
2289     if (!prev->isRenderBlock()) return;
2290     RenderBlock* block = static_cast<RenderBlock *>(prev);
2291     if (!block->m_floatingObjects) return;
2292     if (block->floatBottom() > offset)
2293         addIntrudingFloats(block, xoffset, offset);
2294 }
2295
2296 void RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff)
2297 {
2298     // Prevent floats from being added to the canvas by the root element, e.g., <html>.
2299     if (child->hasOverflowClip() || !child->hasOverhangingFloats() || child->isRoot())
2300         return;
2301     
2302     // We think that we must be in a bad state if child->m_floatingObjects is nil at this point, 
2303     // so we assert on Debug builds and nil-check Release builds.
2304     ASSERT(child->m_floatingObjects);
2305     if (!child->m_floatingObjects)
2306         return;
2307
2308     DeprecatedPtrListIterator<FloatingObject> it(*child->m_floatingObjects);
2309     for (FloatingObject *r; (r = it.current()); ++it) {
2310         if (child->yPos() + r->endY > height()) {
2311             // The object may already be in our list. Check for it up front to avoid
2312             // creating duplicate entries.
2313             FloatingObject* f = 0;
2314             if (m_floatingObjects) {
2315                 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2316                 while ((f = it.current())) {
2317                     if (f->node == r->node) break;
2318                     ++it;
2319                 }
2320             }
2321
2322             // If the object is not in the list, we add it now.
2323             if (!f) {
2324                 FloatingObject *floatingObj = new FloatingObject(r->type());
2325                 floatingObj->startY = r->startY - yoff;
2326                 floatingObj->endY = r->endY - yoff;
2327                 floatingObj->left = r->left - xoff;
2328                 floatingObj->width = r->width;
2329                 floatingObj->node = r->node;
2330
2331                 // The nearest enclosing layer always paints the float (so that zindex and stacking
2332                 // behaves properly).  We always want to propagate the desire to paint the float as
2333                 // far out as we can, to the outermost block that overlaps the float, stopping only
2334                 // if we hit a layer boundary.
2335                 if (r->node->enclosingLayer() == enclosingLayer())
2336                     r->noPaint = true;
2337                 else
2338                     floatingObj->noPaint = true;
2339                 
2340                 // We create the floating object list lazily.
2341                 if (!m_floatingObjects) {
2342                     m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
2343                     m_floatingObjects->setAutoDelete(true);
2344                 }
2345                 m_floatingObjects->append(floatingObj);
2346             }
2347         }
2348     }
2349 }
2350
2351 void RenderBlock::addIntrudingFloats(RenderBlock* prev, int xoff, int yoff)
2352 {
2353     // If the parent or previous sibling doesn't have any floats to add, don't bother.
2354     if (!prev->m_floatingObjects)
2355         return;
2356
2357     DeprecatedPtrListIterator<FloatingObject> it(*prev->m_floatingObjects);
2358     for (FloatingObject *r; (r = it.current()); ++it) {
2359         if (r->endY > yoff) {
2360             // The object may already be in our list. Check for it up front to avoid
2361             // creating duplicate entries.
2362             FloatingObject* f = 0;
2363             if (m_floatingObjects) {
2364                 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2365                 while ((f = it.current())) {
2366                     if (f->node == r->node) break;
2367                     ++it;
2368                 }
2369             }
2370             if (!f) {
2371                 FloatingObject *floatingObj = new FloatingObject(r->type());
2372                 floatingObj->startY = r->startY - yoff;
2373                 floatingObj->endY = r->endY - yoff;
2374                 floatingObj->left = r->left - xoff;
2375                 // Applying the child's margin makes no sense in the case where the child was passed in.
2376                 // since his own margin was added already through the subtraction of the |xoff| variable
2377                 // above.  |xoff| will equal -flow->marginLeft() in this case, so it's already been taken
2378                 // into account.  Only apply this code if |child| is false, since otherwise the left margin
2379                 // will get applied twice.
2380                 if (prev != parent())
2381                     floatingObj->left += prev->marginLeft();
2382                 floatingObj->left -= marginLeft();
2383                 floatingObj->noPaint = true;  // We are not in the direct inheritance chain for this float. We will never paint it.
2384                 floatingObj->width = r->width;
2385                 floatingObj->node = r->node;
2386                 
2387                 // We create the floating object list lazily.
2388                 if (!m_floatingObjects) {
2389                     m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
2390                     m_floatingObjects->setAutoDelete(true);
2391                 }
2392                 m_floatingObjects->append(floatingObj);
2393             }
2394         }
2395     }
2396 }
2397
2398 bool RenderBlock::containsFloat(RenderObject* o)
2399 {
2400     if (m_floatingObjects) {
2401         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2402         while (it.current()) {
2403             if (it.current()->node == o)
2404                 return true;
2405             ++it;
2406         }
2407     }
2408     return false;
2409 }
2410
2411 void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove)
2412 {
2413     setChildNeedsLayout(true);
2414
2415     if (floatToRemove)
2416         removeFloatingObject(floatToRemove);
2417
2418     // Iterate over our children and mark them as needed.
2419     if (!childrenInline()) {
2420         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
2421             if (isBlockFlow() && !child->isFloatingOrPositioned() &&
2422                 ((floatToRemove ? child->containsFloat(floatToRemove) : child->containsFloats()) || child->usesLineWidth()))
2423                 child->markAllDescendantsWithFloatsForLayout(floatToRemove);
2424         }
2425     }
2426 }
2427
2428 int RenderBlock::getClearDelta(RenderObject *child)
2429 {
2430     bool clearSet = child->style()->clear() != CNONE;
2431     int bottom = 0;
2432     switch (child->style()->clear()) {
2433         case CNONE:
2434             break;
2435         case CLEFT:
2436             bottom = leftBottom();
2437             break;
2438         case CRIGHT:
2439             bottom = rightBottom();
2440             break;
2441         case CBOTH:
2442             bottom = floatBottom();
2443             break;
2444     }
2445
2446     // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
2447     // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed
2448     // to fit) and not all (we should be using nearestFloatBottom and looping).
2449     // Do not allow tables to wrap in quirks or even in almost strict mode 
2450     // (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work)
2451     int result = clearSet ? max(0, bottom - child->yPos()) : 0;
2452     if (!result && child->avoidsFloats() && child->style()->width().isFixed() && 
2453         child->minWidth() > lineWidth(child->yPos()) && child->minWidth() <= contentWidth() && 
2454         document()->inStrictMode())   
2455         result = max(0, floatBottom() - child->yPos());
2456     return result;
2457 }
2458
2459 bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
2460 {
2461     if (!scrollsOverflow())
2462         return false;
2463
2464     if (m_layer->verticalScrollbarWidth()) {
2465         IntRect vertRect(_tx + width() - borderRight() - m_layer->verticalScrollbarWidth(),
2466                        _ty + borderTop() - borderTopExtra(),
2467                        m_layer->verticalScrollbarWidth(),
2468                        height() + borderTopExtra() + borderBottomExtra() - borderTop() - borderBottom() -  m_layer->horizontalScrollbarHeight());
2469         if (vertRect.contains(_x, _y)) {
2470             RenderLayer::gScrollBar = m_layer->verticalScrollbar();
2471             return true;
2472         }
2473     }
2474
2475     if (m_layer->horizontalScrollbarHeight()) {
2476         IntRect horizRect(_tx + borderLeft(),
2477                         _ty + height() + borderBottomExtra() - m_layer->horizontalScrollbarHeight() - borderBottom(),
2478                         width() - borderLeft() - borderRight() - m_layer->verticalScrollbarWidth(),
2479                         m_layer->horizontalScrollbarHeight());
2480         if (horizRect.contains(_x, _y)) {
2481             RenderLayer::gScrollBar = m_layer->horizontalScrollbar();
2482             return true;
2483         }
2484     }
2485
2486     return false;    
2487 }
2488
2489 bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
2490 {
2491     bool inlineFlow = isInlineFlow();
2492
2493     int tx = _tx + m_x;
2494     int ty = _ty + m_y + borderTopExtra();
2495     
2496     if (!inlineFlow && !isRoot()) {
2497         // Check if we need to do anything at all.
2498         IntRect overflowBox = overflowRect(false);
2499         overflowBox.move(tx, ty);
2500         bool insideOverflowBox = overflowBox.contains(_x, _y);
2501         if (!insideOverflowBox) {
2502             // Check floats next.
2503             if (hitTestAction != HitTestFloat)
2504                 return false;
2505             IntRect floatBox = floatRect();
2506             floatBox.move(tx, ty);
2507             if (!floatBox.contains(_x, _y))
2508                 return false;
2509         }
2510     }
2511
2512     if (isPointInScrollbar(_x, _y, tx, ty)) {
2513         if (hitTestAction == HitTestBlockBackground) {
2514             setInnerNode(info);
2515             return true;
2516         }
2517         return false;
2518     }
2519
2520     // Hit test descendants first.
2521     int scrolledX = tx;
2522     int scrolledY = ty;
2523     if (hasOverflowClip())
2524         m_layer->subtractScrollOffset(scrolledX, scrolledY);
2525     if (childrenInline() && !isTable()) {
2526         // We have to hit-test our line boxes.
2527         if (hitTestLines(info, _x, _y, scrolledX, scrolledY, hitTestAction)) {
2528             setInnerNode(info);
2529             return true;
2530         }
2531     }
2532     else {
2533         // Hit test our children.
2534         HitTestAction childHitTest = hitTestAction;
2535         if (hitTestAction == HitTestChildBlockBackgrounds)
2536             childHitTest = HitTestChildBlockBackground;
2537         for (RenderObject* child = lastChild(); child; child = child->previousSibling())
2538             // FIXME: We have to skip over inline flows, since they can show up inside RenderTables at the moment (a demoted inline <form> for example).  If we ever implement a
2539             // table-specific hit-test method (which we should do for performance reasons anyway), then we can remove this check.
2540             if (!child->layer() && !child->isFloating() && !child->isInlineFlow() && child->nodeAtPoint(info, _x, _y, scrolledX, scrolledY, childHitTest)) {
2541                 setInnerNode(info);
2542                 return true;
2543             }
2544     }
2545     
2546     // Hit test floats.
2547     if (hitTestAction == HitTestFloat && m_floatingObjects) {
2548         if (isRenderView()) {
2549             scrolledX += static_cast<RenderView*>(this)->frameView()->contentsX();
2550             scrolledY += static_cast<RenderView*>(this)->frameView()->contentsY();
2551         }
2552         
2553         FloatingObject* o;
2554         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
2555         for (it.toLast(); (o = it.current()); --it)
2556             if (!o->noPaint && !o->node->layer() && o->node->hitTest(info, _x, _y,
2557                                      scrolledX + o->left + o->node->marginLeft() - o->node->xPos(),
2558                                      scrolledY + o->startY + o->node->marginTop() - o->node->yPos())) {
2559                 setInnerNode(info);
2560                 return true;
2561             }
2562     }
2563
2564     // Now hit test our background.
2565     if (!inlineFlow && (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground)) {
2566         int topExtra = borderTopExtra();
2567         IntRect boundsRect(tx, ty - topExtra, m_width, m_height + topExtra + borderBottomExtra());
2568         if (isRoot() || (style()->visibility() == VISIBLE && boundsRect.contains(_x, _y))) {
2569             setInnerNode(info);
2570             return true;
2571         }
2572     }
2573
2574     return false;
2575 }
2576
2577 Position RenderBlock::positionForBox(InlineBox *box, bool start) const
2578 {
2579     if (!box)
2580         return Position();
2581
2582     if (!box->object()->element())
2583         return Position(element(), start ? caretMinOffset() : caretMaxOffset());
2584
2585     if (!box->isInlineTextBox())
2586         return Position(box->object()->element(), start ? box->object()->caretMinOffset() : box->object()->caretMaxOffset());
2587
2588     InlineTextBox *textBox = static_cast<InlineTextBox *>(box);
2589     return Position(box->object()->element(), start ? textBox->start() : textBox->start() + textBox->len());
2590 }
2591
2592 Position RenderBlock::positionForRenderer(RenderObject *renderer, bool start) const
2593 {
2594     if (!renderer)
2595         return Position(element(), 0);
2596
2597     Node *node = renderer->element() ? renderer->element() : element();
2598     if (!node)
2599         return Position();
2600
2601     int offset = start ? node->caretMinOffset() : node->caretMaxOffset();
2602     return Position(node, offset);
2603 }
2604
2605 VisiblePosition RenderBlock::positionForCoordinates(int x, int y)
2606 {
2607     if (isTable())
2608         return RenderFlow::positionForCoordinates(x, y); 
2609
2610     int absx, absy;
2611     absolutePositionForContent(absx, absy);
2612
2613     int top = absy + borderTop() + paddingTop();
2614     int bottom = top + contentHeight();
2615
2616     int left = absx + borderLeft() + paddingLeft();
2617     int right = left + contentWidth();
2618
2619     Node* n = element();
2620
2621     bool isEditableRoot = n && n->rootEditableElement() == n;
2622
2623     if (y < top || (isEditableRoot && (y < bottom && x < left))) {
2624         if (!isEditableRoot)
2625             if (RenderObject* c = firstChild()) {
2626                 VisiblePosition p = c->positionForCoordinates(x, y);
2627                 if (p.isNotNull())
2628                     return p;
2629             }
2630         if (n) {
2631             if (Node* sp = n->shadowParentNode())
2632                 n = sp;
2633             if (Node* p = n->parent())
2634                 return VisiblePosition(p, n->nodeIndex(), DOWNSTREAM);
2635         }
2636         return VisiblePosition(n, 0, DOWNSTREAM);
2637     }
2638
2639     if (y >= bottom || (isEditableRoot && (y >= top && x >= right))) {
2640         if (!isEditableRoot)
2641             if (RenderObject* c = lastChild()) {
2642                 VisiblePosition p = c->positionForCoordinates(x, y);
2643                 if (p.isNotNull())
2644                     return p;
2645             }
2646         if (n) {
2647             if (Node* sp = n->shadowParentNode())
2648                 n = sp;
2649             if (Node* p = n->parent())
2650                 return VisiblePosition(p, n->nodeIndex() + 1, DOWNSTREAM);
2651         }
2652         return VisiblePosition(n, 0, DOWNSTREAM);
2653     }
2654
2655     if (childrenInline()) {
2656         if (!firstRootBox())
2657             return VisiblePosition(n, 0, DOWNSTREAM);
2658             
2659         if (y >= top && y < absy + firstRootBox()->topOverflow())
2660             // y coordinate is above first root line box
2661             return VisiblePosition(positionForBox(firstRootBox()->firstLeafChild(), true), DOWNSTREAM);
2662         
2663         // look for the closest line box in the root box which is at the passed-in y coordinate
2664         for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
2665             top = absy + root->topOverflow();
2666             // set the bottom based on whether there is a next root box
2667             if (root->nextRootBox())
2668                 bottom = absy + root->nextRootBox()->topOverflow();
2669             else
2670                 bottom = absy + root->bottomOverflow();
2671             // check if this root line box is located at this y coordinate
2672             if (y >= top && y < bottom && root->firstChild()) {
2673                 InlineBox* closestBox = root->closestLeafChildForXPos(x, absx);
2674                 if (closestBox)
2675                     // pass the box a y position that is inside it
2676                     return closestBox->object()->positionForCoordinates(x, absy + closestBox->m_y);
2677             }
2678         }
2679
2680         if (lastRootBox())
2681             // y coordinate is below last root line box
2682             return VisiblePosition(positionForBox(lastRootBox()->lastLeafChild(), false), DOWNSTREAM);
2683
2684         return VisiblePosition(n, 0, DOWNSTREAM);
2685     }
2686     
2687     // see if any child blocks exist at this y coordinate
2688     RenderObject* lastVisibleChild = 0;
2689     for (RenderObject* renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
2690         if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned())
2691             continue;
2692         renderer->absolutePositionForContent(absx, top);
2693         RenderObject* next = renderer->nextSibling();
2694         while (next && next->isFloatingOrPositioned())
2695             next = next->nextSibling();
2696         if (next) 
2697             next->absolutePositionForContent(absx, bottom);
2698         else
2699             bottom = top + contentHeight();
2700         if (y >= top && y < bottom)
2701             return renderer->positionForCoordinates(x, y);
2702         lastVisibleChild = renderer;
2703     }
2704
2705     // pass along to the last child we saw that had a height and is visible.
2706     if (lastVisibleChild)
2707         return lastVisibleChild->positionForCoordinates(x, y);
2708     
2709     // still no luck...return this render object's element and offset 0
2710     return VisiblePosition(n, 0, DOWNSTREAM);
2711 }
2712
2713 void RenderBlock::calcMinMaxWidth()
2714 {
2715     KHTMLAssert( !minMaxKnown() );
2716
2717 #ifdef DEBUG_LAYOUT
2718     kdDebug( 6040 ) << renderName() << "(RenderBlock)::calcMinMaxWidth() this=" << this << endl;
2719 #endif
2720
2721     m_minWidth = 0;
2722     m_maxWidth = 0;
2723
2724     if (childrenInline())
2725         calcInlineMinMaxWidth();
2726     else
2727         calcBlocminMaxWidth();
2728
2729     if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
2730
2731     if (!style()->autoWrap() && childrenInline()) {
2732         m_minWidth = m_maxWidth;
2733         
2734         // A horizontal marquee with inline children has no minimum width.
2735         if (m_layer && m_layer->marquee() && m_layer->marquee()->isHorizontal() && !m_layer->marquee()->isUnfurlMarquee())
2736             m_minWidth = 0;
2737     }
2738
2739     if (isTableCell()) {
2740         Length w = static_cast<RenderTableCell*>(this)->styleOrColWidth();
2741         if (w.isFixed() && w.value() > 0)
2742             m_maxWidth = max(m_minWidth, calcContentBoxWidth(w.value()));
2743     } else if (style()->width().isFixed() && style()->width().value() > 0)
2744         m_minWidth = m_maxWidth = calcContentBoxWidth(style()->width().value());
2745     
2746     if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
2747         m_maxWidth = max(m_maxWidth, calcContentBoxWidth(style()->minWidth().value()));
2748         m_minWidth = max(m_minWidth, calcContentBoxWidth(style()->minWidth().value()));
2749     }
2750     
2751     if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
2752         m_maxWidth = min(m_maxWidth, calcContentBoxWidth(style()->maxWidth().value()));
2753         m_minWidth = min(m_minWidth, calcContentBoxWidth(style()->maxWidth().value()));
2754     }
2755
2756     int toAdd = 0;
2757     toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
2758
2759     m_minWidth += toAdd;
2760     m_maxWidth += toAdd;
2761
2762     setMinMaxKnown();
2763
2764     //kdDebug( 6040 ) << "Text::calcMinMaxWidth(" << this << "): min = " << m_minWidth << " max = " << m_maxWidth << endl;
2765 }
2766
2767 struct InlineMinMaxIterator
2768 {
2769 /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
2770    inline min/max width calculations.  Note the following about the way it walks:
2771    (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
2772    (2) We do not drill into the children of floats or replaced elements, since you can't break
2773        in the middle of such an element.
2774    (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
2775        distinct borders/margin/padding that contribute to the min/max width.
2776 */
2777     RenderObject* parent;
2778     RenderObject* current;
2779     bool endOfInline;
2780
2781     InlineMinMaxIterator(RenderObject* p, RenderObject* o, bool end = false)
2782         :parent(p), current(o), endOfInline(end) {}
2783
2784     RenderObject* next();
2785 };
2786
2787 RenderObject* InlineMinMaxIterator::next()
2788 {
2789     RenderObject* result = 0;
2790     bool oldEndOfInline = endOfInline;
2791     endOfInline = false;
2792     while (current != 0 || (current == parent))
2793     {
2794         //kdDebug( 6040 ) << "current = " << current << endl;
2795         if (!oldEndOfInline &&
2796             (current == parent ||
2797              (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
2798             result = current->firstChild();
2799         if (!result) {
2800             // We hit the end of our inline. (It was empty, e.g., <span></span>.)
2801             if (!oldEndOfInline && current->isInlineFlow()) {
2802                 result = current;
2803                 endOfInline = true;
2804                 break;
2805             }
2806
2807             while (current && current != parent) {
2808                 result = current->nextSibling();
2809                 if (result) break;
2810                 current = current->parent();
2811                 if (current && current != parent && current->isInlineFlow()) {
2812                     result = current;
2813                     endOfInline = true;
2814                     break;
2815                 }
2816             }
2817         }
2818
2819         if (!result) break;
2820
2821         if (!result->isPositioned() && (result->isText() || result->isBR() ||
2822             result->isFloating() || result->isReplaced() ||
2823             result->isInlineFlow()))
2824             break;
2825         
2826         current = result;
2827         result = 0;
2828     }
2829
2830     // Update our position.
2831     current = result;
2832     return current;
2833 }
2834
2835 static int getBPMWidth(int childValue, Length cssUnit)
2836 {
2837     if (cssUnit.type() != Auto)
2838         return (cssUnit.isFixed() ? cssUnit.value() : childValue);
2839     return 0;
2840 }
2841
2842 static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
2843 {
2844     RenderStyle* cstyle = child->style();
2845     int result = 0;
2846     bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
2847     result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
2848                           (leftSide ? cstyle->marginLeft() :
2849                                       cstyle->marginRight()));
2850     result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
2851                           (leftSide ? cstyle->paddingLeft() :
2852                                       cstyle->paddingRight()));
2853     result += leftSide ? child->borderLeft() : child->borderRight();
2854     return result;
2855 }
2856
2857 static inline void stripTrailingSpace(int& inlineMax, int& inlineMin,
2858                                       RenderObject* trailingSpaceChild)
2859 {
2860     if (trailingSpaceChild && trailingSpaceChild->isText()) {
2861         // Collapse away the trailing space at the end of a block.
2862         RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
2863         const Font *f = t->font(false);  // FIXME: Why are we ignoring first-line?
2864         const UChar space = ' ';
2865         int spaceWidth = f->width(TextRun(&space, 1));
2866         inlineMax -= spaceWidth;
2867         if (inlineMin > inlineMax)
2868             inlineMin = inlineMax;
2869     }
2870 }
2871
2872 void RenderBlock::calcInlineMinMaxWidth()
2873 {
2874     int inlineMax=0;
2875     int inlineMin=0;
2876
2877     int cw = containingBlock()->contentWidth();
2878
2879     // If we are at the start of a line, we want to ignore all white-space.
2880     // Also strip spaces if we previously had text that ended in a trailing space.
2881     bool stripFrontSpaces = true;
2882     RenderObject* trailingSpaceChild = 0;
2883
2884     bool autoWrap, oldAutoWrap;
2885     autoWrap = oldAutoWrap = style()->autoWrap();
2886
2887     InlineMinMaxIterator childIterator(this, this);
2888     bool addedTextIndent = false; // Only gets added in once.
2889     RenderObject* prevFloat = 0;
2890     while (RenderObject* child = childIterator.next())
2891     {
2892         autoWrap = child->style()->autoWrap();
2893
2894         if (!child->isBR()) {
2895             // Step One: determine whether or not we need to go ahead and
2896             // terminate our current line.  Each discrete chunk can become
2897             // the new min-width, if it is the widest chunk seen so far, and
2898             // it can also become the max-width.
2899
2900             // Children fall into three categories:
2901             // (1) An inline flow object.  These objects always have a min/max of 0,
2902             // and are included in the iteration solely so that their margins can
2903             // be added in.
2904             //
2905             // (2) An inline non-text non-flow object, e.g., an inline replaced element.
2906             // These objects can always be on a line by themselves, so in this situation
2907             // we need to go ahead and break the current line, and then add in our own
2908             // margins and min/max width on its own line, and then terminate the line.
2909             //
2910             // (3) A text object.  Text runs can have breakable characters at the start,
2911             // the middle or the end.  They may also lose whitespace off the front if
2912             // we're already ignoring whitespace.  In order to compute accurate min-width
2913             // information, we need three pieces of information.
2914             // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
2915             // starts with whitespace.
2916             // (b) the min-width of the last non-breakable run. Should be 0 if the text string
2917             // ends with whitespace.
2918             // (c) the min/max width of the string (trimmed for whitespace).
2919             //
2920             // If the text string starts with whitespace, then we need to go ahead and
2921             // terminate our current line (unless we're already in a whitespace stripping
2922             // mode.
2923             //
2924             // If the text string has a breakable character in the middle, but didn't start
2925             // with whitespace, then we add the width of the first non-breakable run and
2926             // then end the current line.  We then need to use the intermediate min/max width
2927             // values (if any of them are larger than our current min/max).  We then look at
2928             // the width of the last non-breakable run and use that to start a new line
2929             // (unless we end in whitespace).
2930             RenderStyle* cstyle = child->style();
2931             int childMin = 0;
2932             int childMax = 0;
2933
2934             if (!child->isText()) {
2935                 // Case (1) and (2).  Inline replaced and inline flow elements.
2936                 if (child->isInlineFlow()) {
2937                     // Add in padding/border/margin from the appropriate side of
2938                     // the element.
2939                     int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
2940                     childMin += bpm;
2941                     childMax += bpm;
2942
2943                     inlineMin += childMin;
2944                     inlineMax += childMax;
2945                 }
2946                 else {
2947                     // Inline replaced elts add in their margins to their min/max values.
2948                     int margins = 0;
2949                     Length leftMargin = cstyle->marginLeft();
2950                     Length rightMargin = cstyle->marginRight();
2951                     bool useCalculatedWidths = child->isListMarker();
2952                     if (leftMargin.isPercent() || rightMargin.isPercent() || useCalculatedWidths)
2953                         child->calcWidth();
2954                     if (useCalculatedWidths || leftMargin.isPercent())
2955                         margins += child->marginLeft();
2956                     else if (leftMargin.isFixed())
2957                         margins += leftMargin.value();
2958                     if (useCalculatedWidths || rightMargin.isPercent())
2959                         margins += child->marginRight();
2960                     else if (rightMargin.isFixed())
2961                         margins += rightMargin.value();
2962                     childMin += margins;
2963                     childMax += margins;
2964                 }
2965             }
2966
2967             if (!child->isRenderInline() && !child->isText()) {
2968                 // Case (2). Inline replaced elements and floats.
2969                 // Go ahead and terminate the current line as far as
2970                 // minwidth is concerned.
2971                 childMin += child->minWidth();
2972                 childMax += child->maxWidth();
2973
2974                 // FIXME: This isn't right.  WinIE, Opera, Mozilla all do this differently and
2975                 // treat replaced elements like characters in a word.
2976                 if (autoWrap || oldAutoWrap) {
2977                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2978                     inlineMin = 0;
2979                 }
2980
2981                 // Check our "clear" setting.  If we're supposed to clear the previous float, then
2982                 // go ahead and terminate maxwidth as well.
2983                 if (child->isFloating()) {
2984                     if (prevFloat &&
2985                         ((prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT)) ||
2986                          (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT)))) {
2987                         m_maxWidth = max(inlineMax, m_maxWidth);
2988                         inlineMax = 0;
2989                     }
2990                     prevFloat = child;
2991                 }
2992                 
2993                 // Add in text-indent.  This is added in only once.
2994                 int ti = 0;
2995                 if (!addedTextIndent) {
2996                     addedTextIndent = true;
2997                     ti = style()->textIndent().calcMinValue(cw);
2998                     childMin+=ti;
2999                     childMax+=ti;
3000                 }
3001                 
3002                 // Add our width to the max.
3003                 inlineMax += childMax;
3004
3005                 if (!autoWrap)
3006                     inlineMin += childMin;
3007                 else {
3008                     // Now check our line.
3009                     inlineMin = childMin;
3010                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3011
3012                     // Now start a new line.
3013                     inlineMin = 0;
3014                 }
3015
3016                 // We are no longer stripping whitespace at the start of
3017                 // a line.
3018                 if (!child->isFloating()) {
3019                     stripFrontSpaces = false;
3020                     trailingSpaceChild = 0;
3021                 }
3022             }
3023             else if (child->isText())
3024             {
3025                 // Case (3). Text.
3026                 RenderText* t = static_cast<RenderText *>(child);
3027
3028                 // Determine if we have a breakable character.  Pass in
3029                 // whether or not we should ignore any spaces at the front
3030                 // of the string.  If those are going to be stripped out,
3031                 // then they shouldn't be considered in the breakable char
3032                 // check.
3033                 bool hasBreakableChar, hasBreak;
3034                 int beginMin, endMin;
3035                 bool beginWS, endWS;
3036                 int beginMax, endMax;
3037                 t->trimmedMinMaxWidth(inlineMax, beginMin, beginWS, endMin, endWS,
3038                                       hasBreakableChar, hasBreak, beginMax, endMax,
3039                                       childMin, childMax, stripFrontSpaces);
3040
3041                 // This text object is insignificant and will not be rendered.  Just
3042                 // continue.
3043                 if (!hasBreak && childMax == 0) continue;
3044                 
3045                 if (stripFrontSpaces)
3046                     trailingSpaceChild = child;
3047                 else
3048                     trailingSpaceChild = 0;
3049
3050                 // Add in text-indent.  This is added in only once.
3051                 int ti = 0;
3052                 if (!addedTextIndent) {
3053                     addedTextIndent = true;
3054                     ti = style()->textIndent().calcMinValue(cw);
3055                     childMin+=ti; beginMin += ti;
3056                     childMax+=ti; beginMax += ti;
3057                 }
3058                 
3059                 // If we have no breakable characters at all,
3060                 // then this is the easy case. We add ourselves to the current
3061                 // min and max and continue.
3062                 if (!hasBreakableChar) {
3063                     inlineMin += childMin;
3064                 }
3065                 else {
3066                     // We have a breakable character.  Now we need to know if
3067                     // we start and end with whitespace.
3068                     if (beginWS) {
3069                         // Go ahead and end the current line.
3070                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3071                     }
3072                     else {
3073                         inlineMin += beginMin;
3074                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3075                         childMin -= ti;
3076                     }
3077
3078                     inlineMin = childMin;
3079
3080                     if (endWS) {
3081                         // We end in whitespace, which means we can go ahead
3082                         // and end our current line.
3083                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3084                         inlineMin = 0;
3085                     }
3086                     else {
3087                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3088                         inlineMin = endMin;
3089                     }
3090                 }
3091
3092                 if (hasBreak) {
3093                     inlineMax += beginMax;
3094                     if (m_maxWidth < inlineMax) m_maxWidth = inlineMax;
3095                     if (m_maxWidth < childMax) m_maxWidth = childMax;
3096                     inlineMax = endMax;
3097                 }
3098                 else
3099                     inlineMax += childMax;
3100             }
3101         }
3102         else
3103         {
3104             if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3105             if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
3106             inlineMin = inlineMax = 0;
3107             stripFrontSpaces = true;
3108             trailingSpaceChild = 0;
3109         }
3110
3111         oldAutoWrap = autoWrap;
3112     }
3113
3114     if (style()->collapseWhiteSpace())
3115         stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
3116     
3117     m_minWidth = max(inlineMin, m_minWidth);
3118     m_maxWidth = max(inlineMax, m_maxWidth);
3119 }
3120
3121 // Use a very large value (in effect infinite).
3122 #define BLOCK_MAX_WIDTH 15000
3123
3124 void RenderBlock::calcBlocminMaxWidth()
3125 {
3126     bool nowrap = style()->whiteSpace() == NOWRAP;
3127
3128     RenderObject *child = firstChild();
3129     int floatLeftWidth = 0, floatRightWidth = 0;
3130     while (child) {
3131         // Positioned children don't affect the min/max width
3132         if (child->isPositioned()) {
3133             child = child->nextSibling();
3134             continue;
3135         }
3136
3137         if (child->isFloating() || child->avoidsFloats()) {
3138             int floatTotalWidth = floatLeftWidth + floatRightWidth;
3139             if (child->style()->clear() & CLEFT) {
3140                 m_maxWidth = max(floatTotalWidth, m_maxWidth);
3141                 floatLeftWidth = 0;
3142             }
3143             if (child->style()->clear() & CRIGHT) {
3144                 m_maxWidth = max(floatTotalWidth, m_maxWidth);
3145                 floatRightWidth = 0;
3146             }
3147         }
3148
3149         Length ml = child->style()->marginLeft();
3150         Length mr = child->style()->marginRight();
3151
3152         // Call calcWidth on the child to ensure that our margins are
3153         // up to date.  This method can be called before the child has actually
3154         // calculated its margins (which are computed inside calcWidth).
3155         if (ml.isPercent() || mr.isPercent())
3156             calcWidth();
3157
3158         // A margin basically has three types: fixed, percentage, and auto (variable).
3159         // Auto margins simply become 0 when computing min/max width.
3160         // Fixed margins can be added in as is.
3161         // Percentage margins are computed as a percentage of the width we calculated in
3162         // the calcWidth call above.  In this case we use the actual cached margin values on
3163         // the RenderObject itself.
3164         int margin = 0, marginLeft = 0, marginRight = 0;
3165         if (ml.isFixed())
3166             marginLeft += ml.value();
3167         else if (ml.isPercent())
3168             marginLeft += child->marginLeft();
3169         if (mr.isFixed())
3170             marginRight += mr.value();
3171         else if (mr.isPercent())
3172             marginRight += child->marginRight();
3173         margin = marginLeft + marginRight;
3174
3175         int w = child->minWidth() + margin;
3176         if (m_minWidth < w) m_minWidth = w;
3177         
3178         // IE ignores tables for calculation of nowrap. Makes some sense.
3179         if (nowrap && !child->isTable() && m_maxWidth < w)
3180             m_maxWidth = w;
3181
3182         w = child->maxWidth() + margin;
3183
3184         if (!child->isFloating()) {
3185             if (child->avoidsFloats()) {
3186                 // Determine a left and right max value based off whether or not the floats can fit in the
3187                 // margins of the object.  For negative margins, we will attempt to overlap the float if the negative margin
3188                 // is smaller than the float width.
3189                 int maxLeft = marginLeft > 0 ? max(floatLeftWidth, marginLeft) : floatLeftWidth + marginLeft;
3190                 int maxRight = marginRight > 0 ? max(floatRightWidth, marginRight) : floatRightWidth + marginRight;
3191                 w = child->maxWidth() + maxLeft + maxRight;
3192                 w = max(w, floatLeftWidth + floatRightWidth);
3193             }
3194             else
3195                 m_maxWidth = max(floatLeftWidth + floatRightWidth, m_maxWidth);
3196             floatLeftWidth = floatRightWidth = 0;
3197         }
3198         
3199         if (child->isFloating()) {
3200             if (style()->floating() == FLEFT)
3201                 floatLeftWidth += w;
3202             else
3203                 floatRightWidth += w;
3204         }
3205         else if (m_maxWidth < w)
3206             m_maxWidth = w;
3207
3208         // A very specific WinIE quirk.
3209         // Example:
3210         /*
3211            <div style="position:absolute; width:100px; top:50px;">
3212               <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
3213                 <table style="width:100%"><tr><td></table>
3214               </div>
3215            </div>
3216         */
3217         // In the above example, the inner absolute positioned block should have a computed width
3218         // of 100px because of the table.
3219         // We can achieve this effect by making the maxwidth of blocks that contain tables
3220         // with percentage widths be infinite (as long as they are not inside a table cell).
3221         if (style()->htmlHacks() && child->style()->width().isPercent() &&
3222             !isTableCell() && child->isTable() && m_maxWidth < BLOCK_MAX_WIDTH) {
3223             RenderBlock* cb = containingBlock();
3224             while (!cb->isRenderView() && !cb->isTableCell())
3225                 cb = cb->containingBlock();
3226             if (!cb->isTableCell())
3227                 m_maxWidth = BLOCK_MAX_WIDTH;
3228         }
3229         
3230         child = child->nextSibling();
3231     }
3232
3233     // Always make sure these values are non-negative.
3234     m_minWidth = max(0, m_minWidth);
3235     m_maxWidth = max(0, m_maxWidth);
3236
3237     m_maxWidth = max(floatLeftWidth + floatRightWidth, m_maxWidth);
3238 }
3239
3240 bool RenderBlock::hasLineIfEmpty() const
3241 {
3242     return element() && (element()->isContentEditable() && element()->rootEditableElement() == element() ||
3243                          element()->isShadowNode() && element()->shadowParentNode()->hasTagName(inputTag));
3244 }
3245
3246 short RenderBlock::lineHeight(bool b, bool isRootLineBox) const
3247 {
3248     // Inline blocks are replaced elements. Otherwise, just pass off to
3249     // the base class.  If we're being queried as though we're the root line
3250     // box, then the fact that we're an inline-block is irrelevant, and we behave
3251     // just like a block.
3252     if (isReplaced() && !isRootLineBox)
3253         return height()+marginTop()+marginBottom();
3254     return RenderFlow::lineHeight(b, isRootLineBox);
3255 }
3256
3257 short RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
3258 {
3259     // Inline blocks are replaced elements. Otherwise, just pass off to
3260     // the base class.  If we're being queried as though we're the root line
3261     // box, then the fact that we're an inline-block is irrelevant, and we behave
3262     // just like a block.
3263     if (isReplaced() && !isRootLineBox) {
3264         // For "leaf" theme objects, let the theme decide what the baseline position is.
3265         // FIXME: Might be better to have a custom CSS property instead, so that if the theme
3266         // is turned off, checkboxes/radios will still have decent baselines.
3267         if (style()->hasAppearance() && !theme()->isControlContainer(style()->appearance()))
3268             return theme()->baselinePosition(this);
3269             
3270         // CSS2.1 states that the baseline of an inline block is the baseline of the last line box in
3271         // the normal flow.  We make an exception for marquees, since their baselines are meaningless
3272         // (the content inside them moves).  This matches WinIE as well, which just bottom-aligns them.
3273         // We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
3274         // vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
3275         // of our content box.
3276         int baselinePos = (m_layer && (m_layer->marquee() || m_layer->verticalScrollbar() || m_layer->scrollYOffset() != 0)) ? -1 : getBaselineOfLastLineBox();
3277         if (baselinePos != -1 && baselinePos <= borderTop() + paddingTop() + contentHeight())
3278             return marginTop() + baselinePos;
3279         return height() + marginTop() + marginBottom();
3280     }
3281     return RenderFlow::baselinePosition(b, isRootLineBox);
3282 }
3283
3284 int RenderBlock::getBaselineOfFirstLineBox() const
3285 {
3286     if (!isBlockFlow())
3287         return RenderFlow::getBaselineOfFirstLineBox();
3288
3289     if (childrenInline()) {
3290         if (m_firstLineBox)
3291             return m_firstLineBox->yPos() + m_firstLineBox->baseline();
3292         else
3293             return -1;
3294     }
3295     else {
3296         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
3297             if (!curr->isFloatingOrPositioned()) {
3298                 int result = curr->getBaselineOfFirstLineBox();
3299                 if (result != -1)
3300                     return curr->yPos() + result; // Translate to our coordinate space.
3301             }
3302         }
3303     }
3304
3305     return -1;
3306 }
3307
3308 int RenderBlock::getBaselineOfLastLineBox() const
3309 {
3310     if (!isBlockFlow())
3311         return RenderFlow::getBaselineOfLastLineBox();
3312
3313     if (childrenInline()) {
3314         if (!firstLineBox() && hasLineIfEmpty())
3315             return RenderFlow::baselinePosition(true) + borderTop() + paddingTop();
3316         if (m_lastLineBox)
3317             return m_lastLineBox->yPos() + m_lastLineBox->baseline();
3318         return -1;
3319     }
3320     else {
3321         for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) {
3322             if (!curr->isFloatingOrPositioned()) {
3323                 int result = curr->getBaselineOfLastLineBox();
3324                 if (result != -1)
3325                     return curr->yPos() + result; // Translate to our coordinate space.
3326             }
3327         }
3328     }
3329
3330     return -1;
3331 }
3332
3333 RenderBlock* RenderBlock::firstLineBlock() const
3334 {
3335     const RenderObject* firstLineBlock = this;
3336     bool hasPseudo = false;
3337     while (true) {
3338         hasPseudo = firstLineBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LINE);
3339         if (hasPseudo)
3340             break;
3341         RenderObject* parentBlock = firstLineBlock->parent();
3342         if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() || 
3343             !parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
3344             break;
3345         firstLineBlock = parentBlock;
3346     } 
3347     
3348     if (!hasPseudo)
3349         return 0;
3350     
3351     return (RenderBlock*)(firstLineBlock);
3352 }
3353
3354 void RenderBlock::updateFirstLetter()
3355 {    
3356     // FIXME: We need to destroy the first-letter object if it is no longer the first child.  Need to find
3357     // an efficient way to check for that situation though before implementing anything.
3358     RenderObject* firstLetterBlock = this;
3359     bool hasPseudoStyle = false;
3360     while (true) {
3361         hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LETTER);
3362         if (hasPseudoStyle)
3363             break;
3364         RenderObject* parentBlock = firstLetterBlock->parent();
3365         if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock || 
3366             !parentBlock->isBlockFlow())
3367             break;
3368         firstLetterBlock = parentBlock;
3369     } 
3370
3371     if (!hasPseudoStyle) 
3372         return;
3373     
3374     // Drill into inlines looking for our first text child.
3375     RenderObject* currChild = firstLetterBlock->firstChild();
3376     while (currChild && currChild->needsLayout() && !currChild->isReplaced() && !currChild->isText()) 
3377         currChild = currChild->firstChild();
3378
3379     // Get list markers out of the way.
3380     while (currChild && currChild->isListMarker())
3381         currChild = currChild->nextSibling();
3382     
3383     if (!currChild)
3384         return;
3385     
3386     RenderObject* firstLetterContainer = currChild->parent();
3387
3388     // If the child already has style, then it has already been created, so we just want
3389     // to update it.
3390     if (currChild->style()->styleType() == RenderStyle::FIRST_LETTER) {
3391         RenderStyle* pseudo = firstLetterBlock->getPseudoStyle(RenderStyle::FIRST_LETTER,
3392                                                                firstLetterContainer->firstLineStyle());
3393         currChild->setStyle(pseudo);
3394         for (RenderObject* genChild = currChild->firstChild(); genChild; genChild = genChild->nextSibling()) {
3395             if (genChild->isText()) 
3396                 genChild->setStyle(pseudo);
3397         }
3398         return;
3399     }
3400
3401     // If the child does not already have style, we create it here.
3402     if (currChild->isText() && !currChild->isBR() && 
3403         currChild->parent()->style()->styleType() != RenderStyle::FIRST_LETTER) {
3404         
3405         RenderText* textObj = static_cast<RenderText*>(currChild);
3406         
3407         // Create our pseudo style now that we have our firstLetterContainer determined.
3408         RenderStyle* pseudoStyle = firstLetterBlock->getPseudoStyle(RenderStyle::FIRST_LETTER,
3409                                                                     firstLetterContainer->firstLineStyle());
3410         
3411         // Force inline display (except for floating first-letters)
3412         pseudoStyle->setDisplay( pseudoStyle->isFloating() ? BLOCK : INLINE);
3413         pseudoStyle->setPosition( StaticPosition ); // CSS2 says first-letter can't be positioned.
3414         
3415         RenderObject* firstLetter = RenderFlow::createAnonymousFlow(document(), pseudoStyle); // anonymous box
3416         // FIXME: This adds in the wrong place if list markers were skipped above.  Should be
3417         // firstLetterContainer->addChild(firstLetter, currChild);
3418         firstLetterContainer->addChild(firstLetter, firstLetterContainer->firstChild());
3419         
3420         // The original string is going to be either a generated content string or a DOM node's
3421         // string.  We want the original string before it got transformed in case first-letter has
3422         // no text-transform or a different text-transform applied to it.
3423         RefPtr<StringImpl> oldText = textObj->originalString();
3424         KHTMLAssert(oldText);
3425         
3426         if (oldText && oldText->length() > 0) {
3427             unsigned int length = 0;
3428             
3429             // account for leading spaces and punctuation
3430             while (length < oldText->length() && (QChar((*oldText)[length]).isSpace() || u_ispunct((*oldText)[length])))
3431                 length++;
3432             
3433             // account for first letter
3434             length++;
3435             
3436             // construct text fragment for the text after the first letter
3437             // NOTE: this might empty
3438             RenderTextFragment* remainingText = 
3439                 new (renderArena()) RenderTextFragment(textObj->node(), oldText.get(), length, oldText->length() - length, firstLetter);
3440             remainingText->setStyle(textObj->style());
3441             if (remainingText->element())
3442                 remainingText->element()->setRenderer(remainingText);
3443             
3444             RenderObject* nextObj = textObj->nextSibling();
3445             firstLetterContainer->removeChild(textObj);
3446             firstLetterContainer->addChild(remainingText, nextObj);
3447             
3448             // construct text fragment for the first letter
3449             RenderTextFragment* letter = 
3450                 new (renderArena()) RenderTextFragment(remainingText->node(), oldText.get(), 0, length);
3451             RenderStyle* newStyle = new (renderArena()) RenderStyle();
3452             newStyle->inheritFrom(pseudoStyle);
3453             letter->setStyle(newStyle);
3454             firstLetter->addChild(letter);
3455
3456             textObj->destroy();
3457         }
3458     }
3459 }
3460
3461 bool RenderBlock::inRootBlockContext() const
3462 {
3463     if (isTableCell() || isFloatingOrPositioned() || hasOverflowClip())
3464         return false;
3465     
3466     if (isRoot() || isRenderView())
3467         return true;
3468     
3469     return containingBlock()->inRootBlockContext();
3470 }
3471
3472 // Helper methods for obtaining the last line, computing line counts and heights for line counts
3473 // (crawling into blocks).
3474 static bool shouldCheckLines(RenderObject* obj)
3475 {
3476     return !obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn() &&
3477             obj->isBlockFlow() && obj->style()->height().isAuto() &&
3478             (!obj->isFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
3479 }
3480
3481 static RootInlineBox* getLineAtIndex(RenderBlock* block, int i, int& count)
3482 {
3483     if (block->style()->visibility() == VISIBLE) {
3484         if (block->childrenInline()) {
3485             for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
3486                 if (count++ == i)
3487                     return box;
3488             }
3489         }
3490         else {
3491             for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
3492                 if (shouldCheckLines(obj)) {
3493                     RootInlineBox *box = getLineAtIndex(static_cast<RenderBlock*>(obj), i, count);
3494                     if (box)
3495                         return box;
3496                 }
3497             }
3498         }
3499     }
3500     return 0;
3501 }
3502
3503 int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom, int& count)
3504 {
3505     if (block->style()->visibility() == VISIBLE) {
3506         if (block->childrenInline()) {
3507             for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
3508                 if (++count == l)
3509                     return box->bottomOverflow() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
3510             }
3511         }
3512         else {
3513             RenderObject* normalFlowChildWithoutLines = 0;
3514             for (RenderObject* obj = block->firstChild(); obj; obj = obj->nextSibling()) {
3515                 if (shouldCheckLines(obj)) {
3516                     int result = getHeightForLineCount(static_cast<RenderBlock*>(obj), l, false, count);
3517                     if (result != -1)
3518                         return result + obj->yPos() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
3519                 }
3520                 else if (!obj->isFloatingOrPositioned() && !obj->isCompact() && !obj->isRunIn())
3521                     normalFlowChildWithoutLines = obj;
3522             }
3523             if (normalFlowChildWithoutLines && l == 0)
3524                 return normalFlowChildWithoutLines->yPos() + normalFlowChildWithoutLines->height();
3525         }
3526     }
3527     
3528     return -1;
3529 }
3530
3531 RootInlineBox* RenderBlock::lineAtIndex(int i)
3532 {
3533     int count = 0;
3534     return getLineAtIndex(this, i, count);
3535 }
3536
3537 int RenderBlock::lineCount()
3538 {
3539     int count = 0;
3540     if (style()->visibility() == VISIBLE) {
3541         if (childrenInline())
3542             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
3543                 count++;
3544         else
3545             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
3546                 if (shouldCheckLines(obj))
3547                     count += static_cast<RenderBlock*>(obj)->lineCount();
3548     }
3549     return count;
3550 }
3551
3552 int RenderBlock::heightForLineCount(int l)
3553 {
3554     int count = 0;
3555     return getHeightForLineCount(this, l, true, count);
3556 }
3557
3558 void RenderBlock::clearTruncation()
3559 {
3560     if (style()->visibility() == VISIBLE) {
3561         if (childrenInline() && hasMarkupTruncation()) {
3562             setHasMarkupTruncation(false);
3563             for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
3564                 box->clearTruncation();
3565         }
3566         else
3567             for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
3568                 if (shouldCheckLines(obj))
3569                     static_cast<RenderBlock*>(obj)->clearTruncation();
3570     }
3571 }
3572
3573 const char *RenderBlock::renderName() const
3574 {
3575     if (isBody())
3576         return "RenderBody"; // FIXME: Temporary hack until we know that the regression tests pass.
3577     
3578     if (isFloating())
3579         return "RenderBlock (floating)";
3580     if (isPositioned())
3581         return "RenderBlock (positioned)";
3582     if (isAnonymousBlock())
3583         return "RenderBlock (anonymous)";
3584     else if (isAnonymous())
3585         return "RenderBlock (generated)";
3586     if (isRelPositioned())
3587         return "RenderBlock (relative positioned)";
3588     if (isCompact())
3589         return "RenderBlock (compact)";
3590     if (isRunIn())
3591         return "RenderBlock (run-in)";
3592     return "RenderBlock";
3593 }
3594
3595 #ifndef NDEBUG
3596
3597 void RenderBlock::dump(QTextStream *stream, DeprecatedString ind) const
3598 {
3599     if (m_childrenInline) { *stream << " childrenInline"; }
3600     if (m_firstLine) { *stream << " firstLine"; }
3601
3602     if (m_floatingObjects && !m_floatingObjects->isEmpty())
3603     {
3604         *stream << " special(";
3605         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
3606         FloatingObject *r;
3607         bool first = true;
3608         for ( ; (r = it.current()); ++it )
3609         {
3610             if (!first)
3611                 *stream << ",";
3612             *stream << r->node->renderName();
3613             first = false;
3614         }
3615         *stream << ")";
3616     }
3617
3618     // ### EClear m_clearStatus
3619
3620     RenderFlow::dump(stream,ind);
3621 }
3622
3623 #endif
3624
3625 } // namespace WebCore
3626