Fix for 3992440, text not wrapping correctly on half moon bay web site. Refine...
[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         if (!child->avoidsFloats() || child->usesLineWidth()) {
1051             int fb = floatBottom();
1052             if (fb > m_height || fb > yPosEstimate)
1053                 child->setChildNeedsLayout(true);
1054         }
1055
1056         // Cache our old position so that we can dirty the proper repaint rects if the child moves.
1057         int oldChildX = child->xPos();
1058         int oldChildY = child->yPos();
1059         
1060         // Go ahead and position the child as though it didn't collapse with the top.
1061         child->setPos(child->xPos(), yPosEstimate);
1062         child->layoutIfNeeded();
1063
1064         // Now determine the correct ypos based off examination of collapsing margin
1065         // values.
1066         collapseMargins(child, marginInfo, yPosEstimate);
1067
1068         // Now check for clear.
1069         clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin);
1070
1071         // We are no longer at the top of the block if we encounter a non-empty child.  
1072         // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
1073         if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
1074             marginInfo.setAtTopOfBlock(false);
1075
1076         // Now place the child in the correct horizontal position
1077         determineHorizontalPosition(child);
1078
1079         // Update our top overflow in case the child spills out the top of the block.
1080         m_overflowTop = kMin(m_overflowTop, child->yPos() + child->overflowTop(false));
1081         
1082         // Update our height now that the child has been placed in the correct position.
1083         m_height += child->height();
1084         if (child->style()->marginBottomCollapse() == MSEPARATE) {
1085             m_height += child->marginBottom();
1086             marginInfo.clearMargin();
1087         }
1088         int overflowDelta = child->overflowHeight(false) - child->height();
1089         if (m_height + overflowDelta > m_overflowHeight)
1090             m_overflowHeight = m_height + overflowDelta;
1091
1092         // If the child has overhanging floats that intrude into following siblings (or possibly out
1093         // of this block), then the parent gets notified of the floats now.
1094         addOverhangingFloats(static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos());
1095
1096         // See if this child has made our overflow need to grow.
1097         int rightChildPos = child->xPos() + kMax(child->overflowWidth(false), child->width());
1098         m_overflowWidth = kMax(rightChildPos, m_overflowWidth);
1099         m_overflowLeft = kMin(child->xPos() + child->overflowLeft(false), m_overflowLeft);
1100         
1101         // Insert our compact into the block margin if we have one.
1102         insertCompactIfNeeded(child, compactInfo);
1103
1104         // If the child moved, we have to repaint it as well as any floating/positioned
1105         // descendants.  An exception is if we need a layout.  In this case, we know we're going to
1106         // repaint ourselves (and the child) anyway.
1107         if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
1108             child->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
1109
1110         child = child->nextSibling();
1111     }
1112
1113     // Now do the handling of the bottom of the block, adding in our bottom border/padding and
1114     // determining the correct collapsed bottom margin information.
1115     handleBottomOfBlock(top, bottom, marginInfo);
1116
1117     // Finished. Clear the dirty layout bits.
1118     setNeedsLayout(false);
1119 }
1120
1121 void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
1122 {
1123     if (m_positionedObjects) {
1124         //kdDebug( 6040 ) << renderName() << " " << this << "::layoutPositionedObjects() start" << endl;
1125         RenderObject* r;
1126         QPtrListIterator<RenderObject> it(*m_positionedObjects);
1127         for ( ; (r = it.current()); ++it ) {
1128             // When a non-positioned block element moves, it may have positioned children that are implicitly positioned relative to the
1129             // non-positioned block.  Rather than trying to detect all of these movement cases, we just always lay out positioned
1130             // objects that are positioned implicitly like this.  Such objects are rare, and so in typical DHTML menu usage (where everything is
1131             // positioned explicitly) this should not incur a performance penalty.
1132             if (relayoutChildren || (r->hasStaticY() && r->parent() != this && r->parent()->isBlockFlow()))
1133                 r->setChildNeedsLayout(true);
1134             r->layoutIfNeeded();
1135         }
1136     }
1137 }
1138
1139 void RenderBlock::markPositionedObjectsForLayout()
1140 {
1141     if (m_positionedObjects) {
1142         RenderObject* r;
1143         QPtrListIterator<RenderObject> it(*m_positionedObjects);
1144         for (; (r = it.current()); ++it)
1145             r->setChildNeedsLayout(true);
1146     }
1147 }
1148
1149 void RenderBlock::getAbsoluteRepaintRectIncludingFloats(QRect& bounds, QRect& fullBounds)
1150 {
1151     bounds = fullBounds = getAbsoluteRepaintRect();
1152
1153     // Include any overhanging floats (if we know we're the one to paint them).
1154     // We null-check m_floatingObjects here to catch any cases where m_height ends up negative
1155     // for some reason.  I think I've caught all those cases, but this way we stay robust and don't
1156     // crash.
1157     if (hasOverhangingFloats() && m_floatingObjects) {
1158         FloatingObject* r;
1159         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
1160         for ( ; (r = it.current()); ++it) {
1161             // Only repaint the object if our noPaint flag isn't set and if it isn't in
1162             // its own layer.
1163             if (!r->noPaint && !r->node->layer()) {
1164                 QRect childRect, childFullRect;
1165                 r->node->getAbsoluteRepaintRectIncludingFloats(childRect, childFullRect);
1166                 fullBounds = fullBounds.unite(childFullRect);
1167             }
1168         }
1169     }
1170 }
1171
1172 void RenderBlock::repaintFloatingDescendants()
1173 {
1174     // Repaint any overhanging floats (if we know we're the one to paint them).
1175     if (hasOverhangingFloats()) {
1176         FloatingObject* r;
1177         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
1178         for ( ; (r = it.current()); ++it) {
1179             // Only repaint the object if our noPaint flag isn't set and if it isn't in
1180             // its own layer.
1181             if (!r->noPaint && !r->node->layer()) {                
1182                 r->node->repaint();
1183                 r->node->repaintFloatingDescendants();
1184             }
1185         }
1186     }
1187 }
1188
1189 void RenderBlock::repaintObjectsBeforeLayout()
1190 {
1191     RenderFlow::repaintObjectsBeforeLayout();
1192     if (!needsLayout())
1193         return;
1194
1195     // Walk our positioned objects.
1196     if (m_positionedObjects) {
1197         RenderObject* r;
1198         QPtrListIterator<RenderObject> it(*m_positionedObjects);
1199         for ( ; (r = it.current()); ++it )
1200             r->repaintObjectsBeforeLayout();
1201     }
1202 }
1203
1204 void RenderBlock::paint(PaintInfo& i, int _tx, int _ty)
1205 {
1206     _tx += m_x;
1207     _ty += m_y;
1208
1209     // Check if we need to do anything at all.
1210     if (!isInlineFlow() && !isRoot()) {
1211         QRect overflowBox = overflowRect(false);
1212         overflowBox.inflate(maximalOutlineSize(i.phase));
1213         overflowBox.setX(overflowBox.x() + _tx);
1214         overflowBox.setY(overflowBox.y() + _ty);
1215         bool intersectsOverflowBox = overflowBox.intersects(i.r);
1216         if (!intersectsOverflowBox) {
1217             // Check floats next.
1218             QRect floatBox = floatRect();
1219             floatBox.inflate(maximalOutlineSize(i.phase));
1220             floatBox.setX(floatBox.x() + _tx);
1221             floatBox.setY(floatBox.y() + _ty);
1222             if (!floatBox.intersects(i.r))
1223                 return;
1224         }
1225     }
1226
1227     return paintObject(i, _tx, _ty);
1228 }
1229
1230 void RenderBlock::paintChildren(PaintInfo& i, int _tx, int _ty)
1231 {
1232     // We don't paint our own background, but we do let the kids paint their backgrounds.
1233     PaintInfo paintInfo(i.p, i.r, i.phase == PaintActionChildBlockBackgrounds ? PaintActionChildBlockBackground : i.phase,
1234                         paintingRootForChildren(i));
1235     bool isPrinting = (i.p->device()->devType() == QInternal::Printer);
1236
1237     for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {        
1238         // Check for page-break-before: always, and if it's set, break and bail.
1239         if (isPrinting && !childrenInline() && child->style()->pageBreakBefore() == PBALWAYS &&
1240             inRootBlockContext() && (_ty + child->yPos()) > i.r.y() && 
1241             (_ty + child->yPos()) < i.r.y() + i.r.height()) {
1242             canvas()->setBestTruncatedAt(_ty + child->yPos(), this, true);
1243             return;
1244         }
1245         
1246         if (!child->layer() && !child->isFloating())
1247             child->paint(paintInfo, _tx, _ty);
1248         
1249         // Check for page-break-after: always, and if it's set, break and bail.
1250         if (isPrinting && !childrenInline() && child->style()->pageBreakAfter() == PBALWAYS && 
1251             inRootBlockContext() && (_ty + child->yPos() + child->height()) > i.r.y() && 
1252             (_ty + child->yPos() + child->height()) < i.r.y() + i.r.height()) {
1253             canvas()->setBestTruncatedAt(_ty + child->yPos() + child->height() + child->collapsedMarginBottom(), this, true);
1254             return;
1255         }
1256     }
1257 }
1258
1259 void RenderBlock::paintCaret(PaintInfo& i, CaretType type)
1260 {
1261     const Selection &s = type == CursorCaret ? document()->part()->selection() : document()->part()->dragCaret();
1262     NodeImpl *caretNode = s.start().node();
1263     RenderObject *renderer = caretNode ? caretNode->renderer() : 0;
1264     if (renderer && (renderer == this || renderer->containingBlock() == this) && caretNode && caretNode->isContentEditable()) {
1265         if (type == CursorCaret) {
1266             document()->part()->paintCaret(i.p, i.r);
1267         } else {
1268             document()->part()->paintDragCaret(i.p, i.r);
1269         }
1270     }
1271 }
1272
1273 void RenderBlock::paintObject(PaintInfo& i, int _tx, int _ty)
1274 {
1275     PaintAction paintAction = i.phase;
1276
1277     // If we're a repositioned run-in or a compact, don't paint background/borders.
1278     bool inlineFlow = isInlineFlow();
1279
1280     // 1. paint background, borders etc
1281     if (!inlineFlow &&
1282         (paintAction == PaintActionBlockBackground || paintAction == PaintActionChildBlockBackground) &&
1283         shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE) {
1284         paintBoxDecorations(i, _tx, _ty);
1285     }
1286
1287     // We're done.  We don't bother painting any children.
1288     if (paintAction == PaintActionBlockBackground)
1289         return;
1290
1291     // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).s
1292     int scrolledX = _tx;
1293     int scrolledY = _ty;
1294     if (hasOverflowClip())
1295         m_layer->subtractScrollOffset(scrolledX, scrolledY);
1296
1297     // 2. paint contents  
1298     if (childrenInline())
1299         paintLines(i, scrolledX, scrolledY);
1300     else
1301         paintChildren(i, scrolledX, scrolledY);
1302     
1303     // 3. paint selection
1304     if (!inlineFlow)
1305         paintSelection(i, scrolledX, scrolledY); // Fill in gaps in selection on lines and between blocks.
1306
1307     // 4. paint floats.
1308     if (!inlineFlow && (paintAction == PaintActionFloat || paintAction == PaintActionSelection))
1309         paintFloats(i, scrolledX, scrolledY, paintAction == PaintActionSelection);
1310
1311     // 5. paint outline.
1312     if (!inlineFlow && paintAction == PaintActionOutline && 
1313         style()->outlineWidth() && style()->visibility() == VISIBLE)
1314         paintOutline(i.p, _tx, _ty, width(), height(), style());
1315
1316     // 6. paint caret.
1317     // If the caret's node's render object's containing block is this block, and the paint action is PaintActionForeground,
1318     // then paint the caret.
1319     if (!inlineFlow && paintAction == PaintActionForeground) {        
1320         paintCaret(i, CursorCaret);
1321         paintCaret(i, DragCaret);
1322     }
1323
1324 #ifdef BOX_DEBUG
1325     if ( style() && style()->visibility() == VISIBLE ) {
1326         if(isAnonymous())
1327             outlineBox(i.p, _tx, _ty, "green");
1328         if(isFloating())
1329             outlineBox(i.p, _tx, _ty, "yellow");
1330         else
1331             outlineBox(i.p, _tx, _ty);
1332     }
1333 #endif
1334 }
1335
1336 void RenderBlock::paintFloats(PaintInfo& i, int _tx, int _ty, bool paintSelection)
1337 {
1338     if (!m_floatingObjects)
1339         return;
1340
1341     FloatingObject* r;
1342     QPtrListIterator<FloatingObject> it(*m_floatingObjects);
1343     for ( ; (r = it.current()); ++it) {
1344         // Only paint the object if our noPaint flag isn't set.
1345         if (!r->noPaint && !r->node->layer()) {
1346             PaintInfo info(i.p, i.r, paintSelection ? PaintActionSelection : PaintActionBlockBackground, i.paintingRoot);
1347             int tx = _tx + r->left - r->node->xPos() + r->node->marginLeft();
1348             int ty = _ty + r->startY - r->node->yPos() + r->node->marginTop();
1349             r->node->paint(info, tx, ty);
1350             if (!paintSelection) {
1351                 info.phase = PaintActionChildBlockBackgrounds;
1352                 r->node->paint(info, tx, ty);
1353                 info.phase = PaintActionFloat;
1354                 r->node->paint(info, tx, ty);
1355                 info.phase = PaintActionForeground;
1356                 r->node->paint(info, tx, ty);
1357                 info.phase = PaintActionOutline;
1358                 r->node->paint(info, tx, ty);
1359             }
1360         }
1361     }
1362 }
1363
1364 void RenderBlock::paintEllipsisBoxes(PaintInfo& i, int _tx, int _ty)
1365 {
1366     if (!shouldPaintWithinRoot(i) || !firstLineBox())
1367         return;
1368
1369     if (style()->visibility() == VISIBLE && i.phase == PaintActionForeground) {
1370         // We can check the first box and last box and avoid painting if we don't
1371         // intersect.
1372         int yPos = _ty + firstLineBox()->yPos();;
1373         int h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
1374         if( (yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
1375             return;
1376
1377         // See if our boxes intersect with the dirty rect.  If so, then we paint
1378         // them.  Note that boxes can easily overlap, so we can't make any assumptions
1379         // based off positions of our first line box or our last line box.
1380         for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
1381             yPos = _ty + curr->yPos();
1382             h = curr->height();
1383             if (curr->ellipsisBox() && (yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
1384                 curr->paintEllipsisBox(i, _tx, _ty);
1385         }
1386     }
1387 }
1388
1389 void RenderBlock::setSelectionState(SelectionState s)
1390 {
1391     if (m_selectionState == s)
1392         return;
1393     
1394     if (s == SelectionInside && m_selectionState != SelectionNone)
1395         return;
1396
1397     if ((s == SelectionStart && m_selectionState == SelectionEnd) ||
1398         (s == SelectionEnd && m_selectionState == SelectionStart))
1399         m_selectionState = SelectionBoth;
1400     else
1401         m_selectionState = s;
1402     
1403     RenderBlock* cb = containingBlock();
1404     if (cb && !cb->isCanvas())
1405         cb->setSelectionState(s);
1406 }
1407
1408 bool RenderBlock::shouldPaintSelectionGaps() const
1409 {
1410     return m_selectionState != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
1411 }
1412
1413 bool RenderBlock::isSelectionRoot() const
1414 {
1415     // FIXME: Eventually tables should have to learn how to fill gaps between cells, at least in simple non-spanning cases.
1416     return (isBody() || isRoot() || hasOverflowClip() || isRelPositioned() ||
1417             isFloatingOrPositioned() || isTableCell() || isInlineBlockOrInlineTable());
1418 }
1419
1420 GapRects RenderBlock::selectionGapRects()
1421 {
1422     if (!shouldPaintSelectionGaps())
1423         return GapRects();
1424
1425     int tx, ty;
1426     absolutePosition(tx, ty);
1427     
1428     int lastTop = -borderTopExtra();
1429     int lastLeft = leftSelectionOffset(this, lastTop);
1430     int lastRight = rightSelectionOffset(this, lastTop);
1431     
1432     return fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight);
1433 }
1434
1435 void RenderBlock::paintSelection(PaintInfo& i, int tx, int ty)
1436 {
1437     if (shouldPaintSelectionGaps() && i.phase == PaintActionForeground) {
1438         int lastTop = -borderTopExtra();
1439         int lastLeft = leftSelectionOffset(this, lastTop);
1440         int lastRight = rightSelectionOffset(this, lastTop);
1441         fillSelectionGaps(this, tx, ty, tx, ty, lastTop, lastLeft, lastRight, &i);
1442     }
1443 }
1444
1445 GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, int& lastTop, int& lastLeft, int& lastRight, 
1446                                         const PaintInfo* i)
1447 {
1448     // 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
1449     // fixed).
1450     GapRects result;
1451     if (!isBlockFlow())
1452         return result;
1453
1454     if (childrenInline())
1455         result = fillInlineSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, i);
1456     else
1457         result = fillBlockSelectionGaps(rootBlock, blockX, blockY, tx, ty, lastTop, lastLeft, lastRight, i);
1458         
1459     // Go ahead and fill the vertical gap all the way to the bottom of our block if the selection extends past our block.
1460     if (rootBlock == this && (m_selectionState != SelectionBoth && m_selectionState != SelectionEnd))
1461         result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + height() + borderBottomExtra(),
1462                                                     rootBlock, blockX, blockY, i));
1463     return result;
1464 }
1465
1466 GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, 
1467                                               int& lastTop, int& lastLeft, int& lastRight, const PaintInfo* i)
1468 {
1469     GapRects result;
1470     
1471     RenderObject* selStart = canvas()->selectionStart();
1472     // If there is no selection, don't try to get the selection's containing block. 
1473     // If we do, we'll crash.
1474     bool containsStart = (selStart && (selStart == this || selStart->containingBlock() == this));
1475
1476     if (!firstLineBox()) {
1477         if (containsStart) {
1478             // Go ahead and update our lastY to be the bottom of the block.  <hr>s or empty blocks with height can trip this
1479             // case.
1480             lastTop = (ty - blockY) + height();
1481             lastLeft = leftSelectionOffset(rootBlock, height());
1482             lastRight = rightSelectionOffset(rootBlock, height());
1483         }
1484         return result;
1485     }
1486
1487     RootInlineBox* lastSelectedLine = 0;
1488     RootInlineBox* curr;
1489     for (curr = firstRootBox(); curr && !curr->hasSelectedChildren(); curr = curr->nextRootBox());
1490
1491     // Now paint the gaps for the lines.
1492     for (; curr && curr->hasSelectedChildren(); curr = curr->nextRootBox()) {
1493         int selTop =  curr->selectionTop();
1494         int selHeight = curr->selectionHeight();
1495
1496         if (!containsStart && !lastSelectedLine && selectionState() != SelectionStart)
1497             result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, ty + selTop,
1498                                                         rootBlock, blockX, blockY, i));
1499
1500         if (!i || (ty + selTop < i->r.y() + i->r.height()) && (ty + selTop + selHeight > i->r.y()))
1501             result.unite(curr->fillLineSelectionGap(selTop, selHeight, rootBlock, blockX, blockY, tx, ty, i));
1502
1503         lastSelectedLine = curr;
1504     }
1505
1506     if (containsStart && !lastSelectedLine)
1507         // Selection must start just after our last line.
1508         lastSelectedLine = lastRootBox();
1509
1510     if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
1511         // Go ahead and update our lastY to be the bottom of the last selected line.
1512         lastTop = (ty - blockY) + lastSelectedLine->bottomOverflow();
1513         lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
1514         lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
1515     }
1516     return result;
1517 }
1518
1519 GapRects RenderBlock::fillBlockSelectionGaps(RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, int& lastTop, int& lastLeft, int& lastRight,
1520                                           const PaintInfo* i)
1521 {
1522     GapRects result;
1523     
1524     // Go ahead and jump right to the first block child that contains some selected objects.
1525     RenderObject* curr;
1526     for (curr = firstChild(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSibling());
1527     
1528     for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSibling()) {
1529         SelectionState childState = curr->selectionState();
1530         if (childState == SelectionBoth || childState == SelectionEnd)
1531             sawSelectionEnd = true;
1532
1533         if (curr->isFloatingOrPositioned())
1534             continue; // We must be a normal flow object in order to even be considered.
1535         
1536         if (curr->isRelPositioned() && curr->layer()) {
1537             // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
1538             // Just disregard it completely.
1539             int x, y;
1540             curr->layer()->relativePositionOffset(x, y);
1541             if (x || y)
1542                 continue;
1543         }
1544
1545         bool paintsOwnSelection = curr->shouldPaintSelectionGaps() || curr->isTable(); // FIXME: Eventually we won't special-case table like this.
1546         bool fillBlockGaps = paintsOwnSelection || (curr->canBeSelectionLeaf() && childState != SelectionNone);
1547         if (fillBlockGaps) {
1548             // We need to fill the vertical gap above this object.
1549             if (childState == SelectionEnd || childState == SelectionInside)
1550                 // Fill the gap above the object.
1551                 result.uniteCenter(fillVerticalSelectionGap(lastTop, lastLeft, lastRight, 
1552                                                             ty + curr->yPos(), rootBlock, blockX, blockY, i));
1553
1554             // 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*
1555             // our object.  We know this if the selection did not end inside our object.
1556             if (paintsOwnSelection && (childState == SelectionStart || sawSelectionEnd))
1557                 childState = SelectionNone;
1558
1559             // Fill side gaps on this object based off its state.
1560             bool leftGap, rightGap;
1561             getHorizontalSelectionGapInfo(childState, leftGap, rightGap);
1562             
1563             if (leftGap)
1564                 result.uniteLeft(fillLeftSelectionGap(this, curr->xPos(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, i));
1565             if (rightGap)
1566                 result.uniteRight(fillRightSelectionGap(this, curr->xPos() + curr->width(), curr->yPos(), curr->height(), rootBlock, blockX, blockY, tx, ty, i));
1567
1568             // Update lastTop to be just underneath the object.  lastLeft and lastRight extend as far as
1569             // they can without bumping into floating or positioned objects.  Ideally they will go right up
1570             // to the border of the root selection block.
1571             lastTop = (ty - blockY) + (curr->yPos() + curr->height());
1572             lastLeft = leftSelectionOffset(rootBlock, curr->yPos() + curr->height());
1573             lastRight = rightSelectionOffset(rootBlock, curr->yPos() + curr->height());
1574         }
1575         else if (childState != SelectionNone)
1576             // We must be a block that has some selected object inside it.  Go ahead and recur.
1577             result.unite(static_cast<RenderBlock*>(curr)->fillSelectionGaps(rootBlock, blockX, blockY, tx + curr->xPos(), ty + curr->yPos(), 
1578                                                                             lastTop, lastLeft, lastRight, i));
1579     }
1580     return result;
1581 }
1582
1583 QRect RenderBlock::fillHorizontalSelectionGap(RenderObject* selObj, int xPos, int yPos, int width, int height,
1584                                               const PaintInfo* i)
1585 {
1586     if (width <= 0 || height <= 0)
1587         return QRect();
1588
1589     QRect gapRect(xPos, yPos, width, height);
1590     if (i) {
1591         // Paint the rect.
1592         QBrush selBrush(selObj->selectionColor(i->p));
1593         i->p->fillRect(gapRect, selBrush);
1594     }
1595     return gapRect;
1596 }
1597
1598 QRect RenderBlock::fillVerticalSelectionGap(int lastTop, int lastLeft, int lastRight,
1599                                             int bottomY, RenderBlock* rootBlock, int blockX, int blockY,
1600                                             const PaintInfo* i)
1601 {
1602     int top = blockY + lastTop;
1603     int height = bottomY - top;
1604     if (height <= 0)
1605         return QRect();
1606         
1607     // Get the selection offsets for the bottom of the gap
1608     int left = blockX + kMax(lastLeft, leftSelectionOffset(rootBlock, bottomY));
1609     int right = blockX + kMin(lastRight, rightSelectionOffset(rootBlock, bottomY));
1610     int width = right - left;
1611     if (width <= 0)
1612         return QRect();
1613
1614     QRect gapRect(left, top, width, height);
1615     if (i) {
1616         // Paint the rect.
1617         QBrush selBrush(selectionColor(i->p));
1618         i->p->fillRect(gapRect, selBrush);
1619     }
1620     return gapRect;
1621 }
1622
1623 QRect RenderBlock::fillLeftSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const PaintInfo* i)
1624 {
1625     int top = yPos + ty;
1626     int left = blockX + kMax(leftSelectionOffset(rootBlock, yPos), leftSelectionOffset(rootBlock, yPos + height));
1627     int width = tx + xPos - left;
1628     if (width <= 0)
1629         return QRect();
1630
1631     QRect gapRect(left, top, width, height);
1632     if (i) {
1633         // Paint the rect.
1634         QBrush selBrush(selObj->selectionColor(i->p));
1635         i->p->fillRect(gapRect, selBrush);
1636     }
1637     return gapRect;
1638 }
1639
1640 QRect RenderBlock::fillRightSelectionGap(RenderObject* selObj, int xPos, int yPos, int height, RenderBlock* rootBlock, int blockX, int blockY, int tx, int ty, const PaintInfo* i)
1641 {
1642     int left = xPos + tx;
1643     int top = yPos + ty;
1644     int right = blockX + kMin(rightSelectionOffset(rootBlock, yPos), rightSelectionOffset(rootBlock, yPos + height));
1645     int width = right - left;
1646     if (width <= 0)
1647         return QRect();
1648
1649     QRect gapRect(left, top, width, height);
1650     if (i) {
1651         // Paint the rect.
1652         QBrush selBrush(selObj->selectionColor(i->p));
1653         i->p->fillRect(gapRect, selBrush);
1654     }
1655     return gapRect;
1656 }
1657
1658 void RenderBlock::getHorizontalSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
1659 {
1660     bool ltr = style()->direction() == LTR;
1661     leftGap = (state == RenderObject::SelectionInside) ||
1662               (state == RenderObject::SelectionEnd && ltr) ||
1663               (state == RenderObject::SelectionStart && !ltr);
1664     rightGap = (state == RenderObject::SelectionInside) ||
1665                (state == RenderObject::SelectionStart && ltr) ||
1666                (state == RenderObject::SelectionEnd && !ltr);
1667 }
1668
1669 int RenderBlock::leftSelectionOffset(RenderBlock* rootBlock, int y)
1670 {
1671     int left = leftOffset(y);
1672     if (left == borderLeft() + paddingLeft()) {
1673         if (rootBlock != this)
1674             // The border can potentially be further extended by our containingBlock().
1675             return containingBlock()->leftSelectionOffset(rootBlock, y + yPos());
1676         return 0;
1677     }
1678     else {
1679         RenderBlock* cb = this;
1680         while (cb != rootBlock) {
1681             left += cb->xPos();
1682             cb = cb->containingBlock();
1683         }
1684     }
1685     
1686     return left;
1687 }
1688
1689 int RenderBlock::rightSelectionOffset(RenderBlock* rootBlock, int y)
1690 {
1691     int right = rightOffset(y);
1692     if (right == (contentWidth() + (borderLeft() + paddingLeft()))) {
1693         if (rootBlock != this)
1694             // The border can potentially be further extended by our containingBlock().
1695             return containingBlock()->rightSelectionOffset(rootBlock, y + yPos());
1696         return width();
1697     }
1698     else {
1699         RenderBlock* cb = this;
1700         while (cb != rootBlock) {
1701             right += cb->xPos();
1702             cb = cb->containingBlock();
1703         }
1704     }
1705     return right;
1706 }
1707
1708 void RenderBlock::insertPositionedObject(RenderObject *o)
1709 {
1710     // Create the list of special objects if we don't aleady have one
1711     if (!m_positionedObjects) {
1712         m_positionedObjects = new QPtrList<RenderObject>;
1713         m_positionedObjects->setAutoDelete(false);
1714     }
1715     else {
1716         // Don't insert the object again if it's already in the list
1717         QPtrListIterator<RenderObject> it(*m_positionedObjects);
1718         RenderObject* f;
1719         while ( (f = it.current()) ) {
1720             if (f == o) return;
1721             ++it;
1722         }
1723     }
1724
1725     m_positionedObjects->append(o);
1726 }
1727
1728 void RenderBlock::removePositionedObject(RenderObject *o)
1729 {
1730     if (m_positionedObjects) {
1731         QPtrListIterator<RenderObject> it(*m_positionedObjects);
1732         while (it.current()) {
1733             if (it.current() == o)
1734                 m_positionedObjects->removeRef(it.current());
1735             ++it;
1736         }
1737     }
1738 }
1739
1740 void RenderBlock::insertFloatingObject(RenderObject *o)
1741 {
1742     // Create the list of special objects if we don't aleady have one
1743     if (!m_floatingObjects) {
1744         m_floatingObjects = new QPtrList<FloatingObject>;
1745         m_floatingObjects->setAutoDelete(true);
1746     }
1747     else {
1748         // Don't insert the object again if it's already in the list
1749         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
1750         FloatingObject* f;
1751         while ( (f = it.current()) ) {
1752             if (f->node == o) return;
1753             ++it;
1754         }
1755     }
1756
1757     // Create the special object entry & append it to the list
1758
1759     FloatingObject *newObj;
1760     if (o->isFloating()) {
1761         // floating object
1762         o->layoutIfNeeded();
1763
1764         if(o->style()->floating() == FLEFT)
1765             newObj = new FloatingObject(FloatingObject::FloatLeft);
1766         else
1767             newObj = new FloatingObject(FloatingObject::FloatRight);
1768
1769         newObj->startY = -1;
1770         newObj->endY = -1;
1771         newObj->width = o->width() + o->marginLeft() + o->marginRight();
1772         newObj->noPaint = o->layer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
1773     }
1774     else {
1775         // We should never get here, as insertFloatingObject() should only ever be called with floating
1776         // objects.
1777         KHTMLAssert(false);
1778         newObj = 0; // keep gcc's uninitialized variable warnings happy
1779     }
1780
1781     newObj->node = o;
1782
1783     m_floatingObjects->append(newObj);
1784 }
1785
1786 void RenderBlock::removeFloatingObject(RenderObject *o)
1787 {
1788     if (m_floatingObjects) {
1789         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
1790         while (it.current()) {
1791             if (it.current()->node == o)
1792                 m_floatingObjects->removeRef(it.current());
1793             ++it;
1794         }
1795     }
1796 }
1797
1798 void RenderBlock::positionNewFloats()
1799 {
1800     if(!m_floatingObjects) return;
1801     FloatingObject *f = m_floatingObjects->getLast();
1802     if(!f || f->startY != -1) return;
1803     FloatingObject *lastFloat;
1804     while(1)
1805     {
1806         lastFloat = m_floatingObjects->prev();
1807         if (!lastFloat || lastFloat->startY != -1) {
1808             m_floatingObjects->next();
1809             break;
1810         }
1811         f = lastFloat;
1812     }
1813
1814
1815     int y = m_height;
1816
1817
1818     // the float can not start above the y position of the last positioned float.
1819     if(lastFloat && lastFloat->startY > y)
1820         y = lastFloat->startY;
1821
1822     while(f)
1823     {
1824         //skip elements copied from elsewhere and positioned elements
1825         if (f->node->containingBlock()!=this)
1826         {
1827             f = m_floatingObjects->next();
1828             continue;
1829         }
1830
1831         RenderObject *o = f->node;
1832         int _height = o->height() + o->marginTop() + o->marginBottom();
1833
1834         int ro = rightOffset(); // Constant part of right offset.
1835         int lo = leftOffset(); // Constat part of left offset.
1836         int fwidth = f->width; // The width we look for.
1837                                //kdDebug( 6040 ) << " Object width: " << fwidth << " available width: " << ro - lo << endl;
1838         if (ro - lo < fwidth)
1839             fwidth = ro - lo; // Never look for more than what will be available.
1840         
1841         int oldChildX = o->xPos();
1842         int oldChildY = o->yPos();
1843         
1844         if ( o->style()->clear() & CLEFT )
1845             y = kMax( leftBottom(), y );
1846         if ( o->style()->clear() & CRIGHT )
1847             y = kMax( rightBottom(), y );
1848
1849         if (o->style()->floating() == FLEFT)
1850         {
1851             int heightRemainingLeft = 1;
1852             int heightRemainingRight = 1;
1853             int fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
1854             while (rightRelOffset(y,ro, false, &heightRemainingRight)-fx < fwidth)
1855             {
1856                 y += kMin( heightRemainingLeft, heightRemainingRight );
1857                 fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
1858             }
1859             if (fx<0) fx=0;
1860             f->left = fx;
1861             //kdDebug( 6040 ) << "positioning left aligned float at (" << fx + o->marginLeft()  << "/" << y + o->marginTop() << ") fx=" << fx << endl;
1862             o->setPos(fx + o->marginLeft(), y + o->marginTop());
1863         }
1864         else
1865         {
1866             int heightRemainingLeft = 1;
1867             int heightRemainingRight = 1;
1868             int fx = rightRelOffset(y,ro, false, &heightRemainingRight);
1869             while (fx - leftRelOffset(y,lo, false, &heightRemainingLeft) < fwidth)
1870             {
1871                 y += kMin(heightRemainingLeft, heightRemainingRight);
1872                 fx = rightRelOffset(y,ro, false, &heightRemainingRight);
1873             }
1874             if (fx<f->width) fx=f->width;
1875             f->left = fx - f->width;
1876             //kdDebug( 6040 ) << "positioning right aligned float at (" << fx - o->marginRight() - o->width() << "/" << y + o->marginTop() << ")" << endl;
1877             o->setPos(fx - o->marginRight() - o->width(), y + o->marginTop());
1878         }
1879         f->startY = y;
1880         f->endY = f->startY + _height;
1881
1882         // If the child moved, we have to repaint it.
1883         if (o->checkForRepaintDuringLayout())
1884             o->repaintDuringLayoutIfMoved(oldChildX, oldChildY);
1885
1886         //kdDebug( 6040 ) << "floatingObject x/y= (" << f->left << "/" << f->startY << "-" << f->width << "/" << f->endY - f->startY << ")" << endl;
1887
1888         f = m_floatingObjects->next();
1889     }
1890 }
1891
1892 void RenderBlock::newLine()
1893 {
1894     positionNewFloats();
1895     // set y position
1896     int newY = 0;
1897     switch(m_clearStatus)
1898     {
1899         case CLEFT:
1900             newY = leftBottom();
1901             break;
1902         case CRIGHT:
1903             newY = rightBottom();
1904             break;
1905         case CBOTH:
1906             newY = floatBottom();
1907         default:
1908             break;
1909     }
1910     if(m_height < newY)
1911     {
1912         //      kdDebug( 6040 ) << "adjusting y position" << endl;
1913         m_height = newY;
1914     }
1915     m_clearStatus = CNONE;
1916 }
1917
1918 int
1919 RenderBlock::leftOffset() const
1920 {
1921     return borderLeft()+paddingLeft();
1922 }
1923
1924 int
1925 RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent,
1926                            int *heightRemaining ) const
1927 {
1928     int left = fixedOffset;
1929     if (m_floatingObjects) {
1930         if ( heightRemaining ) *heightRemaining = 1;
1931         FloatingObject* r;
1932         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
1933         for ( ; (r = it.current()); ++it )
1934         {
1935             //kdDebug( 6040 ) <<(void *)this << " left: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
1936             if (r->startY <= y && r->endY > y &&
1937                 r->type == FloatingObject::FloatLeft &&
1938                 r->left + r->width > left) {
1939                 left = r->left + r->width;
1940                 if ( heightRemaining ) *heightRemaining = r->endY - y;
1941             }
1942         }
1943     }
1944
1945     if (applyTextIndent && m_firstLine && style()->direction() == LTR) {
1946         int cw=0;
1947         if (style()->textIndent().isPercent())
1948             cw = containingBlock()->contentWidth();
1949         left += style()->textIndent().minWidth(cw);
1950     }
1951
1952     //kdDebug( 6040 ) << "leftOffset(" << y << ") = " << left << endl;
1953     return left;
1954 }
1955
1956 int
1957 RenderBlock::rightOffset() const
1958 {
1959     int right = m_width - borderRight() - paddingRight();
1960     if (includeScrollbarSize())
1961         right -= m_layer->verticalScrollbarWidth();
1962     return right;
1963 }
1964
1965 int
1966 RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent,
1967                             int *heightRemaining ) const
1968 {
1969     int right = fixedOffset;
1970
1971     if (m_floatingObjects) {
1972         if (heightRemaining) *heightRemaining = 1;
1973         FloatingObject* r;
1974         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
1975         for ( ; (r = it.current()); ++it )
1976         {
1977             //kdDebug( 6040 ) << "right: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
1978             if (r->startY <= y && r->endY > y &&
1979                 r->type == FloatingObject::FloatRight &&
1980                 r->left < right) {
1981                 right = r->left;
1982                 if ( heightRemaining ) *heightRemaining = r->endY - y;
1983             }
1984         }
1985     }
1986     
1987     if (applyTextIndent && m_firstLine && style()->direction() == RTL) {
1988         int cw=0;
1989         if (style()->textIndent().isPercent())
1990             cw = containingBlock()->contentWidth();
1991         right += style()->textIndent().minWidth(cw);
1992     }
1993     
1994     //kdDebug( 6040 ) << "rightOffset(" << y << ") = " << right << endl;
1995     return right;
1996 }
1997
1998 int
1999 RenderBlock::lineWidth(int y) const
2000 {
2001     //kdDebug( 6040 ) << "lineWidth(" << y << ")=" << rightOffset(y) - leftOffset(y) << endl;
2002     int result = rightOffset(y) - leftOffset(y);
2003     return (result < 0) ? 0 : result;
2004 }
2005
2006 int
2007 RenderBlock::nearestFloatBottom(int height) 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>height && (r->endY<bottom || bottom==0))
2015             bottom=r->endY;
2016     return QMAX(bottom, height);
2017 }
2018
2019 int
2020 RenderBlock::floatBottom() const
2021 {
2022     if (!m_floatingObjects) return 0;
2023     int bottom=0;
2024     FloatingObject* r;
2025     QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2026     for ( ; (r = it.current()); ++it )
2027         if (r->endY>bottom)
2028             bottom=r->endY;
2029     return bottom;
2030 }
2031
2032 QRect RenderBlock::floatRect() const
2033 {
2034     QRect result(borderBox());
2035     if (!m_floatingObjects)
2036         return result;
2037     FloatingObject* r;
2038     QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2039     for (; (r = it.current()); ++it) {
2040         if (!r->noPaint && !r->node->layer()) {
2041             // Check this float.
2042             int bottomDelta = kMax(0, r->startY + r->node->marginTop() + r->node->overflowHeight(false) -
2043                                       (result.y() + result.height()));
2044             if (bottomDelta)
2045                 result.setHeight(result.height() + bottomDelta);
2046             int rightDelta = kMax(0, r->left + r->node->marginLeft() + r->node->overflowWidth(false) -
2047                                      (result.x() + result.width()));
2048             if (rightDelta)
2049                 result.setWidth(result.width() + rightDelta);
2050             
2051             // Now check left and top
2052             int topDelta = kMin(0, r->startY + r->node->marginTop() - result.y());
2053             if (topDelta < 0) {
2054                 result.setY(result.y() + topDelta);
2055                 result.setHeight(result.height() - 2*topDelta);
2056             }
2057             int leftDelta = kMin(0, r->left + r->node->marginLeft() - result.x());
2058             if (topDelta < 0) {
2059                 result.setX(result.x() + leftDelta);
2060                 result.setHeight(result.width() - 2*leftDelta);
2061             }
2062         }
2063     }
2064
2065     return result;
2066 }
2067
2068 int
2069 RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
2070 {
2071     int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf);
2072     if (!includeOverflowInterior && hasOverflowClip())
2073         return bottom;
2074     if (includeSelf && m_overflowHeight > bottom)
2075         bottom = m_overflowHeight;
2076     
2077     if (m_floatingObjects) {
2078         FloatingObject* r;
2079         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2080         for ( ; (r = it.current()); ++it ) {
2081             if (!r->noPaint || r->node->layer()) {
2082                 int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false);
2083                 bottom = kMax(bottom, lp);
2084             }
2085         }
2086     }
2087
2088     // Fixed positioned objects do not scroll and thus should not constitute
2089     // part of the lowest position.
2090     if (m_positionedObjects && !isCanvas()) {
2091         RenderObject* r;
2092         QPtrListIterator<RenderObject> it(*m_positionedObjects);
2093         for ( ; (r = it.current()); ++it ) {
2094             int lp = r->yPos() + r->lowestPosition(false);
2095             bottom = kMax(bottom, lp);
2096         }
2097     }
2098
2099     if (!includeSelf && lastLineBox()) {
2100         int lp = lastLineBox()->yPos() + lastLineBox()->height();
2101         bottom = kMax(bottom, lp);
2102     }
2103     
2104     return bottom;
2105 }
2106
2107 int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
2108 {
2109     int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf);
2110     if (!includeOverflowInterior && hasOverflowClip())
2111         return right;
2112     if (includeSelf && m_overflowWidth > right)
2113         right = m_overflowWidth;
2114     
2115     if (m_floatingObjects) {
2116         FloatingObject* r;
2117         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2118         for ( ; (r = it.current()); ++it ) {
2119             if (!r->noPaint || r->node->layer()) {
2120                 int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false);
2121                 right = kMax(right, rp);
2122             }
2123         }
2124     }
2125
2126     if (m_positionedObjects && !isCanvas()) {
2127         RenderObject* r;
2128         QPtrListIterator<RenderObject> it(*m_positionedObjects);
2129         for ( ; (r = it.current()); ++it ) {
2130             int rp = r->xPos() + r->rightmostPosition(false);
2131             right = kMax(right, rp);
2132         }
2133     }
2134
2135     if (!includeSelf && firstLineBox()) {
2136         for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
2137             int rp = currBox->xPos() + currBox->width();
2138             right = kMax(right, rp);
2139         }
2140     }
2141     
2142     return right;
2143 }
2144
2145 int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
2146 {
2147     int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf);
2148     if (!includeOverflowInterior && hasOverflowClip())
2149         return left;
2150
2151     // FIXME: Check left overflow when we eventually support it.
2152     
2153     if (m_floatingObjects) {
2154         FloatingObject* r;
2155         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2156         for ( ; (r = it.current()); ++it ) {
2157             if (!r->noPaint || r->node->layer()) {
2158                 int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false);
2159                 left = kMin(left, lp);
2160             }
2161         }
2162     }
2163     
2164     if (m_positionedObjects && !isCanvas()) {
2165         RenderObject* r;
2166         QPtrListIterator<RenderObject> it(*m_positionedObjects);
2167         for ( ; (r = it.current()); ++it ) {
2168             int lp = r->xPos() + r->leftmostPosition(false);
2169             left = kMin(left, lp);
2170         }
2171     }
2172     
2173     if (!includeSelf && firstLineBox()) {
2174         for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
2175             left = kMin(left, (int)currBox->xPos());
2176     }
2177     
2178     return left;
2179 }
2180
2181 int
2182 RenderBlock::leftBottom()
2183 {
2184     if (!m_floatingObjects) return 0;
2185     int bottom=0;
2186     FloatingObject* r;
2187     QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2188     for ( ; (r = it.current()); ++it )
2189         if (r->endY>bottom && r->type == FloatingObject::FloatLeft)
2190             bottom=r->endY;
2191
2192     return bottom;
2193 }
2194
2195 int
2196 RenderBlock::rightBottom()
2197 {
2198     if (!m_floatingObjects) return 0;
2199     int bottom=0;
2200     FloatingObject* r;
2201     QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2202     for ( ; (r = it.current()); ++it )
2203         if (r->endY>bottom && r->type == FloatingObject::FloatRight)
2204             bottom=r->endY;
2205
2206     return bottom;
2207 }
2208
2209 void
2210 RenderBlock::clearFloats()
2211 {
2212     if (m_floatingObjects)
2213         m_floatingObjects->clear();
2214
2215     // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
2216     if (avoidsFloats() || isRoot() || isCanvas() || isFloatingOrPositioned() || isTableCell())
2217         return;
2218     
2219     // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
2220     // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
2221     // to avoid floats.
2222     bool parentHasFloats = false;
2223     RenderObject *prev = previousSibling();
2224     while (prev && (!prev->isRenderBlock() || prev->avoidsFloats() || prev->isFloatingOrPositioned())) {
2225         if (prev->isFloating())
2226             parentHasFloats = true;
2227          prev = prev->previousSibling();
2228     }
2229
2230     // First add in floats from the parent.
2231     int offset = m_y;
2232     if (parentHasFloats)
2233         addIntrudingFloats(static_cast<RenderBlock *>(parent()),
2234                            parent()->borderLeft() + parent()->paddingLeft(), offset);
2235
2236     int xoffset = 0;
2237     if (prev)
2238         offset -= prev->yPos();
2239     else {
2240         prev = parent();
2241         xoffset += prev->borderLeft() + prev->paddingLeft();
2242     }
2243     //kdDebug() << "RenderBlock::clearFloats found previous "<< (void *)this << " prev=" << (void *)prev<< endl;
2244
2245     // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
2246     if (!prev->isRenderBlock()) return;
2247     RenderBlock* block = static_cast<RenderBlock *>(prev);
2248     if (!block->m_floatingObjects) return;
2249     if (block->floatBottom() > offset)
2250         addIntrudingFloats(block, xoffset, offset);
2251 }
2252
2253 void RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff)
2254 {
2255     // Prevent floats from being added to the canvas by the root element, e.g., <html>.
2256     if (child->hasOverflowClip() || !child->hasOverhangingFloats() || child->isRoot())
2257         return;
2258
2259     QPtrListIterator<FloatingObject> it(*child->m_floatingObjects);
2260     for (FloatingObject *r; (r = it.current()); ++it) {
2261         if (child->yPos() + r->endY > height()) {
2262             // The object may already be in our list. Check for it up front to avoid
2263             // creating duplicate entries.
2264             FloatingObject* f = 0;
2265             if (m_floatingObjects) {
2266                 QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2267                 while ((f = it.current())) {
2268                     if (f->node == r->node) break;
2269                     ++it;
2270                 }
2271             }
2272
2273             // If the object is not in the list, we add it now.
2274             if (!f) {
2275                 FloatingObject *floatingObj = new FloatingObject(r->type);
2276                 floatingObj->startY = r->startY - yoff;
2277                 floatingObj->endY = r->endY - yoff;
2278                 floatingObj->left = r->left - xoff;
2279                 floatingObj->width = r->width;
2280                 floatingObj->node = r->node;
2281
2282                 // The nearest enclosing layer always paints the float (so that zindex and stacking
2283                 // behaves properly).  We always want to propagate the desire to paint the float as
2284                 // far out as we can, to the outermost block that overlaps the float, stopping only
2285                 // if we hit a layer boundary.
2286                 if (r->node->enclosingLayer() == enclosingLayer())
2287                     r->noPaint = true;
2288                 else
2289                     floatingObj->noPaint = true;
2290                 
2291                 // We create the floating object list lazily.
2292                 if (!m_floatingObjects) {
2293                     m_floatingObjects = new QPtrList<FloatingObject>;
2294                     m_floatingObjects->setAutoDelete(true);
2295                 }
2296                 m_floatingObjects->append(floatingObj);
2297             }
2298         }
2299     }
2300 }
2301
2302 void RenderBlock::addIntrudingFloats(RenderBlock* prev, int xoff, int yoff)
2303 {
2304     // If the parent or previous sibling doesn't have any floats to add, don't bother.
2305     if (!prev->m_floatingObjects)
2306         return;
2307
2308     QPtrListIterator<FloatingObject> it(*prev->m_floatingObjects);
2309     for (FloatingObject *r; (r = it.current()); ++it) {
2310         if (r->endY > yoff) {
2311             // The object may already be in our list. Check for it up front to avoid
2312             // creating duplicate entries.
2313             FloatingObject* f = 0;
2314             if (m_floatingObjects) {
2315                 QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2316                 while ((f = it.current())) {
2317                     if (f->node == r->node) break;
2318                     ++it;
2319                 }
2320             }
2321             if (!f) {
2322                 FloatingObject *floatingObj = new FloatingObject(r->type);
2323                 floatingObj->startY = r->startY - yoff;
2324                 floatingObj->endY = r->endY - yoff;
2325                 floatingObj->left = r->left - xoff;
2326                 // Applying the child's margin makes no sense in the case where the child was passed in.
2327                 // since his own margin was added already through the subtraction of the |xoff| variable
2328                 // above.  |xoff| will equal -flow->marginLeft() in this case, so it's already been taken
2329                 // into account.  Only apply this code if |child| is false, since otherwise the left margin
2330                 // will get applied twice.
2331                 if (prev != parent())
2332                     floatingObj->left += prev->marginLeft();
2333                 floatingObj->left -= marginLeft();
2334                 floatingObj->noPaint = true;  // We are not in the direct inheritance chain for this float. We will never paint it.
2335                 floatingObj->width = r->width;
2336                 floatingObj->node = r->node;
2337                 
2338                 // We create the floating object list lazily.
2339                 if (!m_floatingObjects) {
2340                     m_floatingObjects = new QPtrList<FloatingObject>;
2341                     m_floatingObjects->setAutoDelete(true);
2342                 }
2343                 m_floatingObjects->append(floatingObj);
2344             }
2345         }
2346     }
2347 }
2348
2349 bool RenderBlock::containsFloat(RenderObject* o)
2350 {
2351     if (m_floatingObjects) {
2352         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2353         while (it.current()) {
2354             if (it.current()->node == o)
2355                 return true;
2356             ++it;
2357         }
2358     }
2359     return false;
2360 }
2361
2362 void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove)
2363 {
2364     setChildNeedsLayout(true);
2365
2366     if (floatToRemove)
2367         removeFloatingObject(floatToRemove);
2368
2369     // Iterate over our children and mark them as needed.
2370     if (!childrenInline()) {
2371         for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
2372             if (isBlockFlow() && !child->isFloatingOrPositioned() &&
2373                 (floatToRemove ? child->containsFloat(floatToRemove) : child->containsFloats()))
2374                 child->markAllDescendantsWithFloatsForLayout(floatToRemove);
2375         }
2376     }
2377 }
2378
2379 int RenderBlock::getClearDelta(RenderObject *child)
2380 {
2381     bool clearSet = child->style()->clear() != CNONE;
2382     int bottom = 0;
2383     switch (child->style()->clear()) {
2384         case CNONE:
2385             break;
2386         case CLEFT:
2387             bottom = leftBottom();
2388             break;
2389         case CRIGHT:
2390             bottom = rightBottom();
2391             break;
2392         case CBOTH:
2393             bottom = floatBottom();
2394             break;
2395     }
2396
2397     // 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).
2398     // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed
2399     // to fit) and not all (we should be using nearestFloatBottom and looping).
2400     // Do not allow tables to wrap in quirks or even in almost strict mode 
2401     // (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work)
2402     int result = clearSet ? kMax(0, bottom - child->yPos()) : 0;
2403     if (!result && child->avoidsFloats() && child->style()->width().isFixed() && 
2404         child->minWidth() > lineWidth(child->yPos()) && child->minWidth() <= contentWidth() && 
2405         document()->inStrictMode())   
2406         result = kMax(0, floatBottom() - child->yPos());
2407     return result;
2408 }
2409
2410 bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
2411 {
2412     if (!scrollsOverflow())
2413         return false;
2414
2415     if (m_layer->verticalScrollbarWidth()) {
2416         QRect vertRect(_tx + width() - borderRight() - m_layer->verticalScrollbarWidth(),
2417                        _ty + borderTop(),
2418                        m_layer->verticalScrollbarWidth(),
2419                        height()-borderTop()-borderBottom());
2420         if (vertRect.contains(_x, _y)) {
2421             RenderLayer::gScrollBar = m_layer->verticalScrollbar();
2422             return true;
2423         }
2424     }
2425
2426     if (m_layer->horizontalScrollbarHeight()) {
2427         QRect horizRect(_tx + borderLeft(),
2428                         _ty + height() - borderBottom() - m_layer->horizontalScrollbarHeight(),
2429                         width()-borderLeft()-borderRight(),
2430                         m_layer->horizontalScrollbarHeight());
2431         if (horizRect.contains(_x, _y)) {
2432             RenderLayer::gScrollBar = m_layer->horizontalScrollbar();
2433             return true;
2434         }
2435     }
2436
2437     return false;    
2438 }
2439
2440 bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
2441                               HitTestAction hitTestAction)
2442 {
2443     bool inlineFlow = isInlineFlow();
2444
2445     int tx = _tx + m_x;
2446     int ty = _ty + m_y + borderTopExtra();
2447     
2448     if (!inlineFlow && !isRoot()) {
2449         // Check if we need to do anything at all.
2450         QRect overflowBox = overflowRect(false);
2451         overflowBox.setX(overflowBox.x() + tx);
2452         overflowBox.setY(overflowBox.y() + ty);
2453         bool insideOverflowBox = overflowBox.contains(_x, _y);
2454         if (!insideOverflowBox) {
2455             // Check floats next.
2456             QRect floatBox = floatRect();
2457             floatBox.setX(floatBox.x() + tx);
2458             floatBox.setY(floatBox.y() + ty);
2459             if (!floatBox.contains(_x, _y))
2460                 return false;
2461         }
2462     }
2463
2464     // See if we're inside the scrollbar (if we're overflow:scroll/auto).
2465     if (isPointInScrollbar(_x, _y, tx, ty)) {
2466         if (hitTestAction == HitTestBlockBackground) {
2467             setInnerNode(info);
2468             return true;
2469         }
2470         return false;
2471     }
2472
2473     // Hit test descendants first.
2474     int scrolledX = tx;
2475     int scrolledY = ty;
2476     if (hasOverflowClip())
2477         m_layer->subtractScrollOffset(scrolledX, scrolledY);
2478     if (childrenInline() && !isTable()) {
2479         // We have to hit-test our line boxes.
2480         if (hitTestLines(info, _x, _y, scrolledX, scrolledY, hitTestAction)) {
2481             setInnerNode(info);
2482             return true;
2483         }
2484     }
2485     else {
2486         // Hit test our children.
2487         HitTestAction childHitTest = hitTestAction;
2488         if (hitTestAction == HitTestChildBlockBackgrounds)
2489             childHitTest = HitTestChildBlockBackground;
2490         for (RenderObject* child = lastChild(); child; child = child->previousSibling())
2491             // FIXME: We have to skip over inline flows, since they can show up inside RenderTables at the moment (a demoted inline <form> for example).  If we ever implement a
2492             // table-specific hit-test method (which we should do for performance reasons anyway), then we can remove this check.
2493             if (!child->layer() && !child->isFloating() && !child->isInlineFlow() && child->nodeAtPoint(info, _x, _y, scrolledX, scrolledY, childHitTest)) {
2494                 setInnerNode(info);
2495                 return true;
2496             }
2497     }
2498     
2499     // Hit test floats.
2500     if (hitTestAction == HitTestFloat && m_floatingObjects) {
2501         if (isCanvas()) {
2502             scrolledX += static_cast<RenderCanvas*>(this)->view()->contentsX();
2503             scrolledY += static_cast<RenderCanvas*>(this)->view()->contentsY();
2504         }
2505         
2506         FloatingObject* o;
2507         QPtrListIterator<FloatingObject> it(*m_floatingObjects);
2508         for (it.toLast(); (o = it.current()); --it)
2509             if (!o->noPaint && !o->node->layer() && o->node->hitTest(info, _x, _y,
2510                                      scrolledX + o->left + o->node->marginLeft() - o->node->xPos(),
2511                                      scrolledY + o->startY + o->node->marginTop() - o->node->yPos())) {
2512                 setInnerNode(info);
2513                 return true;
2514             }
2515     }
2516
2517     // Now hit test our background.
2518     if (!inlineFlow && (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground)) {
2519         QRect boundsRect(tx, ty, m_width, m_height);
2520         if (isRoot() || (style()->visibility() == VISIBLE && boundsRect.contains(_x, _y))) {
2521             setInnerNode(info);
2522             return true;
2523         }
2524     }
2525
2526     return false;
2527 }
2528
2529 Position RenderBlock::positionForBox(InlineBox *box, bool start) const
2530 {
2531     if (!box)
2532         return Position();
2533
2534     if (!box->object()->element())
2535         return Position(element(), start ? caretMinOffset() : caretMaxOffset());
2536
2537     if (!box->isInlineTextBox())
2538         return Position(box->object()->element(), start ? box->object()->caretMinOffset() : box->object()->caretMaxOffset());
2539
2540     InlineTextBox *textBox = static_cast<InlineTextBox *>(box);
2541     return Position(box->object()->element(), start ? textBox->start() : textBox->start() + textBox->len());
2542 }
2543
2544 Position RenderBlock::positionForRenderer(RenderObject *renderer, bool start) const
2545 {
2546     if (!renderer)
2547         return Position(element(), 0);
2548
2549     NodeImpl *node = renderer->element() ? renderer->element() : element();
2550     if (!node)
2551         return Position();
2552
2553     long offset = start ? node->caretMinOffset() : node->caretMaxOffset();
2554     return Position(node, offset);
2555 }
2556
2557 Position RenderBlock::positionForCoordinates(int _x, int _y, EAffinity *affinity)
2558 {
2559     if (affinity)
2560         *affinity = UPSTREAM;
2561
2562     if (isTable())
2563         return RenderFlow::positionForCoordinates(_x, _y, affinity); 
2564
2565     int absx, absy;
2566     absolutePosition(absx, absy);
2567
2568     int top = absy + borderTop() + paddingTop();
2569     int bottom = top + contentHeight();
2570
2571     if (_y < top)
2572         // y coordinate is above block
2573         return positionForRenderer(firstLeafChild(), true);
2574
2575     if (_y >= bottom)
2576         // y coordinate is below block
2577         return positionForRenderer(lastLeafChild(), false);
2578
2579     if (childrenInline()) {
2580         if (!firstRootBox())
2581             return Position(element(), 0);
2582             
2583         if (_y >= top && _y < absy + firstRootBox()->topOverflow())
2584             // y coordinate is above first root line box
2585             return positionForBox(firstRootBox()->firstLeafChild(), true);
2586         
2587         // look for the closest line box in the root box which is at the passed-in y coordinate
2588         for (RootInlineBox *root = firstRootBox(); root; root = root->nextRootBox()) {
2589             top = absy + root->topOverflow();
2590             // set the bottom based on whether there is a next root box
2591             if (root->nextRootBox())
2592                 bottom = absy + root->nextRootBox()->topOverflow();
2593             else
2594                 bottom = absy + root->bottomOverflow();
2595             // check if this root line box is located at this y coordinate
2596             if (_y >= top && _y < bottom && root->firstChild()) {
2597                 InlineBox *closestBox = root->closestLeafChildForXPos(_x, absx);
2598                 if (closestBox) {
2599                     // pass the box a y position that is inside it
2600                     return closestBox->object()->positionForCoordinates(_x, absy + closestBox->m_y, affinity);
2601                 }
2602             }
2603         }
2604
2605         if (lastRootBox())
2606             // y coordinate is below last root line box
2607             return positionForBox(lastRootBox()->lastLeafChild(), false);
2608         
2609         return Position(element(), 0);
2610     }
2611     
2612     // see if any child blocks exist at this y coordinate
2613     for (RenderObject *renderer = firstChild(); renderer; renderer = renderer->nextSibling()) {
2614         if (renderer->isFloatingOrPositioned())
2615             continue;
2616         renderer->absolutePosition(absx, top);
2617         RenderObject *next = renderer->nextSibling();
2618         while (next && next->isFloatingOrPositioned())
2619             next = next->nextSibling();
2620         if (next) 
2621             next->absolutePosition(absx, bottom);
2622         else
2623             bottom = top + contentHeight();
2624         if (_y >= top && _y < bottom) {
2625             return renderer->positionForCoordinates(_x, _y, affinity);
2626         }
2627     }
2628
2629     // pass along to the first child
2630     if (firstChild())
2631         return firstChild()->positionForCoordinates(_x, _y, affinity);
2632     
2633     // still no luck...return this render object's element and offset 0
2634     return Position(element(), 0);
2635 }
2636
2637 void RenderBlock::calcMinMaxWidth()
2638 {
2639     KHTMLAssert( !minMaxKnown() );
2640
2641 #ifdef DEBUG_LAYOUT
2642     kdDebug( 6040 ) << renderName() << "(RenderBlock)::calcMinMaxWidth() this=" << this << endl;
2643 #endif
2644
2645     m_minWidth = 0;
2646     m_maxWidth = 0;
2647
2648     bool preOrNowrap = style()->whiteSpace() != NORMAL;
2649     if (childrenInline())
2650         calcInlineMinMaxWidth();
2651     else
2652         calcBlockMinMaxWidth();
2653
2654     if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
2655
2656     if (preOrNowrap && childrenInline()) {
2657         m_minWidth = m_maxWidth;
2658         
2659         // A horizontal marquee with inline children has no minimum width.
2660         if (style()->overflow() == OMARQUEE && m_layer && m_layer->marquee() && 
2661             m_layer->marquee()->isHorizontal() && !m_layer->marquee()->isUnfurlMarquee())
2662             m_minWidth = 0;
2663     }
2664
2665     if (style()->width().isFixed() && style()->width().value > 0) {
2666         if (isTableCell())
2667             m_maxWidth = KMAX(m_minWidth, style()->width().value);
2668         else
2669             m_minWidth = m_maxWidth = style()->width().value;
2670     }
2671     
2672     if (style()->minWidth().isFixed() && style()->minWidth().value > 0) {
2673         m_maxWidth = KMAX(m_maxWidth, style()->minWidth().value);
2674         m_minWidth = KMAX(m_minWidth, style()->minWidth().value);
2675     }
2676     
2677     if (style()->maxWidth().isFixed() && style()->maxWidth().value != UNDEFINED) {
2678         m_maxWidth = KMIN(m_maxWidth, style()->maxWidth().value);
2679         m_minWidth = KMIN(m_minWidth, style()->maxWidth().value);
2680     }
2681
2682     int toAdd = 0;
2683     toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
2684
2685     m_minWidth += toAdd;
2686     m_maxWidth += toAdd;
2687
2688     setMinMaxKnown();
2689
2690     //kdDebug( 6040 ) << "Text::calcMinMaxWidth(" << this << "): min = " << m_minWidth << " max = " << m_maxWidth << endl;
2691 }
2692
2693 struct InlineMinMaxIterator
2694 {
2695 /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
2696    inline min/max width calculations.  Note the following about the way it walks:
2697    (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
2698    (2) We do not drill into the children of floats or replaced elements, since you can't break
2699        in the middle of such an element.
2700    (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
2701        distinct borders/margin/padding that contribute to the min/max width.
2702 */
2703     RenderObject* parent;
2704     RenderObject* current;
2705     bool endOfInline;
2706
2707     InlineMinMaxIterator(RenderObject* p, RenderObject* o, bool end = false)
2708         :parent(p), current(o), endOfInline(end) {}
2709
2710     RenderObject* next();
2711 };
2712
2713 RenderObject* InlineMinMaxIterator::next()
2714 {
2715     RenderObject* result = 0;
2716     bool oldEndOfInline = endOfInline;
2717     endOfInline = false;
2718     while (current != 0 || (current == parent))
2719     {
2720         //kdDebug( 6040 ) << "current = " << current << endl;
2721         if (!oldEndOfInline &&
2722             (current == parent ||
2723              (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
2724             result = current->firstChild();
2725         if (!result) {
2726             // We hit the end of our inline. (It was empty, e.g., <span></span>.)
2727             if (!oldEndOfInline && current->isInlineFlow()) {
2728                 result = current;
2729                 endOfInline = true;
2730                 break;
2731             }
2732
2733             while (current && current != parent) {
2734                 result = current->nextSibling();
2735                 if (result) break;
2736                 current = current->parent();
2737                 if (current && current != parent && current->isInlineFlow()) {
2738                     result = current;
2739                     endOfInline = true;
2740                     break;
2741                 }
2742             }
2743         }
2744
2745         if (!result) break;
2746
2747         if (!result->isPositioned() && (result->isText() || result->isBR() ||
2748             result->isFloating() || result->isReplaced() ||
2749             result->isInlineFlow()))
2750             break;
2751         
2752         current = result;
2753         result = 0;
2754     }
2755
2756     // Update our position.
2757     current = result;
2758     return current;
2759 }
2760
2761 static int getBPMWidth(int childValue, Length cssUnit)
2762 {
2763     if (cssUnit.type != Variable)
2764         return (cssUnit.type == Fixed ? cssUnit.value : childValue);
2765     return 0;
2766 }
2767
2768 static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
2769 {
2770     RenderStyle* cstyle = child->style();
2771     int result = 0;
2772     bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
2773     result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
2774                           (leftSide ? cstyle->marginLeft() :
2775                                       cstyle->marginRight()));
2776     result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
2777                           (leftSide ? cstyle->paddingLeft() :
2778                                       cstyle->paddingRight()));
2779     result += leftSide ? child->borderLeft() : child->borderRight();
2780     return result;
2781 }
2782
2783 static void stripTrailingSpace(bool pre,
2784                                int& inlineMax, int& inlineMin,
2785                                RenderObject* trailingSpaceChild)
2786 {
2787     if (!pre && trailingSpaceChild && trailingSpaceChild->isText()) {
2788         // Collapse away the trailing space at the end of a block.
2789         RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
2790         const Font *f = t->htmlFont( false );
2791         QChar space[1]; space[0] = ' ';
2792         int spaceWidth = f->width(space, 1, 0);
2793         inlineMax -= spaceWidth;
2794         if (inlineMin > inlineMax)
2795             inlineMin = inlineMax;
2796     }
2797 }
2798
2799 void RenderBlock::calcInlineMinMaxWidth()
2800 {
2801     int inlineMax=0;
2802     int inlineMin=0;
2803
2804     int cw = containingBlock()->contentWidth();
2805
2806     // If we are at the start of a line, we want to ignore all white-space.
2807     // Also strip spaces if we previously had text that ended in a trailing space.
2808     bool stripFrontSpaces = true;
2809     RenderObject* trailingSpaceChild = 0;
2810
2811     bool normal, oldnormal;
2812     normal = oldnormal = style()->whiteSpace() == NORMAL;
2813
2814     InlineMinMaxIterator childIterator(this, this);
2815     bool addedTextIndent = false; // Only gets added in once.
2816     RenderObject* prevFloat = 0;
2817     while (RenderObject* child = childIterator.next())
2818     {
2819         normal = child->style()->whiteSpace() == NORMAL;
2820
2821         if (!child->isBR()) {
2822             // Step One: determine whether or not we need to go ahead and
2823             // terminate our current line.  Each discrete chunk can become
2824             // the new min-width, if it is the widest chunk seen so far, and
2825             // it can also become the max-width.
2826
2827             // Children fall into three categories:
2828             // (1) An inline flow object.  These objects always have a min/max of 0,
2829             // and are included in the iteration solely so that their margins can
2830             // be added in.
2831             //
2832             // (2) An inline non-text non-flow object, e.g., an inline replaced element.
2833             // These objects can always be on a line by themselves, so in this situation
2834             // we need to go ahead and break the current line, and then add in our own
2835             // margins and min/max width on its own line, and then terminate the line.
2836             //
2837             // (3) A text object.  Text runs can have breakable characters at the start,
2838             // the middle or the end.  They may also lose whitespace off the front if
2839             // we're already ignoring whitespace.  In order to compute accurate min-width
2840             // information, we need three pieces of information.
2841             // (a) the min-width of the first non-breakable run.  Should be 0 if the text string
2842             // starts with whitespace.
2843             // (b) the min-width of the last non-breakable run. Should be 0 if the text string
2844             // ends with whitespace.
2845             // (c) the min/max width of the string (trimmed for whitespace).
2846             //
2847             // If the text string starts with whitespace, then we need to go ahead and
2848             // terminate our current line (unless we're already in a whitespace stripping
2849             // mode.
2850             //
2851             // If the text string has a breakable character in the middle, but didn't start
2852             // with whitespace, then we add the width of the first non-breakable run and
2853             // then end the current line.  We then need to use the intermediate min/max width
2854             // values (if any of them are larger than our current min/max).  We then look at
2855             // the width of the last non-breakable run and use that to start a new line
2856             // (unless we end in whitespace).
2857             RenderStyle* cstyle = child->style();
2858             int childMin = 0;
2859             int childMax = 0;
2860
2861             if (!child->isText()) {
2862                 // Case (1) and (2).  Inline replaced and inline flow elements.
2863                 if (child->isInlineFlow()) {
2864                     // Add in padding/border/margin from the appropriate side of
2865                     // the element.
2866                     int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
2867                     childMin += bpm;
2868                     childMax += bpm;
2869
2870                     inlineMin += childMin;
2871                     inlineMax += childMax;
2872                 }
2873                 else {
2874                     // Inline replaced elts add in their margins to their min/max values.
2875                     int margins = 0;
2876                     LengthType type = cstyle->marginLeft().type;
2877                     if ( type != Variable )
2878                         margins += (type == Fixed ? cstyle->marginLeft().value : child->marginLeft());
2879                     type = cstyle->marginRight().type;
2880                     if ( type != Variable )
2881                         margins += (type == Fixed ? cstyle->marginRight().value : child->marginRight());
2882                     childMin += margins;
2883                     childMax += margins;
2884                 }
2885             }
2886
2887             if (!child->isRenderInline() && !child->isText()) {
2888                 // Case (2). Inline replaced elements and floats.
2889                 // Go ahead and terminate the current line as far as
2890                 // minwidth is concerned.
2891                 childMin += child->minWidth();
2892                 childMax += child->maxWidth();
2893
2894                 if (normal || oldnormal) {
2895                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2896                     inlineMin = 0;
2897                 }
2898
2899                 // Check our "clear" setting.  If we're supposed to clear the previous float, then
2900                 // go ahead and terminate maxwidth as well.
2901                 if (child->isFloating()) {
2902                     if (prevFloat &&
2903                         ((prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT)) ||
2904                          (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT)))) {
2905                         m_maxWidth = kMax(inlineMax, m_maxWidth);
2906                         inlineMax = 0;
2907                     }
2908                     prevFloat = child;
2909                 }
2910                 
2911                 // Add in text-indent.  This is added in only once.
2912                 int ti = 0;
2913                 if (!addedTextIndent) {
2914                     addedTextIndent = true;
2915                     ti = style()->textIndent().minWidth(cw);
2916                     childMin+=ti;
2917                     childMax+=ti;
2918                 }
2919                 
2920                 // Add our width to the max.
2921                 inlineMax += childMax;
2922
2923                 if (!normal)
2924                     inlineMin += childMin;
2925                 else {
2926                     // Now check our line.
2927                     inlineMin = childMin;
2928                     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2929
2930                     // Now start a new line.
2931                     inlineMin = 0;
2932                 }
2933
2934                 // We are no longer stripping whitespace at the start of
2935                 // a line.
2936                 if (!child->isFloating()) {
2937                     stripFrontSpaces = false;
2938                     trailingSpaceChild = 0;
2939                 }
2940             }
2941             else if (child->isText())
2942             {
2943                 // Case (3). Text.
2944                 RenderText* t = static_cast<RenderText *>(child);
2945
2946                 // Determine if we have a breakable character.  Pass in
2947                 // whether or not we should ignore any spaces at the front
2948                 // of the string.  If those are going to be stripped out,
2949                 // then they shouldn't be considered in the breakable char
2950                 // check.
2951                 bool hasBreakableChar, hasBreak;
2952                 int beginMin, endMin;
2953                 bool beginWS, endWS;
2954                 int beginMax, endMax;
2955                 t->trimmedMinMaxWidth(beginMin, beginWS, endMin, endWS, hasBreakableChar,
2956                                       hasBreak, beginMax, endMax,
2957                                       childMin, childMax, stripFrontSpaces);
2958
2959                 // This text object is insignificant and will not be rendered.  Just
2960                 // continue.
2961                 if (!hasBreak && childMax == 0) continue;
2962                 
2963                 if (stripFrontSpaces)
2964                     trailingSpaceChild = child;
2965                 else
2966                     trailingSpaceChild = 0;
2967
2968                 // Add in text-indent.  This is added in only once.
2969                 int ti = 0;
2970                 if (!addedTextIndent) {
2971                     addedTextIndent = true;
2972                     ti = style()->textIndent().minWidth(cw);
2973                     childMin+=ti; beginMin += ti;
2974                     childMax+=ti; beginMax += ti;
2975                 }
2976                 
2977                 // If we have no breakable characters at all,
2978                 // then this is the easy case. We add ourselves to the current
2979                 // min and max and continue.
2980                 if (!hasBreakableChar) {
2981                     inlineMin += childMin;
2982                 }
2983                 else {
2984                     // We have a breakable character.  Now we need to know if
2985                     // we start and end with whitespace.
2986                     if (beginWS) {
2987                         // Go ahead and end the current line.
2988                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2989                     }
2990                     else {
2991                         inlineMin += beginMin;
2992                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
2993                         childMin -= ti;
2994                     }
2995
2996                     inlineMin = childMin;
2997
2998                     if (endWS) {
2999                         // We end in whitespace, which means we can go ahead
3000                         // and end our current line.
3001                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3002                         inlineMin = 0;
3003                     }
3004                     else {
3005                         if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3006                         inlineMin = endMin;
3007                     }
3008                 }
3009
3010                 if (hasBreak) {
3011                     inlineMax += beginMax;
3012                     if (m_maxWidth < inlineMax) m_maxWidth = inlineMax;
3013                     if (m_maxWidth < childMax) m_maxWidth = childMax;
3014                     inlineMax = endMax;
3015                 }
3016                 else
3017                     inlineMax += childMax;
3018             }
3019         }
3020         else
3021         {
3022             if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3023             if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
3024             inlineMin = inlineMax = 0;
3025             stripFrontSpaces = true;
3026             trailingSpaceChild = 0;
3027         }
3028
3029         oldnormal = normal;
3030     }
3031
3032     stripTrailingSpace(m_pre, inlineMax, inlineMin, trailingSpaceChild);
3033     
3034     if(m_minWidth < inlineMin) m_minWidth = inlineMin;
3035     if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
3036
3037     //         kdDebug( 6040 ) << "m_minWidth=" << m_minWidth
3038     //                  << " m_maxWidth=" << m_maxWidth << endl;
3039 }
3040
3041 // Use a very large value (in effect infinite).
3042 #define BLOCK_MAX_WIDTH 15000
3043
3044 void RenderBlock::calcBlockMinMaxWidth()
3045 {
3046     bool nowrap = style()->whiteSpace() == NOWRAP;
3047
3048     RenderObject *child = firstChild();
3049     int floatLeftWidth = 0, floatRightWidth = 0;
3050     while (child) {
3051         // Positioned children don't affect the min/max width
3052         if (child->isPositioned()) {
3053             child = child->nextSibling();
3054             continue;
3055         }
3056
3057         if (child->isFloating() || child->avoidsFloats()) {
3058             int floatTotalWidth = floatLeftWidth + floatRightWidth;
3059             if (child->style()->clear() & CLEFT) {
3060                 m_maxWidth = kMax(floatTotalWidth, m_maxWidth);
3061                 floatLeftWidth = 0;
3062             }
3063             if (child->style()->clear() & CRIGHT) {
3064                 m_maxWidth = kMax(floatTotalWidth, m_maxWidth);
3065                 floatRightWidth = 0;
3066             }
3067         }
3068
3069         Length ml = child->style()->marginLeft();
3070         Length mr = child->style()->marginRight();
3071
3072         // Call calcWidth on the child to ensure that our margins are
3073         // up to date.  This method can be called before the child has actually
3074         // calculated its margins (which are computed inside calcWidth).
3075         if (ml.type == Percent || mr.type == Percent)
3076             calcWidth();
3077
3078         // A margin basically has three types: fixed, percentage, and auto (variable).
3079         // Auto margins simply become 0 when computing min/max width.
3080         // Fixed margins can be added in as is.
3081         // Percentage margins are computed as a percentage of the width we calculated in
3082         // the calcWidth call above.  In this case we use the actual cached margin values on
3083         // the RenderObject itself.
3084         int margin = 0, marginLeft = 0, marginRight = 0;
3085         if (ml.type == Fixed)
3086             marginLeft += ml.value;
3087         else if (ml.type == Percent)
3088             marginLeft += child->marginLeft();
3089         marginLeft = kMax(0, marginLeft);
3090         if (mr.type == Fixed)
3091             marginRight += mr.value;
3092         else if (mr.type == Percent)
3093             marginRight += child->marginRight();
3094         marginRight = kMax(0, marginRight);
3095         margin = marginLeft + marginRight;
3096
3097         int w = child->minWidth() + margin;
3098         if (m_minWidth < w) m_minWidth = w;
3099         
3100         // IE ignores tables for calculation of nowrap. Makes some sense.
3101         if (nowrap && !child->isTable() && m_maxWidth < w)
3102             m_maxWidth = w;
3103
3104         w = child->maxWidth() + margin;
3105
3106         if (!child->isFloating()) {
3107             if (child->avoidsFloats()) {
3108                 // Determine a left and right max value based off whether or not the floats can fit in the
3109                 // margins of the object.
3110                 int maxLeft = kMax(floatLeftWidth, marginLeft);
3111                 int maxRight = kMax(floatRightWidth, marginRight);
3112                 w = child->maxWidth() + maxLeft + maxRight;
3113             }
3114             else
3115                 m_maxWidth = kMax(floatLeftWidth + floatRightWidth, m_maxWidth);
3116             floatLeftWidth = floatRightWidth = 0;
3117         }
3118         
3119         if (child->isFloating()) {
3120             if (style()->floating() == FLEFT)
3121                 floatLeftWidth += w;
3122             else
3123                 floatRightWidth += w;
3124         }
3125         else if (m_maxWidth < w)
3126             m_maxWidth = w;
3127
3128         // A very specific WinIE quirk.
3129         // Example:
3130         /*
3131            <div style="position:absolute; width:100px; top:50px;">
3132               <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
3133                 <table style="width:100%"><tr><td></table>
3134               </div>
3135            </div>
3136         */
3137         // In the above example, the inner absolute positioned block should have a computed width
3138         // of 100px because of the table.
3139         // We can achieve this effect by making the maxwidth of blocks that contain tables
3140         // with percentage widths be infinite (as long as they are not inside a table cell).
3141         if (style()->htmlHacks() && child->style()->width().type == Percent &&
3142             !isTableCell() && child->isTable() && m_maxWidth < BLOCK_MAX_WIDTH) {
3143             RenderBlock* cb = containingBlock();
3144             while (!cb->isCanvas() && !cb->isTableCell())
3145                 cb = cb->containingBlock();
3146             if (!cb->isTableCell())
3147                 m_maxWidth = BLOCK_MAX_WIDTH;
3148         }
3149         
3150         child = child->nextSibling();
3151     }
3152     
3153     m_maxWidth = kMax(floatLeftWidth + floatRightWidth, m_maxWidth);
3154 }
3155
3156 short RenderBlock::lineHeight(bool b, bool isRootLineBox) const
3157 {
3158     // Inline blocks are replaced elements. Otherwise, just pass off to
3159     // the base class.  If we're being queried as though we're the root line
3160     // box, then the fact that we're an inline-block is irrelevant, and we behave
3161     // just like a block.
3162     if (isReplaced() && !isRootLineBox)
3163         return height()+marginTop()+marginBottom();
3164     return RenderFlow::lineHeight(b, isRootLineBox);
3165 }
3166
3167 short RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
3168 {
3169     // Inline blocks are replaced elements. Otherwise, just pass off to
3170     // the base class.  If we're being queried as though we're the root line
3171     // box, then the fact that we're an inline-block is irrelevant, and we behave
3172     // just like a block.
3173     if (isReplaced() && !isRootLineBox)
3174         return height() + marginTop() + marginBottom();
3175     return RenderFlow::baselinePosition(b, isRootLineBox);
3176 }
3177
3178 int RenderBlock::getBaselineOfFirstLineBox() const
3179 {
3180     if (!isBlockFlow())
3181         return RenderFlow::getBaselineOfFirstLineBox();
3182
3183     if (childrenInline()) {
3184         if (m_firstLineBox)
3185             return m_firstLineBox->yPos() + m_firstLineBox->baseline();
3186         else
3187             return -1;
3188     }
3189     else {
3190         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
3191             if (!curr->isFloatingOrPositioned()) {
3192                 int result = curr->getBaselineOfFirstLineBox();
3193                 if (result != -1)
3194                     return curr->yPos() + result; // Translate to our coordinate space.
3195             }
3196         }