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