Fix for 3615411, the linesAppended optimization was old and broken, and it's easier...
[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     int result = clearSet ? kMax(0, bottom - child->yPos()) : 0;
2354     if (!result && child->avoidsFloats() && child->style()->width().isFixed() && child->minWidth() > lineWidth(child->yPos()))
2355         result = kMax(0, floatBottom() - child->yPos());
2356     return result;
2357 }
2358
2359 bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
2360 {
2361     if (!scrollsOverflow())
2362         return false;
2363
2364     if (m_layer->verticalScrollbarWidth()) {
2365         QRect vertRect(_tx + width() - borderRight() - m_layer->verticalScrollbarWidth(),
2366                        _ty + borderTop(),
2367                        m_layer->verticalScrollbarWidth(),
2368                        height()-borderTop()-borderBottom());
2369         if (vertRect.contains(_x, _y)) {
2370             RenderLayer::gScrollBar = m_layer->verticalScrollbar();
2371             return true;
2372         }
2373     }
2374
2375     if (m_layer->horizontalScrollbarHeight()) {
2376         QRect horizRect(_tx + borderLeft(),
2377                         _ty + height() - borderBottom() - m_layer->horizontalScrollbarHeight(),
2378                         width()-borderLeft()-borderRight(),
2379                         m_layer->horizontalScrollbarHeight());
2380         if (horizRect.contains(_x, _y)) {
2381             RenderLayer::gScrollBar = m_layer->horizontalScrollbar();
2382             return true;
2383         }
2384     }
2385
2386     return false;    
2387 }
2388
2389 bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
2390                               HitTestAction hitTestAction)
2391 {
2392     bool inlineFlow = isInlineFlow();
2393
2394     int tx = _tx + m_x;
2395     int ty = _ty + m_y + borderTopExtra();
2396     
2397     if (!inlineFlow && !isRoot()) {
2398         // Check if we need to do anything at all.
2399         QRect overflowBox = overflowRect(false);
2400         overflowBox.setX(overflowBox.x() + tx);
2401         overflowBox.setY(overflowBox.y() + ty);
2402         bool insideOverflowBox = overflowBox.contains(_x, _y);
2403         if (!insideOverflowBox) {
2404             // Check floats next.
2405             QRect floatBox = floatRect();
2406             floatBox.setX(overflowBox.x() + tx);
2407             floatBox.setY(overflowBox.y() + ty);
2408             if (!floatBox.contains(_x, _y))
2409                 return false;
2410         }
2411     }
2412
2413     // See if we're inside the scrollbar (if we're overflow:scroll/auto).
2414     if (isPointInScrollbar(_x, _y, tx, ty)) {
2415         if (hitTestAction == HitTestBlockBackground) {
2416             setInnerNode(info);
2417             return true;
2418         }
2419         return false;
2420     }
2421
2422     // Hit test descendants first.
2423     int scrolledX = tx;
2424     int scrolledY = ty;
2425     if (hasOverflowClip())
2426         m_layer->subtractScrollOffset(scrolledX, scrolledY);
2427     if (childrenInline() && !isTable()) {
2428         // We have to hit-test our line boxes.
2429         if (hitTestLines(info, _x, _y, scrolledX, scrolledY, hitTestAction)) {
2430             setInnerNode(info);
2431             return true;
2432         }
2433     }
2434     else {
2435         // Hit test our children.
2436         HitTestAction childHitTest = hitTestAction;
2437         if (hitTestAction == HitTestChildBlockBackgrounds)
2438             childHitTest = HitTestChildBlockBackground;
2439         for (RenderObject* child = lastChild(); child; child = child->previousSibling())
2440             if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, scrolledX, scrolledY, childHitTest)) {
2441                 setInnerNode(info);
2442                 return true;
2443             }
2444     }
2445     
2446     // Hit test floats.
2447     if (hitTestAction == HitTestFloat && m_floatingObjects) {
2448         if (isCanvas()) {
2449             scrolledX += static_cast<RenderCanvas*>(this)->view()->contentsX();
2450             scrolledY += static_cast<RenderCanvas*>(this)->view()->contentsY();
2451         }
2452         
2453         FloatingObject* o;
2454         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2455         for (it.toLast(); (o = it.current()); --it)
2456             if (!o->noPaint && !o->node->layer() && o->node->hitTest(info, _x, _y,
2457                                      scrolledX + o->left + o->node->marginLeft() - o->node->xPos(),
2458                                      scrolledY + o->startY + o->node->marginTop() - o->node->yPos())) {
2459                 setInnerNode(info);
2460                 return true;
2461             }
2462     }
2463
2464     // Now hit test our background.
2465     if (!inlineFlow && (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground)) {
2466         QRect boundsRect(tx, ty, m_width, m_height);
2467         if (isRoot() || (style()->visibility() == VISIBLE && boundsRect.contains(_x, _y))) {
2468             setInnerNode(info);
2469             return true;
2470         }
2471     }
2472
2473     return false;
2474 }
2475
2476 Position RenderBlock::positionForBox(InlineBox *box, bool start) const
2477 {
2478     if (!box)
2479         return Position();
2480
2481     if (!box->object()->element())
2482         return Position(element(), start ? caretMinOffset() : caretMaxOffset());
2483
2484     if (!box->isInlineTextBox())
2485         return Position(box->object()->element(), start ? box->object()->caretMinOffset() : box->object()->caretMaxOffset());
2486
2487     InlineTextBox *textBox = static_cast<InlineTextBox *>(box);
2488     return Position(box->object()->element(), start ? textBox->start() : textBox->start() + textBox->len());
2489 }
2490
2491 Position RenderBlock::positionForRenderer(RenderObject *renderer, bool start) const
2492 {
2493     if (!renderer)
2494         return Position(element(), 0);
2495
2496     NodeImpl *node = renderer->element() ? renderer->element() : element();
2497     if (!node)
2498         return Position();
2499
2500     long offset = start ? node->caretMinOffset() : node->caretMaxOffset();
2501     return Position(node, offset);
2502 }
2503
2504 Position RenderBlock::positionForCoordinates(int _x, int _y, EAffinity *affinity)
2505 {
2506     if (affinity)
2507         *affinity = UPSTREAM;
2508
2509     if (isTable())
2510         return RenderFlow::positionForCoordinates(_x, _y, affinity); 
2511
2512     int absx, absy;
2513     absolutePosition(absx, absy);
2514
2515     int top = absy + borderTop() + paddingTop();
2516     int bottom = top + contentHeight();
2517
2518     if (_y < top)
2519         // y coordinate is above block
2520         return positionForRenderer(firstLeafChild(), true);
2521
2522     if (_y >= bottom)
2523         // y coordinate is below block
2524         return positionForRenderer(lastLeafChild(), false);
2525
2526     if (childrenInline()) {
2527         if (!firstRootBox())
2528             return Position(element(), 0);
2529             
2530         if (_y >= top && _y < absy + firstRootBox()->topOverflow())
2531             // y coordinate is above first root line box
2532             return positionForBox(firstRootBox()->firstLeafChild(), true);
2533         
2534         // look for the closest line box in the root box which is at the passed-in y coordinate
2535         for (RootInlineBox *root = firstRootBox(); root; root = root->nextRootBox()) {
2536             top = absy + root->topOverflow();
2537             // set the bottom based on whether there is a next root box
2538             if (root->nextRootBox())
2539                 bottom = absy + root->nextRootBox()->topOverflow();
2540             else
2541                 bottom = absy + root->bottomOverflow();
2542             // check if this root line box is located at this y coordinate
2543             if (_y >= top && _y < bottom && root->firstChild()) {
2544                 InlineBox *closestBox = root->closestLeafChildForXPos(_x, absx);
2545                 if (closestBox) {
2546                     // pass the box a y position that is inside it
2547                     return closestBox->object()->positionForCoordinates(_x, absy + closestBox->m_y, affinity);
2548                 }
2549             }
2550         }
2551
2552         if (lastRootBox())
2553             // y coordinate is below last root line box
2554             return positionForBox(lastRootBox()->lastLeafChild(), false);
2555         
2556         return Position(element(), 0);
2557     }
2558     
2559     // see if any child blocks exist at this y coordinate
2560     for (RenderObject *renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
2561         if (renderer->isFloatingOrPositioned())
2562             continue;
2563         renderer->absolutePosition(absx, top);
2564         RenderObject *next = renderer->nextSibling();
2565         while (next && next->isFloatingOrPositioned())
2566             next = next->nextSibling();
2567         if (next) 
2568             next->absolutePosition(absx, bottom);
2569         else
2570             bottom = top + contentHeight();
2571         if (_y >= top && _y < bottom) {
2572             return renderer->positionForCoordinates(_x, _y, affinity);
2573         }
2574     }
2575
2576     // pass along to the first child
2577     if (firstChild())
2578         return firstChild()->positionForCoordinates(_x, _y, affinity);
2579     
2580     // still no luck...return this render object's element and offset 0
2581     return Position(element(), 0);
2582 }
2583
2584 void RenderBlock::calcMinMaxWidth()
2585 {
2586     KHTMLAssert( !minMaxKnown() );
2587
2588 #ifdef DEBUG_LAYOUT
2589     kdDebug( 6040 ) << renderName() << "(RenderBlock)::calcMinMaxWidth() this=" << this << endl;
2590 #endif
2591
2592     m_minWidth = 0;
2593     m_maxWidth = 0;
2594
2595     bool preOrNowrap = style()->whiteSpace() != NORMAL;
2596     if (childrenInline())
2597         calcInlineMinMaxWidth();
2598     else
2599         calcBlockMinMaxWidth();
2600
2601     if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
2602
2603     if (preOrNowrap && childrenInline()) {
2604         m_minWidth = m_maxWidth;
2605         
2606         // A horizontal marquee with inline children has no minimum width.
2607         if (style()->overflow() == OMARQUEE && m_layer && m_layer->marquee() && 
2608             m_layer->marquee()->isHorizontal() && !m_layer->marquee()->isUnfurlMarquee())
2609             m_minWidth = 0;
2610     }
2611
2612     if (style()->width().isFixed() && style()->width().value > 0) {
2613         if (isTableCell())
2614             m_maxWidth = KMAX(m_minWidth, style()->width().value);
2615         else
2616             m_minWidth = m_maxWidth = style()->width().value;
2617     }
2618     
2619     if (style()->minWidth().isFixed() && style()->minWidth().value > 0) {
2620         m_maxWidth = KMAX(m_maxWidth, style()->minWidth().value);
2621         m_minWidth = KMAX(m_minWidth, style()->minWidth().value);
2622     }
2623     
2624     if (style()->maxWidth().isFixed() && style()->maxWidth().value != UNDEFINED) {
2625         m_maxWidth = KMIN(m_maxWidth, style()->maxWidth().value);
2626         m_minWidth = KMIN(m_minWidth, style()->maxWidth().value);
2627     }
2628
2629     int toAdd = 0;
2630     toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
2631
2632     m_minWidth += toAdd;
2633     m_maxWidth += toAdd;
2634
2635     setMinMaxKnown();
2636
2637     //kdDebug( 6040 ) << "Text::calcMinMaxWidth(" << this << "): min = " << m_minWidth << " max = " << m_maxWidth << endl;
2638 }
2639
2640 struct InlineMinMaxIterator
2641 {
2642 /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
2643    inline min/max width calculations.  Note the following about the way it walks:
2644    (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
2645    (2) We do not drill into the children of floats or replaced elements, since you can't break
2646        in the middle of such an element.
2647    (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
2648        distinct borders/margin/padding that contribute to the min/max width.
2649 */
2650     RenderObject* parent;
2651     RenderObject* current;
2652     bool endOfInline;
2653
2654     InlineMinMaxIterator(RenderObject* p, RenderObject* o, bool end = false)
2655         :parent(p), current(o), endOfInline(end) {}
2656
2657     RenderObject* next();
2658 };
2659
2660 RenderObject* InlineMinMaxIterator::next()
2661 {
2662     RenderObject* result = 0;
2663     bool oldEndOfInline = endOfInline;
2664     endOfInline = false;
2665     while (current != 0 || (current == parent))
2666     {
2667         //kdDebug( 6040 ) << "current = " << current << endl;
2668         if (!oldEndOfInline &&
2669             (current == parent ||
2670              (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
2671             result = current->firstChild();
2672         if (!result) {
2673             // We hit the end of our inline. (It was empty, e.g., <span></span>.)
2674             if (!oldEndOfInline && current->isInlineFlow()) {
2675                 result = current;
2676                 endOfInline = true;
2677                 break;
2678             }
2679
2680             while (current && current != parent) {
2681                 result = current->nextSibling();
2682                 if (result) break;
2683                 current = current->parent();
2684                 if (current && current != parent && current->isInlineFlow()) {
2685                     result = current;
2686                     endOfInline = true;
2687                     break;
2688                 }
2689             }
2690         }
2691
2692         if (!result) break;
2693
2694         if (!result->isPositioned() && (result->isText() || result->isBR() ||
2695             result->isFloating() || result->isReplaced() ||
2696             result->isInlineFlow()))
2697             break;
2698         
2699         current = result;
2700         result = 0;
2701     }
2702
2703     // Update our position.
2704     current = result;
2705     return current;
2706 }
2707
2708 static int getBPMWidth(int childValue, Length cssUnit)
2709 {
2710     if (cssUnit.type != Variable)
2711         return (cssUnit.type == Fixed ? cssUnit.value : childValue);
2712     return 0;
2713 }
2714
2715 static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
2716 {
2717     RenderStyle* cstyle = child->style();
2718     int result = 0;
2719     bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
2720     result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
2721                           (leftSide ? cstyle->marginLeft() :
2722                                       cstyle->marginRight()));
2723     result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
2724                           (leftSide ? cstyle->paddingLeft() :
2725                                       cstyle->paddingRight()));
2726     result += leftSide ? child->borderLeft() : child->borderRight();
2727     return result;
2728 }
2729
2730 static void stripTrailingSpace(bool pre,
2731                                int& inlineMax, int& inlineMin,
2732                                RenderObject* trailingSpaceChild)
2733 {
2734     if (!pre && trailingSpaceChild && trailingSpaceChild->isText()) {
2735         // Collapse away the trailing space at the end of a block.
2736         RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
2737         const Font *f = t->htmlFont( false );
2738         QChar space[1]; space[0] = ' ';
2739         int spaceWidth = f->width(space, 1, 0);
2740         inlineMax -= spaceWidth;
2741         if (inlineMin > inlineMax)
2742             inlineMin = inlineMax;
2743     }
2744 }
2745
2746 void RenderBlock::calcInlineMinMaxWidth()
2747 {
2748     int inlineMax=0;
2749     int inlineMin=0;
2750
2751     int cw = containingBlock()->contentWidth();
2752
2753     // If we are at the start of a line, we want to ignore all white-space.
2754     // Also strip spaces if we previously had text that ended in a trailing space.
2755     bool stripFrontSpaces = true;
2756     RenderObject* trailingSpaceChild = 0;
2757
2758     bool normal, oldnormal;
2759     normal = oldnormal = style()->whiteSpace() == NORMAL;
2760
2761     InlineMinMaxIterator childIterator(this, this);
2762     bool addedTextIndent = false; // Only gets added in once.
2763     RenderObject* prevFloat = 0;
2764     while (RenderObject* child = childIterator.next())
2765     {
2766         normal = child->style()->whiteSpace() == NORMAL;
2767
2768         if (!child->isBR()) {
2769             // Step One: determine whether or not we need to go ahead and
2770             // terminate our current line.  Each discrete chunk can become
2771             // the new min-width, if it is the widest chunk seen so far, and
2772             // it can also become the max-width.
2773
2774             // Children fall into three categories:
2775             // (1) An inline flow object.  These objects always have a min/max of 0,
2776             // and are included in the iteration solely so that their margins can
2777             // be added in.
2778             //
2779             // (2) An inline non-text non-flow object, e.g., an inline replaced element.
2780             // These objects can always be on a line by themselves, so in this situation
2781             // we need to go ahead and break the current line, and then add in our own
2782             // margins and min/max width on its own line, and then terminate the line.
2783             //
2784             // (3) A text object.  Text runs can have breakable characters at the start,
2785             // the middle or the end.  They may also lose whitespace off the front if
2786             // we're already ignoring whitespace.  In order to compute accurate min-width
2787             // information, we need three pieces of information.
2788             // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
2789             // starts with whitespace.
2790             // (b) the min-width of the last non-breakable run. Should be 0 if the text string
2791             // ends with whitespace.
2792             // (c) the min/max width of the string (trimmed for whitespace).
2793             //
2794             // If the text string starts with whitespace, then we need to go ahead and
2795             // terminate our current line (unless we're already in a whitespace stripping
2796             // mode.
2797             //
2798             // If the text string has a breakable character in the middle, but didn't start
2799             // with whitespace, then we add the width of the first non-breakable run and
2800             // then end the current line.  We then need to use the intermediate min/max width
2801             // values (if any of them are larger than our current min/max).  We then look at
2802             // the width of the last non-breakable run and use that to start a new line
2803             // (unless we end in whitespace).
2804             RenderStyle* cstyle = child->style();
2805             int childMin = 0;
2806             int childMax = 0;
2807
2808             if (!child->isText()) {
2809                 // Case (1) and (2).  Inline replaced and inline flow elements.
2810                 if (child->isInlineFlow()) {
2811                     // Add in padding/border/margin from the appropriate side of
2812                     // the element.
2813                     int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
2814                     childMin += bpm;
2815                     childMax += bpm;
2816
2817                     inlineMin += childMin;
2818                     inlineMax += childMax;
2819                 }
2820                 else {
2821                     // Inline replaced elts add in their margins to their min/max values.
2822                     int margins = 0;
2823                     LengthType type = cstyle->marginLeft().type;
2824                     if ( type != Variable )
2825                         margins += (type == Fixed ? cstyle->marginLeft().value : child->marginLeft());
2826                     type = cstyle->marginRight().type;
2827                     if ( type != Variable )
2828                         margins += (type == Fixed ? cstyle->marginRight().value : child->marginRight());
2829                     childMin += margins;
2830                     childMax += margins;
2831                 }
2832             }
2833
2834             if (!child->isRenderInline() && !child->isText()) {
2835                 // Case (2). Inline replaced elements and floats.
2836                 // Go ahead and terminate the current line as far as
2837                 // minwidth is concerned.
2838                 childMin += child->minWidth();
2839                 childMax += child->maxWidth();
2840
2841                 if (normal || oldnormal) {
2842                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2843                     inlineMin = 0;
2844                 }
2845
2846                 // Check our "clear" setting.  If we're supposed to clear the previous float, then
2847                 // go ahead and terminate maxwidth as well.
2848                 if (child->isFloating()) {
2849                     if (prevFloat &&
2850                         ((prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT)) ||
2851                          (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT)))) {
2852                         m_maxWidth = kMax(inlineMax, m_maxWidth);
2853                         inlineMax = 0;
2854                     }
2855                     prevFloat = child;
2856                 }
2857                 
2858                 // Add in text-indent.  This is added in only once.
2859                 int ti = 0;
2860                 if (!addedTextIndent) {
2861                     addedTextIndent = true;
2862                     ti = style()->textIndent().minWidth(cw);
2863                     childMin+=ti;
2864                     childMax+=ti;
2865                 }
2866                 
2867                 // Add our width to the max.
2868                 inlineMax += childMax;
2869
2870                 if (!normal)
2871                     inlineMin += childMin;
2872                 else {
2873                     // Now check our line.
2874                     inlineMin = childMin;
2875                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2876
2877                     // Now start a new line.
2878                     inlineMin = 0;
2879                 }
2880
2881                 // We are no longer stripping whitespace at the start of
2882                 // a line.
2883                 if (!child->isFloating()) {
2884                     stripFrontSpaces = false;
2885                     trailingSpaceChild = 0;
2886                 }
2887             }
2888             else if (child->isText())
2889             {
2890                 // Case (3). Text.
2891                 RenderText* t = static_cast<RenderText *>(child);
2892
2893                 // Determine if we have a breakable character.  Pass in
2894                 // whether or not we should ignore any spaces at the front
2895                 // of the string.  If those are going to be stripped out,
2896                 // then they shouldn't be considered in the breakable char
2897                 // check.
2898                 bool hasBreakableChar, hasBreak;
2899                 int beginMin, endMin;
2900                 bool beginWS, endWS;
2901                 int beginMax, endMax;
2902                 t->trimmedMinMaxWidth(beginMin, beginWS, endMin, endWS, hasBreakableChar,
2903                                       hasBreak, beginMax, endMax,
2904                                       childMin, childMax, stripFrontSpaces);
2905
2906                 // This text object is insignificant and will not be rendered.  Just
2907                 // continue.
2908                 if (!hasBreak && childMax == 0) continue;
2909                 
2910                 if (stripFrontSpaces)
2911                     trailingSpaceChild = child;
2912                 else
2913                     trailingSpaceChild = 0;
2914
2915                 // Add in text-indent.  This is added in only once.
2916                 int ti = 0;
2917                 if (!addedTextIndent) {
2918                     addedTextIndent = true;
2919                     ti = style()->textIndent().minWidth(cw);
2920                     childMin+=ti; beginMin += ti;
2921                     childMax+=ti; beginMax += ti;
2922                 }
2923                 
2924                 // If we have no breakable characters at all,
2925                 // then this is the easy case. We add ourselves to the current
2926                 // min and max and continue.
2927                 if (!hasBreakableChar) {
2928                     inlineMin += childMin;
2929                 }
2930                 else {
2931                     // We have a breakable character.  Now we need to know if
2932                     // we start and end with whitespace.
2933                     if (beginWS) {
2934                         // Go ahead and end the current line.
2935                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2936                     }
2937                     else {
2938                         inlineMin += beginMin;
2939                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2940                         childMin -= ti;
2941                     }
2942
2943                     inlineMin = childMin;
2944
2945                     if (endWS) {
2946                         // We end in whitespace, which means we can go ahead
2947                         // and end our current line.
2948                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2949                         inlineMin = 0;
2950                     }
2951                     else {
2952                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2953                         inlineMin = endMin;
2954                     }
2955                 }
2956
2957                 if (hasBreak) {
2958                     inlineMax += beginMax;
2959                     if (m_maxWidth < inlineMax) m_maxWidth = inlineMax;
2960                     if (m_maxWidth < childMax) m_maxWidth = childMax;
2961                     inlineMax = endMax;
2962                 }
2963                 else
2964                     inlineMax += childMax;
2965             }
2966         }
2967         else
2968         {
2969             if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2970             if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
2971             inlineMin = inlineMax = 0;
2972             stripFrontSpaces = true;
2973             trailingSpaceChild = 0;
2974         }
2975
2976         oldnormal = normal;
2977     }
2978
2979     stripTrailingSpace(m_pre, inlineMax, inlineMin, trailingSpaceChild);
2980     
2981     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2982     if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
2983
2984     //         kdDebug( 6040 ) << "m_minWidth=" << m_minWidth
2985     //                  << " m_maxWidth=" << m_maxWidth << endl;
2986 }
2987
2988 // Use a very large value (in effect infinite).
2989 #define BLOCK_MAX_WIDTH 15000
2990
2991 void RenderBlock::calcBlockMinMaxWidth()
2992 {
2993     bool nowrap = style()->whiteSpace() == NOWRAP;
2994
2995     RenderObject *child = firstChild();
2996     int floatLeftWidth = 0, floatRightWidth = 0;
2997     while (child) {
2998         // Positioned children don't affect the min/max width
2999         if (child->isPositioned()) {
3000             child = child->nextSibling();
3001             continue;
3002         }
3003
3004         if (child->isFloating() || child->avoidsFloats()) {
3005             int floatTotalWidth = floatLeftWidth + floatRightWidth;
3006             if (child->style()->clear() & CLEFT) {
3007                 m_maxWidth = kMax(floatTotalWidth, m_maxWidth);
3008                 floatLeftWidth = 0;
3009             }
3010             if (child->style()->clear() & CRIGHT) {
3011                 m_maxWidth = kMax(floatTotalWidth, m_maxWidth);
3012                 floatRightWidth = 0;
3013             }
3014         }
3015
3016         Length ml = child->style()->marginLeft();
3017         Length mr = child->style()->marginRight();
3018
3019         // Call calcWidth on the child to ensure that our margins are
3020         // up to date.  This method can be called before the child has actually
3021         // calculated its margins (which are computed inside calcWidth).
3022         if (ml.type == Percent || mr.type == Percent)
3023             calcWidth();
3024
3025         // A margin basically has three types: fixed, percentage, and auto (variable).
3026         // Auto margins simply become 0 when computing min/max width.
3027         // Fixed margins can be added in as is.
3028         // Percentage margins are computed as a percentage of the width we calculated in
3029         // the calcWidth call above.  In this case we use the actual cached margin values on
3030         // the RenderObject itself.
3031         int margin = 0, marginLeft = 0, marginRight = 0;
3032         if (ml.type == Fixed)
3033             marginLeft += ml.value;
3034         else if (ml.type == Percent)
3035             marginLeft += child->marginLeft();
3036         marginLeft = kMax(0, marginLeft);
3037         if (mr.type == Fixed)
3038             marginRight += mr.value;
3039         else if (mr.type == Percent)
3040             marginRight += child->marginRight();
3041         marginRight = kMax(0, marginRight);
3042         margin = marginLeft + marginRight;
3043
3044         int w = child->minWidth() + margin;
3045         if (m_minWidth < w) m_minWidth = w;
3046         
3047         // IE ignores tables for calculation of nowrap. Makes some sense.
3048         if (nowrap && !child->isTable() && m_maxWidth < w)
3049             m_maxWidth = w;
3050
3051         w = child->maxWidth() + margin;
3052
3053         if (!child->isFloating()) {
3054             if (child->avoidsFloats()) {
3055                 // Determine a left and right max value based off whether or not the floats can fit in the
3056                 // margins of the object.
3057                 int maxLeft = kMax(floatLeftWidth, marginLeft);
3058                 int maxRight = kMax(floatRightWidth, marginRight);
3059                 w = child->maxWidth() + maxLeft + maxRight;
3060             }
3061             else
3062                 m_maxWidth = kMax(floatLeftWidth + floatRightWidth, m_maxWidth);
3063             floatLeftWidth = floatRightWidth = 0;
3064         }
3065         
3066         if (child->isFloating()) {
3067             if (style()->floating() == FLEFT)
3068                 floatLeftWidth += w;
3069             else
3070                 floatRightWidth += w;
3071         }
3072         else if (m_maxWidth < w)
3073             m_maxWidth = w;
3074
3075         // A very specific WinIE quirk.
3076         // Example:
3077         /*
3078            <div style="position:absolute; width:100px; top:50px;">
3079               <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
3080                 <table style="width:100%"><tr><td></table>
3081               </div>
3082            </div>
3083         */
3084         // In the above example, the inner absolute positioned block should have a computed width
3085         // of 100px because of the table.
3086         // We can achieve this effect by making the maxwidth of blocks that contain tables
3087         // with percentage widths be infinite (as long as they are not inside a table cell).
3088         if (style()->htmlHacks() && child->style()->width().type == Percent &&
3089             !isTableCell() && child->isTable() && m_maxWidth < BLOCK_MAX_WIDTH) {
3090             RenderBlock* cb = containingBlock();
3091             while (!cb->isCanvas() && !cb->isTableCell())
3092                 cb = cb->containingBlock();
3093             if (!cb->isTableCell())
3094                 m_maxWidth = BLOCK_MAX_WIDTH;
3095         }
3096         
3097         child = child->nextSibling();
3098     }
3099     
3100     m_maxWidth = kMax(floatLeftWidth + floatRightWidth, m_maxWidth);
3101 }
3102
3103 short RenderBlock::lineHeight(bool b, bool isRootLineBox) const
3104 {
3105     // Inline blocks are replaced elements. Otherwise, just pass off to
3106     // the base class.  If we're being queried as though we're the root line
3107     // box, then the fact that we're an inline-block is irrelevant, and we behave
3108     // just like a block.
3109     if (isReplaced() && !isRootLineBox)
3110         return height()+marginTop()+marginBottom();
3111     return RenderFlow::lineHeight(b, isRootLineBox);
3112 }
3113
3114 short RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
3115 {
3116     // Inline blocks are replaced elements. Otherwise, just pass off to
3117     // the base class.  If we're being queried as though we're the root line
3118     // box, then the fact that we're an inline-block is irrelevant, and we behave
3119     // just like a block.
3120     if (isReplaced() && !isRootLineBox)
3121         return height() + marginTop() + marginBottom();
3122     return RenderFlow::baselinePosition(b, isRootLineBox);
3123 }
3124
3125 int RenderBlock::getBaselineOfFirstLineBox() const
3126 {
3127     if (!isBlockFlow())
3128         return RenderFlow::getBaselineOfFirstLineBox();
3129
3130     if (childrenInline()) {
3131         if (m_firstLineBox)
3132             return m_firstLineBox->yPos() + m_firstLineBox->baseline();
3133         else
3134             return -1;
3135     }
3136     else {
3137         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
3138             if (!curr->isFloatingOrPositioned()) {
3139                 int result = curr->getBaselineOfFirstLineBox();
3140                 if (result != -1)
3141                     return curr->yPos() + result; // Translate to our coordinate space.
3142             }
3143         }
3144     }
3145
3146     return -1;
3147 }
3148
3149 RenderBlock* RenderBlock::firstLineBlock() const
3150 {
3151     const RenderObject* firstLineBlock = this;
3152     bool hasPseudo = false;
3153     while (true) {
3154         hasPseudo = firstLineBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LINE);
3155         if (hasPseudo)
3156             break;
3157         RenderObject* parentBlock = firstLineBlock->parent();
3158         if (firstLineBlock->isReplaced() || firstLineBlock->isFloating() || 
3159             !parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow())
3160             break;
3161         firstLineBlock = parentBlock;
3162     } 
3163     
3164     if (!hasPseudo)
3165         return 0;
3166     
3167     return (RenderBlock*)(firstLineBlock);
3168 }
3169
3170 void RenderBlock::updateFirstLetter()
3171 {
3172     // FIXME: We need to destroy the first-letter object if it is no longer the first child.  Need to find
3173     // an efficient way to check for that situation though before implementing anything.
3174     RenderObject* firstLetterBlock = this;
3175     bool hasPseudoStyle = false;
3176     while (true) {
3177         hasPseudoStyle = firstLetterBlock->style()->hasPseudoStyle(RenderStyle::FIRST_LETTER);
3178         if (hasPseudoStyle)
3179             break;
3180         RenderObject* parentBlock = firstLetterBlock->parent();
3181         if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock || 
3182             !parentBlock->isBlockFlow())
3183             break;
3184         firstLetterBlock = parentBlock;
3185     } 
3186
3187     if (!hasPseudoStyle)
3188         return;
3189     
3190     // Drill into inlines looking for our first text child.
3191     RenderObject* currChild = firstLetterBlock->firstChild();
3192     while (currChild && currChild->needsLayout() && !currChild->isReplaced() && !currChild->isText())
3193         currChild = currChild->firstChild();
3194     
3195     if (currChild && currChild->isText() && !currChild->isBR() && 
3196         currChild->parent()->style()->styleType() != RenderStyle::FIRST_LETTER) {
3197         RenderObject* firstLetterContainer = currChild->parent();
3198         if (!firstLetterContainer)
3199             firstLetterContainer = this;
3200         
3201         RenderText* textObj = static_cast<RenderText*>(currChild);
3202         
3203         // Create our pseudo style now that we have our firstLetterContainer determined.
3204         RenderStyle* pseudoStyle = firstLetterBlock->getPseudoStyle(RenderStyle::FIRST_LETTER,
3205                                                                     firstLetterContainer->style(true));
3206         
3207         // Force inline display (except for floating first-letters)