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