Fix the crash in the layout tests caused by my recent selection changes. Simply...
[WebKit-https.git] / WebCore / khtml / rendering / render_object.cpp
1 /**
2  * This file is part of the html renderer for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2000 Dirk Mueller (mueller@kde.org)
7  * Copyright (C) 2003 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  *
24  */
25
26 #include "rendering/render_object.h"
27 #include "rendering/render_table.h"
28 #include "rendering/render_text.h"
29 #include "rendering/render_line.h"
30 #include "rendering/render_list.h"
31 #include "rendering/render_canvas.h"
32 #include "xml/dom_elementimpl.h"
33 #include "xml/dom2_eventsimpl.h"
34 #include "xml/dom_docimpl.h"
35 #include "xml/dom_position.h"
36 #include "css/cssstyleselector.h"
37 #include "misc/htmlhashes.h"
38 #include <kdebug.h>
39 #include <qpainter.h>
40 #include "khtmlview.h"
41 #include "khtml_part.h"
42 #include "render_arena.h"
43 #include "render_inline.h"
44 #include "render_block.h"
45 #include "render_flexbox.h"
46
47 #if APPLE_CHANGES
48 // For accessibility
49 #include "KWQAccObjectCache.h" 
50 #endif
51
52 #include <assert.h>
53 using namespace DOM;
54 using namespace khtml;
55
56 #ifndef NDEBUG
57 static void *baseOfRenderObjectBeingDeleted;
58 #endif
59
60 void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
61 {
62     return renderArena->allocate(sz);
63 }
64
65 void RenderObject::operator delete(void* ptr, size_t sz)
66 {
67     assert(baseOfRenderObjectBeingDeleted == ptr);
68     
69     // Stash size where detach can find it.
70     *(size_t *)ptr = sz;
71 }
72
73 RenderObject *RenderObject::createObject(DOM::NodeImpl* node,  RenderStyle* style)
74 {
75     RenderObject *o = 0;
76     RenderArena* arena = node->getDocument()->renderArena();
77     switch(style->display())
78     {
79     case NONE:
80         break;
81     case INLINE:
82         o = new (arena) RenderInline(node);
83         break;
84     case BLOCK:
85         o = new (arena) RenderBlock(node);
86         break;
87     case INLINE_BLOCK:
88         o = new (arena) RenderBlock(node);
89         break;
90     case LIST_ITEM:
91         o = new (arena) RenderListItem(node);
92         break;
93     case RUN_IN:
94     case COMPACT:
95         o = new (arena) RenderBlock(node);
96         break;
97     case TABLE:
98     case INLINE_TABLE:
99         //kdDebug( 6040 ) << "creating RenderTable" << endl;
100         o = new (arena) RenderTable(node);
101         break;
102     case TABLE_ROW_GROUP:
103     case TABLE_HEADER_GROUP:
104     case TABLE_FOOTER_GROUP:
105         o = new (arena) RenderTableSection(node);
106         break;
107     case TABLE_ROW:
108         o = new (arena) RenderTableRow(node);
109         break;
110     case TABLE_COLUMN_GROUP:
111     case TABLE_COLUMN:
112         o = new (arena) RenderTableCol(node);
113         break;
114     case TABLE_CELL:
115         o = new (arena) RenderTableCell(node);
116         break;
117     case TABLE_CAPTION:
118         o = new (arena) RenderBlock(node);
119         break;
120     case BOX:
121     case INLINE_BOX:
122         o = new (arena) RenderFlexibleBox(node);
123         break;
124     }
125     return o;
126 }
127
128 RenderObject::RenderObject(DOM::NodeImpl* node)
129     : CachedObjectClient(),
130 m_style( 0 ),
131 m_node( node ),
132 m_parent( 0 ),
133 m_previous( 0 ),
134 m_next( 0 ),
135 m_verticalPosition( PositionUndefined ),
136 m_needsLayout( false ),
137 m_normalChildNeedsLayout( false ),
138 m_posChildNeedsLayout( false ),
139 m_minMaxKnown( false ),
140 m_floating( false ),
141
142 m_positioned( false ),
143 m_relPositioned( false ),
144 m_paintBackground( false ),
145
146 m_isAnonymous( node == node->getDocument() ),
147 m_recalcMinMax( false ),
148 m_isText( false ),
149 m_inline( true ),
150
151 m_replaced( false ),
152 m_mouseInside( false ),
153 m_isDragging( false ),
154 m_hasOverflowClip(false)
155 {
156 }
157
158 RenderObject::~RenderObject()
159 {
160 }
161
162 bool RenderObject::hasAncestor(const RenderObject *obj) const
163 {
164     for (const RenderObject *r = this; r; r = r->m_parent)
165         if (r == obj)
166             return true;
167     return false;
168 }
169
170 bool RenderObject::isRoot() const
171 {
172     return element() && element()->renderer() == this &&
173            element()->getDocument()->documentElement() == element();
174 }
175
176 bool RenderObject::isBody() const
177 {
178     return element() && element()->renderer() == this && element()->id() == ID_BODY;
179 }
180
181 bool RenderObject::isHR() const
182 {
183     return element() && element()->id() == ID_HR;
184 }
185
186 bool RenderObject::isHTMLMarquee() const
187 {
188     return element() && element()->renderer() == this && element()->id() == ID_MARQUEE;
189 }
190
191 bool RenderObject::canHaveChildren() const
192 {
193     return false;
194 }
195
196 RenderFlow* RenderObject::continuation() const
197 {
198     return 0;
199 }
200
201 bool RenderObject::isInlineContinuation() const
202 {
203     return false;
204 }
205
206 void RenderObject::addChild(RenderObject* , RenderObject *)
207 {
208     KHTMLAssert(0);
209 }
210
211 RenderObject* RenderObject::removeChildNode(RenderObject* )
212 {
213     KHTMLAssert(0);
214     return 0;
215 }
216
217 void RenderObject::removeChild(RenderObject* )
218 {
219     KHTMLAssert(0);
220 }
221
222 void RenderObject::appendChildNode(RenderObject*)
223 {
224     KHTMLAssert(0);
225 }
226
227 void RenderObject::insertChildNode(RenderObject*, RenderObject*)
228 {
229     KHTMLAssert(0);
230 }
231
232 RenderObject *RenderObject::nextRenderer() const
233 {
234     if (firstChild())
235         return firstChild();
236     else if (nextSibling())
237         return nextSibling();
238     else {
239         const RenderObject *r = this;
240         while (r && !r->nextSibling())
241             r = r->parent();
242         if (r)
243             return r->nextSibling();
244     }
245     return 0;
246 }
247
248 RenderObject *RenderObject::previousRenderer() const
249 {
250     if (previousSibling()) {
251         RenderObject *r = previousSibling();
252         while (r->lastChild())
253             r = r->lastChild();
254         return r;
255     }
256     else if (parent()) {
257         return parent();
258     }
259     else {
260         return 0;
261     }
262 }
263
264 bool RenderObject::isEditable() const
265 {
266     RenderText *textRenderer = 0;
267     if (isText()) {
268         textRenderer = static_cast<RenderText *>(const_cast<RenderObject *>(this));
269     }
270
271     return style()->visibility() == VISIBLE && 
272         element() && element()->isContentEditable() &&
273         ((isBlockFlow() && !firstChild()) || 
274         isReplaced() || 
275         isBR() || 
276         (textRenderer && textRenderer->firstTextBox()));
277 }
278
279 RenderObject *RenderObject::nextEditable() const
280 {
281     RenderObject *r = const_cast<RenderObject *>(this);
282     RenderObject *n = firstChild();
283     if (n) {
284         while (n) { 
285             r = n; 
286             n = n->firstChild(); 
287         }
288         if (r->isEditable())
289             return r;
290         else 
291             return r->nextEditable();
292     }
293     n = r->nextSibling();
294     if (n) {
295         r = n;
296         while (n) { 
297             r = n; 
298             n = n->firstChild(); 
299         }
300         if (r->isEditable())
301             return r;
302         else 
303             return r->nextEditable();
304     }
305     n = r->parent();
306     while (n) {
307         r = n;
308         n = r->nextSibling();
309         if (n) {
310             r = n;
311             n = r->firstChild();
312             while (n) { 
313                 r = n; 
314                 n = n->firstChild(); 
315             }
316             if (r->isEditable())
317                 return r;
318             else 
319                 return r->nextEditable();
320         }
321         n = r->parent();
322     }
323     return 0;
324 }
325
326 RenderObject *RenderObject::previousEditable() const
327 {
328     RenderObject *r = const_cast<RenderObject *>(this);
329     RenderObject *n = firstChild();
330     if (n) {
331         while (n) { 
332             r = n; 
333             n = n->lastChild(); 
334         }
335         if (r->isEditable())
336             return r;
337         else 
338             return r->previousEditable();
339     }
340     n = r->previousSibling();
341     if (n) {
342         r = n;
343         while (n) { 
344             r = n; 
345             n = n->lastChild(); 
346         }
347         if (r->isEditable())
348             return r;
349         else 
350             return r->previousEditable();
351     }    
352     n = r->parent();
353     while (n) {
354         r = n;
355         n = r->previousSibling();
356         if (n) {
357             r = n;
358             n = r->lastChild();
359             while (n) { 
360                 r = n; 
361                 n = n->lastChild(); 
362             }
363             if (r->isEditable())
364                 return r;
365             else 
366                 return r->previousEditable();
367         }
368         n = r->parent();
369     }
370     return 0;
371
372
373 RenderObject *RenderObject::firstLeafChild() const
374 {
375     RenderObject *r = firstChild();
376     while (r) {
377         RenderObject *n = 0;
378         n = r->firstChild();
379         if (!n)
380             break;
381         r = n;
382     }
383     return r;
384 }
385
386 RenderObject *RenderObject::lastLeafChild() const
387 {
388     RenderObject *r = lastChild();
389     while (r) {
390         RenderObject *n = 0;
391         n = r->lastChild();
392         if (!n)
393             break;
394         r = n;
395     }
396     return r;
397 }
398
399 static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject,
400                       RenderLayer*& beforeChild)
401 {
402     if (obj->layer()) {
403         if (!beforeChild && newObject) {
404             // We need to figure out the layer that follows newObject.  We only do
405             // this the first time we find a child layer, and then we update the
406             // pointer values for newObject and beforeChild used by everyone else.
407             beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
408             newObject = 0;
409         }
410         parentLayer->addChild(obj->layer(), beforeChild);
411         return;
412     }
413
414     for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
415         addLayers(curr, parentLayer, newObject, beforeChild);
416 }
417
418 void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
419 {
420     if (!parentLayer)
421         return;
422     
423     RenderObject* object = newObject;
424     RenderLayer* beforeChild = 0;
425     ::addLayers(this, parentLayer, object, beforeChild);
426 }
427
428 void RenderObject::removeLayers(RenderLayer* parentLayer)
429 {
430     if (!parentLayer)
431         return;
432     
433     if (layer()) {
434         parentLayer->removeChild(layer());
435         return;
436     }
437
438     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
439         curr->removeLayers(parentLayer);
440 }
441
442 void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
443 {
444     if (!newParent)
445         return;
446     
447     if (layer()) {
448         if (oldParent)
449             oldParent->removeChild(layer());
450         newParent->addChild(layer());
451         return;
452     }
453
454     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
455         curr->moveLayers(oldParent, newParent);
456 }
457
458 RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
459                                          bool checkParent)
460 {
461     // Error check the parent layer passed in.  If it's null, we can't find anything.
462     if (!parentLayer)
463         return 0;
464         
465     // Step 1: Descend into our siblings trying to find the next layer.  If we do find
466     // a layer, and if its parent layer matches our desired parent layer, then we have
467     // a match.
468     for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
469          curr; curr = curr->nextSibling()) {
470         RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
471         if (nextLayer) {
472             if (nextLayer->parent() == parentLayer)
473                 return nextLayer;
474             return 0;
475         }
476     }
477     
478     // Step 2: If our layer is the desired parent layer, then we're finished.  We didn't
479     // find anything.
480     RenderLayer* ourLayer = layer();
481     if (parentLayer == ourLayer)
482         return 0;
483     
484     // Step 3: If we have a layer, then return that layer.  It will be checked against
485     // the desired parent layer in the for loop above.
486     if (ourLayer)
487         return ourLayer;
488     
489     // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
490     // follow us to see if we can locate a layer.
491     if (checkParent && parent())
492         return parent()->findNextLayer(parentLayer, this, true);
493     
494     return 0;
495 }
496     
497 RenderLayer* RenderObject::enclosingLayer()
498 {
499     RenderObject* curr = this;
500     while (curr) {
501         RenderLayer *layer = curr->layer();
502         if (layer)
503             return layer;
504         curr = curr->parent();
505     }
506     return 0;
507 }
508
509 bool RenderObject::requiresLayer()
510 {
511     return isRoot() || isPositioned() || isRelPositioned() || style()->opacity() < 1.0f ||
512            m_hasOverflowClip;
513 }
514
515 RenderBlock* RenderObject::firstLineBlock() const
516 {
517     return 0;
518 }
519
520 void RenderObject::updateFirstLetter()
521 {}
522
523 int RenderObject::offsetLeft() const
524 {
525     int x = xPos();
526     if (!isPositioned()) {
527         if (isRelPositioned()) {
528             int y = 0;
529             ((RenderBox*)this)->relativePositionOffset(x, y);
530         }
531         
532         RenderObject* offsetPar = offsetParent();
533         RenderObject* curr = parent();
534         while (curr && curr != offsetPar) {
535             x += curr->xPos();
536             curr = curr->parent();
537         }
538     }
539     return x;
540 }
541
542 int RenderObject::offsetTop() const
543 {
544     int y = yPos();
545     if (!isPositioned()) {
546         if (isRelPositioned()) {
547             int x = 0;
548             ((RenderBox*)this)->relativePositionOffset(x, y);
549         }
550         RenderObject* offsetPar = offsetParent();
551         RenderObject* curr = parent();
552         while (curr && curr != offsetPar) {
553             y += curr->yPos();
554             curr = curr->parent();
555         }
556     }
557     return y;
558 }
559     
560 RenderObject* RenderObject::offsetParent() const
561 {
562     bool skipTables = isPositioned() || isRelPositioned();
563     RenderObject* curr = parent();
564     while (curr && !curr->isPositioned() && !curr->isRelPositioned() &&
565            !curr->isBody()) {
566         if (!skipTables && (curr->isTableCell() || curr->isTable()))
567             break;
568         curr = curr->parent();
569     }
570     return curr;
571 }
572
573 // More IE extensions.  clientWidth and clientHeight represent the interior of an object
574 // excluding border and scrollbar.
575 int
576 RenderObject::clientWidth() const
577 {
578     return width() - borderLeft() - borderRight() -
579         (includeScrollbarSize() ? layer()->verticalScrollbarWidth() : 0);
580 }
581
582 int
583 RenderObject::clientHeight() const
584 {
585     return height() - borderTop() - borderBottom() -
586       (includeScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0);
587 }
588
589 // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
590 // object has overflow:hidden/scroll/auto specified and also has overflow.
591 int
592 RenderObject::scrollWidth() const
593 {
594     return hasOverflowClip() ? layer()->scrollWidth() : overflowWidth();
595 }
596
597 int
598 RenderObject::scrollHeight() const
599 {
600     return hasOverflowClip() ? layer()->scrollHeight() : overflowHeight();
601 }
602
603 bool
604 RenderObject::hasStaticX() const
605 {
606     return (style()->left().isVariable() && style()->right().isVariable()) ||
607             style()->left().isStatic() ||
608             style()->right().isStatic();
609 }
610
611 bool
612 RenderObject::hasStaticY() const
613 {
614     return (style()->top().isVariable() && style()->bottom().isVariable()) || style()->top().isStatic();
615 }
616
617 void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
618 {
619 }
620
621 void RenderObject::setNeedsLayout(bool b, bool markParents) 
622 {
623     bool alreadyNeededLayout = m_needsLayout;
624     m_needsLayout = b;
625     if (b) {
626         if (!alreadyNeededLayout && markParents)
627             markContainingBlocksForLayout();
628     }
629     else {
630         m_posChildNeedsLayout = false;
631         m_normalChildNeedsLayout = false;
632     }
633 }
634
635 void RenderObject::setChildNeedsLayout(bool b, bool markParents)
636 {
637     bool alreadyNeededLayout = m_normalChildNeedsLayout;
638     m_normalChildNeedsLayout = b;
639     if (b) {
640         if (!alreadyNeededLayout && markParents)
641             markContainingBlocksForLayout();
642     }
643     else {
644         m_posChildNeedsLayout = false;
645         m_normalChildNeedsLayout = false;
646     }
647 }
648
649 void RenderObject::markContainingBlocksForLayout()
650 {
651     RenderObject *o = container();
652     RenderObject *last = this;
653
654     while (o) {
655         if (!last->isText() && (last->style()->position() == FIXED || last->style()->position() == ABSOLUTE)) {
656             if (o->m_posChildNeedsLayout)
657                 return;
658             o->m_posChildNeedsLayout = true;
659         }
660         else {
661             if (o->m_normalChildNeedsLayout)
662                 return;
663             o->m_normalChildNeedsLayout = true;
664         }
665
666         last = o;
667         o = o->container();
668     }
669
670     last->scheduleRelayout();
671 }
672
673 RenderBlock* RenderObject::containingBlock() const
674 {
675     if(isTableCell())
676         return static_cast<const RenderTableCell *>(this)->table();
677     if (isCanvas())
678         return (RenderBlock*)this;
679
680     RenderObject *o = parent();
681     if (!isText() && m_style->position() == FIXED) {
682         while ( o && !o->isCanvas() )
683             o = o->parent();
684     }
685     else if (!isText() && m_style->position() == ABSOLUTE) {
686         while (o && (o->style()->position() == STATIC || (o->isInline() && !o->isReplaced()))
687                && !o->isRoot() && !o->isCanvas()) {
688             // For relpositioned inlines, we return the nearest enclosing block.  We don't try
689             // to return the inline itself.  This allows us to avoid having a positioned objects
690             // list in all RenderInlines and lets us return a strongly-typed RenderBlock* result
691             // from this method.  The container() method can actually be used to obtain the
692             // inline directly.
693             if (o->style()->position() == RELATIVE && o->isInline() && !o->isReplaced())
694                 return o->containingBlock();
695             o = o->parent();
696         }
697     } else {
698         while (o && ((o->isInline() && !o->isReplaced()) || o->isTableRow() || o->isTableSection()
699                      || o->isTableCol()))
700             o = o->parent();
701     }
702
703     if (!o || !o->isRenderBlock())
704         return 0; // Probably doesn't happen any more, but leave just in case. -dwh
705     
706     return static_cast<RenderBlock*>(o);
707 }
708
709 int RenderObject::containingBlockWidth() const
710 {
711     // ###
712     return containingBlock()->contentWidth();
713 }
714
715 int RenderObject::containingBlockHeight() const
716 {
717     // ###
718     return containingBlock()->contentHeight();
719 }
720
721 bool RenderObject::sizesToMaxWidth() const
722 {
723     // Marquees in WinIE are like a mixture of blocks and inline-blocks.  They size as though they're blocks,
724     // but they allow text to sit on the same line as the marquee.
725     if (isFloating() || isCompact() || 
726         (isInlineBlockOrInlineTable() && !isHTMLMarquee()) ||
727         (element() && (element()->id() == ID_BUTTON || element()->id() == ID_LEGEND)))
728         return true;
729     
730     // Children of a horizontal marquee do not fill the container by default.
731     // FIXME: Need to deal with MAUTO value properly.  It could be vertical.
732     if (parent()->style()->overflow() == OMARQUEE) {
733         EMarqueeDirection dir = parent()->style()->marqueeDirection();
734         if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
735             return true;
736     }
737     
738     // Flexible horizontal boxes lay out children at their maxwidths.  Also vertical boxes
739     // that don't stretch their kids lay out their children at their maxwidths.
740     if (parent()->isFlexibleBox() &&
741         (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
742         return true;
743
744     return false;
745 }
746
747 void RenderObject::drawBorder(QPainter *p, int x1, int y1, int x2, int y2,
748                               BorderSide s, QColor c, const QColor& textcolor, EBorderStyle style,
749                               int adjbw1, int adjbw2, bool invalidisInvert)
750 {
751     int width = (s==BSTop||s==BSBottom?y2-y1:x2-x1);
752
753     if(style == DOUBLE && width < 3)
754         style = SOLID;
755
756     if(!c.isValid()) {
757         if(invalidisInvert)
758         {
759             p->setRasterOp(Qt::XorROP);
760             c = Qt::white;
761         }
762         else {
763             if(style == INSET || style == OUTSET || style == RIDGE || style ==
764             GROOVE)
765                 c.setRgb(238, 238, 238);
766             else
767                 c = textcolor;
768         }
769     }
770
771     switch(style)
772     {
773     case BNONE:
774     case BHIDDEN:
775         // should not happen
776         if(invalidisInvert && p->rasterOp() == Qt::XorROP)
777             p->setRasterOp(Qt::CopyROP);
778
779         return;
780     case DOTTED:
781         p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DotLine));
782         /* nobreak; */
783     case DASHED:
784         if(style == DASHED)
785             p->setPen(QPen(c, width == 1 ? 0 : width, Qt::DashLine));
786
787         if (width > 0)
788             switch(s)
789             {
790             case BSBottom:
791             case BSTop:
792                 p->drawLine(x1, (y1+y2)/2, x2, (y1+y2)/2);
793                 break;
794             case BSRight:
795             case BSLeft:
796                 p->drawLine((x1+x2)/2, y1, (x1+x2)/2, y2);
797                 break;
798             }
799                 
800         break;
801
802     case DOUBLE:
803     {
804         int third = (width+1)/3;
805
806         if (adjbw1 == 0 && adjbw2 == 0)
807         {
808             p->setPen(Qt::NoPen);
809             p->setBrush(c);
810             switch(s)
811             {
812             case BSTop:
813             case BSBottom:
814                 p->drawRect(x1, y1      , x2-x1, third);
815                 p->drawRect(x1, y2-third, x2-x1, third);
816                 break;
817             case BSLeft:
818                 p->drawRect(x1      , y1+1, third, y2-y1-1);
819                 p->drawRect(x2-third, y1+1, third, y2-y1-1);
820                 break;
821             case BSRight:
822                 p->drawRect(x1      , y1+1, third, y2-y1-1);
823                 p->drawRect(x2-third, y1+1, third, y2-y1-1);
824                 break;
825             }
826         }
827         else
828         {
829             int adjbw1bigthird;
830             if (adjbw1>0) adjbw1bigthird = adjbw1+1;
831             else adjbw1bigthird = adjbw1 - 1;
832             adjbw1bigthird /= 3;
833
834             int adjbw2bigthird;
835             if (adjbw2>0) adjbw2bigthird = adjbw2 + 1;
836             else adjbw2bigthird = adjbw2 - 1;
837             adjbw2bigthird /= 3;
838
839           switch(s)
840             {
841             case BSTop:
842               drawBorder(p, x1+QMAX((-adjbw1*2+1)/3,0), y1        , x2-QMAX((-adjbw2*2+1)/3,0), y1 + third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
843               drawBorder(p, x1+QMAX(( adjbw1*2+1)/3,0), y2 - third, x2-QMAX(( adjbw2*2+1)/3,0), y2        , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
844               break;
845             case BSLeft:
846               drawBorder(p, x1        , y1+QMAX((-adjbw1*2+1)/3,0), x1+third, y2-QMAX((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
847               drawBorder(p, x2 - third, y1+QMAX(( adjbw1*2+1)/3,0), x2      , y2-QMAX(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
848               break;
849             case BSBottom:
850               drawBorder(p, x1+QMAX(( adjbw1*2+1)/3,0), y1      , x2-QMAX(( adjbw2*2+1)/3,0), y1+third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
851               drawBorder(p, x1+QMAX((-adjbw1*2+1)/3,0), y2-third, x2-QMAX((-adjbw2*2+1)/3,0), y2      , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
852               break;
853             case BSRight:
854             drawBorder(p, x1      , y1+QMAX(( adjbw1*2+1)/3,0), x1+third, y2-QMAX(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
855             drawBorder(p, x2-third, y1+QMAX((-adjbw1*2+1)/3,0), x2      , y2-QMAX((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
856               break;
857             default:
858               break;
859             }
860         }
861         break;
862     }
863     case RIDGE:
864     case GROOVE:
865     {
866         EBorderStyle s1;
867         EBorderStyle s2;
868         if (style==GROOVE)
869         {
870             s1 = INSET;
871             s2 = OUTSET;
872         }
873         else
874         {
875             s1 = OUTSET;
876             s2 = INSET;
877         }
878
879         int adjbw1bighalf;
880         int adjbw2bighalf;
881         if (adjbw1>0) adjbw1bighalf=adjbw1+1;
882         else adjbw1bighalf=adjbw1-1;
883         adjbw1bighalf/=2;
884
885         if (adjbw2>0) adjbw2bighalf=adjbw2+1;
886         else adjbw2bighalf=adjbw2-1;
887         adjbw2bighalf/=2;
888
889         switch (s)
890         {
891         case BSTop:
892             drawBorder(p, x1+QMAX(-adjbw1  ,0)/2,  y1        , x2-QMAX(-adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
893             drawBorder(p, x1+QMAX( adjbw1+1,0)/2, (y1+y2+1)/2, x2-QMAX( adjbw2+1,0)/2,  y2        , s, c, textcolor, s2, adjbw1/2, adjbw2/2);
894             break;
895         case BSLeft:
896             drawBorder(p,  x1        , y1+QMAX(-adjbw1  ,0)/2, (x1+x2+1)/2, y2-QMAX(-adjbw2,0)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
897             drawBorder(p, (x1+x2+1)/2, y1+QMAX( adjbw1+1,0)/2,  x2        , y2-QMAX( adjbw2+1,0)/2, s, c, textcolor, s2, adjbw1/2, adjbw2/2);
898             break;
899         case BSBottom:
900             drawBorder(p, x1+QMAX( adjbw1  ,0)/2,  y1        , x2-QMAX( adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s2,  adjbw1bighalf, adjbw2bighalf);
901             drawBorder(p, x1+QMAX(-adjbw1+1,0)/2, (y1+y2+1)/2, x2-QMAX(-adjbw2+1,0)/2,  y2        , s, c, textcolor, s1, adjbw1/2, adjbw2/2);
902             break;
903         case BSRight:
904             drawBorder(p,  x1        , y1+QMAX( adjbw1  ,0)/2, (x1+x2+1)/2, y2-QMAX( adjbw2,0)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
905             drawBorder(p, (x1+x2+1)/2, y1+QMAX(-adjbw1+1,0)/2,  x2        , y2-QMAX(-adjbw2+1,0)/2, s, c, textcolor, s1, adjbw1/2, adjbw2/2);
906             break;
907         }
908         break;
909     }
910     case INSET:
911         if(s == BSTop || s == BSLeft)
912             c = c.dark();
913
914         /* nobreak; */
915     case OUTSET:
916         if(style == OUTSET && (s == BSBottom || s == BSRight))
917             c = c.dark();
918         /* nobreak; */
919     case SOLID:
920         QPointArray quad(4);
921         p->setPen(Qt::NoPen);
922         p->setBrush(c);
923         Q_ASSERT(x2>=x1);
924         Q_ASSERT(y2>=y1);
925         if (adjbw1==0 && adjbw2 == 0)
926           {
927             p->drawRect(x1,y1,x2-x1,y2-y1);
928             return;
929           }
930         switch(s) {
931         case BSTop:
932             quad.setPoints(4,
933                            x1+QMAX(-adjbw1,0), y1,
934                            x1+QMAX( adjbw1,0), y2,
935                            x2-QMAX( adjbw2,0), y2,
936                            x2-QMAX(-adjbw2,0), y1);
937             break;
938         case BSBottom:
939             quad.setPoints(4,
940                            x1+QMAX( adjbw1,0), y1,
941                            x1+QMAX(-adjbw1,0), y2,
942                            x2-QMAX(-adjbw2,0), y2,
943                            x2-QMAX( adjbw2,0), y1);
944             break;
945         case BSLeft:
946           quad.setPoints(4,
947                          x1, y1+QMAX(-adjbw1,0),
948                          x1, y2-QMAX(-adjbw2,0),
949                          x2, y2-QMAX( adjbw2,0),
950                          x2, y1+QMAX( adjbw1,0));
951             break;
952         case BSRight:
953           quad.setPoints(4,
954                          x1, y1+QMAX( adjbw1,0),
955                          x1, y2-QMAX( adjbw2,0),
956                          x2, y2-QMAX(-adjbw2,0),
957                          x2, y1+QMAX(-adjbw1,0));
958             break;
959         }
960         p->drawConvexPolygon(quad);
961         break;
962     }
963
964     if(invalidisInvert && p->rasterOp() == Qt::XorROP)
965         p->setRasterOp(Qt::CopyROP);
966 }
967
968 void RenderObject::paintBorder(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin, bool end)
969 {
970     const QColor& tc = style->borderTopColor();
971     const QColor& bc = style->borderBottomColor();
972     const QColor& lc = style->borderLeftColor();
973     const QColor& rc = style->borderRightColor();
974
975     bool tt = style->borderTopIsTransparent();
976     bool bt = style->borderBottomIsTransparent();
977     bool rt = style->borderRightIsTransparent();
978     bool lt = style->borderLeftIsTransparent();
979     
980     EBorderStyle ts = style->borderTopStyle();
981     EBorderStyle bs = style->borderBottomStyle();
982     EBorderStyle ls = style->borderLeftStyle();
983     EBorderStyle rs = style->borderRightStyle();
984
985     bool render_t = ts > BHIDDEN && !tt;
986     bool render_l = ls > BHIDDEN && begin && !lt;
987     bool render_r = rs > BHIDDEN && end && !rt;
988     bool render_b = bs > BHIDDEN && !bt;
989
990     if(render_t) {
991         bool ignore_left =
992             (tc == lc) && (tt == lt) &&
993             (ts >= OUTSET) &&
994             (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET);
995
996         bool ignore_right =
997             (tc == rc) && (tt == rt) &&
998             (ts >= OUTSET) &&
999             (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET);
1000         
1001         drawBorder(p, _tx, _ty, _tx + w, _ty +  style->borderTopWidth(), BSTop, tc, style->color(), ts,
1002                    ignore_left?0:style->borderLeftWidth(),
1003                    ignore_right?0:style->borderRightWidth());
1004     }
1005
1006     if(render_b) {
1007         bool ignore_left =
1008         (bc == lc) && (bt == lt) &&
1009         (bs >= OUTSET) &&
1010         (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET);
1011
1012         bool ignore_right =
1013             (bc == rc) && (bt == rt) &&
1014             (bs >= OUTSET) &&
1015             (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET);
1016         
1017         drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
1018                    ignore_left?0:style->borderLeftWidth(),
1019                    ignore_right?0:style->borderRightWidth());
1020     }
1021     
1022     if(render_l)
1023     {
1024         bool ignore_top =
1025           (tc == lc) && (tt == lt) &&
1026           (ls >= OUTSET) &&
1027           (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
1028
1029         bool ignore_bottom =
1030           (bc == lc) && (bt == lt) &&
1031           (ls >= OUTSET) &&
1032           (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
1033
1034         drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
1035                    ignore_top?0:style->borderTopWidth(),
1036                    ignore_bottom?0:style->borderBottomWidth());
1037     }
1038
1039     if(render_r)
1040     {
1041         bool ignore_top =
1042           (tc == rc) && (tt == rt) &&
1043           (rs >= DOTTED || rs == INSET) &&
1044           (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
1045
1046         bool ignore_bottom =
1047           (bc == rc) && (bt == rt) &&
1048           (rs >= DOTTED || rs == INSET) &&
1049           (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
1050
1051         drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
1052                    ignore_top?0:style->borderTopWidth(),
1053                    ignore_bottom?0:style->borderBottomWidth());
1054     }
1055 }
1056
1057 void RenderObject::absoluteRects(QValueList<QRect>& rects, int _tx, int _ty)
1058 {
1059     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1060     // inline boxes above and below us (thus getting merged with them to form a single irregular
1061     // shape).
1062     if (continuation()) {
1063         rects.append(QRect(_tx, _ty - collapsedMarginTop(), 
1064                            width(), height()+collapsedMarginTop()+collapsedMarginBottom()));
1065         continuation()->absoluteRects(rects, 
1066                                       _tx - xPos() + continuation()->containingBlock()->xPos(),
1067                                       _ty - yPos() + continuation()->containingBlock()->yPos());
1068     }
1069     else
1070         rects.append(QRect(_tx, _ty, width(), height()));
1071 }
1072
1073 QRect RenderObject::absoluteBoundingBoxRect()
1074 {
1075     int x, y;
1076     absolutePosition(x, y);
1077     QValueList<QRect> rects;
1078     absoluteRects(rects, x, y);
1079     
1080     QValueList<QRect>::ConstIterator it = rects.begin();
1081     QRect result = *it;
1082     while (++it != rects.end()) {
1083         result = result.unite(*it);
1084     }
1085     return result;
1086 }
1087
1088 void RenderObject::addAbsoluteRectForLayer(QRect& result)
1089 {
1090     if (layer()) {
1091         result = result.unite(absoluteBoundingBoxRect());
1092     }
1093     for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1094         current->addAbsoluteRectForLayer(result);
1095     }
1096 }
1097
1098 QRect RenderObject::paintingRootRect(QRect& topLevelRect)
1099 {
1100     QRect result = absoluteBoundingBoxRect();
1101     topLevelRect = result;
1102     for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1103         current->addAbsoluteRectForLayer(result);
1104     }
1105     return result;
1106 }
1107
1108 #if APPLE_CHANGES
1109 void RenderObject::addFocusRingRects(QPainter *p, int _tx, int _ty)
1110 {
1111     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1112     // inline boxes above and below us (thus getting merged with them to form a single irregular
1113     // shape).
1114     if (continuation()) {
1115         p->addFocusRingRect(_tx, _ty - collapsedMarginTop(), width(), height()+collapsedMarginTop()+collapsedMarginBottom());
1116         continuation()->addFocusRingRects(p, 
1117                                           _tx - xPos() + continuation()->containingBlock()->xPos(),
1118                                           _ty - yPos() + continuation()->containingBlock()->yPos());
1119     }
1120     else
1121         p->addFocusRingRect(_tx, _ty, width(), height());
1122 }
1123 #endif
1124
1125 void RenderObject::paintOutline(QPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style)
1126 {
1127     int ow = style->outlineWidth();
1128     if(!ow) return;
1129
1130     EBorderStyle os = style->outlineStyle();
1131     if (os <= BHIDDEN)
1132         return;
1133     
1134     QColor oc = style->outlineColor();
1135     if (!oc.isValid())
1136         oc = style->color();
1137     
1138     int offset = style->outlineOffset();
1139     
1140 #ifdef APPLE_CHANGES
1141     if (style->outlineStyleIsAuto()) {
1142         p->initFocusRing(ow, offset, oc);
1143         addFocusRingRects(p, _tx, _ty);
1144         p->drawFocusRing();
1145         p->clearFocusRing();
1146         return;
1147     }
1148 #endif
1149
1150     _tx -= offset;
1151     _ty -= offset;
1152     w += 2*offset;
1153     h += 2*offset;
1154     
1155     drawBorder(p, _tx-ow, _ty-ow, _tx, _ty+h+ow, BSLeft,
1156                QColor(oc), style->color(),
1157                os, ow, ow, true);
1158
1159     drawBorder(p, _tx-ow, _ty-ow, _tx+w+ow, _ty, BSTop,
1160                QColor(oc), style->color(),
1161                os, ow, ow, true);
1162
1163     drawBorder(p, _tx+w, _ty-ow, _tx+w+ow, _ty+h+ow, BSRight,
1164                QColor(oc), style->color(),
1165                os, ow, ow, true);
1166
1167     drawBorder(p, _tx-ow, _ty+h, _tx+w+ow, _ty+h+ow, BSBottom,
1168                QColor(oc), style->color(),
1169                os, ow, ow, true);
1170
1171 }
1172
1173 void RenderObject::paint(PaintInfo& i, int tx, int ty)
1174 {
1175 }
1176
1177 void RenderObject::repaint(bool immediate)
1178 {
1179     // Can't use canvas(), since we might be unrooted.
1180     RenderObject* o = this;
1181     while ( o->parent() ) o = o->parent();
1182     if (!o->isCanvas())
1183         return;
1184     RenderCanvas* c = static_cast<RenderCanvas*>(o);
1185     if (c->printingMode())
1186         return; // Don't repaint if we're printing.
1187     c->repaintViewRectangle(getAbsoluteRepaintRect(), immediate);    
1188 }
1189
1190 void RenderObject::repaintRectangle(const QRect& r, bool immediate)
1191 {
1192     // Can't use canvas(), since we might be unrooted.
1193     RenderObject* o = this;
1194     while ( o->parent() ) o = o->parent();
1195     if (!o->isCanvas())
1196         return;
1197     RenderCanvas* c = static_cast<RenderCanvas*>(o);
1198     if (c->printingMode())
1199         return; // Don't repaint if we're printing.
1200     QRect absRect(r);
1201     computeAbsoluteRepaintRect(absRect);
1202     c->repaintViewRectangle(absRect, immediate);
1203 }
1204
1205 bool RenderObject::repaintAfterLayoutIfNeeded(const QRect& oldBounds, const QRect& oldFullBounds)
1206 {
1207     QRect newBounds, newFullBounds;
1208     getAbsoluteRepaintRectIncludingFloats(newBounds, newFullBounds);
1209     if (newBounds != oldBounds || selfNeedsLayout()) {
1210         RenderCanvas* c = canvas();
1211         if (c->printingMode())
1212             return false; // Don't repaint if we're printing.
1213         c->repaintViewRectangle(oldFullBounds);
1214         if (newBounds != oldBounds)
1215             c->repaintViewRectangle(newFullBounds);
1216         return true;
1217     }
1218     return false;
1219 }
1220
1221 void RenderObject::repaintDuringLayoutIfMoved(int x, int y)
1222 {
1223 }
1224
1225 void RenderObject::repaintFloatingDescendants()
1226 {
1227 }
1228
1229 bool RenderObject::checkForRepaintDuringLayout() const
1230 {
1231     return !document()->view()->needsFullRepaint() && !layer();
1232 }
1233
1234 void RenderObject::repaintObjectsBeforeLayout()
1235 {
1236     if (!needsLayout() || isText())
1237         return;
1238     
1239     bool blockWithInlineChildren = (isRenderBlock() && !isTable() && normalChildNeedsLayout() && childrenInline());
1240     if (selfNeedsLayout()) {
1241         repaint();
1242         if (blockWithInlineChildren)
1243             return;
1244     }
1245
1246     for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1247         if (!current->isPositioned()) // RenderBlock subclass method handles walking the positioned objects.
1248             current->repaintObjectsBeforeLayout();
1249     }
1250 }
1251
1252 QRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
1253 {
1254     QRect r(getAbsoluteRepaintRect());
1255     r.setRect(r.x()-ow, r.y()-ow, r.width()+ow*2, r.height()+ow*2);
1256
1257     if (continuation() && !isInline())
1258         r.setRect(r.x(), r.y()-collapsedMarginTop(), r.width(), r.height()+collapsedMarginTop()+collapsedMarginBottom());
1259     
1260     if (isInlineFlow()) {
1261         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1262             if (!curr->isText()) {
1263                 QRect childRect = curr->getAbsoluteRepaintRectWithOutline(ow);
1264                 r = r.unite(childRect);
1265             }
1266         }
1267     }
1268
1269     return r;
1270 }
1271
1272 QRect RenderObject::getAbsoluteRepaintRect()
1273 {
1274     if (parent())
1275         return parent()->getAbsoluteRepaintRect();
1276     return QRect();
1277 }
1278
1279 void RenderObject::getAbsoluteRepaintRectIncludingFloats(QRect& bounds, QRect& fullBounds)
1280 {
1281     bounds = fullBounds = getAbsoluteRepaintRect();
1282 }
1283
1284 void RenderObject::computeAbsoluteRepaintRect(QRect& r, bool f)
1285 {
1286     if (parent())
1287         return parent()->computeAbsoluteRepaintRect(r, f);
1288 }
1289
1290 void RenderObject::dirtyLinesFromChangedChild(RenderObject* child, bool adding)
1291 {
1292 }
1293
1294 #ifndef NDEBUG
1295
1296 QString RenderObject::information() const
1297 {
1298     QString str;
1299     QTextStream ts( &str, IO_WriteOnly );
1300     ts << renderName()
1301         << "(" << (style() ? style()->refCount() : 0) << ")"
1302        << ": " << (void*)this << "  ";
1303     if (isInline()) ts << "il ";
1304     if (childrenInline()) ts << "ci ";
1305     if (isFloating()) ts << "fl ";
1306     if (isAnonymous()) ts << "an ";
1307     if (isRelPositioned()) ts << "rp ";
1308     if (isPositioned()) ts << "ps ";
1309     if (needsLayout()) ts << "nl ";
1310     if (m_recalcMinMax) ts << "rmm ";
1311     if (mouseInside()) ts << "mi ";
1312     if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
1313     if (element() && element()->active()) ts << "act ";
1314     if (element() && element()->hasAnchor()) ts << "anchor ";
1315     if (element() && element()->focused()) ts << "focus ";
1316     if (element()) ts << " <" <<  getTagName(element()->id()).string() << ">";
1317     ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"
1318         << (isTableCell() ?
1319             ( QString::fromLatin1(" [r=") +
1320               QString::number( static_cast<const RenderTableCell *>(this)->row() ) +
1321               QString::fromLatin1(" c=") +
1322               QString::number( static_cast<const RenderTableCell *>(this)->col() ) +
1323               QString::fromLatin1(" rs=") +
1324               QString::number( static_cast<const RenderTableCell *>(this)->rowSpan() ) +
1325               QString::fromLatin1(" cs=") +
1326               QString::number( static_cast<const RenderTableCell *>(this)->colSpan() ) +
1327               QString::fromLatin1("]") ) : QString::null );
1328         return str;
1329 }
1330
1331 void RenderObject::printTree(int indent) const
1332 {
1333     QString ind;
1334     ind.fill(' ', indent);
1335
1336     kdDebug() << ind << information() << endl;
1337
1338     RenderObject *child = firstChild();
1339     while( child != 0 )
1340     {
1341         child->printTree(indent+2);
1342         child = child->nextSibling();
1343     }
1344 }
1345
1346 void RenderObject::dump(QTextStream *stream, QString ind) const
1347 {
1348     if (isAnonymous()) { *stream << " anonymous"; }
1349     if (isFloating()) { *stream << " floating"; }
1350     if (isPositioned()) { *stream << " positioned"; }
1351     if (isRelPositioned()) { *stream << " relPositioned"; }
1352     if (isText()) { *stream << " text"; }
1353     if (isInline()) { *stream << " inline"; }
1354     if (isReplaced()) { *stream << " replaced"; }
1355     if (shouldPaintBackgroundOrBorder()) { *stream << " paintBackground"; }
1356     if (needsLayout()) { *stream << " needsLayout"; }
1357     if (minMaxKnown()) { *stream << " minMaxKnown"; }
1358     *stream << endl;
1359
1360     RenderObject *child = firstChild();
1361     while( child != 0 )
1362     {
1363         *stream << ind << child->renderName() << ": ";
1364         child->dump(stream,ind+"  ");
1365         child = child->nextSibling();
1366     }
1367 }
1368 #endif
1369
1370 bool RenderObject::shouldSelect() const
1371 {
1372     const RenderObject* curr = this;
1373     DOM::NodeImpl *node = 0;
1374     bool forcedOn = false;
1375
1376     while (curr) {
1377         if (curr->style()->userSelect() == SELECT_TEXT)
1378             forcedOn = true;
1379         if (!forcedOn && curr->style()->userSelect() == SELECT_NONE)
1380             return false;
1381
1382         if (!node)
1383             node = curr->element();
1384         curr = curr->parent();
1385     }
1386
1387     // somewhere up the render tree there must be an element!
1388     assert(node);
1389
1390     return node->dispatchHTMLEvent(DOM::EventImpl::SELECTSTART_EVENT, true, true);
1391 }
1392
1393 DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
1394 {
1395     if (!dhtmlOK && !uaOK)
1396         return 0;
1397
1398     const RenderObject* curr = this;
1399     while (curr) {
1400         DOM::NodeImpl *elt = curr->element();
1401         if (elt && elt->nodeType() == Node::TEXT_NODE) {
1402             // Since there's no way for the author to address the -khtml-user-drag style for a text node,
1403             // we use our own judgement.
1404             if (uaOK && canvas()->view()->part()->shouldDragAutoNode(curr->node(), x, y)) {
1405                 dhtmlWillDrag = false;
1406                 return curr->node();
1407             } else if (curr->shouldSelect()) {
1408                 // In this case we have a click in the unselected portion of text.  If this text is
1409                 // selectable, we want to start the selection process instead of looking for a parent
1410                 // to try to drag.
1411                 return 0;
1412             }
1413         } else {
1414             EUserDrag dragMode = curr->style()->userDrag();
1415             if (dhtmlOK && dragMode == DRAG_ELEMENT) {
1416                 dhtmlWillDrag = true;
1417                 return curr->node();
1418             } else if (uaOK && dragMode == DRAG_AUTO
1419                        && canvas()->view()->part()->shouldDragAutoNode(curr->node(), x, y))
1420             {
1421                 dhtmlWillDrag = false;
1422                 return curr->node();
1423             }
1424         }
1425         curr = curr->parent();
1426     }
1427     return 0;
1428 }
1429
1430 void RenderObject::selectionStartEnd(int& spos, int& epos)
1431 {
1432     canvas()->selectionStartEnd(spos, epos);
1433 }
1434
1435 RenderBlock* RenderObject::createAnonymousBlock()
1436 {
1437     RenderStyle *newStyle = new (renderArena()) RenderStyle();
1438     newStyle->inheritFrom(m_style);
1439     newStyle->setDisplay(BLOCK);
1440
1441     RenderBlock *newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
1442     newBox->setStyle(newStyle);
1443     return newBox;
1444 }
1445
1446 void RenderObject::handleDynamicFloatPositionChange()
1447 {
1448     // We have gone from not affecting the inline status of the parent flow to suddenly
1449     // having an impact.  See if there is a mismatch between the parent flow's
1450     // childrenInline() state and our state.
1451     setInline(style()->isDisplayInlineType());
1452     if (isInline() != parent()->childrenInline()) {
1453         if (!isInline()) {
1454             if (parent()->isRenderInline()) {
1455                 // We have to split the parent flow.
1456                 RenderInline* parentInline = static_cast<RenderInline*>(parent());
1457                 RenderBlock* newBox = parentInline->createAnonymousBlock();
1458                 
1459                 RenderFlow* oldContinuation = parent()->continuation();
1460                 parentInline->setContinuation(newBox);
1461
1462                 RenderObject* beforeChild = nextSibling();
1463                 parent()->removeChildNode(this);
1464                 parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
1465             }
1466             else if (parent()->isRenderBlock())
1467                 static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
1468         }
1469         else {
1470             // An anonymous block must be made to wrap this inline.
1471             RenderBlock* box = createAnonymousBlock();
1472             parent()->insertChildNode(box, this);
1473             box->appendChildNode(parent()->removeChildNode(this));
1474         }
1475     }
1476 }
1477
1478 void RenderObject::setStyle(RenderStyle *style)
1479 {
1480     if (m_style == style)
1481         return;
1482
1483     bool affectsParentBlock = false;
1484     RenderStyle::Diff d = RenderStyle::Equal;
1485     if (m_style) {
1486         // If our z-index changes value or our visibility changes,
1487         // we need to dirty our stacking context's z-order list.
1488         if (style) {
1489             if ((m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1490                  m_style->zIndex() != style->zIndex() ||
1491                  m_style->visibility() != style->visibility()) && layer()) {
1492                 layer()->stackingContext()->dirtyZOrderLists();
1493                 if (m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1494                     m_style->visibility() != style->visibility())
1495                     layer()->dirtyZOrderLists();
1496             }
1497         }
1498
1499         d = m_style->diff(style);
1500
1501         // The background of the root element or the body element could propagate up to
1502         // the canvas.  Just dirty the entire canvas when our style changes substantially.
1503         if (d >= RenderStyle::Visible && element() &&
1504             (element()->id() == ID_HTML || element()->id() == ID_BODY))
1505             canvas()->repaint();
1506         else if (m_parent && d == RenderStyle::Visible && !isText())
1507             // Do a repaint with the old style first, e.g., for example if we go from
1508             // having an outline to not having an outline.
1509             repaint();
1510
1511         if (m_style->position() != style->position() && layer())
1512             layer()->repaintIncludingDescendants();
1513
1514         if (isFloating() && (m_style->floating() != style->floating()))
1515             // For changes in float styles, we need to conceivably remove ourselves
1516             // from the floating objects list.
1517             removeFromObjectLists();
1518         else if (isPositioned() && (style->position() != ABSOLUTE && style->position() != FIXED))
1519             // For changes in positioning styles, we need to conceivably remove ourselves
1520             // from the positioned objects list.
1521             removeFromObjectLists();
1522         
1523         affectsParentBlock = m_style && isFloatingOrPositioned() &&
1524             (!style->isFloating() && style->position() != ABSOLUTE && style->position() != FIXED)
1525             && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
1526         
1527         // reset style flags
1528         m_floating = false;
1529         m_positioned = false;
1530         m_relPositioned = false;
1531         m_paintBackground = false;
1532         m_hasOverflowClip = false;
1533     }
1534
1535     RenderStyle *oldStyle = m_style;
1536     m_style = style;
1537
1538     CachedImage* ob = 0;
1539     CachedImage* nb = 0;
1540
1541     if (m_style) {
1542         m_style->ref();
1543         nb = m_style->backgroundImage();
1544     }
1545     if (oldStyle) {
1546         ob = oldStyle->backgroundImage();
1547         oldStyle->deref(renderArena());
1548     }
1549
1550     if (ob != nb) {
1551         if (ob) ob->deref(this);
1552         if (nb) nb->ref(this);
1553     }
1554
1555     setShouldPaintBackgroundOrBorder((m_style->backgroundColor().isValid() &&
1556                                       qAlpha(m_style->backgroundColor().rgb()) > 0) || 
1557                                      m_style->hasBorder() || nb );
1558     
1559     if (affectsParentBlock)
1560         handleDynamicFloatPositionChange();
1561     
1562     // No need to ever schedule repaints from a style change of a text run, since
1563     // we already did this for the parent of the text run.
1564     if (d >= RenderStyle::Position && m_parent)
1565         setNeedsLayoutAndMinMaxRecalc();
1566     else if (d == RenderStyle::Visible && !isText() && m_parent)
1567         repaint();
1568 }
1569
1570 QRect RenderObject::viewRect() const
1571 {
1572     return canvas()->viewRect();
1573 }
1574
1575 bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
1576 {
1577     RenderObject* o = parent();
1578     if (o) {
1579         o->absolutePosition(xPos, yPos, f);
1580         if (o->hasOverflowClip())
1581             o->layer()->subtractScrollOffset(xPos, yPos); 
1582         return true;
1583     }
1584     else
1585     {
1586         xPos = yPos = 0;
1587         return false;
1588     }
1589 }
1590
1591 QRect RenderObject::caretRect(int /*offset*/, bool /*override*/)
1592 {
1593     // the caret has a default width of one pixel. If you want
1594     // to check for validity, only test the x-coordinate for >= 0.
1595     return QRect(-1, -1, 1, -1);
1596 }
1597
1598 int RenderObject::paddingTop() const
1599 {
1600     int w = 0;
1601     Length padding = m_style->paddingTop();
1602     if (padding.isPercent())
1603         w = containingBlock()->contentWidth();
1604     w = padding.minWidth(w);
1605     if ( isTableCell() && padding.isVariable() )
1606         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1607     return w;
1608 }
1609
1610 int RenderObject::paddingBottom() const
1611 {
1612     int w = 0;
1613     Length padding = style()->paddingBottom();
1614     if (padding.isPercent())
1615         w = containingBlock()->contentWidth();
1616     w = padding.minWidth(w);
1617     if ( isTableCell() && padding.isVariable() )
1618         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1619     return w;
1620 }
1621
1622 int RenderObject::paddingLeft() const
1623 {
1624     int w = 0;
1625     Length padding = style()->paddingLeft();
1626     if (padding.isPercent())
1627         w = containingBlock()->contentWidth();
1628     w = padding.minWidth(w);
1629     if ( isTableCell() && padding.isVariable() )
1630         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1631     return w;
1632 }
1633
1634 int RenderObject::paddingRight() const
1635 {
1636     int w = 0;
1637     Length padding = style()->paddingRight();
1638     if (padding.isPercent())
1639         w = containingBlock()->contentWidth();
1640     w = padding.minWidth(w);
1641     if ( isTableCell() && padding.isVariable() )
1642         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1643     return w;
1644 }
1645
1646 RenderCanvas* RenderObject::canvas() const
1647 {
1648     return static_cast<RenderCanvas*>(document()->renderer());
1649 }
1650
1651 RenderObject *RenderObject::container() const
1652 {
1653     // This method is extremely similar to containingBlock(), but with a few notable
1654     // exceptions.
1655     // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
1656     // the object is not part of the primary document subtree yet.
1657     // (2) For normal flow elements, it just returns the parent.
1658     // (3) For absolute positioned elements, it will return a relative positioned inline.
1659     // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
1660     // the layout of the positioned object.  This does mean that calcAbsoluteHorizontal and
1661     // calcAbsoluteVertical have to use container().
1662     EPosition pos = m_style->position();
1663     RenderObject *o = 0;
1664     if (!isText() && pos == FIXED) {
1665         // container() can be called on an object that is not in the
1666         // tree yet.  We don't call canvas() since it will assert if it
1667         // can't get back to the canvas.  Instead we just walk as high up
1668         // as we can.  If we're in the tree, we'll get the root.  If we
1669         // aren't we'll get the root of our little subtree (most likely
1670         // we'll just return 0).
1671         o = parent();
1672         while (o && o->parent()) o = o->parent();
1673     }
1674     else if (!isText() && pos == ABSOLUTE) {
1675         // Same goes here.  We technically just want our containing block, but
1676         // we may not have one if we're part of an uninstalled subtree.  We'll
1677         // climb as high as we can though.
1678         o = parent();
1679         while (o && o->style()->position() == STATIC && !o->isRoot() && !o->isCanvas())
1680             o = o->parent();
1681     }
1682     else
1683         o = parent();
1684     return o;
1685 }
1686
1687 bool RenderObject::isSelectionBorder() const
1688 {
1689     SelectionState st = selectionState();
1690     return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
1691 }
1692
1693 #if 0
1694 static void checkFloats(RenderObject* o, RenderObject* f)
1695 {
1696     if (o->isRenderBlock()) {
1697         RenderBlock* b = static_cast<RenderBlock*>(o);
1698         if (b->containsFloat(f))
1699             assert(false);
1700     }
1701     
1702     for (RenderObject* c = o->firstChild(); c; c = c->nextSibling())
1703         checkFloats(c, f);
1704 }
1705 #endif
1706
1707 void RenderObject::removeFromObjectLists()
1708 {
1709     if (isFloating()) {
1710         RenderBlock* outermostBlock = containingBlock();
1711         for (RenderBlock* p = outermostBlock; p && !p->isCanvas(); p = p->containingBlock()) {
1712             if (p->containsFloat(this))
1713                 outermostBlock = p;
1714         }
1715         
1716         if (outermostBlock)
1717             outermostBlock->markAllDescendantsWithFloatsForLayout(this);
1718 #if 0
1719         // Debugging code for float checking.
1720         checkFloats(canvas(), this);
1721 #endif
1722     }
1723
1724     if (isPositioned()) {
1725         RenderObject *p;
1726         for (p = parent(); p; p = p->parent()) {
1727             if (p->isRenderBlock())
1728                 static_cast<RenderBlock*>(p)->removePositionedObject(this);
1729         }
1730     }
1731 }
1732
1733 RenderArena* RenderObject::renderArena() const
1734 {
1735     DOM::DocumentImpl* doc = document();
1736     return doc ? doc->renderArena() : 0;
1737 }
1738
1739 void RenderObject::remove()
1740 {
1741 #if APPLE_CHANGES
1742     // Delete our accessibility object if we have one.
1743     KWQAccObjectCache* cache = document()->getExistingAccObjectCache();
1744     if (cache)
1745         cache->detach(this);
1746 #endif
1747
1748     removeFromObjectLists();
1749
1750     if (parent())
1751         //have parent, take care of the tree integrity
1752         parent()->removeChild(this);
1753 }
1754
1755 void RenderObject::detach()
1756 {
1757     remove();
1758     
1759     // by default no refcounting
1760     arenaDelete(document()->renderArena(), this);
1761 }
1762
1763 void RenderObject::arenaDelete(RenderArena *arena, void *base)
1764 {
1765     if (m_style->backgroundImage())
1766         m_style->backgroundImage()->deref(this);
1767     if (m_style)
1768         m_style->deref(arena);
1769     
1770 #ifndef NDEBUG
1771     void *savedBase = baseOfRenderObjectBeingDeleted;
1772     baseOfRenderObjectBeingDeleted = base;
1773 #endif
1774     delete this;
1775 #ifndef NDEBUG
1776     baseOfRenderObjectBeingDeleted = savedBase;
1777 #endif
1778     
1779     // Recover the size left there for us by operator delete and free the memory.
1780     arena->free(*(size_t *)base, base);
1781 }
1782
1783 void RenderObject::arenaDelete(RenderArena *arena)
1784 {
1785     arenaDelete(arena, dynamic_cast<void *>(this));
1786 }
1787
1788 Position RenderObject::positionForCoordinates(int x, int y)
1789 {
1790     return Position(element(), caretMinOffset());
1791 }
1792
1793 bool RenderObject::mouseInside() const
1794
1795     if (!m_mouseInside && continuation()) 
1796         return continuation()->mouseInside();
1797     return m_mouseInside; 
1798 }
1799
1800 bool RenderObject::isDragging() const
1801
1802     return m_isDragging; 
1803 }
1804
1805 void RenderObject::updateDragState(bool dragOn)
1806 {
1807     bool valueChanged = (dragOn != m_isDragging);
1808     m_isDragging = dragOn;
1809     if (valueChanged && style()->affectedByDragRules())
1810         element()->setChanged();
1811     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
1812         curr->updateDragState(dragOn);
1813     if (continuation())
1814         continuation()->updateDragState(dragOn);
1815 }
1816
1817 bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
1818                                HitTestAction hitTestAction, bool inside)
1819 {
1820     int tx = _tx + xPos();
1821     int ty = _ty + yPos();
1822
1823     QRect boundsRect(tx, ty, width(), height());
1824     inside |= (style()->visibility() != HIDDEN && boundsRect.contains(_x, _y)) || isBody() || isRoot();
1825     bool inOverflowRect = inside;
1826     if (!inOverflowRect) {
1827         QRect overflowRect(tx, ty, overflowWidth(false), overflowHeight(false));
1828         inOverflowRect = overflowRect.contains(_x, _y);
1829     }
1830     
1831     // ### table should have its own, more performant method
1832     if (hitTestAction != HitTestSelfOnly &&
1833         ((!isRenderBlock() ||
1834          !static_cast<RenderBlock*>(this)->isPointInScrollbar(_x, _y, _tx, _ty)) &&
1835         (inOverflowRect || isInline() || isCanvas() ||
1836          isTableRow() || isTableSection() || inside || mouseInside() ||
1837          (childrenInline() && firstChild() && firstChild()->isCompact())))) {
1838         if (hitTestAction == HitTestChildrenOnly)
1839             inside = false;
1840         int stx = _tx + xPos();
1841         int sty = _ty + yPos();
1842         if (hasOverflowClip())
1843             layer()->subtractScrollOffset(stx, sty);
1844         for (RenderObject* child = lastChild(); child; child = child->previousSibling())
1845             if (!child->layer() && !child->isFloating() &&
1846                 child->nodeAtPoint(info, _x, _y, stx, sty))
1847                 inside = true;
1848     }
1849
1850     if (inside) {
1851         if (!info.innerNode() && !isInline() && continuation()) {
1852             // We are in the margins of block elements that are part of a continuation.  In
1853             // this case we're actually still inside the enclosing inline element that was
1854             // split.  Go ahead and set our inner node accordingly.
1855             info.setInnerNode(continuation()->element());
1856             if (!info.innerNonSharedNode())
1857                 info.setInnerNonSharedNode(continuation()->element());
1858         }
1859             
1860         if (info.innerNode() && info.innerNode()->renderer() && 
1861             !info.innerNode()->renderer()->isInline() && element() && isInline()) {
1862             // Within the same layer, inlines are ALWAYS fully above blocks.  Change inner node.
1863             info.setInnerNode(element());
1864             
1865             // Clear everything else.
1866             info.setInnerNonSharedNode(0);
1867             info.setURLElement(0);
1868         }
1869         
1870         if (!info.innerNode() && element())
1871             info.setInnerNode(element());
1872
1873         if(!info.innerNonSharedNode() && element())
1874             info.setInnerNonSharedNode(element());
1875     }
1876
1877     return inside;
1878 }
1879
1880 short RenderObject::verticalPositionHint( bool firstLine ) const
1881 {
1882     short vpos = m_verticalPosition;
1883     if ( m_verticalPosition == PositionUndefined || firstLine ) {
1884         vpos = getVerticalPosition( firstLine );
1885         if ( !firstLine )
1886             m_verticalPosition = vpos;
1887     }
1888     return vpos;
1889
1890 }
1891
1892 short RenderObject::getVerticalPosition( bool firstLine ) const
1893 {
1894     if (!isInline())
1895         return 0;
1896
1897     // This method determines the vertical position for inline elements.
1898     int vpos = 0;
1899     EVerticalAlign va = style()->verticalAlign();
1900     if ( va == TOP ) {
1901         vpos = PositionTop;
1902     } else if ( va == BOTTOM ) {
1903         vpos = PositionBottom;
1904     } else if ( va == LENGTH ) {
1905         vpos = -style()->verticalAlignLength().width( lineHeight( firstLine ) );
1906     } else  {
1907         bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable();
1908         vpos = checkParent ? parent()->verticalPositionHint( firstLine ) : 0;
1909         // don't allow elements nested inside text-top to have a different valignment.
1910         if ( va == BASELINE )
1911             return vpos;
1912
1913     //     if ( vpos == PositionTop )
1914 //                 vpos = 0;
1915
1916         const QFont &f = parent()->font( firstLine );
1917         int fontsize = f.pixelSize();
1918     
1919         if ( va == SUB )
1920             vpos += fontsize/5 + 1;
1921         else if ( va == SUPER )
1922             vpos -= fontsize/3 + 1;
1923         else if ( va == TEXT_TOP ) {
1924 //                 qDebug( "got TEXT_TOP vertical pos hint" );
1925 //                 qDebug( "parent:" );
1926 //                 qDebug( "CSSLH: %d, CSS_FS: %d, basepos: %d", fontheight, fontsize, parent()->baselinePosition( firstLine ) );
1927 //                 qDebug( "this:" );
1928 //                 qDebug( "CSSLH: %d, CSS_FS: %d, basepos: %d", lineHeight( firstLine ), style()->font().pixelSize(), baselinePosition( firstLine ) );
1929             vpos += ( baselinePosition( firstLine ) -
1930                       parent()->baselinePosition( firstLine, !checkParent ) );
1931         } else if ( va == MIDDLE ) {
1932 #if APPLE_CHANGES
1933             vpos += - (int)(QFontMetrics(f).xHeight()/2) - lineHeight( firstLine )/2 + baselinePosition( firstLine );
1934 #else
1935             QRect b = QFontMetrics(f).boundingRect('x');
1936             vpos += -b.height()/2 - lineHeight( firstLine )/2 + baselinePosition( firstLine );
1937 #endif
1938         } else if ( va == TEXT_BOTTOM ) {
1939             vpos += QFontMetrics(f).descent();
1940             if ( !isReplaced() )
1941                 vpos -= fontMetrics(firstLine).descent();
1942         } else if ( va == BASELINE_MIDDLE )
1943             vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
1944     }
1945     
1946     return vpos;
1947 }
1948
1949 short RenderObject::lineHeight( bool firstLine, bool ) const
1950 {
1951     RenderStyle* s = style(firstLine);
1952     
1953     Length lh = s->lineHeight();
1954
1955     // its "unset", choose nice default
1956     if (lh.value < 0)
1957         return s->fontMetrics().lineSpacing();
1958
1959     if (lh.isPercent())
1960         return lh.minWidth(s->font().pixelSize());
1961
1962     // its fixed
1963     return lh.value;
1964 }
1965
1966 short RenderObject::baselinePosition( bool firstLine, bool isRootLineBox ) const
1967 {
1968     const QFontMetrics &fm = fontMetrics( firstLine );
1969     return fm.ascent() + ( lineHeight( firstLine, isRootLineBox ) - fm.height() ) / 2;
1970 }
1971
1972 void RenderObject::invalidateVerticalPositions()
1973 {
1974     m_verticalPosition = PositionUndefined;
1975     RenderObject *child = firstChild();
1976     while( child ) {
1977         child->invalidateVerticalPositions();
1978         child = child->nextSibling();
1979     }
1980 }
1981
1982 void RenderObject::recalcMinMaxWidths()
1983 {
1984     KHTMLAssert( m_recalcMinMax );
1985
1986 #ifdef DEBUG_LAYOUT
1987     kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
1988 #endif
1989
1990     if (m_recalcMinMax)
1991         updateFirstLetter();
1992     
1993     RenderObject *child = firstChild();
1994     while( child ) {
1995         // gcc sucks. if anybody knows a trick to get rid of the
1996         // warning without adding an extra (unneeded) initialisation,
1997         // go ahead
1998         int cmin = 0;
1999         int cmax = 0;
2000         bool test = false;
2001         if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
2002             cmin = child->minWidth();
2003             cmax = child->maxWidth();
2004             test = true;
2005         }
2006         if ( child->m_recalcMinMax )
2007             child->recalcMinMaxWidths();
2008         if ( !child->m_minMaxKnown )
2009             child->calcMinMaxWidth();
2010         if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) )
2011             m_minMaxKnown = false;
2012         child = child->nextSibling();
2013     }
2014
2015     // we need to recalculate, if the contains inline children, as the change could have
2016     // happened somewhere deep inside the child tree. Also do this for blocks or tables that
2017     // are inline (i.e., inline-block and inline-table).
2018     if ((!isInline() || isInlineBlockOrInlineTable()) && childrenInline())
2019         m_minMaxKnown = false;
2020
2021     if ( !m_minMaxKnown )
2022         calcMinMaxWidth();
2023     m_recalcMinMax = false;
2024 }
2025
2026 void RenderObject::scheduleRelayout()
2027 {
2028     if (!isCanvas()) return;
2029     KHTMLView *view = static_cast<RenderCanvas *>(this)->view();
2030     if (view)
2031         view->scheduleRelayout();
2032 }
2033
2034
2035 void RenderObject::removeLeftoverAnonymousBoxes()
2036 {
2037 }
2038
2039 InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
2040 {
2041     KHTMLAssert(!isRootLineBox);
2042     return new (renderArena()) InlineBox(this);
2043 }
2044
2045 void RenderObject::dirtyLineBoxes(bool, bool)
2046 {
2047 }
2048
2049 InlineBox* RenderObject::inlineBoxWrapper() const
2050 {
2051     return 0;
2052 }
2053
2054 void RenderObject::setInlineBoxWrapper(InlineBox* b)
2055 {
2056 }
2057
2058 void RenderObject::deleteLineBoxWrapper()
2059 {
2060 }
2061
2062 RenderStyle* RenderObject::style(bool firstLine) const {
2063     RenderStyle *s = m_style;
2064     if (firstLine) {
2065         const RenderObject* obj = isText() ? parent() : this;
2066         if (obj->isBlockFlow()) {
2067             RenderBlock* firstLineBlock = obj->firstLineBlock();
2068             if (firstLineBlock)
2069                 s = firstLineBlock->getPseudoStyle(RenderStyle::FIRST_LINE, style());
2070         }
2071         else if (!obj->isAnonymous() && obj->isInlineFlow()) {
2072             RenderStyle* parentStyle = obj->parent()->style(true);
2073             if (parentStyle != obj->parent()->style()) {
2074                 // A first-line style is in effect. We need to cache a first-line style
2075                 // for ourselves.
2076                 style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED);
2077                 s = obj->getPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle);
2078             }
2079         }
2080     }
2081     return s;
2082 }
2083
2084 RenderStyle* RenderObject::getPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
2085 {
2086     if (!style()->hasPseudoStyle(pseudo))
2087         return 0;
2088     
2089     if (!parentStyle)
2090         parentStyle = style();
2091
2092     RenderStyle* result = style()->getPseudoStyle(pseudo);
2093     if (result) return result;
2094     
2095     DOM::NodeImpl* node = element();
2096     if (isText())
2097         node = element()->parentNode();
2098     if (!node) return 0;
2099     
2100     if (pseudo == RenderStyle::FIRST_LINE_INHERITED)
2101         result = document()->styleSelector()->styleForElement(static_cast<DOM::ElementImpl*>(node), 
2102                                                               parentStyle, false);
2103     else
2104         result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<DOM::ElementImpl*>(node), 
2105                                                                     parentStyle);
2106     if (result)
2107         style()->addPseudoStyle(result);
2108     return result;
2109 }
2110
2111 void RenderObject::getTextDecorationColors(int decorations, QColor& underline, QColor& overline,
2112                                            QColor& linethrough, bool quirksMode)
2113 {
2114     RenderObject* curr = this;
2115     do {
2116         int currDecs = curr->style()->textDecoration();
2117         if (currDecs) {
2118             if (currDecs & UNDERLINE) {
2119                 decorations &= ~UNDERLINE;
2120                 underline = curr->style()->color();
2121             }
2122             if (currDecs & OVERLINE) {
2123                 decorations &= ~OVERLINE;
2124                 overline = curr->style()->color();
2125             }
2126             if (currDecs & LINE_THROUGH) {
2127                 decorations &= ~LINE_THROUGH;
2128                 linethrough = curr->style()->color();
2129             }
2130         }
2131         curr = curr->parent();
2132         if (curr && curr->isRenderBlock() && curr->continuation())
2133             curr = curr->continuation();
2134     } while (curr && decorations && (!quirksMode || !curr->element() ||
2135                                      (curr->element()->id() != ID_A && curr->element()->id() != ID_FONT)));
2136
2137     // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
2138     if (decorations && curr) {
2139         if (decorations & UNDERLINE)
2140             underline = curr->style()->color();
2141         if (decorations & OVERLINE)
2142             overline = curr->style()->color();
2143         if (decorations & LINE_THROUGH)
2144             linethrough = curr->style()->color();
2145     }        
2146 }
2147
2148 #if APPLE_CHANGES
2149 void RenderObject::updateWidgetPositions()
2150 {
2151     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2152         curr->updateWidgetPositions();
2153 }
2154 #endif
2155
2156 void RenderObject::collectBorders(QValueList<CollapsedBorderValue>& borderStyles)
2157 {
2158     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2159         curr->collectBorders(borderStyles);
2160 }
2161
2162 bool RenderObject::avoidsFloats() const
2163 {
2164     return isReplaced() || isTable() || hasOverflowClip() || isHR() || isFlexibleBox(); 
2165 }
2166
2167 bool RenderObject::usesLineWidth() const
2168 {
2169     // 1. All auto-width objects that avoid floats should always use lineWidth
2170     // 2. For objects with a specified width, we match WinIE's behavior:
2171     // (a) tables use contentWidth
2172     // (b) <hr>s use lineWidth
2173     // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode.
2174     return (avoidsFloats() && (style()->width().isVariable() || isHR() || (style()->htmlHacks() && !isTable())));
2175 }
2176
2177 QChar RenderObject::backslashAsCurrencySymbol() const
2178 {
2179 #if !APPLE_CHANGES
2180     return '\\';
2181 #else
2182     NodeImpl *node = element();
2183     if (!node)
2184         return '\\';
2185     DocumentImpl *document = node->getDocument();
2186     if (!document)
2187         return '\\';
2188     Decoder *decoder = document->decoder();
2189     if (!decoder)
2190         return '\\';
2191     const QTextCodec *codec = decoder->codec();
2192     if (!codec)
2193         return '\\';
2194     return codec->backslashAsCurrencySymbol();
2195 #endif
2196 }
2197
2198 void RenderObject::setPixmap(const QPixmap&, const QRect&, CachedImage *image)
2199 {
2200     // Repaint when the background image finishes loading.
2201     // This is needed for RenderBox objects, and also for table objects that hold
2202     // backgrounds that are then respected by the table cells (which are RenderBox
2203     // subclasses). It would be even better to find a more elegant way of doing this that
2204     // would avoid putting this function and the CachedObjectClient base class into RenderObject.
2205
2206     if (image && image->pixmap_size() == image->valid_rect().size() && parent()) {
2207         if (element() && (element()->id() == ID_HTML || element()->id() == ID_BODY))
2208             canvas()->repaint();    // repaint the entire canvas since the background gets propagated up
2209         else
2210             repaint();              // repaint object, which is a box or a container with boxes inside it
2211     }
2212 }
2213
2214 int RenderObject::maximalOutlineSize(PaintAction p) const
2215 {
2216     if (p != PaintActionOutline)
2217         return 0;
2218     return static_cast<RenderCanvas*>(document()->renderer())->maximalOutlineSize();
2219 }
2220
2221 long RenderObject::caretMinOffset() const
2222 {
2223     return 0;
2224 }
2225
2226 long RenderObject::caretMaxOffset() const
2227 {
2228     return 0;
2229 }
2230
2231 unsigned long RenderObject::caretMaxRenderedOffset() const
2232 {
2233     return 0;
2234 }
2235
2236 InlineBox *RenderObject::inlineBox(long offset)
2237 {
2238     return inlineBoxWrapper();
2239 }