LayoutTests:
[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     return RenderFlow::positionForCoordinates(x, y);
2706 }
2707
2708 void RenderBlock::calcMinMaxWidth()
2709 {
2710     KHTMLAssert( !minMaxKnown() );
2711
2712 #ifdef DEBUG_LAYOUT
2713     kdDebug( 6040 ) << renderName() << "(RenderBlock)::calcMinMaxWidth() this=" << this << endl;
2714 #endif
2715
2716     m_minWidth = 0;
2717     m_maxWidth = 0;
2718
2719     if (childrenInline())
2720         calcInlineMinMaxWidth();
2721     else
2722         calcBlocminMaxWidth();
2723
2724     if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
2725
2726     if (!style()->autoWrap() && childrenInline()) {
2727         m_minWidth = m_maxWidth;
2728         
2729         // A horizontal marquee with inline children has no minimum width.
2730         if (m_layer && m_layer->marquee() && m_layer->marquee()->isHorizontal() && !m_layer->marquee()->isUnfurlMarquee())
2731             m_minWidth = 0;
2732     }
2733
2734     if (isTableCell()) {
2735         Length w = static_cast<RenderTableCell*>(this)->styleOrColWidth();
2736         if (w.isFixed() && w.value() > 0)
2737             m_maxWidth = max(m_minWidth, calcContentBoxWidth(w.value()));
2738     } else if (style()->width().isFixed() && style()->width().value() > 0)
2739         m_minWidth = m_maxWidth = calcContentBoxWidth(style()->width().value());
2740     
2741     if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
2742         m_maxWidth = max(m_maxWidth, calcContentBoxWidth(style()->minWidth().value()));
2743         m_minWidth = max(m_minWidth, calcContentBoxWidth(style()->minWidth().value()));
2744     }
2745     
2746     if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
2747         m_maxWidth = min(m_maxWidth, calcContentBoxWidth(style()->maxWidth().value()));
2748         m_minWidth = min(m_minWidth, calcContentBoxWidth(style()->maxWidth().value()));
2749     }
2750
2751     int toAdd = 0;
2752     toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
2753
2754     m_minWidth += toAdd;
2755     m_maxWidth += toAdd;
2756
2757     setMinMaxKnown();
2758
2759     //kdDebug( 6040 ) << "Text::calcMinMaxWidth(" << this << "): min = " << m_minWidth << " max = " << m_maxWidth << endl;
2760 }
2761
2762 struct InlineMinMaxIterator
2763 {
2764 /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
2765    inline min/max width calculations.  Note the following about the way it walks:
2766    (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
2767    (2) We do not drill into the children of floats or replaced elements, since you can't break
2768        in the middle of such an element.
2769    (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
2770        distinct borders/margin/padding that contribute to the min/max width.
2771 */
2772     RenderObject* parent;
2773     RenderObject* current;
2774     bool endOfInline;
2775
2776     InlineMinMaxIterator(RenderObject* p, RenderObject* o, bool end = false)
2777         :parent(p), current(o), endOfInline(end) {}
2778
2779     RenderObject* next();
2780 };
2781
2782 RenderObject* InlineMinMaxIterator::next()
2783 {
2784     RenderObject* result = 0;
2785     bool oldEndOfInline = endOfInline;
2786     endOfInline = false;
2787     while (current != 0 || (current == parent))
2788     {
2789         //kdDebug( 6040 ) << "current = " << current << endl;
2790         if (!oldEndOfInline &&
2791             (current == parent ||
2792              (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
2793             result = current->firstChild();
2794         if (!result) {
2795             // We hit the end of our inline. (It was empty, e.g., <span></span>.)
2796             if (!oldEndOfInline && current->isInlineFlow()) {
2797                 result = current;
2798                 endOfInline = true;
2799                 break;
2800             }
2801
2802             while (current && current != parent) {
2803                 result = current->nextSibling();
2804                 if (result) break;
2805                 current = current->parent();
2806                 if (current && current != parent && current->isInlineFlow()) {
2807                     result = current;
2808                     endOfInline = true;
2809                     break;
2810                 }
2811             }
2812         }
2813
2814         if (!result) break;
2815
2816         if (!result->isPositioned() && (result->isText() || result->isBR() ||
2817             result->isFloating() || result->isReplaced() ||
2818             result->isInlineFlow()))
2819             break;
2820         
2821         current = result;
2822         result = 0;
2823     }
2824
2825     // Update our position.
2826     current = result;
2827     return current;
2828 }
2829
2830 static int getBPMWidth(int childValue, Length cssUnit)
2831 {
2832     if (cssUnit.type() != Auto)
2833         return (cssUnit.isFixed() ? cssUnit.value() : childValue);
2834     return 0;
2835 }
2836
2837 static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
2838 {
2839     RenderStyle* cstyle = child->style();
2840     int result = 0;
2841     bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
2842     result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
2843                           (leftSide ? cstyle->marginLeft() :
2844                                       cstyle->marginRight()));
2845     result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
2846                           (leftSide ? cstyle->paddingLeft() :
2847                                       cstyle->paddingRight()));
2848     result += leftSide ? child->borderLeft() : child->borderRight();
2849     return result;
2850 }
2851
2852 static inline void stripTrailingSpace(int& inlineMax, int& inlineMin,
2853                                       RenderObject* trailingSpaceChild)
2854 {
2855     if (trailingSpaceChild && trailingSpaceChild->isText()) {
2856         // Collapse away the trailing space at the end of a block.
2857         RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
2858         const Font *f = t->font(false);  // FIXME: Why are we ignoring first-line?
2859         const UChar space = ' ';
2860         int spaceWidth = f->width(TextRun(&space, 1));
2861         inlineMax -= spaceWidth;
2862         if (inlineMin > inlineMax)
2863             inlineMin = inlineMax;
2864     }
2865 }
2866
2867 void RenderBlock::calcInlineMinMaxWidth()
2868 {
2869     int inlineMax=0;
2870     int inlineMin=0;
2871
2872     int cw = containingBlock()->contentWidth();
2873
2874     // If we are at the start of a line, we want to ignore all white-space.
2875     // Also strip spaces if we previously had text that ended in a trailing space.
2876     bool stripFrontSpaces = true;
2877     RenderObject* trailingSpaceChild = 0;
2878
2879     bool autoWrap, oldAutoWrap;
2880     autoWrap = oldAutoWrap = style()->autoWrap();
2881
2882     InlineMinMaxIterator childIterator(this, this);
2883     bool addedTextIndent = false; // Only gets added in once.
2884     RenderObject* prevFloat = 0;
2885     while (RenderObject* child = childIterator.next())
2886     {
2887         autoWrap = child->style()->autoWrap();
2888
2889         if (!child->isBR()) {
2890             // Step One: determine whether or not we need to go ahead and
2891             // terminate our current line.  Each discrete chunk can become
2892             // the new min-width, if it is the widest chunk seen so far, and
2893             // it can also become the max-width.
2894
2895             // Children fall into three categories:
2896             // (1) An inline flow object.  These objects always have a min/max of 0,
2897             // and are included in the iteration solely so that their margins can
2898             // be added in.
2899             //
2900             // (2) An inline non-text non-flow object, e.g., an inline replaced element.
2901             // These objects can always be on a line by themselves, so in this situation
2902             // we need to go ahead and break the current line, and then add in our own
2903             // margins and min/max width on its own line, and then terminate the line.
2904             //
2905             // (3) A text object.  Text runs can have breakable characters at the start,
2906             // the middle or the end.  They may also lose whitespace off the front if
2907             // we're already ignoring whitespace.  In order to compute accurate min-width
2908             // information, we need three pieces of information.
2909             // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
2910             // starts with whitespace.
2911             // (b) the min-width of the last non-breakable run. Should be 0 if the text string
2912             // ends with whitespace.
2913             // (c) the min/max width of the string (trimmed for whitespace).
2914             //
2915             // If the text string starts with whitespace, then we need to go ahead and
2916             // terminate our current line (unless we're already in a whitespace stripping
2917             // mode.
2918             //
2919             // If the text string has a breakable character in the middle, but didn't start
2920             // with whitespace, then we add the width of the first non-breakable run and
2921             // then end the current line.  We then need to use the intermediate min/max width
2922             // values (if any of them are larger than our current min/max).  We then look at
2923             // the width of the last non-breakable run and use that to start a new line
2924             // (unless we end in whitespace).
2925             RenderStyle* cstyle = child->style();
2926             int childMin = 0;
2927             int childMax = 0;
2928
2929             if (!child->isText()) {
2930                 // Case (1) and (2).  Inline replaced and inline flow elements.
2931                 if (child->isInlineFlow()) {
2932                     // Add in padding/border/margin from the appropriate side of
2933                     // the element.
2934                     int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
2935                     childMin += bpm;
2936                     childMax += bpm;
2937
2938                     inlineMin += childMin;
2939                     inlineMax += childMax;
2940                 }
2941                 else {
2942                     // Inline replaced elts add in their margins to their min/max values.
2943                     int margins = 0;
2944                     Length leftMargin = cstyle->marginLeft();
2945                     Length rightMargin = cstyle->marginRight();
2946                     bool useCalculatedWidths = child->isListMarker();
2947                     if (leftMargin.isPercent() || rightMargin.isPercent() || useCalculatedWidths)
2948                         child->calcWidth();
2949                     if (useCalculatedWidths || leftMargin.isPercent())
2950                         margins += child->marginLeft();
2951                     else if (leftMargin.isFixed())
2952                         margins += leftMargin.value();
2953                     if (useCalculatedWidths || rightMargin.isPercent())
2954                         margins += child->marginRight();
2955                     else if (rightMargin.isFixed())
2956                         margins += rightMargin.value();
2957                     childMin += margins;
2958                     childMax += margins;
2959                 }
2960             }
2961
2962             if (!child->isRenderInline() && !child->isText()) {
2963                 // Case (2). Inline replaced elements and floats.
2964                 // Go ahead and terminate the current line as far as
2965                 // minwidth is concerned.
2966                 childMin += child->minWidth();
2967                 childMax += child->maxWidth();
2968
2969                 // FIXME: This isn't right.  WinIE, Opera, Mozilla all do this differently and
2970                 // treat replaced elements like characters in a word.
2971                 if (autoWrap || oldAutoWrap) {
2972                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2973                     inlineMin = 0;
2974                 }
2975
2976                 // Check our "clear" setting.  If we're supposed to clear the previous float, then
2977                 // go ahead and terminate maxwidth as well.
2978                 if (child->isFloating()) {
2979                     if (prevFloat &&
2980                         ((prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT)) ||
2981                          (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT)))) {
2982                         m_maxWidth = max(inlineMax, m_maxWidth);
2983                         inlineMax = 0;
2984                     }
2985                     prevFloat = child;
2986                 }
2987                 
2988                 // Add in text-indent.  This is added in only once.
2989                 int ti = 0;
2990                 if (!addedTextIndent) {
2991                     addedTextIndent = true;
2992                     ti = style()->textIndent().calcMinValue(cw);
2993                     childMin+=ti;
2994                     childMax+=ti;
2995                 }
2996                 
2997                 // Add our width to the max.
2998                 inlineMax += childMax;
2999
3000                 if (!autoWrap)
3001                     inlineMin += childMin;
3002                 else {
3003                     // Now check our line.
3004                     inlineMin = childMin;
3005                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3006
3007                     // Now start a new line.
3008                     inlineMin = 0;
3009                 }
3010
3011                 // We are no longer stripping whitespace at the start of
3012                 // a line.
3013                 if (!child->isFloating()) {
3014                     stripFrontSpaces = false;
3015                     trailingSpaceChild = 0;
3016                 }
3017             }
3018             else if (child->isText())
3019             {
3020                 // Case (3). Text.
3021                 RenderText* t = static_cast<RenderText *>(child);
3022
3023                 // Determine if we have a breakable character.  Pass in
3024                 // whether or not we should ignore any spaces at the front
3025                 // of the string.  If those are going to be stripped out,
3026                 // then they shouldn't be considered in the breakable char
3027                 // check.
3028                 bool hasBreakableChar, hasBreak;
3029                 int beginMin, endMin;
3030                 bool beginWS, endWS;
3031                 int beginMax, endMax;
3032                 t->trimmedMinMaxWidth(inlineMax, beginMin, beginWS, endMin, endWS,
3033                                       hasBreakableChar, hasBreak, beginMax, endMax,
3034                                       childMin, childMax, stripFrontSpaces);
3035
3036                 // This text object is insignificant and will not be rendered.  Just
3037                 // continue.
3038                 if (!hasBreak && childMax == 0) continue;
3039                 
3040                 if (stripFrontSpaces)
3041                     trailingSpaceChild = child;
3042                 else
3043                     trailingSpaceChild = 0;
3044
3045                 // Add in text-indent.  This is added in only once.
3046                 int ti = 0;
3047                 if (!addedTextIndent) {
3048                     addedTextIndent = true;
3049                     ti = style()->textIndent().calcMinValue(cw);
3050                     childMin+=ti; beginMin += ti;
3051                     childMax+=ti; beginMax += ti;
3052                 }
3053                 
3054                 // If we have no breakable characters at all,
3055                 // then this is the easy case. We add ourselves to the current
3056                 // min and max and continue.
3057                 if (!hasBreakableChar) {
3058                     inlineMin += childMin;
3059                 }
3060                 else {
3061                     // We have a breakable character.  Now we need to know if
3062                     // we start and end with whitespace.
3063                     if (beginWS) {
3064                         // Go ahead and end the current line.
3065                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3066                     }
3067                     else {
3068                         inlineMin += beginMin;
3069                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3070                         childMin -= ti;
3071                     }
3072
3073                     inlineMin = childMin;
3074
3075                     if (endWS) {
3076                         // We end in whitespace, which means we can go ahead
3077                         // and end our current line.
3078                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3079                         inlineMin = 0;
3080                     }
3081                     else {
3082                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3083                         inlineMin = endMin;
3084                     }
3085                 }
3086
3087                 if (hasBreak) {
3088                     inlineMax += beginMax;
3089                     if (m_maxWidth < inlineMax) m_maxWidth = inlineMax;
3090                     if (m_maxWidth < childMax) m_maxWidth = childMax;
3091                     inlineMax = endMax;
3092                 }
3093                 else
3094                     inlineMax += childMax;
3095             }
3096         }
3097         else
3098         {
3099             if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3100             if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
3101             inlineMin = inlineMax = 0;
3102             stripFrontSpaces = true;
3103             trailingSpaceChild = 0;
3104         }
3105
3106         oldAutoWrap = autoWrap;
3107     }
3108
3109     if (style()->collapseWhiteSpace())
3110         stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
3111     
3112     m_minWidth = max(inlineMin, m_minWidth);
3113     m_maxWidth = max(inlineMax, m_maxWidth);
3114 }
3115
3116 // Use a very large value (in effect infinite).
3117 #define BLOCK_MAX_WIDTH 15000
3118
3119 void RenderBlock::calcBlocminMaxWidth()
3120 {
3121     bool nowrap = style()->whiteSpace() == NOWRAP;
3122
3123     RenderObject *child = firstChild();
3124     int floatLeftWidth = 0, floatRightWidth = 0;
3125     while (child) {
3126         // Positioned children don't affect the min/max width
3127         if (child->isPositioned()) {
3128             child = child->nextSibling();
3129             continue;
3130         }
3131
3132         if (child->isFloating() || child->avoidsFloats()) {
3133             int floatTotalWidth = floatLeftWidth + floatRightWidth;
3134             if (child->style()->clear() & CLEFT) {
3135                 m_maxWidth = max(floatTotalWidth, m_maxWidth);
3136                 floatLeftWidth = 0;
3137             }
3138             if (child->style()->clear() & CRIGHT) {
3139                 m_maxWidth = max(floatTotalWidth, m_maxWidth);
3140                 floatRightWidth = 0;
3141             }
3142         }
3143
3144         Length ml = child->style()->marginLeft();
3145         Length mr = child->style()->marginRight();
3146
3147         // Call calcWidth on the child to ensure that our margins are
3148         // up to date.  This method can be called before the child has actually
3149         // calculated its margins (which are computed inside calcWidth).
3150         if (ml.isPercent() || mr.isPercent())
3151             calcWidth();
3152
3153         // A margin basically has three types: fixed, percentage, and auto (variable).
3154         // Auto margins simply become 0 when computing min/max width.
3155         // Fixed margins can be added in as is.
3156         // Percentage margins are computed as a percentage of the width we calculated in
3157         // the calcWidth call above.  In this case we use the actual cached margin values on
3158         // the RenderObject itself.
3159         int margin = 0, marginLeft = 0, marginRight = 0;
3160         if (ml.isFixed())
3161             marginLeft += ml.value();
3162         else if (ml.isPercent())
3163             marginLeft += child->marginLeft();
3164         if (mr.isFixed())
3165             marginRight += mr.value();
3166         else if (mr.isPercent())
3167             marginRight += child->marginRight();
3168         margin = marginLeft + marginRight;
3169
3170         int w = child->minWidth() + margin;
3171         if (m_minWidth < w) m_minWidth = w;
3172         
3173         // IE ignores tables for calculation of nowrap. Makes some sense.
3174         if (nowrap && !child->isTable() && m_maxWidth < w)
3175             m_maxWidth = w;
3176
3177         w = child->maxWidth() + margin;
3178
3179         if (!child->isFloating()) {
3180             if (child->avoidsFloats()) {
3181                 // Determine a left and right max value based off whether or not the floats can fit in the
3182                 // margins of the object.  For negative margins, we will attempt to overlap the float if the negative margin
3183                 // is smaller than the float width.
3184                 int maxLeft = marginLeft > 0 ? max(floatLeftWidth, marginLeft) : floatLeftWidth + marginLeft;
3185                 int maxRight = marginRight > 0 ? max(floatRightWidth, marginRight) : floatRightWidth + marginRight;
3186                 w = child->maxWidth() + maxLeft + maxRight;
3187                 w = max(w, floatLeftWidth + floatRightWidth);
3188             }
3189             else
3190                 m_maxWidth = max(floatLeftWidth + floatRightWidth, m_maxWidth);
3191             floatLeftWidth = floatRightWidth = 0;
3192         }
3193         
3194         if (child->isFloating()) {
3195             if (style()->floating() == FLEFT)
3196                 floatLeftWidth += w;
3197             else
3198                 floatRightWidth += w;
3199         }
3200         else if (m_maxWidth < w)
3201             m_maxWidth = w;
3202
3203         // A very specific WinIE quirk.
3204         // Example:
3205         /*
3206            <div style="position:absolute; width:100px; top:50px;">
3207               <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
3208                 <table style="width:100%"><tr><td></table>
3209               </div>
3210            </div>
3211         */
3212         // In the above example, the inner absolute positioned block should have a computed width
3213         // of 100px because of the table.
3214         // We can achieve this effect by making the maxwidth of blocks that contain tables
3215         // with percentage widths be infinite (as long as they are not inside a table cell).
3216         if (style()->htmlHacks() && child->style()->width().isPercent() &&
3217             !isTableCell() && child->isTable() && m_maxWidth < BLOCK_MAX_WIDTH) {
3218             RenderBlock* cb = containingBlock();
3219             while (!cb->isRenderView() && !cb->isTableCell())
3220                 cb = cb->containingBlock();
3221             if (!cb->isTableCell())
3222                 m_maxWidth = BLOCK_MAX_WIDTH;
3223         }
3224         
3225         child = child->nextSibling();
3226     }
3227
3228     // Always make sure these values are non-negative.
3229     m_minWidth = max(0, m_minWidth);
3230     m_maxWidth = max(0, m_maxWidth);
3231
3232     m_maxWidth = max(floatLeftWidth + floatRightWidth, m_maxWidth);
3233 }
3234
3235 bool RenderBlock::hasLineIfEmpty() const
3236 {
3237     return element() && (element()->isContentEditable() && element()->rootEditableElement() == element() ||
3238                          element()->isShadowNode() && element()->shadowParentNode()->hasTagName(inputTag));
3239 }
3240
3241 short RenderBlock::lineHeight(bool b, bool isRootLineBox) const
3242 {
3243     // Inline blocks are replaced elements. Otherwise, just pass off to
3244     // the base class.  If we're being queried as though we're the root line
3245     // box, then the fact that we're an inline-block is irrelevant, and we behave
3246     // just like a block.
3247     if (isReplaced() && !isRootLineBox)
3248         return height()+marginTop()+marginBottom();
3249     return RenderFlow::lineHeight(b, isRootLineBox);
3250 }
3251
3252 short RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
3253 {
3254     // Inline blocks are replaced elements. Otherwise, just pass off to
3255     // the base class.  If we're being queried as though we're the root line
3256     // box, then the fact that we're an inline-block is irrelevant, and we behave
3257     // just like a block.
3258     if (isReplaced() && !isRootLineBox) {
3259         // For "leaf" theme objects, let the theme decide what the baseline position is.
3260         // FIXME: Might be better to have a custom CSS property instead, so that if the theme
3261         // is turned off, checkboxes/radios will still have decent baselines.
3262         if (style()->hasAppearance() && !theme()->isControlContainer(style()->appearance()))
3263             return theme()->baselinePosition(this);
3264