summaryrefslogtreecommitdiffstats
path: root/khtml/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'khtml/rendering')
-rw-r--r--khtml/rendering/CMakeLists.txt46
-rw-r--r--khtml/rendering/Makefile.am57
-rw-r--r--khtml/rendering/bidi.cpp2250
-rw-r--r--khtml/rendering/bidi.h172
-rw-r--r--khtml/rendering/break_lines.cpp126
-rw-r--r--khtml/rendering/break_lines.h163
-rw-r--r--khtml/rendering/counter_tree.cpp222
-rw-r--r--khtml/rendering/counter_tree.h114
-rw-r--r--khtml/rendering/enumerate.cpp411
-rw-r--r--khtml/rendering/enumerate.h66
-rw-r--r--khtml/rendering/font.cpp502
-rw-r--r--khtml/rendering/font.h188
-rw-r--r--khtml/rendering/img-loading.pngbin318 -> 0 bytes
-rw-r--r--khtml/rendering/loading_icon.cpp25
-rw-r--r--khtml/rendering/render_applet.cpp145
-rw-r--r--khtml/rendering/render_applet.h60
-rw-r--r--khtml/rendering/render_arena.cpp146
-rw-r--r--khtml/rendering/render_arena.h72
-rw-r--r--khtml/rendering/render_block.cpp3155
-rw-r--r--khtml/rendering/render_block.h378
-rw-r--r--khtml/rendering/render_body.cpp121
-rw-r--r--khtml/rendering/render_body.h56
-rw-r--r--khtml/rendering/render_box.cpp2325
-rw-r--r--khtml/rendering/render_box.h213
-rw-r--r--khtml/rendering/render_br.cpp79
-rw-r--r--khtml/rendering/render_br.h77
-rw-r--r--khtml/rendering/render_canvas.cpp780
-rw-r--r--khtml/rendering/render_canvas.h250
-rw-r--r--khtml/rendering/render_container.cpp597
-rw-r--r--khtml/rendering/render_container.h85
-rw-r--r--khtml/rendering/render_flow.cpp412
-rw-r--r--khtml/rendering/render_flow.h96
-rw-r--r--khtml/rendering/render_form.cpp1914
-rw-r--r--khtml/rendering/render_form.h511
-rw-r--r--khtml/rendering/render_frames.cpp1025
-rw-r--r--khtml/rendering/render_frames.h172
-rw-r--r--khtml/rendering/render_generated.cpp392
-rw-r--r--khtml/rendering/render_generated.h125
-rw-r--r--khtml/rendering/render_image.cpp604
-rw-r--r--khtml/rendering/render_image.h105
-rw-r--r--khtml/rendering/render_inline.cpp935
-rw-r--r--khtml/rendering/render_inline.h94
-rw-r--r--khtml/rendering/render_layer.cpp1830
-rw-r--r--khtml/rendering/render_layer.h342
-rw-r--r--khtml/rendering/render_line.cpp996
-rw-r--r--khtml/rendering/render_line.h310
-rw-r--r--khtml/rendering/render_list.cpp586
-rw-r--r--khtml/rendering/render_list.h140
-rw-r--r--khtml/rendering/render_object.cpp2330
-rw-r--r--khtml/rendering/render_object.h866
-rw-r--r--khtml/rendering/render_replaced.cpp940
-rw-r--r--khtml/rendering/render_replaced.h169
-rw-r--r--khtml/rendering/render_style.cpp1301
-rw-r--r--khtml/rendering/render_style.h1524
-rw-r--r--khtml/rendering/render_table.cpp3070
-rw-r--r--khtml/rendering/render_table.h524
-rw-r--r--khtml/rendering/render_text.cpp1546
-rw-r--r--khtml/rendering/render_text.h345
-rw-r--r--khtml/rendering/table_layout.cpp1193
-rw-r--r--khtml/rendering/table_layout.h112
-rw-r--r--khtml/rendering/table_layout.txt74
61 files changed, 0 insertions, 37464 deletions
diff --git a/khtml/rendering/CMakeLists.txt b/khtml/rendering/CMakeLists.txt
deleted file mode 100644
index fe3301265..000000000
--- a/khtml/rendering/CMakeLists.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-#################################################
-#
-# (C) 2010 Serghei Amelian
-# serghei (DOT) amelian (AT) gmail.com
-#
-# Improvements and feedback are welcome
-#
-# This file is released under GPL >= 2
-#
-#################################################
-
-include_directories(
- ${TQT_INCLUDE_DIRS}
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_BINARY_DIR}
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_BINARY_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}/khtml
- ${CMAKE_SOURCE_DIR}/tdecore
- ${CMAKE_SOURCE_DIR}/tdeui
- ${CMAKE_SOURCE_DIR}/kio
- ${CMAKE_SOURCE_DIR}/kio/kio
- ${CMAKE_SOURCE_DIR}/kio/kfile
- ${CMAKE_SOURCE_DIR}/kutils
-)
-
-
-##### khtmlrender-static #########################
-
-set( target khtmlrender )
-
-set( ${target}_SRCS
- bidi.cpp break_lines.cpp render_block.cpp render_inline.cpp
- render_style.cpp render_object.cpp render_container.cpp render_box.cpp
- render_flow.cpp render_text.cpp render_arena.cpp render_layer.cpp
- render_image.cpp render_table.cpp table_layout.cpp
- render_replaced.cpp render_form.cpp render_list.cpp
- render_canvas.cpp render_frames.cpp render_br.cpp
- render_body.cpp font.cpp render_line.cpp render_generated.cpp
- enumerate.cpp counter_tree.cpp
-)
-
-tde_add_library( ${target} STATIC_PIC AUTOMOC
- SOURCES ${${target}_SRCS}
-)
diff --git a/khtml/rendering/Makefile.am b/khtml/rendering/Makefile.am
deleted file mode 100644
index d41638f27..000000000
--- a/khtml/rendering/Makefile.am
+++ /dev/null
@@ -1,57 +0,0 @@
-# This file is part of the KDE libraries
-# Copyright (C) 1997 Martin Jones (mjones@kde.org)
-# (C) 1997 Torben Weis (weis@kde.org)
-
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-
-# You should have received a copy of the GNU Library General Public License
-# along with this library; see the file COPYING.LIB. If not, write to
-# the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-# Boston, MA 02110-1301, USA.
-
-KDE_CXXFLAGS = $(WOVERLOADED_VIRTUAL)
-
-noinst_LTLIBRARIES = libkhtmlrender.la
-libkhtmlrender_la_SOURCES = \
- bidi.cpp break_lines.cpp render_block.cpp render_inline.cpp \
- render_style.cpp render_object.cpp render_container.cpp render_box.cpp \
- render_flow.cpp render_text.cpp render_arena.cpp render_layer.cpp \
- render_image.cpp render_table.cpp table_layout.cpp \
- render_replaced.cpp render_form.cpp render_list.cpp \
- render_canvas.cpp render_frames.cpp render_br.cpp \
- render_body.cpp font.cpp render_line.cpp render_generated.cpp \
- enumerate.cpp counter_tree.cpp
-
-libkhtmlrender_la_METASOURCES = AUTO
-
-noinst_HEADERS = \
- bidi.h break_lines.h \
- render_arena.h render_layer.h \
- render_style.h render_object.h render_container.h render_box.h \
- render_flow.h render_text.h render_table.h render_replaced.h \
- render_form.h render_list.h render_canvas.h render_frames.h \
- render_br.h render_applet.h font.h table_layout.h render_line.h \
- render_generated.h enumerate.h
-
-INCLUDES = -I$(top_srcdir)/kimgio -I$(top_srcdir)/kio -I$(top_srcdir)/dcop \
- -I$(top_srcdir)/kfile -I$(top_srcdir)/khtml -I$(top_srcdir)/kutils -I$(top_srcdir) $(all_includes)
-
-SRCDOC_DEST=$(kde_htmldir)/en/tdelibs/khtml
-
-## generate lib documentation
-srcdoc:
- $(mkinstalldirs) $(SRCDOC_DEST)
- kdoc -H -d $(SRCDOC_DEST) tdecore -lqt
-
-## maintainer: regen loading icon
-loading-icon:
- bin2c -sploading_icon $(srcdir)/img-loading.png > $(srcdir)/loading_icon.cpp
-
diff --git a/khtml/rendering/bidi.cpp b/khtml/rendering/bidi.cpp
deleted file mode 100644
index 2dcfe48c9..000000000
--- a/khtml/rendering/bidi.cpp
+++ /dev/null
@@ -1,2250 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
- * (C) 2003-2005 Apple Computer, Inc.
- * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include "rendering/bidi.h"
-#include "rendering/break_lines.h"
-#include "rendering/render_block.h"
-#include "rendering/render_text.h"
-#include "rendering/render_arena.h"
-#include "rendering/render_layer.h"
-#include "rendering/render_canvas.h"
-#include "xml/dom_docimpl.h"
-
-#include "kdebug.h"
-#include "tqdatetime.h"
-#include "tqfontmetrics.h"
-
-#define BIDI_DEBUG 0
-//#define DEBUG_LINEBREAKS
-//#define PAGE_DEBUG
-
-namespace khtml {
-
-
-// an iterator which goes through a BidiParagraph
-struct BidiIterator
-{
- BidiIterator() : par(0), obj(0), pos(0), endOfInline(0) {}
- BidiIterator(RenderBlock *_par, RenderObject *_obj, unsigned int _pos, bool eoi=false) : par(_par), obj(_obj), pos(_pos), endOfInline(eoi) {}
-
- void increment( BidiState &bidi, bool skipInlines=true );
-
- bool atEnd() const;
-
- const TQChar &current() const;
- TQChar::Direction direction() const;
-
- RenderBlock *par;
- RenderObject *obj;
- unsigned int pos;
- bool endOfInline;
-};
-
-
-struct BidiStatus {
- BidiStatus() : eor(TQChar::DirON), lastStrong(TQChar::DirON), last(TQChar::DirON) {}
-
- TQChar::Direction eor;
- TQChar::Direction lastStrong;
- TQChar::Direction last;
-};
-
-struct BidiState {
- BidiState() : context(0) {}
-
- BidiIterator sor;
- BidiIterator eor;
- BidiIterator last;
- BidiIterator current;
- BidiContext *context;
- BidiStatus status;
-};
-
-// Used to track a list of chained bidi runs.
-static BidiRun* sFirstBidiRun;
-static BidiRun* sLastBidiRun;
-static int sBidiRunCount;
-static BidiRun* sCompactFirstBidiRun;
-static BidiRun* sCompactLastBidiRun;
-static int sCompactBidiRunCount;
-static bool sBuildingCompactRuns;
-
-// Midpoint globals. The goal is not to do any allocation when dealing with
-// these midpoints, so we just keep an array around and never clear it. We track
-// the number of items and position using the two other variables.
-static TQMemArray<BidiIterator> *smidpoints;
-static uint sNumMidpoints;
-static uint sCurrMidpoint;
-static bool betweenMidpoints;
-
-static bool isLineEmpty = true;
-static bool previousLineBrokeAtBR = true;
-static TQChar::Direction dir;
-static bool adjustEmbedding;
-static bool emptyRun = true;
-static int numSpaces;
-
-static void embed( TQChar::Direction d, BidiState &bidi );
-static void appendRun( BidiState &bidi );
-
-static int getBPMWidth(int childValue, Length cssUnit)
-{
- if (!cssUnit.isVariable())
- return (cssUnit.isFixed() ? cssUnit.value() : childValue);
- return 0;
-}
-
-static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
-{
- RenderStyle* cstyle = child->style();
- int result = 0;
- bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
- result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
- (leftSide ? cstyle->marginLeft() :
- cstyle->marginRight()));
- result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
- (leftSide ? cstyle->paddingLeft() :
- cstyle->paddingRight()));
- result += leftSide ? child->borderLeft() : child->borderRight();
- return result;
-}
-
-#ifndef NDEBUG
-static bool inBidiRunDetach;
-#endif
-
-void BidiRun::detach(RenderArena* renderArena)
-{
-#ifndef NDEBUG
- inBidiRunDetach = true;
-#endif
- delete this;
-#ifndef NDEBUG
- inBidiRunDetach = false;
-#endif
-
- // Recover the size left there for us by operator delete and free the memory.
- renderArena->free(*(size_t *)this, this);
-}
-
-void* BidiRun::operator new(size_t sz, RenderArena* renderArena) throw()
-{
- return renderArena->allocate(sz);
-}
-
-void BidiRun::operator delete(void* ptr, size_t sz)
-{
- assert(inBidiRunDetach);
-
- // Stash size where detach can find it.
- *(size_t*)ptr = sz;
-}
-
-static void deleteBidiRuns(RenderArena* arena)
-{
- if (!sFirstBidiRun)
- return;
-
- BidiRun* curr = sFirstBidiRun;
- while (curr) {
- BidiRun* s = curr->nextRun;
- curr->detach(arena);
- curr = s;
- }
-
- sFirstBidiRun = 0;
- sLastBidiRun = 0;
- sBidiRunCount = 0;
-}
-
-// ---------------------------------------------------------------------
-
-/* a small helper class used internally to resolve Bidi embedding levels.
- Each line of text caches the embedding level at the start of the line for faster
- relayouting
-*/
-BidiContext::BidiContext(unsigned char l, TQChar::Direction e, BidiContext *p, bool o)
- : level(l) , override(o), dir(e)
-{
- parent = p;
- if(p) {
- p->ref();
- basicDir = p->basicDir;
- } else
- basicDir = e;
- count = 0;
-}
-
-BidiContext::~BidiContext()
-{
- if(parent) parent->deref();
-}
-
-void BidiContext::ref() const
-{
- count++;
-}
-
-void BidiContext::deref() const
-{
- count--;
- if(count <= 0) delete this;
-}
-
-// ---------------------------------------------------------------------
-
-inline bool operator==( const BidiIterator &it1, const BidiIterator &it2 )
-{
- if(it1.pos != it2.pos) return false;
- if(it1.obj != it2.obj) return false;
- return true;
-}
-
-inline bool operator!=( const BidiIterator &it1, const BidiIterator &it2 )
-{
- if(it1.pos != it2.pos) return true;
- if(it1.obj != it2.obj) return true;
- return false;
-}
-
-// when modifying this function, make sure you check InlineMinMaxIterator::next() as well.
-static inline RenderObject *Bidinext(RenderObject *par, RenderObject *current, BidiState &bidi,
- bool skipInlines = true, bool *endOfInline = 0 )
-{
- RenderObject *next = 0;
- bool oldEndOfInline = endOfInline ? *endOfInline : false;
- if (oldEndOfInline)
- *endOfInline = false;
-
- while(current != 0)
- {
- //kdDebug( 6040 ) << "current = " << current << endl;
- if (!oldEndOfInline && !current->isFloating() && !current->isReplaced() && !current->isPositioned()) {
- next = current->firstChild();
- if ( next && adjustEmbedding ) {
- EUnicodeBidi ub = next->style()->unicodeBidi();
- if ( ub != UBNormal && !emptyRun ) {
- EDirection dir = next->style()->direction();
- TQChar::Direction d = ( ub == Embed ? ( dir == RTL ? TQChar::DirRLE : TQChar::DirLRE )
- : ( dir == RTL ? TQChar::DirRLO : TQChar::DirLRO ) );
- embed( d, bidi );
- }
- }
- }
- if (!next) {
- if (!skipInlines && !oldEndOfInline && current->isInlineFlow() && endOfInline) {
- next = current;
- *endOfInline = true;
- break;
- }
-
- while (current && current != par) {
- next = current->nextSibling();
- if (next) break;
- if ( adjustEmbedding && current->style()->unicodeBidi() != UBNormal && !emptyRun ) {
- embed( TQChar::DirPDF, bidi );
- }
- current = current->parent();
- if (!skipInlines && current && current != par && current->isInlineFlow() && endOfInline) {
- next = current;
- *endOfInline = true;
- break;
- }
- }
- }
-
- if (!next) break;
-
- if (next->isText() || next->isBR() || next->isFloating() || next->isReplaced() || next->isPositioned() || next->isGlyph()
- || ((!skipInlines || !next->firstChild()) // Always return EMPTY inlines.
- && next->isInlineFlow()))
- break;
- current = next;
- }
- return next;
-}
-
-static RenderObject *first( RenderObject *par, BidiState &bidi, bool skipInlines = true )
-{
- if(!par->firstChild()) return 0;
- RenderObject *o = par->firstChild();
-
- if (o->isInlineFlow()) {
- if (skipInlines && o->firstChild())
- o = Bidinext( par, o, bidi, skipInlines );
- else
- return o; // Never skip empty inlines.
- }
-
- if (o && !o->isText() && !o->isBR() && !o->isReplaced() && !o->isFloating() && !o->isPositioned() && !o->isGlyph())
- o = Bidinext( par, o, bidi, skipInlines );
- return o;
-}
-
-inline void BidiIterator::increment (BidiState &bidi, bool skipInlines)
-{
- if(!obj) return;
- if(obj->isText()) {
- pos++;
- if(pos >= static_cast<RenderText *>(obj)->stringLength()) {
- obj = Bidinext( par, obj, bidi, skipInlines );
- pos = 0;
- }
- } else {
- obj = Bidinext( par, obj, bidi, skipInlines, &endOfInline );
- pos = 0;
- }
-}
-
-inline bool BidiIterator::atEnd() const
-{
- if(!obj) return true;
- return false;
-}
-
-const TQChar &BidiIterator::current() const
-{
- static TQChar nonBreakingSpace(0xA0);
-
- if (!obj || !obj->isText())
- return nonBreakingSpace;
-
- RenderText* text = static_cast<RenderText*>(obj);
- if (!text->text())
- return nonBreakingSpace;
-
- return text->text()[pos];
-}
-
-inline TQChar::Direction BidiIterator::direction() const
-{
- if(!obj || !obj->isText() ) return TQChar::DirON;
-
- RenderText *renderTxt = static_cast<RenderText *>( obj );
- if ( pos >= renderTxt->stringLength() )
- return TQChar::DirON;
- return renderTxt->text()[pos].direction();
-}
-
-// -------------------------------------------------------------------------------------------------
-
-static void addRun(BidiRun* bidiRun)
-{
- if (!sFirstBidiRun)
- sFirstBidiRun = sLastBidiRun = bidiRun;
- else {
- sLastBidiRun->nextRun = bidiRun;
- sLastBidiRun = bidiRun;
- }
- sBidiRunCount++;
- bidiRun->compact = sBuildingCompactRuns;
-
- // Compute the number of spaces in this run,
- if (bidiRun->obj && bidiRun->obj->isText()) {
- RenderText* text = static_cast<RenderText*>(bidiRun->obj);
- if (text->text()) {
- for (int i = bidiRun->start; i < bidiRun->stop; i++) {
- const TQChar c = text->text()[i];
- if (c.category() == TQChar::Separator_Space || c == '\n')
- numSpaces++;
- }
- }
- }
-}
-
-static void reverseRuns(int start, int end)
-{
- if (start >= end)
- return;
-
- assert(start >= 0 && end < sBidiRunCount);
-
- // Get the item before the start of the runs to reverse and put it in
- // |beforeStart|. |curr| should point to the first run to reverse.
- BidiRun* curr = sFirstBidiRun;
- BidiRun* beforeStart = 0;
- int i = 0;
- while (i < start) {
- i++;
- beforeStart = curr;
- curr = curr->nextRun;
- }
-
- BidiRun* startRun = curr;
- while (i < end) {
- i++;
- curr = curr->nextRun;
- }
- BidiRun* endRun = curr;
- BidiRun* afterEnd = curr->nextRun;
-
- i = start;
- curr = startRun;
- BidiRun* newNext = afterEnd;
- while (i <= end) {
- // Do the reversal.
- BidiRun* next = curr->nextRun;
- curr->nextRun = newNext;
- newNext = curr;
- curr = next;
- i++;
- }
-
- // Now hook up beforeStart and afterEnd to the newStart and newEnd.
- if (beforeStart)
- beforeStart->nextRun = endRun;
- else
- sFirstBidiRun = endRun;
-
- startRun->nextRun = afterEnd;
- if (!afterEnd)
- sLastBidiRun = startRun;
-}
-
-static void chopMidpointsAt(RenderObject* obj, uint pos)
-{
- if (!sNumMidpoints) return;
- BidiIterator* midpoints = smidpoints->data();
- for (uint i = 0; i < sNumMidpoints; i++) {
- const BidiIterator& point = midpoints[i];
- if (point.obj == obj && point.pos == pos) {
- sNumMidpoints = i;
- break;
- }
- }
-}
-
-static void checkMidpoints(BidiIterator& lBreak, BidiState &bidi)
-{
- // Check to see if our last midpoint is a start point beyond the line break. If so,
- // shave it off the list, and shave off a trailing space if the previous end point isn't
- // white-space: pre.
- if (lBreak.obj && sNumMidpoints && sNumMidpoints%2 == 0) {
- BidiIterator* midpoints = smidpoints->data();
- BidiIterator& endpoint = midpoints[sNumMidpoints-2];
- const BidiIterator& startpoint = midpoints[sNumMidpoints-1];
- BidiIterator currpoint = endpoint;
- while (!currpoint.atEnd() && currpoint != startpoint && currpoint != lBreak)
- currpoint.increment( bidi );
- if (currpoint == lBreak) {
- // We hit the line break before the start point. Shave off the start point.
- sNumMidpoints--;
- if (!endpoint.obj->style()->preserveWS()) {
- if (endpoint.obj->isText()) {
- // Don't shave a character off the endpoint if it was from a soft hyphen.
- RenderText* textObj = static_cast<RenderText*>(endpoint.obj);
- if (endpoint.pos+1 < textObj->length() &&
- textObj->text()[endpoint.pos+1].unicode() == SOFT_HYPHEN)
- return;
- }
- endpoint.pos--;
- }
- }
- }
-}
-
-static void addMidpoint(const BidiIterator& midpoint)
-{
- if (!smidpoints)
- return;
-
- if (smidpoints->size() <= sNumMidpoints)
- smidpoints->resize(sNumMidpoints+10);
-
- BidiIterator* midpoints = smidpoints->data();
- midpoints[sNumMidpoints++] = midpoint;
-}
-
-static void appendRunsForObject(int start, int end, RenderObject* obj, BidiState &bidi)
-{
- if (start > end || obj->isFloating() ||
- (obj->isPositioned() && !obj->hasStaticX() && !obj->hasStaticY()))
- return;
-
- bool haveNextMidpoint = (smidpoints && sCurrMidpoint < sNumMidpoints);
- BidiIterator nextMidpoint;
- if (haveNextMidpoint)
- nextMidpoint = smidpoints->at(sCurrMidpoint);
- if (betweenMidpoints) {
- if (!(haveNextMidpoint && nextMidpoint.obj == obj))
- return;
- // This is a new start point. Stop ignoring objects and
- // adjust our start.
- betweenMidpoints = false;
- start = nextMidpoint.pos;
- sCurrMidpoint++;
- if (start < end)
- return appendRunsForObject(start, end, obj, bidi);
- }
- else {
- if (!smidpoints || !haveNextMidpoint || (obj != nextMidpoint.obj)) {
- addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context, dir));
- return;
- }
-
- // An end midpoint has been encountered within our object. We
- // need to go ahead and append a run with our endpoint.
- if (int(nextMidpoint.pos+1) <= end) {
- betweenMidpoints = true;
- sCurrMidpoint++;
- if (nextMidpoint.pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
- addRun(new (obj->renderArena())
- BidiRun(start, nextMidpoint.pos+1, obj, bidi.context, dir));
- return appendRunsForObject(nextMidpoint.pos+1, end, obj, bidi);
- }
- }
- else
- addRun(new (obj->renderArena()) BidiRun(start, end, obj, bidi.context, dir));
- }
-}
-
-static void appendRun( BidiState &bidi )
-{
- if ( emptyRun ) return;
-#if BIDI_DEBUG > 1
- kdDebug(6041) << "appendRun: dir="<<(int)dir<<endl;
-#endif
-
- bool b = adjustEmbedding;
- adjustEmbedding = false;
-
- int start = bidi.sor.pos;
- RenderObject *obj = bidi.sor.obj;
- while( obj && obj != bidi.eor.obj ) {
- appendRunsForObject(start, obj->length(), obj, bidi);
- start = 0;
- obj = Bidinext( bidi.sor.par, obj, bidi );
- }
- if (obj)
- appendRunsForObject(start, bidi.eor.pos+1, obj, bidi);
-
- bidi.eor.increment( bidi );
- bidi.sor = bidi.eor;
- dir = TQChar::DirON;
- bidi.status.eor = TQChar::DirON;
- adjustEmbedding = b;
-}
-
-static void embed( TQChar::Direction d, BidiState &bidi )
-{
-#if BIDI_DEBUG > 1
- tqDebug("*** embed dir=%d emptyrun=%d", d, emptyRun );
-#endif
- bool b = adjustEmbedding ;
- adjustEmbedding = false;
- if ( d == TQChar::DirPDF ) {
- BidiContext *c = bidi.context->parent;
- if (c) {
- if ( bidi.eor != bidi.last ) {
- appendRun( bidi );
- bidi.eor = bidi.last;
- }
- appendRun( bidi );
- emptyRun = true;
- bidi.status.last = bidi.context->dir;
- bidi.context->deref();
- bidi.context = c;
- if(bidi.context->override)
- dir = bidi.context->dir;
- else
- dir = TQChar::DirON;
- bidi.status.lastStrong = bidi.context->dir;
- }
- } else {
- TQChar::Direction runDir;
- if( d == TQChar::DirRLE || d == TQChar::DirRLO )
- runDir = TQChar::DirR;
- else
- runDir = TQChar::DirL;
- bool override;
- if( d == TQChar::DirLRO || d == TQChar::DirRLO )
- override = true;
- else
- override = false;
-
- unsigned char level = bidi.context->level;
- if ( runDir == TQChar::DirR ) {
- if(level%2) // we have an odd level
- level += 2;
- else
- level++;
- } else {
- if(level%2) // we have an odd level
- level++;
- else
- level += 2;
- }
-
- if(level < 61) {
- if ( bidi.eor != bidi.last ) {
- appendRun( bidi );
- bidi.eor = bidi.last;
- }
- appendRun( bidi );
- emptyRun = true;
-
- bidi.context = new BidiContext(level, runDir, bidi.context, override);
- bidi.context->ref();
- dir = runDir;
- bidi.status.last = runDir;
- bidi.status.lastStrong = runDir;
- bidi.status.eor = runDir;
- }
- }
- adjustEmbedding = b;
-}
-
-InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj)
-{
- // See if we have an unconstructed line box for this object that is also
- // the last item on the line.
- KHTMLAssert(obj->isInlineFlow() || obj == this);
- RenderFlow* flow = static_cast<RenderFlow*>(obj);
-
- // Get the last box we made for this render object.
- InlineFlowBox* box = flow->lastLineBox();
-
- // If this box is constructed then it is from a previous line, and we need
- // to make a new box for our line. If this box is unconstructed but it has
- // something following it on the line, then we know we have to make a new box
- // as well. In this situation our inline has actually been split in two on
- // the same line (this can happen with very fancy language mixtures).
- if (!box || box->isConstructed() || box->nextOnLine()) {
- // We need to make a new box for this render object. Once
- // made, we need to place it at the end of the current line.
- InlineBox* newBox = obj->createInlineBox(false, obj == this);
- KHTMLAssert(newBox->isInlineFlowBox());
- box = static_cast<InlineFlowBox*>(newBox);
- box->setFirstLineStyleBit(m_firstLine);
-
- // We have a new box. Append it to the inline box we get by constructing our
- // parent. If we have hit the block itself, then |box| represents the root
- // inline box for the line, and it doesn't have to be appended to any parent
- // inline.
- if (obj != this) {
- InlineFlowBox* parentBox = createLineBoxes(obj->parent());
- parentBox->addToLine(box);
- }
- }
-
- return box;
-}
-
-InlineFlowBox* RenderBlock::constructLine(const BidiIterator &/*start*/, const BidiIterator &end)
-{
- if (!sFirstBidiRun)
- return 0; // We had no runs. Don't make a root inline box at all. The line is empty.
-
- InlineFlowBox* parentBox = 0;
- for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
- // Create a box for our object.
- r->box = r->obj->createInlineBox(r->obj->isPositioned(), false);
-
- // If we have no parent box yet, or if the run is not simply a sibling,
- // then we need to construct inline boxes as necessary to properly enclose the
- // run's inline box.
- if (!parentBox || (parentBox->object() != r->obj->parent()))
- // Create new inline boxes all the way back to the appropriate insertion point.
- parentBox = createLineBoxes(r->obj->parent());
-
- // Append the inline box to this line.
- parentBox->addToLine(r->box);
- }
-
- // We should have a root inline box. It should be unconstructed and
- // be the last continuation of our line list.
- KHTMLAssert(lastLineBox() && !lastLineBox()->isConstructed());
-
- // Set bits on our inline flow boxes that indicate which sides should
- // paint borders/margins/padding. This knowledge will ultimately be used when
- // we determine the horizontal positions and widths of all the inline boxes on
- // the line.
- RenderObject* endObject = 0;
- bool lastLine = !end.obj;
- if (end.obj && end.pos == 0)
- endObject = end.obj;
- lastLineBox()->determineSpacingForFlowBoxes(lastLine, endObject);
-
- // Now mark the line boxes as being constructed.
- lastLineBox()->setConstructed();
-
- // Return the last line.
- return lastLineBox();
-}
-
-void RenderBlock::computeHorizontalPositionsForLine(InlineFlowBox* lineBox, BidiState &bidi)
-{
- // First determine our total width.
- int totWidth = lineBox->getFlowSpacingWidth();
- BidiRun* r = 0;
- for (r = sFirstBidiRun; r; r = r->nextRun) {
- if (r->obj->isPositioned())
- continue; // Positioned objects are only participating to figure out their
- // correct static x position. They have no effect on the width.
- if (r->obj->isText())
- r->box->setWidth(static_cast<RenderText *>(r->obj)->width(r->start, r->stop-r->start, m_firstLine));
- else if (!r->obj->isInlineFlow()) {
- r->obj->calcWidth();
- r->box->setWidth(r->obj->width());
- totWidth += r->obj->marginLeft() + r->obj->marginRight();
- }
- totWidth += r->box->width();
- }
-
- // Armed with the total width of the line (without justification),
- // we now examine our text-align property in order to determine where to position the
- // objects horizontally. The total width of the line can be increased if we end up
- // justifying text.
- int x = leftOffset(m_height);
- int availableWidth = lineWidth(m_height);
- switch(style()->textAlign()) {
- case LEFT:
- case KHTML_LEFT:
- numSpaces = 0;
- break;
- case JUSTIFY:
- if (numSpaces != 0 && !bidi.current.atEnd() && !bidi.current.obj->isBR() )
- break;
- // fall through
- case TAAUTO:
- numSpaces = 0;
- // for right to left fall through to right aligned
- if (bidi.context->basicDir == TQChar::DirL)
- break;
- case RIGHT:
- case KHTML_RIGHT:
- x += availableWidth - totWidth;
- numSpaces = 0;
- break;
- case CENTER:
- case KHTML_CENTER:
- int xd = (availableWidth - totWidth)/2;
- x += xd >0 ? xd : 0;
- numSpaces = 0;
- break;
- }
-
- if (numSpaces > 0) {
- for (r = sFirstBidiRun; r; r = r->nextRun) {
- int spaceAdd = 0;
- if (numSpaces > 0 && r->obj->isText()) {
- // get the number of spaces in the run
- int spaces = 0;
- for ( int i = r->start; i < r->stop; i++ ) {
- const TQChar c = static_cast<RenderText *>(r->obj)->text()[i];
- if (c.category() == TQChar::Separator_Space || c == '\n')
- spaces++;
- }
-
- KHTMLAssert(spaces <= numSpaces);
-
- // Only justify text with white-space: normal.
- if (r->obj->style()->whiteSpace() == NORMAL) {
- spaceAdd = (availableWidth - totWidth)*spaces/numSpaces;
- static_cast<InlineTextBox*>(r->box)->setSpaceAdd(spaceAdd);
- totWidth += spaceAdd;
- }
- numSpaces -= spaces;
- }
- }
- }
-
- // The widths of all runs are now known. We can now place every inline box (and
- // compute accurate widths for the inline flow boxes).
- int rightPos = lineBox->placeBoxesHorizontally(x);
- if (rightPos > m_overflowWidth)
- m_overflowWidth = rightPos; // FIXME: Work for rtl overflow also.
- if (x < 0)
- m_overflowLeft = kMin(m_overflowLeft, x);
-}
-
-void RenderBlock::computeVerticalPositionsForLine(InlineFlowBox* lineBox)
-{
- lineBox->verticallyAlignBoxes(m_height);
-// lineBox->setBlockHeight(m_height);
-
- // Check for page-breaks
- if (canvas()->pagedMode() && !lineBox->afterPageBreak())
- // If we get a page-break we might need to redo the line-break
- if (clearLineOfPageBreaks(lineBox) && hasFloats()) return;
-
- // See if the line spilled out. If so set overflow height accordingly.
- int bottomOfLine = lineBox->bottomOverflow();
- if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
- m_overflowHeight = bottomOfLine;
-
- bool beforeContent = true;
-
- // Now make sure we place replaced render objects correctly.
- for (BidiRun* r = sFirstBidiRun; r; r = r->nextRun) {
-
- // For positioned placeholders, cache the static Y position an object with non-inline display would have.
- // Either it is unchanged if it comes before any real linebox, or it must clear the current line (already accounted in m_height).
- // This value will be picked up by position() if relevant.
- if (r->obj->isPositioned())
- r->box->setYPos( beforeContent && r->obj->isBox() ? static_cast<RenderBox*>(r->obj)->staticY() : m_height );
- else if (beforeContent)
- beforeContent = false;
-
- // Position is used to properly position both replaced elements and
- // to update the static normal flow x/y of positioned elements.
- r->obj->position(r->box, r->start, r->stop - r->start, r->level%2);
- }
-}
-
-bool RenderBlock::clearLineOfPageBreaks(InlineFlowBox* lineBox)
-{
- bool doPageBreak = false;
- // Check for physical page-breaks
- int xpage = crossesPageBreak(lineBox->topOverflow(), lineBox->bottomOverflow());
- if (xpage) {
-#ifdef PAGE_DEBUG
- kdDebug(6040) << renderName() << " Line crosses to page " << xpage << endl;
- kdDebug(6040) << renderName() << " at pos " << lineBox->yPos() << " height " << lineBox->height() << endl;
-#endif
-
- doPageBreak = true;
- // check page-break-inside
- if (!style()->pageBreakInside()) {
- if (parent()->canClear(this, PageBreakNormal)) {
- setNeedsPageClear(true);
- doPageBreak = false;
- }
-#ifdef PAGE_DEBUG
- else
- kdDebug(6040) << "Ignoring page-break-inside: avoid" << endl;
-#endif
- }
- // check orphans
- int orphans = 0;
- InlineRunBox* box = lineBox->prevLineBox();
- while (box && orphans < style()->orphans()) {
- orphans++;
- box = box->prevLineBox();
- }
-
- if (orphans == 0) {
- setNeedsPageClear(true);
- doPageBreak = false;
- } else
- if (orphans < style()->orphans() ) {
-#ifdef PAGE_DEBUG
- kdDebug(6040) << "Orphans: " << orphans << endl;
-#endif
- // Orphans is a level 2 page-break rule and can be broken only
- // if the break is physically required.
- if (parent()->canClear(this, PageBreakHarder)) {
- // move block instead
- setNeedsPageClear(true);
- doPageBreak = false;
- }
-#ifdef PAGE_DEBUG
- else
- kdDebug(6040) << "Ignoring violated orphans" << endl;
-#endif
- }
- if (doPageBreak) {
- int pTop = pageTopAfter(lineBox->yPos());
-
- m_height = pTop;
- lineBox->setAfterPageBreak(true);
- lineBox->verticallyAlignBoxes(m_height);
- if (lineBox->yPos() < pTop) {
- // ### serious crap. render_line is sometimes placing lines too high
- kdDebug(6040) << "page top overflow by repositioned line" << endl;
- int heightIncrease = pTop - lineBox->yPos();
- m_height = pTop + heightIncrease;
- lineBox->verticallyAlignBoxes(m_height);
- }
-#ifdef PAGE_DEBUG
- kdDebug(6040) << "Cleared line " << lineBox->yPos() - oldYPos << "px" << endl;
-#endif
- setContainsPageBreak(true);
- }
- }
- return doPageBreak;
-}
-
-// collects one line of the paragraph and transforms it to visual order
-void RenderBlock::bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi)
-{
- if ( start == end ) {
- if ( start.current() == '\n' ) {
- m_height += lineHeight( m_firstLine );
- }
- return;
- }
-
-#if BIDI_DEBUG > 1
- kdDebug(6041) << "reordering Line from " << start.obj << "/" << start.pos << " to " << end.obj << "/" << end.pos << endl;
-#endif
-
- sFirstBidiRun = 0;
- sLastBidiRun = 0;
- sBidiRunCount = 0;
-
- // context->ref();
-
- dir = TQChar::DirON;
- emptyRun = true;
-
- numSpaces = 0;
-
- bidi.current = start;
- bidi.last = bidi.current;
- bool atEnd = false;
- while( 1 ) {
-
- TQChar::Direction dirCurrent;
- if (atEnd) {
- //kdDebug(6041) << "atEnd" << endl;
- BidiContext *c = bidi.context;
- if ( bidi.current.atEnd())
- while ( c->parent )
- c = c->parent;
- dirCurrent = c->dir;
- } else {
- dirCurrent = bidi.current.direction();
- }
-
-#ifndef QT_NO_UNICODETABLES
-
-#if BIDI_DEBUG > 1
- kdDebug(6041) << "directions: dir=" << (int)dir << " current=" << (int)dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << (int)context->dir << " level =" << (int)context->level << endl;
-#endif
-
- switch(dirCurrent) {
-
- // embedding and overrides (X1-X9 in the Bidi specs)
- case TQChar::DirRLE:
- case TQChar::DirLRE:
- case TQChar::DirRLO:
- case TQChar::DirLRO:
- case TQChar::DirPDF:
- embed( dirCurrent, bidi );
- break;
-
- // strong types
- case TQChar::DirL:
- if(dir == TQChar::DirON)
- dir = TQChar::DirL;
- switch(bidi.status.last)
- {
- case TQChar::DirL:
- bidi.eor = bidi.current; bidi.status.eor = TQChar::DirL; break;
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirEN:
- case TQChar::DirAN:
- appendRun( bidi );
- break;
- case TQChar::DirES:
- case TQChar::DirET:
- case TQChar::DirCS:
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if( bidi.status.eor != TQChar::DirL ) {
- //last stuff takes embedding dir
- if(bidi.context->dir == TQChar::DirL || bidi.status.lastStrong == TQChar::DirL) {
- if ( bidi.status.eor != TQChar::DirEN && bidi.status.eor != TQChar::DirAN && bidi.status.eor != TQChar::DirON )
- appendRun( bidi );
- dir = TQChar::DirL;
- bidi.eor = bidi.current;
- bidi.status.eor = TQChar::DirL;
- } else {
- if ( bidi.status.eor == TQChar::DirEN || bidi.status.eor == TQChar::DirAN )
- {
- dir = bidi.status.eor;
- appendRun( bidi );
- }
- dir = TQChar::DirR;
- bidi.eor = bidi.last;
- appendRun( bidi );
- dir = TQChar::DirL;
- bidi.status.eor = TQChar::DirL;
- }
- } else {
- bidi.eor = bidi.current; bidi.status.eor = TQChar::DirL;
- }
- default:
- break;
- }
- bidi.status.lastStrong = TQChar::DirL;
- break;
- case TQChar::DirAL:
- case TQChar::DirR:
- if(dir == TQChar::DirON) dir = TQChar::DirR;
- switch(bidi.status.last)
- {
- case TQChar::DirR:
- case TQChar::DirAL:
- bidi.eor = bidi.current; bidi.status.eor = TQChar::DirR; break;
- case TQChar::DirL:
- case TQChar::DirEN:
- case TQChar::DirAN:
- appendRun( bidi );
- dir = TQChar::DirR;
- bidi.eor = bidi.current;
- bidi.status.eor = TQChar::DirR;
- break;
- case TQChar::DirES:
- case TQChar::DirET:
- case TQChar::DirCS:
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if( !(bidi.status.eor == TQChar::DirR) && !(bidi.status.eor == TQChar::DirAL) ) {
- //last stuff takes embedding dir
- if(bidi.context->dir == TQChar::DirR || bidi.status.lastStrong == TQChar::DirR
- || bidi.status.lastStrong == TQChar::DirAL) {
- appendRun( bidi );
- dir = TQChar::DirR;
- bidi.eor = bidi.current;
- bidi.status.eor = TQChar::DirR;
- } else {
- dir = TQChar::DirL;
- bidi.eor = bidi.last;
- appendRun( bidi );
- dir = TQChar::DirR;
- bidi.status.eor = TQChar::DirR;
- }
- } else {
- bidi.eor = bidi.current; bidi.status.eor = TQChar::DirR;
- }
- default:
- break;
- }
- bidi.status.lastStrong = dirCurrent;
- break;
-
- // weak types:
-
- case TQChar::DirNSM:
- // ### if @sor, set dir to dirSor
- break;
- case TQChar::DirEN:
- if(!(bidi.status.lastStrong == TQChar::DirAL)) {
- // if last strong was AL change EN to AN
- if(dir == TQChar::DirON) {
- dir = TQChar::DirL;
- }
- switch(bidi.status.last)
- {
- case TQChar::DirET:
- if ( bidi.status.lastStrong == TQChar::DirR || bidi.status.lastStrong == TQChar::DirAL ) {
- appendRun( bidi );
- dir = TQChar::DirEN;
- bidi.status.eor = TQChar::DirEN;
- }
- // fall through
- case TQChar::DirEN:
- case TQChar::DirL:
- bidi.eor = bidi.current;
- bidi.status.eor = dirCurrent;
- break;
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirAN:
- appendRun( bidi );
- bidi.status.eor = TQChar::DirEN;
- dir = TQChar::DirEN; break;
- case TQChar::DirES:
- case TQChar::DirCS:
- if(bidi.status.eor == TQChar::DirEN) {
- bidi.eor = bidi.current; break;
- }
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if(bidi.status.eor == TQChar::DirR) {
- // neutrals go to R
- bidi.eor = bidi.last;
- appendRun( bidi );
- dir = TQChar::DirEN;
- bidi.status.eor = TQChar::DirEN;
- }
- else if( bidi.status.eor == TQChar::DirL ||
- (bidi.status.eor == TQChar::DirEN && bidi.status.lastStrong == TQChar::DirL)) {
- bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
- } else {
- // numbers on both sides, neutrals get right to left direction
- if(dir != TQChar::DirL) {
- appendRun( bidi );
- bidi.eor = bidi.last;
- dir = TQChar::DirR;
- appendRun( bidi );
- dir = TQChar::DirEN;
- bidi.status.eor = TQChar::DirEN;
- } else {
- bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
- }
- }
- default:
- break;
- }
- break;
- }
- case TQChar::DirAN:
- dirCurrent = TQChar::DirAN;
- if(dir == TQChar::DirON) dir = TQChar::DirAN;
- switch(bidi.status.last)
- {
- case TQChar::DirL:
- case TQChar::DirAN:
- bidi.eor = bidi.current; bidi.status.eor = TQChar::DirAN; break;
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirEN:
- appendRun( bidi );
- dir = TQChar::DirAN; bidi.status.eor = TQChar::DirAN;
- break;
- case TQChar::DirCS:
- if(bidi.status.eor == TQChar::DirAN) {
- bidi.eor = bidi.current; break;
- }
- case TQChar::DirES:
- case TQChar::DirET:
- case TQChar::DirBN:
- case TQChar::DirB:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- if(bidi.status.eor == TQChar::DirR) {
- // neutrals go to R
- bidi.eor = bidi.last;
- appendRun( bidi );
- dir = TQChar::DirAN;
- bidi.status.eor = TQChar::DirAN;
- } else if( bidi.status.eor == TQChar::DirL ||
- (bidi.status.eor == TQChar::DirEN && bidi.status.lastStrong == TQChar::DirL)) {
- bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
- } else {
- // numbers on both sides, neutrals get right to left direction
- if(dir != TQChar::DirL) {
- appendRun( bidi );
- bidi.eor = bidi.last;
- dir = TQChar::DirR;
- appendRun( bidi );
- dir = TQChar::DirAN;
- bidi.status.eor = TQChar::DirAN;
- } else {
- bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
- }
- }
- default:
- break;
- }
- break;
- case TQChar::DirES:
- case TQChar::DirCS:
- break;
- case TQChar::DirET:
- if(bidi.status.last == TQChar::DirEN) {
- dirCurrent = TQChar::DirEN;
- bidi.eor = bidi.current; bidi.status.eor = dirCurrent;
- break;
- }
- break;
-
- // boundary neutrals should be ignored
- case TQChar::DirBN:
- break;
- // neutrals
- case TQChar::DirB:
- // ### what do we do with newline and paragraph seperators that come to here?
- break;
- case TQChar::DirS:
- // ### implement rule L1
- break;
- case TQChar::DirWS:
- break;
- case TQChar::DirON:
- break;
- default:
- break;
- }
-
- //cout << " after: dir=" << // dir << " current=" << dirCurrent << " last=" << status.last << " eor=" << status.eor << " lastStrong=" << status.lastStrong << " embedding=" << context->dir << endl;
-
- if(bidi.current.atEnd()) break;
-
- // set status.last as needed.
- switch(dirCurrent)
- {
- case TQChar::DirET:
- case TQChar::DirES:
- case TQChar::DirCS:
- case TQChar::DirS:
- case TQChar::DirWS:
- case TQChar::DirON:
- switch(bidi.status.last)
- {
- case TQChar::DirL:
- case TQChar::DirR:
- case TQChar::DirAL:
- case TQChar::DirEN:
- case TQChar::DirAN:
- bidi.status.last = dirCurrent;
- break;
- default:
- bidi.status.last = TQChar::DirON;
- }
- break;
- case TQChar::DirNSM:
- case TQChar::DirBN:
- // ignore these
- break;
- case TQChar::DirEN:
- if ( bidi.status.last == TQChar::DirL ) {
- break;
- }
- // fall through
- default:
- bidi.status.last = dirCurrent;
- }
-#endif
-
- if ( atEnd ) break;
- bidi.last = bidi.current;
-
- if ( emptyRun ) {
- bidi.sor = bidi.current;
- bidi.eor = bidi.current;
- emptyRun = false;
- }
-
- // this causes the operator ++ to open and close embedding levels as needed
- // for the CSS unicode-bidi property
- adjustEmbedding = true;
- bidi.current.increment( bidi );
- adjustEmbedding = false;
-
- if ( bidi.current == end ) {
- if ( emptyRun )
- break;
- atEnd = true;
- }
- }
-
-#if BIDI_DEBUG > 0
- kdDebug(6041) << "reached end of line current=" << current.obj << "/" << current.pos
- << ", eor=" << eor.obj << "/" << eor.pos << endl;
-#endif
- if ( !emptyRun && bidi.sor != bidi.current ) {
- bidi.eor = bidi.last;
- appendRun( bidi );
- }
-
- // reorder line according to run structure...
-
- // first find highest and lowest levels
- uchar levelLow = 128;
- uchar levelHigh = 0;
- BidiRun *r = sFirstBidiRun;
- while ( r ) {
- if ( r->level > levelHigh )
- levelHigh = r->level;
- if ( r->level < levelLow )
- levelLow = r->level;
- r = r->nextRun;
- }
-
- // implements reordering of the line (L2 according to Bidi spec):
- // L2. From the highest level found in the text to the lowest odd level on each line,
- // reverse any contiguous sequence of characters that are at that level or higher.
-
- // reversing is only done up to the lowest odd level
- if( !(levelLow%2) ) levelLow++;
-
-#if BIDI_DEBUG > 0
- kdDebug(6041) << "lineLow = " << (uint)levelLow << ", lineHigh = " << (uint)levelHigh << endl;
- kdDebug(6041) << "logical order is:" << endl;
- TQPtrListIterator<BidiRun> it2(runs);
- BidiRun *r2;
- for ( ; (r2 = it2.current()); ++it2 )
- kdDebug(6041) << " " << r2 << " start=" << r2->start << " stop=" << r2->stop << " level=" << (uint)r2->level << endl;
-#endif
-
- int count = sBidiRunCount - 1;
-
- // do not reverse for visually ordered web sites
- if(!style()->visuallyOrdered()) {
- while(levelHigh >= levelLow) {
- int i = 0;
- BidiRun* currRun = sFirstBidiRun;
- while ( i < count ) {
- while(i < count && currRun && currRun->level < levelHigh) {
- i++;
- currRun = currRun->nextRun;
- }
- int start = i;
- while(i <= count && currRun && currRun->level >= levelHigh) {
- i++;
- currRun = currRun->nextRun;
- }
- int end = i-1;
- reverseRuns(start, end);
- }
- levelHigh--;
- }
- }
-
-#if BIDI_DEBUG > 0
- kdDebug(6041) << "visual order is:" << endl;
- for (BidiRun* curr = sFirstRun; curr; curr = curr->nextRun)
- kdDebug(6041) << " " << curr << endl;
-#endif
-}
-
-void RenderBlock::layoutInlineChildren(bool relayoutChildren, int breakBeforeLine)
-{
- BidiState bidi;
-
- m_overflowHeight = 0;
-
- invalidateVerticalPositions();
-#ifdef DEBUG_LAYOUT
- TQTime qt;
- qt.start();
- kdDebug( 6040 ) << renderName() << " layoutInlineChildren( " << this <<" )" << endl;
-#endif
-#if BIDI_DEBUG > 1 || defined( DEBUG_LINEBREAKS )
- kdDebug(6041) << " ------- bidi start " << this << " -------" << endl;
-#endif
-
- m_height = borderTop() + paddingTop();
- int toAdd = borderBottom() + paddingBottom();
- if (m_layer && scrollsOverflowX() && style()->height().isVariable())
- toAdd += m_layer->horizontalScrollbarHeight();
-
- // Clear out our line boxes.
- deleteInlineBoxes();
-
- // Text truncation only kicks in if your overflow isn't visible and your
- // text-overflow-mode isn't clip.
- bool hasTextOverflow = style()->textOverflow() && hasOverflowClip();
-
- // Walk all the lines and delete our ellipsis line boxes if they exist.
- if (hasTextOverflow)
- deleteEllipsisLineBoxes();
-
- if (firstChild()) {
- // layout replaced elements
- RenderObject *o = first( this, bidi, false );
- while ( o ) {
- if (o->markedForRepaint()) {
- o->repaintDuringLayout();
- o->setMarkedForRepaint(false);
- }
- if (o->isReplaced() || o->isFloating() || o->isPositioned()) {
- // clear the placeHolderBox
- if (o->isBox())
- static_cast<RenderBox*>(o)->RenderBox::deleteInlineBoxes();
-
- //kdDebug(6041) << "layouting replaced or floating child" << endl;
- if (relayoutChildren || o->style()->width().isPercent() || o->style()->height().isPercent())
- o->setChildNeedsLayout(true, false);
- if (o->isPositioned())
- o->containingBlock()->insertPositionedObject(o);
- else
- o->layoutIfNeeded();
- }
- else {
- o->deleteInlineBoxes();
- o->setNeedsLayout(false);
- }
- o = Bidinext( this, o, bidi, false );
- }
-
- BidiContext *startEmbed;
- if( style()->direction() == LTR ) {
- startEmbed = new BidiContext( 0, TQChar::DirL );
- bidi.status.eor = TQChar::DirL;
- } else {
- startEmbed = new BidiContext( 1, TQChar::DirR );
- bidi.status.eor = TQChar::DirR;
- }
- startEmbed->ref();
-
- bidi.status.lastStrong = TQChar::DirON;
- bidi.status.last = TQChar::DirON;
-
- bidi.context = startEmbed;
- adjustEmbedding = true;
- BidiIterator start(this, first(this, bidi), 0);
- adjustEmbedding = false;
- BidiIterator end = start;
-
- m_firstLine = true;
-
- if (!smidpoints)
- smidpoints = new TQMemArray<BidiIterator>;
-
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
- sCompactFirstBidiRun = sCompactLastBidiRun = 0;
- sCompactBidiRunCount = 0;
-
- previousLineBrokeAtBR = true;
-
- int lineCount = 0;
- bool pagebreakHint = false;
- int oldPos = 0;
- BidiIterator oldStart;
- BidiState oldBidi;
- const bool pagedMode = canvas()->pagedMode();
-//
- while( !end.atEnd() ) {
- start = end;
- lineCount++;
- betweenMidpoints = false;
- isLineEmpty = true;
- pagebreakHint = false;
- if (pagedMode) {
- oldPos = m_height;
- oldStart = start;
- oldBidi = bidi;
- }
- if (lineCount == breakBeforeLine) {
- m_height = pageTopAfter(oldPos);
- pagebreakHint = true;
- }
-redo_linebreak:
- end = findNextLineBreak(start, bidi);
- if( start.atEnd() ) break;
- if (!isLineEmpty) {
- bidiReorderLine(start, end, bidi);
-
- // Now that the runs have been ordered, we create the line boxes.
- // At the same time we figure out where border/padding/margin should be applied for
- // inline flow boxes.
-
- if (sBidiRunCount) {
- InlineFlowBox* lineBox = constructLine(start, end);
- if (lineBox) {
- if (pagebreakHint) lineBox->setAfterPageBreak(true);
-
- // Now we position all of our text runs horizontally.
- computeHorizontalPositionsForLine(lineBox, bidi);
-
- // Now position our text runs vertically.
- computeVerticalPositionsForLine(lineBox);
-
- deleteBidiRuns(renderArena());
-
- if (lineBox->afterPageBreak() && hasFloats() && !pagebreakHint) {
- start = end = oldStart;
- bidi = oldBidi;
- m_height = pageTopAfter(oldPos);
- deleteLastLineBox(renderArena());
- pagebreakHint = true;
- goto redo_linebreak;
- }
- }
- }
-
- if( end == start || (end.obj && end.obj->isBR() && !start.obj->isBR() ) ) {
- adjustEmbedding = true;
- end.increment(bidi);
- adjustEmbedding = false;
- } else if (end.obj && end.obj->style()->preserveLF() && end.current() == TQChar('\n')) {
- adjustEmbedding = true;
- end.increment(bidi);
- adjustEmbedding = false;
- }
-
- m_firstLine = false;
- newLine();
- }
-
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
- sCompactFirstBidiRun = sCompactLastBidiRun = 0;
- sCompactBidiRunCount = 0;
- }
- startEmbed->deref();
- //embed->deref();
- }
-
- sNumMidpoints = 0;
- sCurrMidpoint = 0;
-
- // If we violate widows page-breaking rules, we set a hint and relayout.
- // Note that the widows rule might still be violated afterwards if the lines have become wider
- if (canvas()->pagedMode() && containsPageBreak() && breakBeforeLine == 0)
- {
- int orphans = 0;
- int widows = 0;
- // find breaking line
- InlineRunBox* lineBox = firstLineBox();
- while (lineBox) {
- if (lineBox->isInlineFlowBox()) {
- InlineFlowBox* flowBox = static_cast<InlineFlowBox*>(lineBox);
- if (flowBox->afterPageBreak()) break;
- }
- orphans++;
- lineBox = lineBox->nextLineBox();
- }
- InlineFlowBox* pageBreaker = static_cast<InlineFlowBox*>(lineBox);
- if (!pageBreaker) goto no_break;
- // count widows
- while (lineBox && widows < style()->widows()) {
- if (lineBox->hasTextChildren())
- widows++;
- lineBox = lineBox->nextLineBox();
- }
- // Widows rule broken and more orphans left to use
- if (widows < style()->widows() && orphans > 0) {
- kdDebug( 6040 ) << "Widows: " << widows << endl;
- // Check if we have enough orphans after respecting widows count
- int newOrphans = orphans - (style()->widows() - widows);
- if (newOrphans < style()->orphans()) {
- if (parent()->canClear(this,PageBreakHarder)) {
- // Relayout to remove incorrect page-break
- setNeedsPageClear(true);
- setContainsPageBreak(false);
- layoutInlineChildren(relayoutChildren, -1);
- return;
- }
- } else {
- // Set hint and try again
- layoutInlineChildren(relayoutChildren, newOrphans+1);
- return;
- }
- }
- }
- no_break:
-
- // in case we have a float on the last line, it might not be positioned up to now.
- // This has to be done before adding in the bottom border/padding, or the float will
- // include the padding incorrectly. -dwh
- positionNewFloats();
-
- // Now add in the bottom border/padding.
- m_height += toAdd;
-
- // Always make sure this is at least our height.
- m_overflowHeight = kMax(m_height, m_overflowHeight);
-
- // See if any lines spill out of the block. If so, we need to update our overflow width.
- checkLinesForOverflow();
-
- // See if we have any lines that spill out of our block. If we do, then we will
- // possibly need to truncate text.
- if (hasTextOverflow)
- checkLinesForTextOverflow();
-
-#if BIDI_DEBUG > 1
- kdDebug(6041) << " ------- bidi end " << this << " -------" << endl;
-#endif
- //kdDebug() << "RenderBlock::layoutInlineChildren time used " << qt.elapsed() << endl;
- //kdDebug(6040) << "height = " << m_height <<endl;
-}
-
-static void setStaticPosition( RenderBlock* p, RenderObject *o, bool *needToSetStaticX = 0, bool *needToSetStaticY = 0 )
-{
- // If our original display wasn't an inline type, then we can
- // determine our static x position now.
- bool nssx, nssy;
- bool isInlineType = o->style()->isOriginalDisplayInlineType();
- nssx = o->hasStaticX();
- if (nssx && !isInlineType && o->isBox()) {
- static_cast<RenderBox*>(o)->setStaticX(o->parent()->style()->direction() == LTR ?
- p->borderLeft()+p->paddingLeft() :
- p->borderRight()+p->paddingRight());
- nssx = false;
- }
-
- // If our original display was an INLINE type, then we can
- // determine our static y position now.
- nssy = o->hasStaticY();
- if (nssy && o->isBox()) {
- static_cast<RenderBox*>(o)->setStaticY(p->height());
- nssy = !isInlineType;
- }
- if (needToSetStaticX) *needToSetStaticX = nssx;
- if (needToSetStaticY) *needToSetStaticY = nssy;
-}
-
-BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi)
-{
- int width = lineWidth(m_height);
- int w = 0;
- int tmpW = 0;
-#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "findNextLineBreak: line at " << m_height << " line width " << width << endl;
- kdDebug(6041) << "sol: " << start.obj << " " << start.pos << endl;
-#endif
-
- BidiIterator posStart = start;
- bool hadPosStart = false;
-
- // eliminate spaces at beginning of line
- // remove leading spaces. Any inline flows we encounter will be empty and should also
- // be skipped.
- while (!start.atEnd() && (start.obj->isInlineFlow() || (!start.obj->style()->preserveWS() && !start.obj->isBR() &&
-#ifndef QT_NO_UNICODETABLES
- ( (start.current().unicode() == (ushort)0x0020) || // ASCII space
- (start.current().unicode() == (ushort)0x0009) || // ASCII tab
- (start.current().unicode() == (ushort)0x000A) || // ASCII line feed
- (start.current().unicode() == (ushort)0x000C) || // ASCII form feed
- (start.current().unicode() == (ushort)0x200B) || // Zero-width space
- start.obj->isFloatingOrPositioned() )
-#else
- ( start.current() == ' ' || start.current() == '\n' || start.obj->isFloatingOrPositioned() )
-#endif
- ))) {
- if( start.obj->isFloatingOrPositioned() ) {
- RenderObject *o = start.obj;
- // add to special objects...
- if (o->isFloating()) {
- insertFloatingObject(o);
- positionNewFloats();
- width = lineWidth(m_height);
- }
- else if (o->isBox() && o->isPositioned()) {
- if (!hadPosStart) {
- hadPosStart = true;
- posStart = start;
- // end
- addMidpoint(BidiIterator(0, o, 0));
- } else {
- // start/end
- addMidpoint(BidiIterator(0, o, 0));
- addMidpoint(BidiIterator(0, o, 0));
- }
- setStaticPosition(this, o);
- }
- }
- adjustEmbedding = true;
- start.increment(bidi, false /*skipInlines*/);
- adjustEmbedding = false;
- }
-
- if (hadPosStart && !start.atEnd())
- addMidpoint(start);
-
- if ( start.atEnd() ){
- if (hadPosStart) {
- start = posStart;
- posStart.increment(bidi);
- return posStart;
- }
- return start;
- }
-
- // This variable says we have encountered an object after which initial whitespace should be ignored (e.g. InlineFlows at the begining of a line).
- // Either we have nothing to do, if there is no whitespace after the object... or we have to enter the ignoringSpaces state.
- // This dilemma will be resolved when we have a peek at the next object.
- bool checkShouldIgnoreInitialWhitespace = false;
-
- // This variable is used only if whitespace isn't set to PRE, and it tells us whether
- // or not we are currently ignoring whitespace.
- bool ignoringSpaces = false;
- BidiIterator ignoreStart;
-
- // This variable tracks whether the very last character we saw was a space. We use
- // this to detect when we encounter a second space so we know we have to terminate
- // a run.
- bool currentCharacterIsSpace = false;
- RenderObject* trailingSpaceObject = 0;
-
- BidiIterator lBreak = start;
-
- InlineMinMaxIterator it(start.par, start.obj, start.endOfInline, false /*skipPositioned*/);
- InlineMinMaxIterator lastIt = it;
- int pos = start.pos;
-
- bool prevLineBrokeCleanly = previousLineBrokeAtBR;
- previousLineBrokeAtBR = false;
-
- RenderObject* o = it.current;
- while( o ) {
-#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "new object "<< o <<" width = " << w <<" tmpw = " << tmpW << endl;
-#endif
- if(o->isBR()) {
- if( w + tmpW <= width ) {
- lBreak.obj = o;
- lBreak.pos = 0;
- lBreak.endOfInline = it.endOfInline;
-
- // A <br> always breaks a line, so don't let the line be collapsed
- // away. Also, the space at the end of a line with a <br> does not
- // get collapsed away. It only does this if the previous line broke
- // cleanly. Otherwise the <br> has no effect on whether the line is
- // empty or not.
- if (prevLineBrokeCleanly)
- isLineEmpty = false;
- trailingSpaceObject = 0;
- previousLineBrokeAtBR = true;
-
- if (!isLineEmpty) {
- // only check the clear status for non-empty lines.
- EClear clear = o->style()->clear();
- if(clear != CNONE)
- m_clearStatus = (EClear) (m_clearStatus | clear);
- }
- }
- goto end;
- }
- if( o->isFloatingOrPositioned() ) {
- // add to special objects...
- if(o->isFloating()) {
- insertFloatingObject(o);
- // check if it fits in the current line.
- // If it does, position it now, otherwise, position
- // it after moving to next line (in newLine() func)
- if (o->width()+o->marginLeft()+o->marginRight()+w+tmpW <= width) {
- positionNewFloats();
- width = lineWidth(m_height);
- }
- }
- else if (o->isPositioned()) {
- bool needToSetStaticX;
- bool needToSetStaticY;
- setStaticPosition(this, o, &needToSetStaticX, &needToSetStaticY);
-
- // If we're ignoring spaces, we have to stop and include this object and
- // then start ignoring spaces again.
- if (needToSetStaticX || needToSetStaticY) {
- trailingSpaceObject = 0;
- ignoreStart.obj = o;
- ignoreStart.pos = 0;
- if (ignoringSpaces) {
- addMidpoint(ignoreStart); // Stop ignoring spaces.
- addMidpoint(ignoreStart); // Start ignoring again.
- }
- }
- }
- } else if (o->isInlineFlow()) {
- tmpW += getBorderPaddingMargin(o, it.endOfInline);
- if (isLineEmpty) isLineEmpty = !tmpW;
- if (o->isWordBreak()) { // #### shouldn't be an InlineFlow!
- w += tmpW;
- tmpW = 0;
- lBreak.obj = o;
- lBreak.pos = 0;
- lBreak.endOfInline = it.endOfInline;
- } else if (!it.endOfInline) {
- // this is the beginning of the line (other non-initial inline flows are handled directly when
- // incrementing the iterator below). We want to skip initial whitespace as much as possible.
- checkShouldIgnoreInitialWhitespace = true;
- }
- } else if ( o->isReplaced() || o->isGlyph() ) {
- EWhiteSpace currWS = o->style()->whiteSpace();
- EWhiteSpace lastWS = lastIt.current->style()->whiteSpace();
-
- // WinIE marquees have different whitespace characteristics by default when viewed from
- // the outside vs. the inside. Text inside is NOWRAP, and so we altered the marquee's
- // style to reflect this, but we now have to get back to the original whitespace value
- // for the marquee when checking for line breaking.
- if (o->isHTMLMarquee() && o->layer() && o->layer()->marquee())
- currWS = o->layer()->marquee()->whiteSpace();
- if (lastIt.current->isHTMLMarquee() && lastIt.current->layer() && lastIt.current->layer()->marquee())
- lastWS = lastIt.current->layer()->marquee()->whiteSpace();
-
- // Break on replaced elements if either has normal white-space.
- if (currWS == NORMAL || lastWS == NORMAL) {
- w += tmpW;
- tmpW = 0;
- lBreak.obj = o;
- lBreak.pos = 0;
- lBreak.endOfInline = false;
- }
-
- tmpW += o->width()+o->marginLeft()+o->marginRight();
- if (ignoringSpaces) {
- BidiIterator startMid( 0, o, 0 );
- addMidpoint(startMid);
- }
- isLineEmpty = false;
- ignoringSpaces = false;
- currentCharacterIsSpace = false;
- trailingSpaceObject = 0;
-
- if (o->isListMarker() && o->style()->listStylePosition() == OUTSIDE) {
- checkShouldIgnoreInitialWhitespace = true;
- }
- } else if ( o->isText() ) {
- RenderText *t = static_cast<RenderText *>(o);
- int strlen = t->stringLength();
- int len = strlen - pos;
- TQChar *str = t->text();
-
- const Font *f = t->htmlFont( m_firstLine );
- // proportional font, needs a bit more work.
- int lastSpace = pos;
- bool autoWrap = o->style()->autoWrap();
- bool preserveWS = o->style()->preserveWS();
- bool preserveLF = o->style()->preserveLF();
-#ifdef APPLE_CHANGES
- int wordSpacing = o->style()->wordSpacing();
-#endif
- bool nextIsSoftBreakable = false;
- bool checkBreakWord = autoWrap && (o->style()->wordWrap() == WWBREAKWORD);
-
- while(len) {
- bool previousCharacterIsSpace = currentCharacterIsSpace;
- bool isSoftBreakable = nextIsSoftBreakable;
- nextIsSoftBreakable = false;
- const TQChar c = str[pos];
- currentCharacterIsSpace = c == ' ';
- checkBreakWord &= !w; // only break words when no other breaking opportunity exists earlier
- // on the line (even within the text object we are currently processing)
-
- if (preserveWS || !currentCharacterIsSpace)
- isLineEmpty = false;
-
- // Check for soft hyphens. Go ahead and ignore them.
- if (c.unicode() == SOFT_HYPHEN && pos > 0) {
- nextIsSoftBreakable = true;
- if (!ignoringSpaces) {
- // Ignore soft hyphens
- BidiIterator endMid(0, o, pos-1);
- addMidpoint(endMid);
-
- // Add the width up to but not including the hyphen.
- tmpW += t->width(lastSpace, pos - lastSpace, f);
-
- // For wrapping text only, include the hyphen. We need to ensure it will fit
- // on the line if it shows when we break.
- if (o->style()->autoWrap())
- tmpW += t->width(pos, 1, f);
-
- BidiIterator startMid(0, o, pos+1);
- addMidpoint(startMid);
- }
-
- pos++;
- len--;
- lastSpace = pos; // Cheesy hack to prevent adding in widths of the run twice.
- continue;
- }
-#ifdef APPLE_CHANGES // KDE applies wordspacing differently
- bool applyWordSpacing = false;
-#endif
- if (ignoringSpaces) {
- // We need to stop ignoring spaces, if we encounter a non-space or
- // a run that doesn't collapse spaces.
- if (!currentCharacterIsSpace || preserveWS) {
- // Stop ignoring spaces and begin at this
- // new point.
- ignoringSpaces = false;
- lastSpace = pos; // e.g., "Foo goo", don't add in any of the ignored spaces.
- BidiIterator startMid ( 0, o, pos );
- addMidpoint(startMid);
- }
- else {
- // Just keep ignoring these spaces.
- pos++;
- len--;
- continue;
- }
- }
-
- const bool isbreakablePosition = (preserveLF && c == '\n') || (autoWrap &&
- (isBreakable( str, pos, strlen ) || isSoftBreakable));
- if ( isbreakablePosition || checkBreakWord ) {
-
- tmpW += t->width(lastSpace, pos - lastSpace, f);
-#ifdef APPLE_CHANGES
- applyWordSpacing = (wordSpacing && currentCharacterIsSpace && !previousCharacterIsSpace &&
- !t->containsOnlyWhitespace(pos+1, strlen-(pos+1)));
-#endif
-#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "found space at " << pos << " in string '" << TQString( str, strlen ).latin1() << "' adding " << tmpW << " new width = " << w << endl;
-#endif
- if ( autoWrap && w + tmpW > width && w == 0 ) {
- int fb = nearestFloatBottom(m_height);
- int newLineWidth = lineWidth(fb);
- // See if |tmpW| will fit on the new line. As long as it does not,
- // keep adjusting our float bottom until we find some room.
- int lastFloatBottom = m_height;
- while (lastFloatBottom < fb && tmpW > newLineWidth) {
- lastFloatBottom = fb;
- fb = nearestFloatBottom(fb);
- newLineWidth = lineWidth(fb);
- }
-
- if(!w && m_height < fb && width < newLineWidth) {
- m_height = fb;
- width = newLineWidth;
-#ifdef DEBUG_LINEBREAKS
- kdDebug() << "RenderBlock::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
-#endif
- }
- }
-
- if (autoWrap) {
- if (w+tmpW > width) {
- if (checkBreakWord && pos) {
- lBreak.obj = o;
- lBreak.pos = pos-1;
- lBreak.endOfInline = false;
- }
- goto end;
- } else if ( (pos > 1 && str[pos-1].unicode() == SOFT_HYPHEN) )
- // Subtract the width of the soft hyphen out since we fit on a line.
- tmpW -= t->width(pos-1, 1, f);
- }
-
- if( preserveLF && *(str+pos) == '\n' ) {
- lBreak.obj = o;
- lBreak.pos = pos;
- lBreak.endOfInline = false;
-
-#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "forced break sol: " << start.obj << " " << start.pos << " end: " << lBreak.obj << " " << lBreak.pos << " width=" << w << endl;
-#endif
- return lBreak;
- }
-
- if ( autoWrap && isbreakablePosition ) {
- w += tmpW;
- tmpW = 0;
- lBreak.obj = o;
- lBreak.pos = pos;
- lBreak.endOfInline = false;
- }
-
- lastSpace = pos;
-#ifdef APPLE_CHANGES
- if (applyWordSpacing)
- w += wordSpacing;
-#endif
- }
-
- if (!ignoringSpaces && !preserveWS) {
- // If we encounter a second space, we need to go ahead and break up this run
- // and enter a mode where we start collapsing spaces.
- if (currentCharacterIsSpace && previousCharacterIsSpace) {
- ignoringSpaces = true;
-
- // We just entered a mode where we are ignoring
- // spaces. Create a midpoint to terminate the run
- // before the second space.
- addMidpoint(ignoreStart);
- lastSpace = pos;
- }
- }
-
- if (currentCharacterIsSpace && !previousCharacterIsSpace) {
- ignoreStart.obj = o;
- ignoreStart.pos = pos;
- }
-
- if (!preserveWS && currentCharacterIsSpace && !ignoringSpaces)
- trailingSpaceObject = o;
- else if (preserveWS || !currentCharacterIsSpace)
- trailingSpaceObject = 0;
-
- pos++;
- len--;
- }
-
- if (!ignoringSpaces) {
- // We didn't find any space that would be beyond the line |width|.
- // Lets add to |tmpW| the remaining width since the last space we found.
- // Before we test this new |tmpW| however, we will have to look ahead to check
- // if the next object/position can serve as a line breaking opportunity.
- tmpW += t->width(lastSpace, pos - lastSpace, f);
- if (checkBreakWord && !w && pos && tmpW > width) {
- // Avoid doing the costly lookahead for break-word,
- // since we know we are allowed to break.
- lBreak.obj = o;
- lBreak.pos = pos-1;
- lBreak.endOfInline = false;
- goto end;
- }
- }
- } else
- KHTMLAssert( false );
-
- InlineMinMaxIterator savedIt = lastIt;
- lastIt = it;
- o = it.next();
-
- // advance the iterator to the next non-inline-flow
- while (o && o->isInlineFlow() && !o->isWordBreak()) {
- tmpW += getBorderPaddingMargin(o, it.endOfInline);
- if (isLineEmpty) isLineEmpty = !tmpW;
- o = it.next();
- }
-
- if (checkShouldIgnoreInitialWhitespace) {
- // Check if we should switch to ignoringSpaces state
- if (!style()->preserveWS() && it.current && it.current->isText()) {
- const RenderText* rt = static_cast<RenderText*>(it.current);
- if (rt->stringLength() > 0 && (rt->text()[0].category() == TQChar::Separator_Space || rt->text()[0] == '\n')) {
- currentCharacterIsSpace = true;
- ignoringSpaces = true;
- BidiIterator endMid( 0, lastIt.current, 0 );
- addMidpoint(endMid);
- }
- }
- checkShouldIgnoreInitialWhitespace = false;
- }
-
- bool autoWrap = lastIt.current->style()->autoWrap();
- bool checkForBreak = autoWrap;
- if (w && w + tmpW > width && lBreak.obj && !lastIt.current->style()->preserveLF() && !autoWrap)
- checkForBreak = true;
- else if (it.current && lastIt.current->isText() && it.current->isText() && !it.current->isBR()) {
- if (autoWrap || it.current->style()->autoWrap()) {
- if (currentCharacterIsSpace)
- checkForBreak = true;
- else {
- checkForBreak = false;
- RenderText* nextText = static_cast<RenderText*>(it.current);
- if (nextText->stringLength() != 0) {
- TQChar c = nextText->text()[0];
- if (c == ' ' || c == '\t' || (c == '\n' && !it.current->style()->preserveLF())) {
- // If the next item on the line is text, and if we did not end with
- // a space, then the next text run continues our word (and so it needs to
- // keep adding to |tmpW|. Just update and continue.
- checkForBreak = true;
- }
- }
-
- bool canPlaceOnLine = (w + tmpW <= width) || !autoWrap;
- if (canPlaceOnLine && checkForBreak) {
- w += tmpW;
- tmpW = 0;
- lBreak.obj = it.current;
- lBreak.pos = 0;
- lBreak.endOfInline = it.endOfInline;
- }
- }
- }
- }
-
- if (checkForBreak && (w + tmpW > width)) {
- //kdDebug() << " too wide w=" << w << " tmpW = " << tmpW << " width = " << width << endl;
- //kdDebug() << "start=" << start.obj << " current=" << o << endl;
- // if we have floats, try to get below them.
- if (currentCharacterIsSpace && !ignoringSpaces && !lastIt.current->style()->preserveWS())
- trailingSpaceObject = 0;
-
- int fb = nearestFloatBottom(m_height);
- int newLineWidth = lineWidth(fb);
- // See if |tmpW| will fit on the new line. As long as it does not,
- // keep adjusting our float bottom until we find some room.
- int lastFloatBottom = m_height;
- while (lastFloatBottom < fb && tmpW > newLineWidth) {
- lastFloatBottom = fb;
- fb = nearestFloatBottom(fb);
- newLineWidth = lineWidth(fb);
- }
- if( !w && m_height < fb && width < newLineWidth ) {
- m_height = fb;
- width = newLineWidth;
-#ifdef DEBUG_LINEBREAKS
- kdDebug() << "RenderBlock::findNextLineBreak new position at " << m_height << " newWidth " << width << endl;
-#endif
- }
-
- // |width| may have been adjusted because we got shoved down past a float (thus
- // giving us more room), so we need to retest, and only jump to
- // the end label if we still don't fit on the line. -dwh
- if (w + tmpW > width) {
- it = lastIt;
- lastIt = savedIt;
- o = it.current;
- goto end;
- }
- }
-
- if (!lastIt.current->isFloatingOrPositioned() && lastIt.current->isReplaced() && lastIt.current->style()->autoWrap()) {
- // Go ahead and add in tmpW.
- w += tmpW;
- tmpW = 0;
- lBreak.obj = o;
- lBreak.pos = 0;
- lBreak.endOfInline = it.endOfInline;
- }
-
- // Clear out our character space bool, since inline <pre>s don't collapse whitespace
- // with adjacent inline normal/nowrap spans.
- if (lastIt.current->style()->preserveWS())
- currentCharacterIsSpace = false;
-
- pos = 0;
- }
-
-#ifdef DEBUG_LINEBREAKS
- kdDebug( 6041 ) << "end of par, width = " << width << " linewidth = " << w + tmpW << endl;
-#endif
- if( w + tmpW <= width || (lastIt.current && !lastIt.current->style()->autoWrap())) {
- lBreak.obj = 0;
- lBreak.pos = 0;
- lBreak.endOfInline = false;
- }
-
- end:
-
- if( lBreak == start && !lBreak.obj->isBR() ) {
- // we just add as much as possible
- if ( style()->whiteSpace() == PRE ) {
- // FIXME: Don't really understand this case.
- if(pos != 0) {
- lBreak.obj = o;
- lBreak.pos = pos - 1;
- lBreak.endOfInline = it.endOfInline;
- } else {
- lBreak.obj = lastIt.current;
- lBreak.pos = lastIt.current->isText() ? lastIt.current->length() : 0;
- lBreak.endOfInline = lastIt.endOfInline;
- }
- } else if( lBreak.obj ) {
- if( lastIt.current != o ) {
- // better to break between object boundaries than in the middle of a word
- lBreak.obj = o;
- lBreak.pos = 0;
- lBreak.endOfInline = it.endOfInline;
- } else {
- // Don't ever break in the middle of a word if we can help it.
- // There's no room at all. We just have to be on this line,
- // even though we'll spill out.
- lBreak.obj = o;
- lBreak.pos = pos;
- lBreak.endOfInline = it.endOfInline;
- }
- }
- }
-
- if (hadPosStart)
- start = posStart;
-
- // make sure we consume at least one char/object.
- // and avoid returning an InlineFlow
- // (FIXME: turn those wordbreaks into empty text objects - they shouldn't be inline flows!)
- if( lBreak == start || (lBreak.obj && lBreak.obj->isInlineFlow() && !lBreak.obj->isWordBreak())) {
- lBreak.increment(bidi);
- }
-
-#ifdef DEBUG_LINEBREAKS
- kdDebug(6041) << "regular break sol: " << start.obj << " " << start.pos << " end: " << lBreak.obj << " " << lBreak.pos << " width=" << w << endl;
-#endif
-
- // Sanity check our midpoints.
- checkMidpoints(lBreak, bidi);
-
- if (trailingSpaceObject) {
- // This object is either going to be part of the last midpoint, or it is going
- // to be the actual endpoint. In both cases we just decrease our pos by 1 level to
- // exclude the space, allowing it to - in effect - collapse into the newline.
- if (sNumMidpoints%2==1) {
- BidiIterator* midpoints = smidpoints->data();
- midpoints[sNumMidpoints-1].pos--;
- }
- //else if (lBreak.pos > 0)
- // lBreak.pos--;
- else if (lBreak.obj == 0 && trailingSpaceObject->isText()) {
- // Add a new end midpoint that stops right at the very end.
- RenderText* text = static_cast<RenderText *>(trailingSpaceObject);
- unsigned pos = text->length() >=2 ? text->length() - 2 : UINT_MAX;
- BidiIterator endMid ( 0, trailingSpaceObject, pos );
- addMidpoint(endMid);
- }
- }
-
- // We might have made lBreak an iterator that points past the end
- // of the object. Do this adjustment to make it point to the start
- // of the next object instead to avoid confusing the rest of the
- // code.
- if (lBreak.pos > 0) {
- lBreak.pos--;
- lBreak.increment(bidi);
- }
-
- if (lBreak.obj && lBreak.pos >= 2 && lBreak.obj->isText()) {
- // For soft hyphens on line breaks, we have to chop out the midpoints that made us
- // ignore the hyphen so that it will render at the end of the line.
- TQChar c = static_cast<RenderText*>(lBreak.obj)->text()[lBreak.pos-1];
- if (c.unicode() == SOFT_HYPHEN)
- chopMidpointsAt(lBreak.obj, lBreak.pos-2);
- }
-
- return lBreak;
-}
-
-void RenderBlock::checkLinesForOverflow()
-{
- for (RootInlineBox* curr = static_cast<khtml::RootInlineBox*>(firstLineBox()); curr; curr = static_cast<khtml::RootInlineBox*>(curr->nextLineBox())) {
-// m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft);
- m_overflowTop = kMin(curr->topOverflow(), m_overflowTop);
-// m_overflowWidth = max(curr->rightOverflow(), m_overflowWidth);
- m_overflowHeight = kMax(curr->bottomOverflow(), m_overflowHeight);
- }
-}
-
-void RenderBlock::deleteEllipsisLineBoxes()
-{
- for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox())
- curr->clearTruncation();
-}
-
-void RenderBlock::checkLinesForTextOverflow()
-{
- // Determine the width of the ellipsis using the current font.
- TQChar ellipsis = 0x2026; // FIXME: CSS3 says this is configurable, also need to use 0x002E (FULL STOP) if 0x2026 not renderable
- static TQString ellipsisStr(ellipsis);
- const Font& firstLineFont = style(true)->htmlFont();
- const Font& font = style()->htmlFont();
- int firstLineEllipsisWidth = firstLineFont.width(&ellipsis, 1, 0);
- int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(&ellipsis, 1, 0);
-
- // For LTR text truncation, we want to get the right edge of our padding box, and then we want to see
- // if the right edge of a line box exceeds that. For RTL, we use the left edge of the padding box and
- // check the left edge of the line box to see if it is less
- // Include the scrollbar for overflow blocks, which means we want to use "contentWidth()"
- bool ltr = style()->direction() == LTR;
- for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
- int blockEdge = ltr ? rightOffset(curr->yPos()) : leftOffset(curr->yPos());
- int lineBoxEdge = ltr ? curr->xPos() + curr->width() : curr->xPos();
- if ((ltr && lineBoxEdge > blockEdge) || (!ltr && lineBoxEdge < blockEdge)) {
- // This line spills out of our box in the appropriate direction. Now we need to see if the line
- // can be truncated. In order for truncation to be possible, the line must have sufficient space to
- // accommodate our truncation string, and no replaced elements (images, tables) can overlap the ellipsis
- // space.
- int width = curr == firstRootBox() ? firstLineEllipsisWidth : ellipsisWidth;
- if (curr->canAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width))
- curr->placeEllipsis(ellipsisStr, ltr, blockEdge, width);
- }
- }
-}
-
-// For --enable-final
-#undef BIDI_DEBUG
-#undef DEBUG_LINEBREAKS
-#undef DEBUG_LAYOUT
-
-}
diff --git a/khtml/rendering/bidi.h b/khtml/rendering/bidi.h
deleted file mode 100644
index c8776ce19..000000000
--- a/khtml/rendering/bidi.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef BIDI_H
-#define BIDI_H
-
-#include <tqstring.h>
-#include "rendering/render_object.h"
-
-namespace khtml {
- class RenderArena;
- class RenderBlock;
- class RenderObject;
- class InlineBox;
-
- class BidiContext {
- public:
- BidiContext(unsigned char level, TQChar::Direction embedding, BidiContext *parent = 0, bool override = false);
- ~BidiContext();
-
- void ref() const;
- void deref() const;
-
- unsigned char level;
- bool override : 1;
- TQChar::Direction dir : 5;
- TQChar::Direction basicDir : 5;
-
- BidiContext *parent;
-
-
- // refcounting....
- mutable int count;
- };
-
- struct BidiRun {
- BidiRun(int _start, int _stop, RenderObject *_obj, BidiContext *context, TQChar::Direction dir)
- : start( _start ), stop( _stop ), obj( _obj ), box(0), nextRun(0)
- {
- if(dir == TQChar::DirON) dir = context->dir;
-
- level = context->level;
-
- // add level of run (cases I1 & I2)
- if( level % 2 ) {
- if(dir == TQChar::DirL || dir == TQChar::DirAN || dir == TQChar::DirEN)
- level++;
- } else {
- if( dir == TQChar::DirR )
- level++;
- else if( dir == TQChar::DirAN || dir == TQChar::DirEN)
- level += 2;
- }
- }
-
- void detach(RenderArena* renderArena);
-
- // Overloaded new operator.
- void* operator new(size_t sz, RenderArena* renderArena) throw();
-
- // Overridden to prevent the normal delete from being called.
- void operator delete(void* ptr, size_t sz);
-
-private:
- // The normal operator new is disallowed.
- void* operator new(size_t sz) throw();
-
-public:
- int start;
- int stop;
-
- RenderObject *obj;
- InlineBox* box;
-
- // explicit + implicit levels here
- uchar level;
-
- bool compact : 1;
-
- BidiRun* nextRun;
- };
-
- struct BidiIterator;
- struct BidiState;
-
- struct InlineMinMaxIterator
- {
- /* InlineMinMaxIterator is a class that will iterate over all render objects that contribute to
- inline min/max width calculations. Note the following about the way it walks:
- (1) Positioned content is skipped (since it does not contribute to min/max width of a block)
- (2) We do not drill into the children of floats or replaced elements, since you can't break
- in the middle of such an element.
- (3) Inline flows (e.g., <a>, <span>, <i>) are walked twice, since each side can have
- distinct borders/margin/padding that contribute to the min/max width.
- */
- RenderObject* parent;
- RenderObject* current;
- bool endOfInline;
- bool skipPositioned;
- InlineMinMaxIterator(RenderObject* p, RenderObject* o, bool eOI=false, bool skipPos=true)
- :parent(p), current(o), endOfInline(eOI), skipPositioned(skipPos) {}
- inline RenderObject* next();
- };
-
- inline RenderObject* InlineMinMaxIterator::next()
- {
- RenderObject* result = 0;
- bool oldEndOfInline = endOfInline;
- endOfInline = false;
- while (current != 0 || (current == parent))
- {
- //kDebug( 6040 ) << "current = " << current;
- if (!oldEndOfInline &&
- (current == parent ||
- (!current->isFloating() && !current->isReplaced() && !current->isPositioned())))
- result = current->firstChild();
- if (!result) {
- // We hit the end of our inline. (It was empty, e.g., <span></span>.)
- if (!oldEndOfInline && current->isInlineFlow()) {
- result = current;
- endOfInline = true;
- break;
- }
- while (current && current != parent) {
- result = current->nextSibling();
- if (result) break;
- current = current->parent();
- if (current && current != parent && current->isInlineFlow()) {
- result = current;
- endOfInline = true;
- break;
- }
- }
- }
-
- if (!result) break;
-
- if ((!skipPositioned || !result->isPositioned()) && (result->isText() || result->isBR() ||
- result->isFloatingOrPositioned() || result->isReplaced() || result->isGlyph() || result->isInlineFlow()))
- break;
-
- current = result;
- result = 0;
- }
-
- // Update our position.
- current = result;
- return current;
- }
-
-}
-
-#endif
diff --git a/khtml/rendering/break_lines.cpp b/khtml/rendering/break_lines.cpp
deleted file mode 100644
index a0d314cee..000000000
--- a/khtml/rendering/break_lines.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-#include <break_lines.h>
-#include <klibloader.h>
-#include "tqcstring.h"
-#include <tqtextcodec.h>
-#include <tqcleanuphandler.h>
-#include <config.h>
-
-
-/* If HAVE_LIBTHAI is defined, libkhtml will link against
- * libthai since compile time. Otherwise it will try to
- * dlopen at run-time
- *
- * Ott Pattara Nov 14, 2004
- */
-
-#ifndef HAVE_LIBTHAI
-typedef int (*th_brk_def)(const unsigned char*, int[], int);
-static th_brk_def th_brk;
-#else
-#include <thai/thailib.h>
-#include <thai/thbrk.h>
-#endif
-
-namespace khtml {
- struct ThaiCache
- {
- ThaiCache() {
- string = 0;
- allocated = 0x400;
- wbrpos = (int *) malloc(allocated*sizeof(int));
- numwbrpos = 0;
- numisbreakable = 0x400;
- isbreakable = (int *) malloc(numisbreakable*sizeof(int));
- library = 0;
- }
- ~ThaiCache() {
- free(wbrpos);
- free(isbreakable);
- if (library) library->unload();
- }
- const TQChar *string;
- int *wbrpos;
- int *isbreakable;
- int allocated;
- int numwbrpos,numisbreakable;
- KLibrary *library;
- };
- static ThaiCache *cache = 0;
-
- void cleanup_thaibreaks()
- {
- delete cache;
- cache = 0;
-#ifndef HAVE_LIBTHAI
- th_brk = 0;
-#endif
- }
-
- bool isBreakableThai( const TQChar *string, const int pos, const int len)
- {
- static TQTextCodec *thaiCodec = TQTextCodec::codecForMib(2259);
- //printf("Entering isBreakableThai with pos = %d\n", pos);
-
-#ifndef HAVE_LIBTHAI
-
- KLibrary *lib = 0;
-
- /* load libthai dynamically */
- if (( !th_brk ) && thaiCodec ) {
- printf("Try to load libthai dynamically...\n");
- KLibLoader *loader = KLibLoader::self();
- lib = loader->library("libthai");
- if (lib && lib->hasSymbol("th_brk")) {
- th_brk = (th_brk_def) lib->symbol("th_brk");
- } else {
- // indication that loading failed and we shouldn't try to load again
- printf("Error, can't load libthai...\n");
- thaiCodec = 0;
- if (lib)
- lib->unload();
- }
- }
-
- if (!th_brk ) {
- return true;
- }
-#endif
-
- if (!cache ) {
- cache = new ThaiCache;
-#ifndef HAVE_LIBTHAI
- cache->library = lib;
-#endif
- }
-
- // build up string of thai chars
- if ( string != cache->string ) {
- //fprintf(stderr,"new string found (not in cache), calling libthai\n");
- TQCString cstr = thaiCodec->fromUnicode( TQConstString(string,len).string());
- //printf("About to call libthai::th_brk with str: %s",cstr.data());
-
- cache->numwbrpos = th_brk((const unsigned char*) cstr.data(), cache->wbrpos, cache->allocated);
- //fprintf(stderr,"libthai returns with value %d\n",cache->numwbrpos);
- if (cache->numwbrpos > cache->allocated) {
- cache->allocated = cache->numwbrpos;
- cache->wbrpos = (int *)realloc(cache->wbrpos, cache->allocated*sizeof(int));
- cache->numwbrpos = th_brk((const unsigned char*) cstr.data(), cache->wbrpos, cache->allocated);
- }
- if ( len > cache->numisbreakable ) {
- cache->numisbreakable=len;
- cache->isbreakable = (int *)realloc(cache->isbreakable, cache->numisbreakable*sizeof(int));
- }
- for (int i = 0 ; i < len ; ++i) {
- cache->isbreakable[i] = 0;
- }
- if ( cache->numwbrpos > 0 ) {
- for (int i = cache->numwbrpos-1; i >= 0; --i) {
- cache->isbreakable[cache->wbrpos[i]] = 1;
- }
- }
- cache->string = string;
- }
- //printf("Returning %d\n", cache->isbreakable[pos]);
- return cache->isbreakable[pos];
- }
-}
diff --git a/khtml/rendering/break_lines.h b/khtml/rendering/break_lines.h
deleted file mode 100644
index 5176e5fb0..000000000
--- a/khtml/rendering/break_lines.h
+++ /dev/null
@@ -1,163 +0,0 @@
-#ifndef BREAK_LINES_H
-#define BREAK_LINES_H
-
-#include <tqstring.h>
-
-namespace khtml {
-
- /*
- array of unicode codes where breaking shouldn't occur.
- (in sorted order because of using with binary search)
- these are currently for Japanese, though simply adding
- Korean, Chinese ones should work as well
- */
- /*
- dontbreakbefore[] contains characters not covered by TQChar::Punctuation_Close that shouldn't be broken before.
- chars included in TQChar::Punctuation_Close are listed below.(look at UAX #14)
- - 3001 ideographic comma
- - 3002 ideographic full stop
- - FE50 small comma
- - FF52 small full stop
- - FF0C fullwidth comma
- - FF0E fullwidth full stop
- - FF61 halfwidth ideographic full stop
- - FF64 halfwidth ideographic comma
- these character is commented out.
- */
- const ushort dontbreakbefore[] = {
- //0x3001, //ideographic comma
- //0x3002, //ideographic full stop
- 0x3005, //ideographic iteration mark
- 0x3009, //right angle bracket
- 0x300b, //right double angle bracket
- 0x300d, //right corner bracket
- 0x300f, //right white corner bracket
- 0x3011, //right black lenticular bracket
- 0x3015, //right tortoise shell bracket
- 0x3041, //small a hiragana
- 0x3043, //small i hiragana
- 0x3045, //small u hiragana
- 0x3047, //small e hiragana
- 0x3049, //small o hiragana
- 0x3063, //small tsu hiragana
- 0x3083, //small ya hiragana
- 0x3085, //small yu hiragana
- 0x3087, //small yo hiragana
- 0x308E, //small wa hiragana
- 0x309B, //jap voiced sound mark
- 0x309C, //jap semi-voiced sound mark
- 0x309D, //jap iteration mark hiragana
- 0x309E, //jap voiced iteration mark hiragana
- 0x30A1, //small a katakana
- 0x30A3, //small i katakana
- 0x30A5, //small u katakana
- 0x30A7, //small e katakana
- 0x30A9, //small o katakana
- 0x30C3, //small tsu katakana
- 0x30E3, //small ya katakana
- 0x30E5, //small yu katakana
- 0x30E7, //small yo katakana
- 0x30EE, //small wa katakana
- 0x30F5, //small ka katakana
- 0x30F6, //small ke katakana
- 0x30FC, //jap prolonged sound mark
- 0x30FD, //jap iteration mark katakana
- 0x30FE, //jap voiced iteration mark katakana
- //0xFE50, //small comma
- //0xFF52, //small full stop
- 0xFF01, //fullwidth exclamation mark
- 0xFF09, //fullwidth right parenthesis
- //0xFF0C, //fullwidth comma
- 0xFF0D, //fullwidth hypen-minus
- //0xFF0E, //fullwidth full stop
- 0xFF1F, //fullwidth question mark
- 0xFF3D, //fullwidth right square bracket
- 0xFF5D, //fullwidth right curly bracket
- //0xFF61, //halfwidth ideographic full stop
- 0xFF63, //halfwidth right corner bracket
- //0xFF64, //halfwidth ideographic comma
- 0xFF67, //halfwidth katakana letter small a
- 0xFF68, //halfwidth katakana letter small i
- 0xFF69, //halfwidth katakana letter small u
- 0xFF6a, //halfwidth katakana letter small e
- 0xFF6b, //halfwidth katakana letter small o
- 0xFF6c, //halfwidth katakana letter small ya
- 0xFF6d, //halfwidth katakana letter small yu
- 0xFF6e, //halfwidth katakana letter small yo
- 0xFF6f, //halfwidth katakana letter small tu
- 0xFF70 //halfwidth katakana-hiragana prolonged sound mark
- };
-
- // characters that aren't covered by TQChar::Punctuation_Open
- const ushort dontbreakafter[] = {
- 0x3012, //postal mark
- 0xFF03, //full width pound mark
- 0xFF04, //full width dollar sign
- 0xFF20, //full width @
- 0xFFE1, //full width british pound sign
- 0xFFE5 //full width yen sign
- };
-
- inline bool break_bsearch( const ushort* arr, const ushort val ) {
- int left = 0;
- int right = (sizeof(arr) / sizeof(ushort)) - 1;
-
- while (1) {
- if (left == right)
- return val != arr[left];
-
- int i = (left + right) >> 1;
- if ( val == arr[i] )
- return false;
- if ( val < arr[i] )
- right = i;
- else
- left = i + 1;
- }
- }
-
- bool isBreakableThai( const TQChar *string, const int pos, const int len);
- void cleanup_thaibreaks();
-
- inline bool isBreakable( const TQChar *str, const int pos, int len )
- {
- const TQChar *c = str+pos;
- unsigned short ch = c->unicode();
- if ( ch > 0xff ) {
- // not latin1, need to do more sophisticated checks for asian fonts
- unsigned char row = c->row();
- if ( row == 0x0e ) {
- // 0e00 - 0e7f == Thai
- if ( c->cell() < 0x80 ) {
- // consult libthai
- return isBreakableThai(str, pos, len);
- } else
- return false;
- }
- if ( row > 0x2d && row < 0xfb || row == 0x11 ) {
- /* asian line breaking. */
- if ( pos == 0 )
- return false; // never break before first character
-
- // check for simple punctuation cases
- TQChar::Category cat = c->category();
- if ( cat == TQChar::Punctuation_Close ||
- cat == TQChar::Punctuation_Other ||
- (str+(pos-1))->category() == TQChar::Punctuation_Open )
- return false;
-
- // do binary search in dontbreak[]
- return break_bsearch(dontbreakbefore, c->unicode()) &&
- break_bsearch(dontbreakafter, (str+(pos-1))->unicode());
- } else // no asian font
- return c->isSpace();
- } else {
- if ( ch == ' ' || ch == '\n' )
- return true;
- }
- return false;
- }
-
-}
-
-#endif
diff --git a/khtml/rendering/counter_tree.cpp b/khtml/rendering/counter_tree.cpp
deleted file mode 100644
index 5b178d96e..000000000
--- a/khtml/rendering/counter_tree.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "rendering/counter_tree.h"
-#include "rendering/render_object.h"
-
-namespace khtml {
-
-CounterNode::CounterNode(RenderObject *o)
- : m_hasCounters(false), m_isVisual(false),
- m_value(0), m_count(0), m_parent(0), m_previous(0), m_next(0),
- m_renderer(o) {}
-
-CounterNode::~CounterNode()
-{
- if (m_parent) m_parent->removeChild(this);
-}
-
-void CounterNode::insertAfter ( CounterNode *, CounterNode *)
-{
- Q_ASSERT( false);
-}
-
-void CounterNode::removeChild ( CounterNode *)
-{
- Q_ASSERT( false);
-}
-
-void CounterNode::remove ()
-{
- if (m_parent) m_parent->removeChild(this);
- else {
- Q_ASSERT(isReset());
- Q_ASSERT(!firstChild());
- Q_ASSERT(!lastChild());
- }
-}
-
-void CounterNode::setHasCounters ()
-{
- m_hasCounters = true;
- if (parent())
- parent()->setHasCounters();
-}
-
-void CounterNode::recount (bool first)
-{
- int old_count = m_count;
- if (m_previous)
- m_count = m_previous->count() + m_value;
- else {
- assert(m_parent->firstChild() == this);
- m_count = m_parent->value() + m_value;
- }
- if (old_count != m_count && !first)
- setSelfDirty();
- if (old_count != m_count || first) {
- if (m_parent) m_parent->updateTotal(m_count);
- if (m_next) m_next->recount();
- }
-}
-
-void CounterNode::setSelfDirty ()
-{
- if (m_renderer && m_isVisual)
- m_renderer->setNeedsLayoutAndMinMaxRecalc();
-}
-
-void CounterNode::setParentDirty ()
-{
- if (m_renderer && m_isVisual && m_hasCounters)
- m_renderer->setNeedsLayoutAndMinMaxRecalc();
-}
-
-CounterReset::CounterReset(RenderObject *o) : CounterNode(o), m_total(0), m_first(0), m_last(0) {}
-CounterReset::~CounterReset() {}
-
-void CounterReset::insertAfter ( CounterNode *newChild, CounterNode *refChild )
-{
- Q_ASSERT( newChild );
- Q_ASSERT( !refChild || refChild->parent() == this );
-
- newChild->m_parent = this;
- newChild->m_previous = refChild;
-
- if (refChild) {
- newChild->m_next = refChild->m_next;
- refChild->m_next = newChild;
- } else {
- newChild->m_next = m_first;
- m_first = newChild;
- }
-
- if (newChild->m_next) {
- assert(newChild->m_next->m_previous == refChild);
- newChild->m_next->m_previous = newChild;
- }
- else {
- assert (m_last == refChild);
- m_last = newChild;
- }
-
- newChild->recount(true);
-}
-
-void CounterReset::removeChild ( CounterNode *oldChild )
-{
- Q_ASSERT( oldChild );
-
- CounterNode* next = oldChild->m_next;
- CounterNode* prev = oldChild->m_previous;
-
- if (oldChild->firstChild()) {
- CounterNode* first = oldChild->firstChild();
- CounterNode* last = oldChild->lastChild();
- if (prev) {
- prev->m_next = first;
- first->m_previous = prev;
- }
- else {
- assert ( m_first == oldChild );
- m_first = first;
- }
-
- if (next) {
- next->m_previous = last;
- last->m_next = next;
- }
- else {
- assert ( m_last == oldChild );
- m_last = last;
- }
-
- next = first;
- while (next) {
- next->m_parent = this;
- if (next == last) break;
- next = next->m_next;
- }
-
- first->recount(true);
- }
- else {
- if (prev) prev->m_next = next;
- else {
- assert ( m_first == oldChild );
- m_first = next;
- }
- if (next) next->m_previous = prev;
- else {
- assert ( m_last == oldChild );
- m_last = prev;
- }
- if (next)
- next->recount();
- }
-
-
- oldChild->m_next = 0;
- oldChild->m_previous = 0;
- oldChild->m_parent = 0;
-}
-
-void CounterReset::recount (bool first)
-{
- int old_count = m_count;
- if (m_previous)
- m_count = m_previous->count();
- else if (m_parent)
- m_count = m_parent->value();
- else
- m_count = 0;
-
- updateTotal(m_value);
- if (!first) setSelfDirty();
- if (first || m_count != old_count) {
- if (m_next) m_next->recount();
- }
-}
-
-void CounterReset::setSelfDirty ()
-{
- setParentDirty();
-}
-
-void CounterReset::setParentDirty ()
-{
- if (hasCounters()) {
- if (m_renderer && m_isVisual) m_renderer->setNeedsLayoutAndMinMaxRecalc();
- CounterNode* n = firstChild();
- for(; n; n = n->nextSibling())
- {
- n->setParentDirty();
- }
- }
-}
-
-void CounterReset::updateTotal (int value)
-{
- if (value > m_total) m_total = value;
-}
-
-} // namespace
diff --git a/khtml/rendering/counter_tree.h b/khtml/rendering/counter_tree.h
deleted file mode 100644
index 55b924b80..000000000
--- a/khtml/rendering/counter_tree.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef _Counter_Tree_h_
-#define _Counter_Tree_h_
-
-#include "misc/shared.h"
-#include "rendering/render_object.h"
-
-namespace khtml {
-
-class CounterReset;
-
-// This file implements a counter-tree that is used for finding all parents in counters() lookup,
-// and for propagating count-changes when nodes are added or removed.
-// Please note that only counter-reset and root can be parents here, and that render-tree parents
-// are just counter-tree siblings
-
-// Implementation of counter-increment and counter-content
-class CounterNode
-{
-public:
- CounterNode(RenderObject *o);
- virtual ~CounterNode();
-
- CounterReset* parent() const { return m_parent; }
- CounterNode* previousSibling() const { return m_previous; }
- CounterNode* nextSibling() const { return m_next; }
- virtual CounterNode* firstChild() const { return 0; } ;
- virtual CounterNode* lastChild() const { return 0; };
- virtual void insertAfter ( CounterNode *newChild, CounterNode *refChild );
- virtual void removeChild ( CounterNode *oldChild );
- // Convenient self-refering version of the above
- void remove();
-
- int value() const { return m_value; };
- void setValue(short v) { m_value = v; };
- int count() const { return m_count; };
-
- virtual bool isReset() { return false; };
- virtual void recount( bool first = false );
- virtual void setSelfDirty();
- virtual void setParentDirty();
-
- bool hasCounters() const { return m_hasCounters; };
- bool isVisual() const { return m_isVisual; };
- void setHasCounters();
- void setIsVisual() { m_isVisual = true; };
- bool isRoot() { return m_renderer && m_renderer->isRoot(); };
-
- void setRenderer(RenderObject *o) { m_renderer = o; };
- RenderObject* renderer() const { return m_renderer; };
-
- friend class CounterReset;
-protected:
- bool m_hasCounters : 1;
- bool m_isVisual : 1;
- short m_value;
- short m_count;
- CounterReset *m_parent;
- CounterNode *m_previous;
- CounterNode *m_next;
- RenderObject *m_renderer;
-};
-
-// Implementation of counter-reset and root
-class CounterReset : public CounterNode
-{
-public:
- CounterReset(RenderObject *o);
- virtual ~CounterReset();
-
- virtual CounterNode *firstChild() const { return m_first; };
- virtual CounterNode *lastChild() const { return m_last; };
- virtual void insertAfter ( CounterNode *newChild, CounterNode *refChild );
- virtual void removeChild ( CounterNode *oldChild );
-
- virtual bool isReset() { return true; };
- virtual void recount( bool first = false );
- virtual void setSelfDirty();
- virtual void setParentDirty();
-
- void updateTotal(int value);
- // The highest value among children
- int total() const { return m_total; };
-
-protected:
- int m_total;
- CounterNode *m_first;
- CounterNode *m_last;
-};
-
-} // namespace
-
-#endif
-
diff --git a/khtml/rendering/enumerate.cpp b/khtml/rendering/enumerate.cpp
deleted file mode 100644
index 9cfe149ad..000000000
--- a/khtml/rendering/enumerate.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/**
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * (C) Hebrew algorithm by herouth@netvision.net.il
- * and schlpbch@iam.unibe.ch
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "rendering/enumerate.h"
-
-#include <tqstring.h>
-#include <tqvaluelist.h>
-
-namespace khtml {
-
-namespace Enumerate {
-
-TQString toRoman( int number, bool upper )
-{
- if (number < 1 || number > 3999) return TQString::number(number);
- TQString roman;
- static const TQChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
- static const TQChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
- const TQChar *digits = upper ? udigits : ldigits;
- int i, d = 0;
-
- do
- {
- int num = number % 10;
-
- if ( num % 5 < 4 )
- for ( i = num % 5; i > 0; i-- )
- roman.prepend( digits[ d ] );
-
- if ( num >= 4 && num <= 8)
- roman.prepend( digits[ d+1 ] );
-
- if ( num == 9 )
- roman.prepend( digits[ d+2 ] );
-
- if ( num % 5 == 4 )
- roman.prepend( digits[ d ] );
-
- number /= 10;
- d += 2;
- }
- while ( number );
-
- return roman;
-}
-
-TQString toGeorgian( int number )
-{
- TQString georgian;
- const TQChar tenthousand = 0x10ef;
- static const TQChar thousands[9] = {0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec,
- 0x10ed, 0x10ee, 0x10f4, 0x10f5 };
- static const TQChar hundreds[9] = {0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10f3,
- 0x10e4, 0x10e5, 0x10e6, 0x10e7 };
- static const TQChar tens[9] = {0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc,
- 0x10f2, 0x10dd, 0x10de, 0x10df };
- static const TQChar units[9] = {0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4,
- 0x10d5, 0x10d6, 0x10f1, 0x10d7 };
-
- if (number < 1 || number > 19999) return TQString::number(number);
- if (number >= 10000) {
- georgian.append(tenthousand);
- number = number - 10000;
- }
- if (number >= 1000) {
- georgian.append(thousands[number/1000-1]);
- number = number % 1000;
- }
- if (number >= 100) {
- georgian.append(hundreds[number/100-1]);
- number = number % 100;
- }
- if (number >= 10) {
- georgian.append(tens[number/10-1]);
- number = number % 10;
- }
- if (number >= 1) {
- georgian.append(units[number-1]);
- }
-
- return georgian;
-}
-
-TQString toArmenian( int number )
-{
- TQString armenian;
- int onethousand = 0x57c;
- int hundreds = 0x572;
- int tens = 0x569;
- int units = 0x560;
-
- // The standard defines values over 1999, but 7000 is very hard to render
- if (number < 1 || number > 1999) return TQString::number(number);
- if (number >= 1000) {
- armenian.append(TQChar(onethousand));
- number = number - 1000;
- }
- if (number >= 100) {
- armenian.append(TQChar(hundreds+number/100));
- number = number % 100;
- }
- if (number >= 10) {
- armenian.append(TQChar(tens+number/10));
- number = number % 10;
- }
- if (number >= 1) {
- armenian.append(TQChar(units+number));
- }
-
- return armenian;
-}
-
-TQString toHebrew( int number ) {
- static const TQChar tenDigit[] = {1497, 1499, 1500, 1502, 1504, 1505, 1506, 1508, 1510};
-
- TQString letter;
- if (number < 1) return TQString::number(number);
- if (number>999) {
- letter = toHebrew(number/1000) + TQString::fromLatin1("'");
- number = number%1000;
- }
-
- int hunderts = (number/400);
- if (hunderts > 0) {
- for(int i=0; i<hunderts; i++) {
- letter += TQChar(1511 + 3);
- }
- }
- number = number % 400;
- if ((number / 100) != 0) {
- letter += TQChar (1511 + (number / 100) -1);
- }
- number = number % 100;
- int tens = number/10;
- if (tens > 0 && !(number == 15 || number == 16)) {
- letter += tenDigit[tens-1];
- }
- if (number == 15 || number == 16) { // special because of religious
- letter += TQChar(1487 + 9); // reasons
- letter += TQChar(1487 + number - 9);
- } else {
- number = number % 10;
- if (number != 0) {
- letter += TQChar (1487 + number);
- }
- }
- return letter;
-}
-
-static inline TQString toLatin( int number, int base ) {
- if (number < 1) return TQString::number(number);
- TQValueList<TQChar> letters;
- while(number > 0) {
- number--; // number 0 is letter a
- TQChar letter = (TQChar) (base + (number % 26));
- letters.prepend(letter);
- number /= 26;
- }
- TQString str;
- str.setLength(letters.size());
- int i=0;
- while(!letters.isEmpty()) {
- str[i++] = letters.front();
- letters.pop_front();
- }
- return str;
-}
-
-TQString toLowerLatin( int number ) {
- return toLatin( number, 'a' );
-}
-
-TQString toUpperLatin( int number ) {
- return toLatin( number, 'A' );
-}
-
-static inline TQString toAlphabetic( int number, int base, const TQChar alphabet[] ) {
- if (number < 1) return TQString::number(number);
- TQValueList<TQChar> letters;
- while(number > 0) {
- number--; // number 0 is letter 1
- TQChar letter = alphabet[number % base];
- letters.prepend(letter);
- number /= base;
- }
- TQString str;
- str.setLength(letters.size());
- int i=0;
- while(!letters.isEmpty()) {
- str[i++] = letters.front();
- letters.pop_front();
- }
- return str;
-}
-
-TQString toHiragana( int number ) {
- static const TQChar hiragana[48] = {0x3042, 0x3044, 0x3046, 0x3048, 0x304A, 0x304B, 0x304D,
- 0x304F, 0x3051, 0x3053, 0x3055, 0x3057, 0x3059, 0x305B, 0x305D,
- 0x305F, 0x3061, 0x3064, 0x3066, 0x3068, 0x306A, 0x306B,
- 0x306C, 0x306D, 0x306E, 0x306F, 0x3072, 0x3075, 0x3078,
- 0x307B, 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, 0x3084, 0x3086,
- 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308F,
- 0x3090, 0x3091, 0x9092, 0x3093};
- return toAlphabetic( number, 48, hiragana );
-}
-
-TQString toHiraganaIroha( int number ) {
- static const TQChar hiragana[47] = {0x3044, 0x308D, 0x306F, 0x306B, 0x307B, 0x3078, 0x3068,
- 0x3061, 0x308A, 0x306C, 0x308B, 0x3092, 0x308F, 0x304B,
- 0x3088, 0x305F, 0x308C, 0x305D, 0x3064, 0x306D, 0x306A,
- 0x3089, 0x3080, 0x3046, 0x3090, 0x306E, 0x304A, 0x304F, 0x3084,
- 0x307E, 0x3051, 0x3075, 0x3053, 0x3048, 0x3066, 0x3042, 0x3055,
- 0x304D, 0x3086, 0x3081, 0x307F, 0x3057, 0x3091, 0x3072, 0x3082,
- 0x305B, 0x3059 };
- return toAlphabetic( number, 47, hiragana );
-}
-
-TQString toKatakana( int number ) {
- static const TQChar katakana[48] = {0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
- 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB,
- 0x30BD, 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA,
- 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5,
- 0x30D8, 0x30DB, 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2,
- 0x30E4, 0x30E6, 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC,
- 0x30ED, 0x30EF, 0x30F0, 0x30F1, 0x90F2, 0x30F3};
- return toAlphabetic( number, 48, katakana );
-}
-
-TQString toKatakanaIroha( int number ) {
- static const TQChar katakana[47] = {0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, 0x30D8, 0x30C8,
- 0x30C1, 0x30EA, 0x30CC, 0x30EB, 0x30F2, 0x30EF, 0x30AB,
- 0x30E8, 0x30BF, 0x30EC, 0x30ED, 0x30C4, 0x30CD, 0x30CA,
- 0x30E9, 0x30E0, 0x30A6, 0x30F0, 0x30CE, 0x30AA, 0x30AF,
- 0x30E4, 0x30DE, 0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6,
- 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, 0x30DF, 0x30B7,
- 0x30F1, 0x30D2, 0x30E2, 0x30BB, 0x90B9};
- return toAlphabetic( number, 47, katakana );
-}
-
-TQString toLowerGreek( int number ) {
- static const TQChar greek[24] = { 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7,
- 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE,
- 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6,
- 0x3C7, 0x3C8, 0x3C0};
-
- return toAlphabetic( number, 24, greek );
-}
-
-TQString toUpperGreek( int number ) {
- // The standard claims to be base 24, but only lists 19 letters.
- static const TQChar greek[19] = { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398,
- 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F,
- 0x3A0, 0x3A1, 0x3A3, 0x3A9};
-
- return toAlphabetic( number, 19, greek );
-}
-
-static inline TQString toNumeric( int number, int base ) {
- TQString letter = TQString::number(number);
- for(unsigned int i = 0; i < letter.length(); i++) {
- if (letter[i].isDigit())
- letter[i] = TQChar(letter[i].digitValue()+base);
- }
- return letter;
-}
-
-TQString toArabicIndic( int number ) {
- return toNumeric(number, 0x660);
-}
-
-TQString toPersianUrdu( int number ) {
- return toNumeric(number, 0x6F0);
-}
-
-TQString toLao( int number ) {
- return toNumeric(number, 0xED0);
-}
-
-TQString toThai( int number ) {
- return toNumeric(number, 0xE50);
-}
-
-TQString toTibetan( int number ) {
- return toNumeric(number, 0xF20);
-}
-
-static inline TQString toIdeographic(int number, const TQChar digits[], const TQChar digitmarkers[]) {
- if (number < 0 || number > 9999) return TQString::number(number);
-
- TQString grp = TQString::number(number);
-
- // ### Append group markers to handle numbers > 9999
-
- TQString str;
-
- // special case
- if (number < 20 && number >= 10) {
- str.append(digitmarkers[0]);
- str.append(digits[grp[1].digitValue()]);
- return str;
- }
-
- int len = grp.length();
- bool collapseZero = false;
- for (int i = 0; i < len ; i++) {
- int digit = grp[i].digitValue();
- // Add digit markers to digits > 0
- if ((len-i-1) > 0 && digit > 0)
- str.append(digitmarkers[(len-i-2)]);
- // Add digit, but collapse consecutive zeros
- if (!collapseZero || digit > 0) {
- str.append(digits[digit]);
-
- if (digit == 0)
- collapseZero = true;
- else
- collapseZero = false;
- }
- }
- return str;
-}
-
-TQString toTradChineseFormal( int number ) {
-// static const TQChar groupMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
- static const TQChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
- static const TQChar digits[10] = {0x96f6, 0x4e00,
- 0x4ebc, 0x4e09,
- 0x56db, 0x4e94,
- 0x516d, 0x4e03,
- 0x516b, 0x4e5d};
- return toIdeographic(number, digits, digitMarkers);
-}
-
-TQString toTradChineseInformal( int number ) {
-// static const TQChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
- static const TQChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
- static const TQChar digits[10] = {0x96f6, 0x4e00,
- 0x4ebc, 0x4e09,
- 0x56db, 0x4e94,
- 0x516d, 0x4e03,
- 0x516b, 0x4e5d};
- return toIdeographic(number, digits, digitMarkers);
-}
-
-TQString toSimpChineseFormal( int number ) {
-// static const TQChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
- static const TQChar digitMarkers[3] = {0x4e07, 0x4ebf, 0x5146};
- static const TQChar digits[10] = {0x96f6, 0x58f9,
- 0x8cb3, 0x53c3,
- 0x8086, 0x4f0d,
- 0x9678, 0x67d2,
- 0x634c, 0x7396};
- return toIdeographic(number, digits, digitMarkers);
-}
-
-TQString toSimpChineseInformal( int number ) {
-// static const TQChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
- static const TQChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
- static const TQChar digits[10] = {0x96f6, 0x58f9,
- 0x8cb3, 0x53c3,
- 0x8086, 0x4f0d,
- 0x9678, 0x67d2,
- 0x634c, 0x7396};
- return toIdeographic(number, digits, digitMarkers);
-}
-
-TQString toJapaneseFormal( int number ) {
-// static const TQChar groupMarkers[3] = {0x4e07, 0x5104, 0x5146};
- static const TQChar digitMarkers[3] = {0x62fe, 0x4f70, 0x4edf};
- static const TQChar digits[10] = {0x96f6, 0x58f9,
- 0x8cb3, 0x53c3,
- 0x8086, 0x4f0d,
- 0x9678, 0x67d2,
- 0x634c, 0x7396};
- return toIdeographic(number, digits, digitMarkers);
-}
-
-TQString toJapaneseInformal( int number ) {
-// static const TQChar groupMarkers[3] = {0x842c, 0x5104, 0x5146};
- static const TQChar digitMarkers[3] = {0x842c, 0x5104, 0x5146};
- static const TQChar digits[10] = {0x96f6, 0x58f9,
- 0x8d30, 0x53c1,
- 0x8086, 0x4f0d,
- 0x9646, 0x67d2,
- 0x634c, 0x7396};
- return toIdeographic(number, digits, digitMarkers);
-}
-
-}} // namespace
diff --git a/khtml/rendering/enumerate.h b/khtml/rendering/enumerate.h
deleted file mode 100644
index c8df6549a..000000000
--- a/khtml/rendering/enumerate.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef ENUMERATE_H
-#define ENUMERATE_H
-
-class TQChar;
-class TQString;
-
-namespace khtml {
-
-namespace Enumerate {
-
-// Numeric
- TQString toArabicIndic( int number );
- TQString toLao( int number );
- TQString toPersianUrdu( int number );
- TQString toThai( int number );
- TQString toTibetan( int number );
-
-// Alphabetic
- TQString toLowerLatin( int number );
- TQString toUpperLatin( int number );
- TQString toLowerGreek( int number );
- TQString toUpperGreek( int number );
- TQString toHiragana( int number );
- TQString toHiraganaIroha( int number );
- TQString toKatakana( int number );
- TQString toKatakanaIroha( int number );
-
-// Algorithmic
- TQString toRoman( int number, bool upper );
- TQString toHebrew( int number );
- TQString toGeorgian( int number );
- TQString toArmenian( int number );
-
-// Ideographic
- TQString toJapaneseFormal ( int number );
- TQString toJapaneseInformal ( int number );
- TQString toSimpChineseFormal ( int number );
- TQString toSimpChineseInformal ( int number );
- TQString toTradChineseFormal ( int number );
- TQString toTradChineseInformal ( int number );
-
-}} // namespaces
-
-#endif
diff --git a/khtml/rendering/font.cpp b/khtml/rendering/font.cpp
deleted file mode 100644
index 1a0591192..000000000
--- a/khtml/rendering/font.cpp
+++ /dev/null
@@ -1,502 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "config.h"
-
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-
-#include "font.h"
-#include "khtml_factory.h"
-#include "khtml_settings.h"
-
-#include <kdebug.h>
-#include <kglobal.h>
-
-#include <tqpainter.h>
-#include <tqfontdatabase.h>
-#include <tqpaintdevicemetrics.h>
-
-using namespace khtml;
-
-/** closes the current word and returns its width in pixels
- * @param fm metrics of font to be used
- * @param str string
- * @param pos zero-indexed position within @p str upon which all other
- * indices are based
- * @param wordStart relative index pointing to the position where the word started
- * @param wordEnd relative index pointing one position after the word ended
- * @return the width in pixels. May be 0 if @p wordStart and @p wordEnd were
- * equal.
- */
-inline int closeWordAndGetWidth(const TQFontMetrics &fm, const TQChar *str, int pos,
- int wordStart, int wordEnd)
-{
- if (wordEnd <= wordStart) return 0;
-
- TQConstString s(str + pos + wordStart, wordEnd - wordStart);
- return fm.width(s.string());
-}
-
-/** closes the current word and draws it
- * @param p painter
- * @param d text direction
- * @param x current x position, will be inc-/decremented correctly according
- * to text direction
- * @param y baseline of text
- * @param widths list of widths; width of word is expected at position
- * wordStart
- * @param str string
- * @param pos zero-indexed position within @p str upon which all other
- * indices are based
- * @param wordStart relative index pointing to the position where the word started,
- * will be set to wordEnd after function
- * @param wordEnd relative index pointing one position after the word ended
- */
-inline void closeAndDrawWord(TQPainter *p, TQPainter::TextDirection d,
- int &x, int y, const short widths[], const TQChar *str, int pos,
- int &wordStart, int wordEnd)
-{
- if (wordEnd <= wordStart) return;
-
- int width = widths[wordStart];
- if (d == TQPainter::RTL)
- x -= width;
-
- TQConstString s(str + pos + wordStart, wordEnd - wordStart);
- p->drawText(x, y, s.string(), -1, d);
-
- if (d != TQPainter::RTL)
- x += width;
-
- wordStart = wordEnd;
-}
-
-void Font::drawText( TQPainter *p, int x, int y, TQChar *str, int slen, int pos, int len,
- int toAdd, TQPainter::TextDirection d, int from, int to, TQColor bg, int uy, int h, int deco ) const
-{
- if (!str) return;
- TQConstString cstr = TQConstString(str, slen);
- TQString qstr = cstr.string();
-
- // ### fixme for RTL
- if ( !scFont && !letterSpacing && !wordSpacing && !toAdd && from==-1 ) {
- // simply draw it
- // Due to some unfounded cause TQPainter::drawText traverses the
- // *whole* string when painting, not only the specified
- // [pos, pos + len) segment. This makes painting *extremely* slow for
- // long render texts (in the order of several megabytes).
- // Hence, only hand over the piece of text of the actual inline text box
- TQConstString cstr = TQConstString(str + pos, len);
- p->drawText( x, y, cstr.string(), 0, len, d );
- } else {
- if (from < 0) from = 0;
- if (to < 0) to = len;
-
- int numSpaces = 0;
- if ( toAdd ) {
- for( int i = 0; i < len; ++i )
- if ( str[i+pos].category() == TQChar::Separator_Space )
- ++numSpaces;
- }
-
- const int totWidth = width( str, slen, pos, len );
- if ( d == TQPainter::RTL ) {
- x += totWidth + toAdd;
- }
- TQString upper = qstr;
- TQFontMetrics sc_fm = fm;
- if ( scFont ) {
- // draw in small caps
- upper = qstr.upper();
- sc_fm = TQFontMetrics( *scFont );
- }
-
- // ### sc could be optimized by only painting uppercase letters extra,
- // and treat the rest WordWise, but I think it's not worth it.
- // Somebody else may volunteer, and implement this ;-) (LS)
-
- // The mode determines whether the text is displayed character by
- // character, word by word, or as a whole
- enum { CharacterWise, WordWise, Whole }
- mode = Whole;
- if (!letterSpacing && !scFont && (wordSpacing || toAdd > 0))
- mode = WordWise;
- else if (letterSpacing || scFont)
- mode = CharacterWise;
-
- if (mode == Whole) { // most likely variant is treated extra
-
- if (to < 0) to = len;
- const TQConstString cstr(str + pos, len);
- const TQConstString segStr(str + pos + from, to - from);
- const int preSegmentWidth = fm.width(cstr.string(), from);
- const int segmentWidth = fm.width(segStr.string());
- const int eff_x = d == TQPainter::RTL ? x - preSegmentWidth - segmentWidth
- : x + preSegmentWidth;
-
- // draw whole string segment, with optional background
- if ( bg.isValid() )
- p->fillRect( eff_x, uy, segmentWidth, h, bg );
- p->drawText(eff_x, y, segStr.string(), -1, d);
- if (deco)
- drawDecoration(p, eff_x, uy, y - uy, segmentWidth - 1, h, deco);
- return;
- }
-
- // We are using two passes. In the first pass, the widths are collected,
- // and stored. In the second, the actual characters are drawn.
-
- // For each letter in the text box, save the width of the character.
- // When word-wise, only the first letter contains the width, but of the
- // whole word.
- short* const widthList = (short *)alloca(to*sizeof(short));
-
- // First pass: gather widths
- int preSegmentWidth = 0;
- int segmentWidth = 0;
- int lastWordBegin = 0;
- bool onSegment = from == 0;
- for( int i = 0; i < to; ++i ) {
- if (i == from) {
- // Also close words on visibility boundary
- if (mode == WordWise) {
- const int width = closeWordAndGetWidth(fm, str, pos, lastWordBegin, i);
-
- if (lastWordBegin < i) {
- widthList[lastWordBegin] = (short)width;
- lastWordBegin = i;
- preSegmentWidth += width;
- }
- }
- onSegment = true;
- }
-
- const TQChar ch = str[pos+i];
- bool lowercase = (ch.category() == TQChar::Letter_Lowercase);
- bool is_space = (ch.category() == TQChar::Separator_Space);
- int chw = 0;
- if ( letterSpacing )
- chw += letterSpacing;
- if ( (wordSpacing || toAdd) && is_space ) {
- if (mode == WordWise) {
- const int width = closeWordAndGetWidth(fm, str, pos, lastWordBegin, i);
- if (lastWordBegin < i) {
- widthList[lastWordBegin] = (short)width;
- lastWordBegin = i;
- (onSegment ? segmentWidth : preSegmentWidth) += width;
- }
- ++lastWordBegin; // ignore this space
- }
- chw += wordSpacing;
- if ( numSpaces ) {
- const int a = toAdd/numSpaces;
- chw += a;
- toAdd -= a;
- --numSpaces;
- }
- }
- if (is_space || mode == CharacterWise) {
- chw += lowercase ? sc_fm.charWidth( upper, pos+i ) : fm.charWidth( qstr, pos+i );
- widthList[i] = (short)chw;
-
- (onSegment ? segmentWidth : preSegmentWidth) += chw;
- }
-
- }
-
- // close last word
- Q_ASSERT(onSegment);
- if (mode == WordWise) {
- const int width = closeWordAndGetWidth(fm, str, pos, lastWordBegin, to);
- segmentWidth += width;
- widthList[lastWordBegin] = (short)width;
- }
-
- if (d == TQPainter::RTL) x -= preSegmentWidth;
- else x += preSegmentWidth;
-
- const int startx = d == TQPainter::RTL ? x-segmentWidth : x;
-
- // optionally draw background
- if ( bg.isValid() )
- p->fillRect( startx, uy, segmentWidth, h, bg );
-
- // second pass: do the actual drawing
- lastWordBegin = from;
- for( int i = from; i < to; ++i ) {
- const TQChar ch = str[pos+i];
- bool lowercase = (ch.category() == TQChar::Letter_Lowercase);
- bool is_space = ch.category() == TQChar::Separator_Space;
- if ( is_space ) {
- if (mode == WordWise) {
- closeAndDrawWord(p, d, x, y, widthList, str, pos, lastWordBegin, i);
- ++lastWordBegin; // jump over space
- }
- }
- if (is_space || mode == CharacterWise) {
- const int chw = widthList[i];
- if (d == TQPainter::RTL)
- x -= chw;
-
- if ( scFont )
- p->setFont( lowercase ? *scFont : f );
- p->drawText( x, y, (lowercase ? upper : qstr), pos+i, 1, d );
-
- if (d != TQPainter::RTL)
- x += chw;
- }
-
- }
-
- // don't forget to draw last word
- if (mode == WordWise) {
- closeAndDrawWord(p, d, x, y, widthList, str, pos, lastWordBegin, to);
- }
-
- if (deco)
- drawDecoration(p, startx, uy, y - uy, segmentWidth - 1, h, deco);
-
- if ( scFont )
- p->setFont( f );
- }
-}
-
-
-int Font::width( TQChar *chs, int, int pos, int len, int start, int end, int toAdd ) const
-{
- const TQConstString cstr(chs+pos, len);
- int w = 0;
-
- const TQString qstr = cstr.string();
- if ( scFont ) {
- const TQString upper = qstr.upper();
- const TQChar *uc = qstr.unicode();
- const TQFontMetrics sc_fm( *scFont );
- for ( int i = 0; i < len; ++i ) {
- if ( (uc+i)->category() == TQChar::Letter_Lowercase )
- w += sc_fm.charWidth( upper, i );
- else
- w += fm.charWidth( qstr, i );
- }
- } else {
- // ### might be a little inaccurate
- w = fm.width( qstr );
- }
-
- if ( letterSpacing )
- w += len*letterSpacing;
-
- if ( wordSpacing )
- // add amount
- for( int i = 0; i < len; ++i ) {
- if( chs[i+pos].category() == TQChar::Separator_Space )
- w += wordSpacing;
- }
-
- if ( toAdd ) {
- // first gather count of spaces
- int numSpaces = 0;
- for( int i = start; i != end; ++i )
- if ( chs[i].category() == TQChar::Separator_Space )
- ++numSpaces;
- // distribute pixels evenly among spaces, but count only those within
- // [pos, pos+len)
- for ( int i = start; numSpaces && i != pos + len; i++ )
- if ( chs[i].category() == TQChar::Separator_Space ) {
- const int a = toAdd/numSpaces;
- if ( i >= pos ) w += a;
- toAdd -= a;
- --numSpaces;
- }
- }
-
- return w;
-}
-
-int Font::width( TQChar *chs, int slen, int pos ) const
-{
- int w;
- if ( scFont && chs[pos].category() == TQChar::Letter_Lowercase ) {
- TQString str( chs, slen );
- str[pos] = chs[pos].upper();
- w = TQFontMetrics( *scFont ).charWidth( str, pos );
- } else {
- const TQConstString cstr( chs, slen );
- w = fm.charWidth( cstr.string(), pos );
- }
- if ( letterSpacing )
- w += letterSpacing;
-
- if ( wordSpacing && (chs+pos)->category() == TQChar::Separator_Space )
- w += wordSpacing;
- return w;
-}
-
-/** Querying QFontDB whether something is scalable is expensive, so we cache. */
-struct Font::ScalKey
-{
- TQString family;
- int weight;
- int italic;
-
- ScalKey(const TQFont& font) :
- family(font.family()), weight(font.weight()), italic(font.italic())
- {}
-
- ScalKey() {}
-
- bool operator<(const ScalKey& other) const {
- if (weight < other.weight)
- return true;
- if (weight > other.weight)
- return false;
-
- if (italic < other.italic)
- return true;
- if (italic > other.italic)
- return false;
-
- return family < other.family;
- }
-
- bool operator==(const ScalKey& other) const {
- return (weight == other.weight &&
- italic == other.italic &&
- family == other.family);
- }
-};
-
-TQMap<Font::ScalKey, Font::ScalInfo>* Font::scalCache;
-TQMap<Font::ScalKey, TQValueList<int> >* Font::scalSizesCache;
-
-bool Font::isFontScalable(TQFontDatabase& db, const TQFont& font)
-{
- if (!scalCache)
- scalCache = new TQMap<ScalKey, ScalInfo>;
-
- ScalKey key(font);
-
- ScalInfo &s = (*scalCache)[key];
- if (s == Unknown) {
- s = db.isSmoothlyScalable(font.family(), db.styleString(font)) ? Yes : No;
-
- if (s == No) {
- /* Cache size info */
- if (!scalSizesCache)
- scalSizesCache = new TQMap<ScalKey, TQValueList<int> >;
- (*scalSizesCache)[key] = db.smoothSizes(font.family(), db.styleString(font));
- }
- }
-
- return (s == Yes);
-}
-
-
-void Font::update( TQPaintDeviceMetrics* devMetrics ) const
-{
- f.setFamily( fontDef.family.isEmpty() ? KHTMLFactory::defaultHTMLSettings()->stdFontName() : fontDef.family );
- f.setItalic( fontDef.italic );
- f.setWeight( fontDef.weight );
-
- TQFontDatabase db;
-
- int size = fontDef.size;
- const int lDpiY = kMax(devMetrics->logicalDpiY(), 96);
-
- // ok, now some magic to get a nice unscaled font
- // all other font properties should be set before this one!!!!
- if( !isFontScalable(db, f) )
- {
- const TQValueList<int>& pointSizes = (*scalSizesCache)[ScalKey(f)];
- // lets see if we find a nice looking font, which is not too far away
- // from the requested one.
- // kdDebug(6080) << "khtml::setFontSize family = " << f.family() << " size requested=" << size << endl;
-
-
- float diff = 1; // ### 100% deviation
- float bestSize = 0;
-
- TQValueList<int>::ConstIterator it = pointSizes.begin();
- const TQValueList<int>::ConstIterator itEnd = pointSizes.end();
-
- for( ; it != itEnd; ++it )
- {
- float newDiff = ((*it)*(lDpiY/72.) - float(size))/float(size);
- //kdDebug( 6080 ) << "smooth font size: " << *it << " diff=" << newDiff << endl;
- if(newDiff < 0) newDiff = -newDiff;
- if(newDiff < diff)
- {
- diff = newDiff;
- bestSize = *it;
- }
- }
- //kdDebug( 6080 ) << "best smooth font size: " << bestSize << " diff=" << diff << endl;
- if ( bestSize != 0 && diff < 0.2 ) // 20% deviation, otherwise we use a scaled font...
- size = (int)((bestSize*lDpiY) / 72);
- }
-
- // make sure we don't bust up X11
- // Also, Qt does not support sizing a TQFont to zero.
- size = kMax(1, kMin(255, size));
-
-// tqDebug("setting font to %s, italic=%d, weight=%d, size=%d", fontDef.family.latin1(), fontDef.italic,
-// fontDef.weight, size );
-
-
- f.setPixelSize( size );
-
- fm = TQFontMetrics( f );
-
- // small caps
- delete scFont;
- scFont = 0;
-
- if ( fontDef.smallCaps ) {
- scFont = new TQFont( f );
- scFont->setPixelSize( kMax(1, f.pixelSize()*7/10) );
- }
-}
-
-void Font::drawDecoration(TQPainter *pt, int _tx, int _ty, int baseline, int width, int height, int deco) const
-{
- Q_UNUSED(height);
- // thick lines on small fonts look ugly
- const int thickness = fm.height() > 20 ? fm.lineWidth() : 1;
- const TQBrush brush = pt->pen().color();
- if (deco & UNDERLINE) {
- int underlineOffset = ( fm.height() + baseline ) / 2;
- if (underlineOffset <= baseline) underlineOffset = baseline+1;
-
- pt->fillRect(_tx, _ty + underlineOffset, width + 1, thickness, brush );
- }
- if (deco & OVERLINE) {
- pt->fillRect(_tx, _ty, width + 1, thickness, brush );
- }
- if (deco & LINE_THROUGH) {
- pt->fillRect(_tx, _ty + 2*baseline/3, width + 1, thickness, brush );
- }
-}
-
diff --git a/khtml/rendering/font.h b/khtml/rendering/font.h
deleted file mode 100644
index 714b03829..000000000
--- a/khtml/rendering/font.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef KHTMLFONT_H
-#define KHTMLFONT_H
-
-#include <tqfont.h>
-#include <tqfontmetrics.h>
-#include <tqmap.h>
-#include <tqpainter.h>
-
-class TQFontDatabase;
-class TQPaintDeviceMetrics;
-
-namespace khtml
-{
-class RenderStyle;
-class CSSStyleSelector;
-
-class FontDef
-{
-public:
- FontDef()
- : size( 0 ), italic( false ), smallCaps( false ), weight( 50 ) {}
- bool operator == ( const FontDef &other ) const {
- return ( family == other.family &&
- size == other.size &&
- italic == other.italic &&
- smallCaps == other.smallCaps &&
- weight == other.weight );
- }
-
- TQString family;
- short int size;
- bool italic : 1;
- bool smallCaps : 1;
- unsigned int weight : 8;
-};
-
-
-class Font
-{
- friend class RenderStyle;
- friend class CSSStyleSelector;
-
-public:
- Font() : fontDef(), f(), fm( f ), scFont( 0 ), letterSpacing( 0 ), wordSpacing( 0 ) {}
- Font( const FontDef &fd )
- : fontDef( fd ), f(), fm( f ), scFont( 0 ), letterSpacing( 0 ), wordSpacing( 0 )
- {}
- Font(const Font& o)
- : fontDef(o.fontDef), f(o.f), fm(o.fm), scFont(o.scFont), letterSpacing(o.letterSpacing), wordSpacing(o.wordSpacing) { if (o.scFont) scFont = new TQFont(*o.scFont); }
- ~Font() { delete scFont; }
-
- bool operator == ( const Font &other ) const {
- return (fontDef == other.fontDef &&
- letterSpacing == other.letterSpacing &&
- wordSpacing == other.wordSpacing );
- }
-
- const FontDef& getFontDef() const { return fontDef; }
-
- void update( TQPaintDeviceMetrics *devMetrics ) const;
-
- /**
- * Draws a piece from the given piece of text.
- * @param p painter
- * @param x x-coordinate to begin drawing, always denotes leftmost position
- * @param y y-coordinate of baseline of text
- * @param str string to draw a piece from
- * @param slen total length of string
- * @param pos zero-based offset of beginning of piece
- * @param len length of piece
- * @param width additional pixels to be distributed equally among all
- * spaces
- * @param d text direction
- * @param from begin with this position relative to @p pos, -1 to start
- * at @p pos
- * @param to stop before this position relative to @p pos, -1 to use full
- * length of piece
- * @param bg if valid, fill the background of the drawn piece with this
- * color
- * @param uy y-coordinate of top position, used for background and text
- * decoration painting
- * @param h total height of line, only used for background and text
- * decoration painting
- * @param deco combined text decoration (see Decoration)
- */
- void drawText( TQPainter *p, int x, int y, TQChar *str, int slen, int pos, int len, int width,
- TQPainter::TextDirection d, int from=-1, int to=-1, TQColor bg=TQColor(),
- int uy=-1, int h=-1, int deco=0 ) const;
-
- /** returns the width of the given string chunk in pixels.
- *
- * The method also considers various styles like text-align and font-variant
- * @param str pointer to string
- * @param slen total length of string
- * @param pos zero-based position in string where to start measuring
- * @param len count of characters up to which the width should be determined
- * @param start starting position of inline text box within str, only
- * used when toAdd is specified.
- * @param end ending position of inline text box within str, only
- * used when toAdd is specified.
- * @param toAdd amount of pixels to distribute evenly among all spaces of
- * str. Note that toAdd applies to all spaces within str, but only those
- * within [pos, pos+len) are counted towards the width.
- */
- int width( TQChar *str, int slen, int pos, int len, int start = 0, int end = 0, int toAdd = 0 ) const;
- /** return the width of the given char in pixels.
- *
- * The method also considers various styles like text-align and font-variant
- * @param str pointer to string
- * @param slen total length of string
- * @param pos zero-based position of char in string
- */
- int width( TQChar *str, int slen, int pos) const;
-
- /** Text decoration constants.
- *
- * The enumeration constant values match those of ETextDecoration, but only
- * a subset is supported.
- */
- enum Decoration { UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH= 0x4 };
- // Keep in sync with ETextDecoration
-
- /** draws text decoration
- * @param p painter
- * @param x x-coordinate
- * @param y top y-coordinate of line box
- * @param baseline baseline
- * @param width length of decoration in pixels
- * @param height height of line box
- * @param deco decoration to be drawn (see Decoration). The enumeration
- * constants may be combined.
- */
- void drawDecoration(TQPainter *p, int x, int y, int baseline, int width, int height, int deco) const;
-
- /** returns letter spacing
- */
- int getLetterSpacing() const { return letterSpacing; }
- /** returns word spacing
- */
- int getWordSpacing() const { return wordSpacing; }
-
-private:
- mutable FontDef fontDef;
- mutable TQFont f;
- mutable TQFontMetrics fm;
- mutable TQFont *scFont;
- short letterSpacing;
- short wordSpacing;
-
- struct ScalKey;
- enum ScalInfo {
- Unknown,
- No,
- Yes
- };
-
- static TQMap<ScalKey, ScalInfo>* scalCache;
- static TQMap<ScalKey, TQValueList<int> >* scalSizesCache;
- static bool isFontScalable(TQFontDatabase& db, const TQFont& font);
-};
-
-} // namespace
-
-#endif
diff --git a/khtml/rendering/img-loading.png b/khtml/rendering/img-loading.png
deleted file mode 100644
index ae5a9732f..000000000
--- a/khtml/rendering/img-loading.png
+++ /dev/null
Binary files differ
diff --git a/khtml/rendering/loading_icon.cpp b/khtml/rendering/loading_icon.cpp
deleted file mode 100644
index 218befcf8..000000000
--- a/khtml/rendering/loading_icon.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-static const unsigned char loading_icon_data[] = {
-0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,
-0x52,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x10,0x08,0x04,0x00,0x00,0x00,0x8c,
-0x9d,0x86,0xb1,0x00,0x00,0x00,0x04,0x67,0x41,0x4d,0x41,0x00,0x00,0xb1,0x8f,
-0x0b,0xfc,0x61,0x05,0x00,0x00,0x00,0x02,0x62,0x4b,0x47,0x44,0x00,0xff,0x87,
-0x8f,0xcc,0xbf,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x12,
-0x00,0x00,0x0b,0x12,0x01,0xd2,0xdd,0x7e,0xfc,0x00,0x00,0x00,0x07,0x74,0x49,
-0x4d,0x45,0x07,0xd4,0x0c,0x17,0x10,0x00,0x23,0xf3,0x04,0xa4,0xbc,0x00,0x00,
-0x00,0xbf,0x49,0x44,0x41,0x54,0x78,0x9c,0x75,0xd1,0x31,0x4e,0x04,0x31,0x0c,
-0x85,0xe1,0x2f,0xc9,0x1c,0x63,0xee,0x02,0x82,0x9a,0x23,0x70,0x01,0xba,0xad,
-0xe8,0x98,0x0d,0x35,0xab,0xe9,0x10,0xf7,0x80,0x76,0xe0,0x32,0x7b,0x01,0x44,
-0x9d,0x84,0x22,0xc3,0x32,0xd2,0x82,0x5d,0xd9,0xbf,0xf5,0xe4,0x67,0x07,0xd9,
-0x59,0x4c,0xf2,0x04,0x91,0xf6,0x47,0x3e,0x64,0x18,0xe0,0x1d,0x51,0x15,0x05,
-0x05,0xc1,0x5e,0xc8,0x79,0x1a,0xba,0x50,0x54,0x3d,0x49,0x76,0xa2,0xaa,0x61,
-0x4f,0x8e,0x1d,0x05,0xb3,0x1b,0xc5,0xb5,0x2a,0x79,0x14,0x04,0xb9,0xcb,0x06,
-0x45,0xf1,0x2a,0x21,0x2a,0x16,0x5c,0x09,0x1d,0x16,0xd1,0xbd,0x4b,0x2c,0xaa,
-0xa4,0x48,0x4e,0x0b,0xf5,0x58,0x24,0xcd,0x2d,0x38,0x6a,0xdd,0x0a,0xd1,0x41,
-0x41,0x01,0xcf,0xa7,0xf1,0x08,0xd5,0x68,0x16,0x11,0x70,0xe7,0x73,0x0b,0x13,
-0x46,0x07,0x34,0x47,0x47,0x5f,0x2b,0x1c,0xa0,0x81,0xd1,0x6c,0x67,0xd9,0x9c,
-0x71,0xe8,0xb2,0x2f,0x6b,0xf9,0xe6,0x43,0xd0,0xd4,0x5f,0x98,0x2c,0x48,0x9a,
-0xba,0xb6,0x37,0x56,0x2e,0xce,0x1f,0xf3,0x03,0xc3,0x3f,0x88,0x6f,0xc1,0xe0,
-0x3e,0x9e,0x60,0xe9,0x10,0xaa,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,
-0x42,0x60,0x82
-};
-static const unsigned int loading_icon_len = 318;
diff --git a/khtml/rendering/render_applet.cpp b/khtml/rendering/render_applet.cpp
deleted file mode 100644
index fce22f7c8..000000000
--- a/khtml/rendering/render_applet.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/**
- * This file is part of the HTML widget for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include <config.h>
-#include <klocale.h>
-
-#include <kdebug.h>
-
-#include "rendering/render_applet.h"
-#include "rendering/render_canvas.h"
-#include "xml/dom_docimpl.h"
-#include "khtmlview.h"
-#include "khtml_part.h"
-
-#include <tqlabel.h>
-
-#ifndef Q_WS_QWS // We don't have Java in Qt Embedded
-
-#include "java/kjavaappletwidget.h"
-#include "misc/htmltags.h"
-#include "html/html_objectimpl.h"
-
-using namespace khtml;
-using namespace DOM;
-
-RenderApplet::RenderApplet(HTMLElementImpl *applet, const TQMap<TQString, TQString> &args )
- : RenderWidget(applet)
-{
- // init RenderObject attributes
- setInline(true);
-
- KJavaAppletContext *context = 0;
- KHTMLView *_view = applet->getDocument()->view();
- if ( _view ) {
- KHTMLPart *part = _view->part();
- context = part->createJavaContext();
- }
-
- if ( context ) {
- //kdDebug(6100) << "RenderApplet::RenderApplet, setting TQWidget" << endl;
- setQWidget( new KJavaAppletWidget(context, _view->viewport()) );
- processArguments(args);
- }
-}
-
-RenderApplet::~RenderApplet()
-{
-}
-
-short RenderApplet::intrinsicWidth() const
-{
- int rval = 300;
-
- if( m_widget )
- rval = ((KJavaAppletWidget*)(m_widget))->sizeHint().width();
-
- return rval > 10 ? rval : 50;
-}
-
-int RenderApplet::intrinsicHeight() const
-{
- int rval = 150;
-
- if( m_widget )
- rval = m_widget->sizeHint().height();
-
- return rval > 10 ? rval : 50;
-}
-
-void RenderApplet::layout()
-{
- //kdDebug(6100) << "RenderApplet::layout" << endl;
-
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
-
- calcWidth();
- calcHeight();
-
- KJavaAppletWidget *tmp = static_cast<KJavaAppletWidget*>(m_widget);
- if ( tmp ) {
- NodeImpl *child = element()->firstChild();
-
- while(child) {
-
- if(child->id() == ID_PARAM) {
- HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>(child);
- if(tmp->applet())
- tmp->applet()->setParameter( p->name(), p->value());
- }
- child = child->nextSibling();
- }
- //kdDebug(6100) << "setting applet widget to size: " << m_width << ", " << m_height << endl;
- m_widget->resize(m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
- m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom());
- tmp->showApplet();
- }
-
- setNeedsLayout(false);
-}
-
-void RenderApplet::processArguments(const TQMap<TQString, TQString> &args)
-{
- KJavaAppletWidget *w = static_cast<KJavaAppletWidget*>(m_widget);
- KJavaApplet* applet = w ? w->applet() : 0;
-
- if ( applet ) {
- applet->setBaseURL( args[TQString::fromLatin1("baseURL") ] );
- applet->setAppletClass( args[TQString::fromLatin1("code") ] );
-
- TQString str = args[TQString::fromLatin1("codeBase") ];
- if( !str.isEmpty() )
- applet->setCodeBase( str );
-
- str = args[TQString::fromLatin1("name") ];
- if( !str.isNull() )
- applet->setAppletName( str );
- else
- applet->setAppletName( args[TQString::fromLatin1("code") ] );
-
- str = args[TQString::fromLatin1("archive") ];
- if( !str.isEmpty() )
- applet->setArchives( args[TQString::fromLatin1("archive") ] );
- }
-}
-
-#endif
diff --git a/khtml/rendering/render_applet.h b/khtml/rendering/render_applet.h
deleted file mode 100644
index 184697a7c..000000000
--- a/khtml/rendering/render_applet.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is part of the HTML widget for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef render_applet_h
-#define render_applet_h
-
-#include "rendering/render_replaced.h"
-#include "html/html_objectimpl.h"
-
-#include <tqwidget.h>
-#include <tqmap.h>
-
-class KHTMLView;
-
-namespace DOM {
- class HTMLElementImpl;
-}
-
-namespace khtml {
-
-class RenderApplet : public RenderWidget
-{
-public:
- RenderApplet(DOM::HTMLElementImpl* node, const TQMap<TQString, TQString> &args);
- virtual ~RenderApplet();
-
- virtual const char *renderName() const { return "RenderApplet"; }
-
- virtual void layout();
- virtual short intrinsicWidth() const;
- virtual int intrinsicHeight() const;
- virtual bool isApplet() const { return true; }
-
- DOM::HTMLElementImpl *element() const
- { return static_cast<DOM::HTMLElementImpl*>(RenderObject::element()); }
-
-private:
- void processArguments( const TQMap<TQString, TQString> &args );
-};
-
-}
-#endif
diff --git a/khtml/rendering/render_arena.cpp b/khtml/rendering/render_arena.cpp
deleted file mode 100644
index 99fbf4f4d..000000000
--- a/khtml/rendering/render_arena.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2002 Apple Computer, Inc.
- * Copyright (C) 2003 Dirk Mueller (mueller@kde.org)
- *
- * Portions are Copyright (C) 1998 Netscape Communications Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Alternatively, the contents of this file may be used under the terms
- * of either the Mozilla Public License Version 1.1, found at
- * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
- * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
- * (the "GPL"), in which case the provisions of the MPL or the GPL are
- * applicable instead of those above. If you wish to allow use of your
- * version of this file only under the terms of one of those two
- * licenses (the MPL or the GPL) and not to allow others to use your
- * version of this file under the LGPL, indicate your decision by
- * deletingthe provisions above and replace them with the notice and
- * other provisions required by the MPL or the GPL, as the case may be.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under any of the LGPL, the MPL or the GPL.
- */
-
-#include "render_arena.h"
-
-#include <string.h>
-#include <assert.h>
-
-using namespace khtml;
-
-namespace khtml {
-
-//#ifdef NDEBUG
-#define KHTML_USE_ARENA_ALLOCATOR
-//#endif
-
-typedef struct {
- RenderArena *arena;
- size_t size;
-} RenderArenaDebugHeader;
-
-#ifdef VALGRIND_SUPPORT
-Arena* findContainingArena(ArenaPool* pool, void* ptr) {
- uword ptrBits = reinterpret_cast<uword>(ptr);
- for (Arena* a = &pool->first; a; a = a->next)
- if (ptrBits >= a->base && ptrBits < a->limit)
- return a;
- return 0; //Should not happen
-}
-#endif
-
-RenderArena::RenderArena(unsigned int arenaSize)
-{
- // Initialize the arena pool
- INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize);
-
- // Zero out the recyclers array
- memset(m_recyclers, 0, sizeof(m_recyclers));
-}
-
-RenderArena::~RenderArena()
-{
- // Free the arena in the pool and finish using it
- FreeArenaPool(&m_pool);
-}
-
-void* RenderArena::allocate(size_t size)
-{
-#ifndef KHTML_USE_ARENA_ALLOCATOR
- // Use standard malloc so that memory debugging tools work.
- void *block = ::malloc(sizeof(RenderArenaDebugHeader) + size);
- RenderArenaDebugHeader *header = (RenderArenaDebugHeader *)block;
- header->arena = this;
- header->size = size;
- return header + 1;
-#else
- void* result = 0;
-
- // Ensure we have correct alignment for pointers. Important for Tru64
- size = KHTML_ROUNDUP(size, sizeof(void*));
-
- // Check recyclers first
- if (size < KHTML_MAX_RECYCLED_SIZE) {
- const int index = size >> 2;
-
- result = m_recyclers[index];
- if (result) {
-#ifdef VALGRIND_SUPPORT
- VALGRIND_MEMPOOL_ALLOC(findContainingArena(&m_pool, result)->base, result, size);
-#endif
- // Need to move to the next object
- void* next = *((void**)result);
- m_recyclers[index] = next;
- }
- }
-
- if (!result) {
- // Allocate a new chunk from the arena
- ARENA_ALLOCATE(result, &m_pool, size);
- }
-
- return result;
-#endif
-}
-
-void RenderArena::free(size_t size, void* ptr)
-{
-#ifndef KHTML_USE_ARENA_ALLOCATOR
- // Use standard free so that memory debugging tools work.
- assert(this);
- RenderArenaDebugHeader *header = (RenderArenaDebugHeader *)ptr - 1;
- assert(header->size == size);
- assert(header->arena == this);
- ::free(header);
-#else
-
-#ifdef VALGRIND_SUPPORT
- VALGRIND_MEMPOOL_FREE(findContainingArena(&m_pool, ptr)->base, ptr);
-#endif
-
- // Ensure we have correct alignment for pointers. Important for Tru64
- size = KHTML_ROUNDUP(size, sizeof(void*));
-
- // See if it's a size that we recycle
- if (size < KHTML_MAX_RECYCLED_SIZE) {
- const int index = size >> 2;
- void* currentTop = m_recyclers[index];
- m_recyclers[index] = ptr;
- *((void**)ptr) = currentTop;
- }
-#endif
-}
-
-}
diff --git a/khtml/rendering/render_arena.h b/khtml/rendering/render_arena.h
deleted file mode 100644
index 786cd208a..000000000
--- a/khtml/rendering/render_arena.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2002 Apple Computer, Inc.
- * Copyright (C) 2003 Dirk Mueller (mueller@kde.org)
- *
- * Portions are Copyright (C) 1998 Netscape Communications Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Alternatively, the contents of this file may be used under the terms
- * of either the Mozilla Public License Version 1.1, found at
- * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
- * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
- * (the "GPL"), in which case the provisions of the MPL or the GPL are
- * applicable instead of those above. If you wish to allow use of your
- * version of this file only under the terms of one of those two
- * licenses (the MPL or the GPL) and not to allow others to use your
- * version of this file under the LGPL, indicate your decision by
- * deletingthe provisions above and replace them with the notice and
- * other provisions required by the MPL or the GPL, as the case may be.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under any of the LGPL, the MPL or the GPL.
- */
-
-#ifndef RENDERARENA_H
-#define RENDERARENA_H
-
-#include "misc/arena.h"
-#include "misc/shared.h"
-
-#include <stdlib.h>
-
-namespace khtml {
-
-#define KHTML_MAX_RECYCLED_SIZE 400
-#define KHTML_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
-
-class RenderArena: public Shared<RenderArena> {
-public:
- RenderArena(unsigned int arenaSize = 4096);
- ~RenderArena();
-
- // Memory management functions
- void* allocate(size_t size);
- void free(size_t size, void* ptr);
-
-private:
- // Underlying arena pool
- ArenaPool m_pool;
-
- // The recycler array is sparse with the indices being multiples of 4,
- // i.e., 0, 4, 8, 12, 16, 20, ...
- void* m_recyclers[KHTML_MAX_RECYCLED_SIZE >> 2];
-};
-
-
-} // namespace
-
-
-#endif
-
diff --git a/khtml/rendering/render_block.cpp b/khtml/rendering/render_block.cpp
deleted file mode 100644
index ccbb6fad0..000000000
--- a/khtml/rendering/render_block.cpp
+++ /dev/null
@@ -1,3155 +0,0 @@
-/*
- * This file is part of the render object implementation for KHTML.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003,2005 Apple Computer, Inc.
- * (C) 2004 Germain Garand (germain@ebooksfrance.org)
- * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- * (C) 2006 Charles Samuels (charles@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-//#define DEBUG
-//#define DEBUG_LAYOUT
-//#define BOX_DEBUG
-//#define FLOAT_DEBUG
-//#define PAGE_DEBUG
-
-#include <kdebug.h>
-#include "rendering/render_text.h"
-#include "rendering/render_table.h"
-#include "rendering/render_canvas.h"
-#include "rendering/render_layer.h"
-#include "rendering/render_block.h"
-
-#include "xml/dom_nodeimpl.h"
-#include "xml/dom_docimpl.h"
-#include "html/html_formimpl.h"
-#include "misc/htmltags.h"
-
-#include "khtmlview.h"
-
-using namespace DOM;
-
-namespace khtml {
-
-// -------------------------------------------------------------------------------------------------------
-
-// Our MarginInfo state used when laying out block children.
-RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
-{
- // Whether or not we can collapse our own margins with our children. We don't do this
- // if we had any border/padding (obviously), if we're the root or HTML elements, or if
- // we're positioned, floating, a table cell.
- m_canCollapseWithChildren = !block->isCanvas() && !block->isRoot() && !block->isPositioned() &&
- !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable();
-
- m_canCollapseTopWithChildren = m_canCollapseWithChildren && (top == 0) /*&& block->style()->marginTopCollapse() != MSEPARATE */;
-
- // If any height other than auto is specified in CSS, then we don't collapse our bottom
- // margins with our children's margins. To do otherwise would be to risk odd visual
- // effects when the children overflow out of the parent block and yet still collapse
- // with it. We also don't collapse if we have any bottom border/padding.
- m_canCollapseBottomWithChildren = m_canCollapseWithChildren && (bottom == 0) &&
- (block->style()->height().isVariable() && block->style()->height().value() == 0) /*&& block->style()->marginBottomCollapse() != MSEPARATE*/;
-
- m_quirkContainer = block->isTableCell() || block->isBody() /*|| block->style()->marginTopCollapse() == MDISCARD ||
- block->style()->marginBottomCollapse() == MDISCARD*/;
-
- m_atTopOfBlock = true;
- m_atBottomOfBlock = false;
-
- m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;
- m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;
-
- m_selfCollapsingBlockClearedFloat = false;
-
- m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;
-}
-
-// -------------------------------------------------------------------------------------------------------
-
-RenderBlock::RenderBlock(DOM::NodeImpl* node)
- : RenderFlow(node)
-{
- m_childrenInline = true;
- m_floatingObjects = 0;
- m_positionedObjects = 0;
- m_firstLine = false;
- m_avoidPageBreak = false;
- m_clearStatus = CNONE;
- m_maxTopPosMargin = m_maxTopNegMargin = m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
- m_topMarginQuirk = m_bottomMarginQuirk = false;
- m_overflowHeight = m_overflowWidth = 0;
- m_overflowLeft = m_overflowTop = 0;
-}
-
-RenderBlock::~RenderBlock()
-{
- delete m_floatingObjects;
- delete m_positionedObjects;
-}
-
-void RenderBlock::setStyle(RenderStyle* _style)
-{
- setReplaced(_style->isDisplayReplacedType());
-
- RenderFlow::setStyle(_style);
-
- // ### we could save this call when the change only affected
- // non inherited properties
- RenderObject *child = firstChild();
- while (child != 0)
- {
- if (child->isAnonymousBlock())
- {
- RenderStyle* newStyle = new RenderStyle();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(BLOCK);
- child->setStyle(newStyle);
- }
- child = child->nextSibling();
- }
-
- if (attached()) {
- // Update generated content and ::inside
- updateReplacedContent();
- // Update pseudos for :before and :after
- updatePseudoChildren();
- }
-
- // handled by close() during parsing
- // ### remove close move upto updatePseudo
- if (!document()->parsing()) {
- updateFirstLetter();
- }
-}
-
-// Attach handles initial setStyle that requires parent nodes
-void RenderBlock::attach()
-{
- RenderFlow::attach();
-
- updateReplacedContent();
- updatePseudoChildren();
-}
-
-void RenderBlock::updateFirstLetter()
-{
- // Only blocks with inline-children can generate a first-letter
- if (!childrenInline() || !firstChild()) return;
-
- // Don't recurse
- if (style()->styleType() == RenderStyle::FIRST_LETTER) return;
-
- // The first-letter style is inheritable.
- RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LETTER);
- RenderObject *o = this;
- while (o && !pseudoStyle) {
- // ### We should ignore empty preceding siblings
- if (o->parent() && o->parent()->firstChild() == this)
- o = o->parent();
- else
- break;
- pseudoStyle = o->style()->getPseudoStyle(RenderStyle::FIRST_LETTER);
- };
-
- // FIXME: Currently we don't delete first-letters, this is
- // handled instead in NodeImpl::diff by issuing Detach on first-letter changes.
- if (!pseudoStyle) {
- return;
- }
-
- // Drill into inlines looking for our first text child.
- RenderObject* firstText = firstChild();
- while (firstText && firstText->needsLayout() && !firstText->isFloating() && !firstText->isRenderBlock() && !firstText->isReplaced() && !firstText->isText())
- // ### We should skip first children with only white-space and punctuation
- firstText = firstText->firstChild();
-
- if (firstText && firstText->isText() && !firstText->isBR()) {
- RenderObject* firstLetterObject = 0;
- // Find the old first-letter
- if (firstText->parent()->style()->styleType() == RenderStyle::FIRST_LETTER)
- firstLetterObject = firstText->parent();
-
- // Force inline display (except for floating first-letters)
- pseudoStyle->setDisplay( pseudoStyle->isFloating() ? BLOCK : INLINE);
- pseudoStyle->setPosition( STATIC ); // CSS2 says first-letter can't be positioned.
-
- if (firstLetterObject != 0) {
- firstLetterObject->setStyle( pseudoStyle );
- RenderStyle* newStyle = new RenderStyle();
- newStyle->inheritFrom( pseudoStyle );
- firstText->setStyle( newStyle );
- return;
- }
-
- RenderText* textObj = static_cast<RenderText*>(firstText);
- RenderObject* firstLetterContainer = firstText->parent();
-
- firstLetterObject = RenderFlow::createFlow(node(), pseudoStyle, renderArena() );
- firstLetterObject->setIsAnonymous( true );
- firstLetterContainer->addChild(firstLetterObject, firstLetterContainer->firstChild());
-
- // if this object is the result of a :begin, then the text may have not been
- // generated yet if it is a counter
- if (textObj->recalcMinMax())
- textObj->recalcMinMaxWidths();
-
- // The original string is going to be either a generated content string or a DOM node's
- // string. We want the original string before it got transformed in case first-letter has
- // no text-transform or a different text-transform applied to it.
- DOMStringImpl* oldText = textObj->originalString();
- if (!oldText)
- oldText = textObj->string();
- // ### In theory a first-letter can stretch across multiple text objects, if they only contain
- // punctuation and white-space
- if(oldText->l >= 1) {
- oldText->ref();
- // begin: we need skip leading whitespace so that RenderBlock::findNextLineBreak
- // won't think we're continuing from a previous run
- unsigned int begin = 0; // the position that first-letter begins
- unsigned int length = 0; // the position that "the rest" begins
- while ( length < oldText->l && (oldText->s+length)->isSpace() )
- length++;
- begin = length;
- while ( length < oldText->l &&
- ( (oldText->s+length)->isPunct()) || (oldText->s+length)->isSpace() )
- length++;
- if ( length < oldText->l &&
- !( (oldText->s+length)->isSpace() || (oldText->s+length)->isPunct() ))
- length++;
- while ( length < oldText->l && (oldText->s+length)->isMark() )
- length++;
-
- // we need to generated a remainingText object even if no text is left
- // because it holds the place and style for the old textObj
- RenderTextFragment* remainingText =
- new (renderArena()) RenderTextFragment(textObj->node(), oldText, length, oldText->l-length);
- remainingText->setIsAnonymous( textObj->isAnonymous() );
- remainingText->setStyle(textObj->style());
- if (remainingText->element())
- remainingText->element()->setRenderer(remainingText);
-
- RenderObject* nextObj = textObj->nextSibling();
- textObj->detach();
- firstLetterContainer->addChild(remainingText, nextObj);
-
- RenderTextFragment* letter =
- new (renderArena()) RenderTextFragment(remainingText->node(), oldText, begin, length-begin);
- letter->setIsAnonymous( remainingText->isAnonymous() );
- RenderStyle* newStyle = new RenderStyle();
- newStyle->inheritFrom(pseudoStyle);
- letter->setStyle(newStyle);
- firstLetterObject->addChild(letter);
- oldText->deref();
- }
- firstLetterObject->close();
- }
-}
-
-void RenderBlock::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
-{
- // Make sure we don't append things after :after-generated content if we have it.
- if ( !beforeChild && lastChild() && lastChild()->style()->styleType() == RenderStyle::AFTER )
- beforeChild = lastChild();
-
- bool madeBoxesNonInline = false;
-
- // If the requested beforeChild is not one of our children, then this is most likely because
- // there is an anonymous block box within this object that contains the beforeChild. So
- // just insert the child into the anonymous block box instead of here. This may also be
- // needed in cases of things like anonymous tables.
- if (beforeChild && beforeChild->parent() != this) {
-
- KHTMLAssert(beforeChild->parent());
-
- // In the special case where we are prepending a block-level element before
- // something contained inside an anonymous block, we can just prepend it before
- // the anonymous block.
- if (!newChild->isInline() && beforeChild->parent()->isAnonymousBlock() &&
- beforeChild->parent()->parent() == this &&
- beforeChild->parent()->firstChild() == beforeChild)
- return addChildToFlow(newChild, beforeChild->parent());
-
- // Otherwise find our kid inside which the beforeChild is, and delegate to it.
- // This may be many levels deep due to anonymous tables, table sections, etc.
- RenderObject* responsible = beforeChild->parent();
- while (responsible->parent() != this)
- responsible = responsible->parent();
-
- return responsible->addChild(newChild,beforeChild);
- }
-
- // prevent elements that haven't received a layout yet from getting painted by pushing
- // them far above the top of the page
- if (!newChild->isInline())
- newChild->setPos(newChild->xPos(), -500000);
-
- if (!newChild->isText() && newChild->style()->position() != STATIC)
- setOverhangingContents();
-
- // A block has to either have all of its children inline, or all of its children as blocks.
- // So, if our children are currently inline and a block child has to be inserted, we move all our
- // inline children into anonymous block boxes
- if ( m_childrenInline && !newChild->isInline() && !newChild->isFloatingOrPositioned() )
- {
- // This is a block with inline content. Wrap the inline content in anonymous blocks.
- makeChildrenNonInline(beforeChild);
- madeBoxesNonInline = true;
-
- if (beforeChild && beforeChild->parent() != this) {
- beforeChild = beforeChild->parent();
- KHTMLAssert(beforeChild->isAnonymousBlock());
- KHTMLAssert(beforeChild->parent() == this);
- }
- }
- else if (!m_childrenInline && !newChild->isFloatingOrPositioned())
- {
- // If we're inserting an inline child but all of our children are blocks, then we have to make sure
- // it is put into an anomyous block box. We try to use an existing anonymous box if possible, otherwise
- // a new one is created and inserted into our list of children in the appropriate position.
- if (newChild->isInline()) {
- if (beforeChild) {
- if ( beforeChild->previousSibling() && beforeChild->previousSibling()->isAnonymousBlock() ) {
- beforeChild->previousSibling()->addChild(newChild);
- return;
- }
- }
- else {
- if ( m_last && m_last->isAnonymousBlock() ) {
- m_last->addChild(newChild);
- return;
- }
- }
-
- // no suitable existing anonymous box - create a new one
- RenderBlock* newBox = createAnonymousBlock();
- RenderBox::addChild(newBox,beforeChild);
- newBox->addChild(newChild);
-
- //the above may actually destroy newBox in case an anonymous
- //table got created, and made the anonymous block redundant.
- //so look up what to hide indirectly.
- RenderObject* toHide = newChild;
- while (toHide->parent() != this)
- toHide = toHide->parent();
-
- toHide->setPos(toHide->xPos(), -500000);
- return;
- }
- else {
- // We are adding another block child... if the current last child is an anonymous box
- // then it needs to be closed.
- // ### get rid of the closing thing altogether this will only work during initial parsing
- if (lastChild() && lastChild()->isAnonymous()) {
- lastChild()->close();
- }
- }
- }
-
- RenderBox::addChild(newChild,beforeChild);
- // ### care about aligned stuff
-
- if ( madeBoxesNonInline )
- removeLeftoverAnonymousBoxes();
-}
-
-static void getInlineRun(RenderObject* start, RenderObject* stop,
- RenderObject*& inlineRunStart,
- RenderObject*& inlineRunEnd)
-{
- // Beginning at |start| we find the largest contiguous run of inlines that
- // we can. We denote the run with start and end points, |inlineRunStart|
- // and |inlineRunEnd|. Note that these two values may be the same if
- // we encounter only one inline.
- //
- // We skip any non-inlines we encounter as long as we haven't found any
- // inlines yet.
- //
- // |stop| indicates a non-inclusive stop point. Regardless of whether |stop|
- // is inline or not, we will not include it in a run with inlines before it. It's as though we encountered
- // a non-inline.
-
- RenderObject * curr = start;
- bool sawInline;
- do {
- while (curr && !(curr->isInline() || curr->isFloatingOrPositioned()))
- curr = curr->nextSibling();
-
- inlineRunStart = inlineRunEnd = curr;
-
- if (!curr)
- return; // No more inline children to be found.
-
- sawInline = curr->isInline();
-
- curr = curr->nextSibling();
- while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != stop)) {
- inlineRunEnd = curr;
- if (curr->isInline())
- sawInline = true;
- curr = curr->nextSibling();
- }
- } while (!sawInline);
-
-}
-
-void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
-{
- // makeChildrenNonInline takes a block whose children are *all* inline and it
- // makes sure that inline children are coalesced under anonymous
- // blocks. If |insertionPoint| is defined, then it represents the insertion point for
- // the new block child that is causing us to have to wrap all the inlines. This
- // means that we cannot coalesce inlines before |insertionPoint| with inlines following
- // |insertionPoint|, because the new child is going to be inserted in between the inlines,
- // splitting them.
- KHTMLAssert(isReplacedBlock() || !isInline());
- KHTMLAssert(!insertionPoint || insertionPoint->parent() == this);
-
- m_childrenInline = false;
-
- RenderObject *child = firstChild();
-
- while (child) {
- RenderObject *inlineRunStart, *inlineRunEnd;
- getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
-
- if (!inlineRunStart)
- break;
-
- child = inlineRunEnd->nextSibling();
-
- RenderBlock* box = createAnonymousBlock();
- insertChildNode(box, inlineRunStart);
- RenderObject* o = inlineRunStart;
- while(o != inlineRunEnd)
- {
- RenderObject* no = o;
- o = no->nextSibling();
- box->appendChildNode(removeChildNode(no));
- }
- box->appendChildNode(removeChildNode(inlineRunEnd));
- box->close();
- box->setPos(box->xPos(), -500000);
- }
-}
-
-void RenderBlock::makePageBreakAvoidBlocks()
-{
- KHTMLAssert(!childrenInline());
- KHTMLAssert(canvas()->pagedMode());
-
- RenderObject *breakAfter = firstChild();
- RenderObject *breakBefore = breakAfter ? breakAfter->nextSibling() : 0;
-
- RenderBlock* pageRun = 0;
-
- // ### Should follow margin-collapsing rules, skipping self-collapsing blocks
- // and exporting page-breaks from first/last child when collapsing with parent margin.
- while (breakAfter) {
- if (breakAfter->isRenderBlock() && !breakAfter->childrenInline())
- static_cast<RenderBlock*>(breakAfter)->makePageBreakAvoidBlocks();
- EPageBreak pbafter = breakAfter->style()->pageBreakAfter();
- EPageBreak pbbefore = breakBefore ? breakBefore->style()->pageBreakBefore() : PBALWAYS;
- if ((pbafter == PBAVOID && pbbefore == PBAVOID) ||
- (pbafter == PBAVOID && pbbefore == PBAUTO) ||
- (pbafter == PBAUTO && pbbefore == PBAVOID))
- {
- if (!pageRun) {
- pageRun = createAnonymousBlock();
- pageRun->m_avoidPageBreak = true;
- pageRun->setChildrenInline(false);
- }
- pageRun->appendChildNode(removeChildNode(breakAfter));
- } else
- {
- if (pageRun) {
- pageRun->appendChildNode(removeChildNode(breakAfter));
- pageRun->close();
- insertChildNode(pageRun, breakBefore);
- pageRun = 0;
- }
- }
- breakAfter = breakBefore;
- breakBefore = breakBefore ? breakBefore->nextSibling() : 0;
- }
-
- // recurse into positioned block children as well.
- if (m_positionedObjects) {
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- for ( ; it.current(); ++it ) {
- if (it.current()->isRenderBlock() && !it.current()->childrenInline()) {
- static_cast<RenderBlock*>(it.current())->makePageBreakAvoidBlocks();
- }
- }
- }
-
- // recurse into floating block children.
- if (m_floatingObjects) {
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; it.current(); ++it ) {
- if (it.current()->node->isRenderBlock() && !it.current()->node->childrenInline()) {
- static_cast<RenderBlock*>(it.current()->node)->makePageBreakAvoidBlocks();
- }
- }
- }
-}
-
-void RenderBlock::removeChild(RenderObject *oldChild)
-{
- // If this child is a block, and if our previous and next siblings are
- // both anonymous blocks with inline content, then we can go ahead and
- // fold the inline content back together.
- RenderObject* prev = oldChild->previousSibling();
- RenderObject* next = oldChild->nextSibling();
- bool mergedBlocks = false;
- if (document()->renderer() && !isInline() && !oldChild->isInline() && !oldChild->continuation() &&
- prev && prev->isAnonymousBlock() && prev->childrenInline() &&
- next && next->isAnonymousBlock() && next->childrenInline()) {
- // Take all the children out of the |next| block and put them in
- // the |prev| block.
- RenderObject* o = next->firstChild();
- while (o) {
- RenderObject* no = o;
- o = no->nextSibling();
- prev->appendChildNode(next->removeChildNode(no));
- no->setNeedsLayoutAndMinMaxRecalc();
- }
- prev->setNeedsLayoutAndMinMaxRecalc();
-
- // Nuke the now-empty block.
- next->detach();
-
- mergedBlocks = true;
- }
-
- RenderFlow::removeChild(oldChild);
-
- if (mergedBlocks && prev && !prev->previousSibling() && !prev->nextSibling()) {
- // The remerge has knocked us down to containing only a single anonymous
- // box. We can go ahead and pull the content right back up into our
- // box.
- RenderObject* anonBlock = removeChildNode(prev);
- m_childrenInline = true;
- RenderObject* o = anonBlock->firstChild();
- while (o) {
- RenderObject* no = o;
- o = no->nextSibling();
- appendChildNode(anonBlock->removeChildNode(no));
- no->setNeedsLayoutAndMinMaxRecalc();
- }
-
- // Nuke the now-empty block.
- anonBlock->detach();
- }
-}
-
-bool RenderBlock::isSelfCollapsingBlock() const
-{
- // We are not self-collapsing if we
- // (a) have a non-zero height according to layout (an optimization to avoid wasting time)
- // (b) are a table,
- // (c) have border/padding,
- // (d) have a min-height
- if (m_height > 0 ||
- isTable() || (borderBottom() + paddingBottom() + borderTop() + paddingTop()) != 0 ||
- style()->minHeight().value() > 0)
- return false;
-
- bool hasAutoHeight = style()->height().isVariable();
- if (style()->height().isPercent() && !style()->htmlHacks()) {
- hasAutoHeight = true;
- for (RenderBlock* cb = containingBlock(); !cb->isCanvas(); cb = cb->containingBlock()) {
- if (cb->style()->height().isFixed() || cb->isTableCell())
- hasAutoHeight = false;
- }
- }
-
- // If the height is 0 or auto, then whether or not we are a self-collapsing block depends
- // on whether we have content that is all self-collapsing or not.
- if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().value() == 0)) {
- // If the block has inline children, see if we generated any line boxes. If we have any
- // line boxes, then we can't be self-collapsing, since we have content.
- if (childrenInline())
- return !firstLineBox();
-
- // Whether or not we collapse is dependent on whether all our normal flow children
- // are also self-collapsing.
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isFloatingOrPositioned())
- continue;
- if (!child->isSelfCollapsingBlock())
- return false;
- }
- return true;
- }
- return false;
-}
-
-void RenderBlock::layout()
-{
- // Table cells call layoutBlock directly, so don't add any logic here. Put code into
- // layoutBlock().
- layoutBlock(false);
-}
-
-void RenderBlock::layoutBlock(bool relayoutChildren)
-{
- if (isInline() && !isReplacedBlock()) {
- setNeedsLayout(false);
- return;
- }
- // kdDebug( 6040 ) << renderName() << " " << this << "::layoutBlock() start" << endl;
- // TQTime t;
- // t.start();
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
-
- if (canvas()->pagedMode()) relayoutChildren = true;
-
- if (!relayoutChildren && posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {
- // All we have to is lay out our positioned objects.
- layoutPositionedObjects(relayoutChildren);
- if (hasOverflowClip())
- m_layer->checkScrollbarsAfterLayout();
- setNeedsLayout(false);
- return;
- }
-
- if (markedForRepaint()) {
- repaintDuringLayout();
- setMarkedForRepaint(false);
- }
-
- int oldWidth = m_width;
-
- calcWidth();
- m_overflowWidth = m_width;
- m_overflowLeft = 0;
- if (style()->direction() == LTR )
- {
- int cw=0;
- if (style()->textIndent().isPercent())
- cw = containingBlock()->contentWidth();
- m_overflowLeft = kMin(0, style()->textIndent().minWidth(cw));
- }
-
- if ( oldWidth != m_width )
- relayoutChildren = true;
-
- // kdDebug( 6040 ) << floatingObjects << "," << oldWidth << ","
- // << m_width << ","<< needsLayout() << "," << isAnonymousBox() << ","
- // << overhangingContents() << "," << isPositioned() << endl;
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(RenderBlock) " << this << " ::layout() width=" << m_width << ", needsLayout=" << needsLayout() << endl;
- if(containingBlock() == static_cast<RenderObject *>(this))
- kdDebug( 6040 ) << renderName() << ": containingBlock == this" << endl;
-#endif
-
- clearFloats();
-
- int previousHeight = m_height;
- m_height = 0;
- m_overflowHeight = 0;
- m_clearStatus = CNONE;
-
- // We use four values, maxTopPos, maxPosNeg, maxBottomPos, and maxBottomNeg, to track
- // our current maximal positive and negative margins. These values are used when we
- // are collapsed with adjacent blocks, so for example, if you have block A and B
- // collapsing together, then you'd take the maximal positive margin from both A and B
- // and subtract it from the maximal negative margin from both A and B to get the
- // true collapsed margin. This algorithm is recursive, so when we finish layout()
- // our block knows its current maximal positive/negative values.
- //
- // Start out by setting our margin values to our current margins. Table cells have
- // no margins, so we don't fill in the values for table cells.
- if (!isTableCell()) {
- initMaxMarginValues();
-
- m_topMarginQuirk = style()->marginTop().isQuirk();
- m_bottomMarginQuirk = style()->marginBottom().isQuirk();
-
- if (element() && element()->id() == ID_FORM && static_cast<HTMLFormElementImpl*>(element())->isMalformed())
- // See if this form is malformed (i.e., unclosed). If so, don't give the form
- // a bottom margin.
- m_maxBottomPosMargin = m_maxBottomNegMargin = 0;
- }
-
- if (scrollsOverflow() && m_layer) {
- // For overflow:scroll blocks, ensure we have both scrollbars in place always.
- if (style()->overflowX() == OSCROLL)
- m_layer->showScrollbar( Qt::Horizontal, true );
- if (style()->overflowY() == OSCROLL)
- m_layer->showScrollbar( Qt::Vertical, true );
- }
-
- setContainsPageBreak(false);
-
- if (childrenInline())
- layoutInlineChildren( relayoutChildren );
- else
- layoutBlockChildren( relayoutChildren );
-
- // Expand our intrinsic height to encompass floats.
- int toAdd = borderBottom() + paddingBottom();
- if (m_layer && scrollsOverflowX() && style()->height().isVariable())
- toAdd += m_layer->horizontalScrollbarHeight();
- if ( hasOverhangingFloats() && (isFloatingOrPositioned() || flowAroundFloats()) )
- m_overflowHeight = m_height = floatBottom() + toAdd;
-
- int oldHeight = m_height;
- calcHeight();
- if (oldHeight != m_height) {
- m_overflowHeight -= toAdd;
- if (m_layer && scrollsOverflowY()) {
- // overflow-height only includes padding-bottom when it scrolls
- m_overflowHeight += paddingBottom();
- }
- // If the block got expanded in size, then increase our overflowheight to match.
- if (m_overflowHeight < m_height)
- m_overflowHeight = m_height;
- }
- if (previousHeight != m_height)
- relayoutChildren = true;
-
- if (isTableCell()) {
- // Table cells need to grow to accommodate both overhanging floats and
- // blocks that have overflowed content.
- // Check for an overhanging float first.
- // FIXME: This needs to look at the last flow, not the last child.
- if (lastChild() && lastChild()->hasOverhangingFloats() && !lastChild()->hasOverflowClip()) {
- KHTMLAssert(lastChild()->isRenderBlock());
- m_height = lastChild()->yPos() + static_cast<RenderBlock*>(lastChild())->floatBottom();
- m_height += borderBottom() + paddingBottom();
- }
-
- if (m_overflowHeight > m_height && !hasOverflowClip())
- m_height = m_overflowHeight + borderBottom() + paddingBottom();
- }
-
- if( hasOverhangingFloats() && ((isFloating() && style()->height().isVariable()) || isTableCell())) {
- m_height = floatBottom();
- m_height += borderBottom() + paddingBottom();
- }
-
- if (canvas()->pagedMode()) {
-#ifdef PAGE_DEBUG
- kdDebug(6040) << renderName() << " Page Bottom: " << pageTopAfter(0) << endl;
- kdDebug(6040) << renderName() << " Bottom: " << m_height << endl;
-#endif
- bool needsPageBreak = false;
- int xpage = crossesPageBreak(0, m_height);
- if (xpage) {
- needsPageBreak = true;
-#ifdef PAGE_DEBUG
- kdDebug( 6040 ) << renderName() << " crosses to page " << xpage << endl;
-#endif
- }
- if (needsPageBreak && !containsPageBreak()) {
- setNeedsPageClear(true);
-#ifdef PAGE_DEBUG
- kdDebug( 6040 ) << renderName() << " marked for page-clear" << endl;
-#endif
- }
- }
-
- layoutPositionedObjects( relayoutChildren );
-
- // Always ensure our overflow width/height are at least as large as our width/height.
- m_overflowWidth = kMax(m_overflowWidth, (int)m_width);
- m_overflowHeight = kMax(m_overflowHeight, m_height);
-
- // Update our scrollbars if we're overflow:auto/scroll now that we know if
- // we overflow or not.
- if (hasOverflowClip() && m_layer)
- m_layer->checkScrollbarsAfterLayout();
-
- setNeedsLayout(false);
-}
-
-void RenderBlock::adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo)
-{
- if (child->isBox() && child->hasStaticX()) {
- if (style()->direction() == LTR)
- static_cast<RenderBox*>(child)->setStaticX(borderLeft() + paddingLeft());
- else
- static_cast<RenderBox*>(child)->setStaticX(borderRight() + paddingRight());
- }
-
- if (child->isBox() && child->hasStaticY()) {
- int y = m_height;
- if (!marginInfo.canCollapseWithTop()) {
- child->calcVerticalMargins();
- int marginTop = child->marginTop();
- int collapsedTopPos = marginInfo.posMargin();
- int collapsedTopNeg = marginInfo.negMargin();
- if (marginTop > 0) {
- if (marginTop > collapsedTopPos)
- collapsedTopPos = marginTop;
- } else {
- if (-marginTop > collapsedTopNeg)
- collapsedTopNeg = -marginTop;
- }
- y += (collapsedTopPos - collapsedTopNeg) - marginTop;
- }
- static_cast<RenderBox*>(child)->setStaticY(y);
- }
-}
-
-void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
-{
- // The float should be positioned taking into account the bottom margin
- // of the previous flow. We add that margin into the height, get the
- // float positioned properly, and then subtract the margin out of the
- // height again. In the case of self-collapsing blocks, we always just
- // use the top margins, since the self-collapsing block collapsed its
- // own bottom margin into its top margin.
- //
- // Note also that the previous flow may collapse its margin into the top of
- // our block. If this is the case, then we do not add the margin in to our
- // height when computing the position of the float. This condition can be tested
- // for by simply calling canCollapseWithTop. See
- // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
- // an example of this scenario.
- int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
- m_height += marginOffset;
- positionNewFloats();
- m_height -= marginOffset;
-}
-
-RenderObject* RenderBlock::handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled)
-{
- // Handle positioned children first.
- RenderObject* next = handlePositionedChild(child, marginInfo, handled);
- if (handled) return next;
-
- // Handle floating children next.
- next = handleFloatingChild(child, marginInfo, handled);
- if (handled) return next;
-
- // 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.
- next = handleCompactChild(child, compactInfo, marginInfo, handled);
- if (handled) return next;
-
- // Finally, see if we have a run-in element.
- return handleRunInChild(child, handled);
-}
-
-RenderObject* RenderBlock::handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
-{
- if (child->isPositioned()) {
- handled = true;
- child->containingBlock()->insertPositionedObject(child);
- adjustPositionedBlock(child, marginInfo);
- return child->nextSibling();
- }
- return 0;
-}
-
-RenderObject* RenderBlock::handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled)
-{
- if (child->isFloating()) {
- handled = true;
- insertFloatingObject(child);
- adjustFloatingBlock(marginInfo);
- return child->nextSibling();
- }
- return 0;
-}
-
-static inline bool isAnonymousWhitespace( RenderObject* o ) {
- if (!o->isAnonymous())
- return false;
- RenderObject *fc = o->firstChild();
- return fc && fc == o->lastChild() && fc->isText() && static_cast<RenderText *>(fc)->stringLength() == 1 &&
- static_cast<RenderText *>(fc)->text()[0].unicode() == ' ';
-}
-
-RenderObject* RenderBlock::handleCompactChild(RenderObject* child, CompactInfo& compactInfo, const MarginInfo& marginInfo, bool& handled)
-{
- // FIXME: We only deal with one compact at a time. It is unclear what should be
- // done if multiple contiguous compacts are encountered. For now we assume that
- // compact A followed by another compact B should simply be treated as block A.
- if (child->isCompact() && !compactInfo.compact() && (child->childrenInline() || child->isReplaced())) {
- // Get the next non-positioned/non-floating RenderBlock.
- RenderObject* next = child->nextSibling();
- RenderObject* curr = next;
- while (curr && (curr->isFloatingOrPositioned() || isAnonymousWhitespace(curr)) )
- curr = curr->nextSibling();
- if (curr && curr->isRenderBlock() && !curr->isCompact() && !curr->isRunIn()) {
- curr->calcWidth(); // So that horizontal margins are correct.
- // Need to compute margins for the child as though it is a block.
- child->style()->setDisplay(BLOCK);
- child->calcWidth();
- child->style()->setDisplay(COMPACT);
-
- int childMargins = child->marginLeft() + child->marginRight();
- int margin = style()->direction() == LTR ? curr->marginLeft() : curr->marginRight();
- if (margin >= (childMargins + child->maxWidth())) {
- // The compact will fit in the margin.
- handled = true;
- compactInfo.set(child, curr);
- child->layoutIfNeeded();
- int off = marginInfo.margin();
- m_height += off + curr->marginTop() < child->marginTop() ?
- child->marginTop() - curr->marginTop() -off: 0;
-
- child->setPos(0,0); // This position will be updated to reflect the compact's
- // desired position and the line box for the compact will
- // pick that position up.
- return next;
- }
- }
- }
- return 0;
-}
-
-void RenderBlock::adjustSizeForCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
-{
- // if the compact is bigger than the block it was run into
- // then "this" block should take the height of the compact
- if (compactInfo.matches(child)) {
- // We have a compact child to squeeze in.
- RenderObject* compactChild = compactInfo.compact();
- if (compactChild->height() > child->height())
- m_height += compactChild->height() - child->height();
- }
-}
-
-void RenderBlock::insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo)
-{
- if (compactInfo.matches(child)) {
- // We have a compact child to squeeze in.
- RenderObject* compactChild = compactInfo.compact();
- int compactXPos = borderLeft() + paddingLeft() + compactChild->marginLeft();
- if (style()->direction() == RTL) {
- compactChild->calcWidth(); // have to do this because of the capped maxwidth
- compactXPos = width() - borderRight() - paddingRight() -
- compactChild->width() - compactChild->marginRight();
- }
-
- int compactYPos = child->yPos() + child->borderTop() + child->paddingTop()
- - compactChild->paddingTop() - compactChild->borderTop();
- int adj = 0;
- KHTMLAssert(child->isRenderBlock());
- InlineRunBox *b = static_cast<RenderBlock*>(child)->firstLineBox();
- InlineRunBox *c = static_cast<RenderBlock*>(compactChild)->firstLineBox();
- if (b && c) {
- // adjust our vertical position
- int vpos = compactChild->getVerticalPosition( true, child );
- if (vpos == PositionBottom)
- adj = b->height() > c->height() ? (b->height() + b->yPos() - c->height() - c->yPos()) : 0;
- else if (vpos == PositionTop)
- adj = b->yPos() - c->yPos();
- else
- adj = vpos;
- compactYPos += adj;
- }
- Length newLineHeight( kMax(compactChild->lineHeight(true)+adj, (int)child->lineHeight(true)), khtml::Fixed);
- child->style()->setLineHeight( newLineHeight );
- child->setNeedsLayout( true, false );
- child->layout();
-
- compactChild->setPos(compactXPos, compactYPos); // Set the x position.
- compactInfo.clear();
- }
-}
-
-RenderObject* RenderBlock::handleRunInChild(RenderObject* child, bool& handled)
-{
- // See if we have a run-in element with inline children. If the
- // children aren't inline, then just treat the run-in as a normal
- // block.
- if (child->isRunIn() && (child->childrenInline() || child->isReplaced())) {
- // Get the next non-positioned/non-floating RenderBlock.
- RenderObject* curr = child->nextSibling();
- while (curr && (curr->isFloatingOrPositioned() || isAnonymousWhitespace(curr)) )
- curr = curr->nextSibling();
- if (curr && (curr->isRenderBlock() && curr->childrenInline() && !curr->isCompact() && !curr->isRunIn())) {
- // The block acts like an inline, so just null out its
- // position.
- handled = true;
- child->setInline(true);
- child->setPos(0,0);
-
- // Remove the child.
- RenderObject* next = child->nextSibling();
- removeChildNode(child);
-
- // Now insert the child under |curr|.
- curr->insertChildNode(child, curr->firstChild());
- return next;
- }
- }
- return 0;
-}
-
-void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate)
-{
- // Get our max pos and neg top margins.
- int posTop = child->maxTopMargin(true);
- int negTop = child->maxTopMargin(false);
-
- // For self-collapsing blocks, collapse our bottom margins into our
- // top to get new posTop and negTop values.
- if (child->isSelfCollapsingBlock()) {
- posTop = kMax(posTop, (int)child->maxBottomMargin(true));
- negTop = kMax(negTop, (int)child->maxBottomMargin(false));
- }
-
- // See if the top margin is quirky. We only care if this child has
- // margins that will collapse with us.
- bool topQuirk = child->isTopMarginQuirk() /*|| style()->marginTopCollapse() == MDISCARD*/;
-
- if (marginInfo.canCollapseWithTop()) {
- // This child is collapsing with the top of the
- // block. If it has larger margin values, then we need to update
- // our own maximal values.
- if (!style()->htmlHacks() || !marginInfo.quirkContainer() || !topQuirk) {
- m_maxTopPosMargin = kMax(posTop, (int)m_maxTopPosMargin);
- m_maxTopNegMargin = kMax(negTop, (int)m_maxTopNegMargin);
- }
-
- // The minute any of the margins involved isn't a quirk, don't
- // collapse it away, even if the margin is smaller (www.webreference.com
- // has an example of this, a <dt> with 0.8em author-specified inside
- // a <dl> inside a <td>.
- if (!marginInfo.determinedTopQuirk() && !topQuirk && (posTop-negTop)) {
- m_topMarginQuirk = false;
- marginInfo.setDeterminedTopQuirk(true);
- }
-
- if (!marginInfo.determinedTopQuirk() && topQuirk && marginTop() == 0)
- // We have no top margin and our top child has a quirky margin.
- // We will pick up this quirky margin and pass it through.
- // This deals with the <td><div><p> case.
- // Don't do this for a block that split two inlines though. You do
- // still apply margins in this case.
- m_topMarginQuirk = true;
- }
-
- if (marginInfo.quirkContainer() && marginInfo.atTopOfBlock() && (posTop - negTop))
- marginInfo.setTopQuirk(topQuirk);
-
- int ypos = m_height;
- if (child->isSelfCollapsingBlock()) {
- // This child has no height. We need to compute our
- // position before we collapse the child's margins together,
- // so that we can get an accurate position for the zero-height block.
- int collapsedTopPos = kMax(marginInfo.posMargin(), (int)child->maxTopMargin(true));
- int collapsedTopNeg = kMax(marginInfo.negMargin(), (int)child->maxTopMargin(false));
- marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
-
- // Now collapse the child's margins together, which means examining our
- // bottom margin values as well.
- marginInfo.setPosMarginIfLarger(child->maxBottomMargin(true));
- marginInfo.setNegMarginIfLarger(child->maxBottomMargin(false));
-
- if (!marginInfo.canCollapseWithTop())
- // We need to make sure that the position of the self-collapsing block
- // is correct, since it could have overflowing content
- // that needs to be positioned correctly (e.g., a block that
- // had a specified height of 0 but that actually had subcontent).
- ypos = m_height + collapsedTopPos - collapsedTopNeg;
- }
- else {
-#ifdef APPLE_CHANGES
- if (child->style()->marginTopCollapse() == MSEPARATE) {
- m_height += marginInfo.margin() + child->marginTop();
- ypos = m_height;
- }
- else
-#endif
- if (!marginInfo.atTopOfBlock() ||
- (!marginInfo.canCollapseTopWithChildren()
- && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.topQuirk()))) {
- // We're collapsing with a previous sibling's margins and not
- // with the top of the block.
- m_height += kMax(marginInfo.posMargin(), posTop) - kMax(marginInfo.negMargin(), negTop);
- ypos = m_height;
- }
-
- marginInfo.setPosMargin(child->maxBottomMargin(true));
- marginInfo.setNegMargin(child->maxBottomMargin(false));
-
- if (marginInfo.margin())
- marginInfo.setBottomQuirk(child->isBottomMarginQuirk() /*|| style()->marginBottomCollapse() == MDISCARD*/);
-
- marginInfo.setSelfCollapsingBlockClearedFloat(false);
- }
-
- child->setPos(child->xPos(), ypos);
- if (ypos != yPosEstimate) {
- if (child->style()->width().isPercent() && child->usesLineWidth())
- // The child's width is a percentage of the line width.
- // When the child shifts to clear an item, its width can
- // change (because it has more available line width).
- // So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true);
-
- if (!child->flowAroundFloats() && child->hasFloats())
- child->markAllDescendantsWithFloatsForLayout();
-
- // Our guess was wrong. Make the child lay itself out again.
- child->layoutIfNeeded();
- }
-}
-
-void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin)
-{
- int heightIncrease = getClearDelta(child);
- if (heightIncrease) {
- // The child needs to be lowered. Move the child so that it just clears the float.
- child->setPos(child->xPos(), child->yPos() + heightIncrease);
-
- // Increase our height by the amount we had to clear.
- bool selfCollapsing = child->isSelfCollapsingBlock();
- if (!selfCollapsing)
- m_height += heightIncrease;
- else {
- // For self-collapsing blocks that clear, they may end up collapsing
- // into the bottom of the parent block. We simulate this behavior by
- // setting our positive margin value to compensate for the clear.
- marginInfo.setPosMargin(kMax(0, child->yPos() - m_height));
- marginInfo.setNegMargin(0);
- marginInfo.setSelfCollapsingBlockClearedFloat(true);
- }
-
- if (marginInfo.canCollapseWithTop()) {
- // We can no longer collapse with the top of the block since a clear
- // occurred. The empty blocks collapse into the cleared block.
- // FIXME: This isn't quite correct. Need clarification for what to do
- // if the height the cleared block is offset by is smaller than the
- // margins involved.
- m_maxTopPosMargin = oldTopPosMargin;
- m_maxTopNegMargin = oldTopNegMargin;
- marginInfo.setAtTopOfBlock(false);
- }
-
- // If our value of clear caused us to be repositioned vertically to be
- // underneath a float, we might have to do another layout to take into account
- // the extra space we now have available.
- if (!selfCollapsing && !child->style()->width().isFixed() && child->usesLineWidth())
- // The child's width is a percentage of the line width.
- // When the child shifts to clear an item, its width can
- // change (because it has more available line width).
- // So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true);
- if (!child->flowAroundFloats() && child->hasFloats())
- child->markAllDescendantsWithFloatsForLayout();
- child->layoutIfNeeded();
- }
-}
-
-bool RenderBlock::canClear(RenderObject *child, PageBreakLevel level)
-{
- KHTMLAssert(child->parent() && child->parent() == this);
- KHTMLAssert(canvas()->pagedMode());
-
- // Positioned elements cannot be moved. Only normal flow and floating.
- if (child->isPositioned() || child->isRelPositioned()) return false;
-
- switch(level) {
- case PageBreakNormal:
- // check page-break-inside: avoid
- if (!style()->pageBreakInside())
- // we cannot, but can our parent?
- if(!parent()->canClear(this, level)) return false;
- case PageBreakHarder:
- // check page-break-after/before: avoid
- if (m_avoidPageBreak)
- // we cannot, but can our parent?
- if(!parent()->canClear(this, level)) return false;
- case PageBreakForced:
- // child is larger than page-height and is forced to break
- if(child->height() > canvas()->pageHeight()) return false;
- return true;
- }
- assert(false);
- return false;
-}
-
-void RenderBlock::clearPageBreak(RenderObject* child, int pageBottom)
-{
- KHTMLAssert(child->parent() && child->parent() == this);
- KHTMLAssert(canvas()->pagedMode());
-
- if (child->yPos() >= pageBottom) return;
-
- int heightIncrease = 0;
-
- heightIncrease = pageBottom - child->yPos();
-
- // ### should never happen, canClear should have been called to detect it.
- if (child->height() > canvas()->pageHeight()) {
- kdDebug(6040) << "### child is too large to clear: " << child->height() << " > " << canvas()->pageHeight() << endl;
- return;
- }
-
- // The child needs to be lowered. Move the child so that it just clears the break.
- child->setPos(child->xPos(), pageBottom);
-
-#ifdef PAGE_DEBUG
- kdDebug(6040) << "Cleared block " << heightIncrease << "px" << endl;
-#endif
-
- // Increase our height by the amount we had to clear.
- m_height += heightIncrease;
-
- // We might have to do another layout to take into account
- // the extra space we now have available.
- if (!child->style()->width().isFixed() && child->usesLineWidth())
- // The child's width is a percentage of the line width.
- // When the child shifts to clear a page-break, its width can
- // change (because it has more available line width).
- // So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true);
- if (!child->flowAroundFloats() && child->hasFloats())
- child->markAllDescendantsWithFloatsForLayout();
- if (child->containsPageBreak())
- child->setNeedsLayout(true);
- child->layoutIfNeeded();
-
- child->setAfterPageBreak(true);
-}
-
-int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo& marginInfo)
-{
- // FIXME: We need to eliminate the estimation of vertical position, because
- // when it's wrong we sometimes trigger a pathological relayout if there are
- // intruding floats.
- int yPosEstimate = m_height;
- if (!marginInfo.canCollapseWithTop()) {
- int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();
- yPosEstimate += kMax(marginInfo.margin(), childMarginTop);
- }
- return yPosEstimate;
-}
-
-void RenderBlock::determineHorizontalPosition(RenderObject* child)
-{
- if (style()->direction() == LTR) {
- int xPos = borderLeft() + paddingLeft();
-
- // Add in our left margin.
- int chPos = xPos + child->marginLeft();
-
- // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
- // to shift over as necessary to dodge any floats that might get in the way.
- if (child->flowAroundFloats()) {
- int leftOff = leftOffset(m_height);
- if (style()->textAlign() != KHTML_CENTER && !child->style()->marginLeft().isVariable()) {
- if (child->marginLeft() < 0)
- leftOff += child->marginLeft();
- chPos = kMax(chPos, leftOff); // Let the float sit in the child's margin if it can fit.
- }
- else if (leftOff != xPos) {
- // The object is shifting right. The object might be centered, so we need to
- // recalculate our horizontal margins. Note that the containing block content
- // width computation will take into account the delta between |leftOff| and |xPos|
- // so that we can just pass the content width in directly to the |calcHorizontalMargins|
- // function.
- static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
- chPos = leftOff + child->marginLeft();
- }
- }
-
- child->setPos(chPos, child->yPos());
- } else {
- int xPos = m_width - borderRight() - paddingRight();
- if (m_layer && scrollsOverflowY())
- xPos -= m_layer->verticalScrollbarWidth();
- int chPos = xPos - (child->width() + child->marginRight());
- if (child->flowAroundFloats()) {
- int rightOff = rightOffset(m_height);
- if (style()->textAlign() != KHTML_CENTER && !child->style()->marginRight().isVariable()) {
- if (child->marginRight() < 0)
- rightOff -= child->marginRight();
- chPos = kMin(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit.
- } else if (rightOff != xPos) {
- // The object is shifting left. The object might be centered, so we need to
- // recalculate our horizontal margins. Note that the containing block content
- // width computation will take into account the delta between |rightOff| and |xPos|
- // so that we can just pass the content width in directly to the |calcHorizontalMargins|
- // function.
- static_cast<RenderBox*>(child)->calcHorizontalMargins(child->style()->marginLeft(), child->style()->marginRight(), lineWidth(child->yPos()));
- chPos = rightOff - child->marginRight() - child->width();
- }
- }
- child->setPos(chPos, child->yPos());
- }
-}
-
-void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
-{
- if (marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()) {
- // Update our max pos/neg bottom margins, since we collapsed our bottom margins
- // with our children.
- m_maxBottomPosMargin = kMax((int)m_maxBottomPosMargin, marginInfo.posMargin());
- m_maxBottomNegMargin = kMax((int)m_maxBottomNegMargin, marginInfo.negMargin());
-
- if (!marginInfo.bottomQuirk())
- m_bottomMarginQuirk = false;
-
- if (marginInfo.bottomQuirk() && marginBottom() == 0)
- // We have no bottom margin and our last child has a quirky margin.
- // We will pick up this quirky margin and pass it through.
- // This deals with the <td><div><p> case.
- m_bottomMarginQuirk = true;
- }
-}
-
-void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
-{
- // If our last flow was a self-collapsing block that cleared a float, then we don't
- // collapse it with the bottom of the block.
- if (!marginInfo.selfCollapsingBlockClearedFloat())
- marginInfo.setAtBottomOfBlock(true);
-
- // If we can't collapse with children then go ahead and add in the bottom margin.
- if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()
- && (!style()->htmlHacks() || !marginInfo.quirkContainer() || !marginInfo.bottomQuirk()))
- m_height += marginInfo.margin();
-
- // Now add in our bottom border/padding.
- m_height += bottom;
-
- // Negative margins can cause our height to shrink below our minimal height (border/padding).
- // If this happens, ensure that the computed height is increased to the minimal height.
- m_height = kMax(m_height, top + bottom);
-
- // Always make sure our overflow height is at least our height.
- m_overflowHeight = kMax(m_height, m_overflowHeight);
-
- // Update our bottom collapsed margin info.
- setCollapsedBottomMargin(marginInfo);
-}
-
-void RenderBlock::layoutBlockChildren( bool relayoutChildren )
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << " layoutBlockChildren( " << this <<" ), relayoutChildren="<< relayoutChildren << endl;
-#endif
-
- int top = borderTop() + paddingTop();
- int bottom = borderBottom() + paddingBottom();
- if (m_layer && scrollsOverflowX() && style()->height().isVariable())
- bottom += m_layer->horizontalScrollbarHeight();
-
- m_height = m_overflowHeight = top;
-
- // The margin struct caches all our current margin collapsing state.
- // The compact struct caches state when we encounter compacts.
- MarginInfo marginInfo(this, top, bottom);
- CompactInfo compactInfo;
-
- // Fieldsets need to find their legend and position it inside the border of the object.
- // The legend then gets skipped during normal layout.
- RenderObject* legend = layoutLegend(relayoutChildren);
-
- PageBreakInfo pageBreakInfo(pageTopAfter(0));
-
- RenderObject* child = firstChild();
- while( child != 0 )
- {
- if (legend == child) {
- child = child->nextSibling();
- continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
- }
-
- int oldTopPosMargin = m_maxTopPosMargin;
- int oldTopNegMargin = m_maxTopNegMargin;
-
- // make sure we relayout children if we need it.
- if (!child->isPositioned() && (relayoutChildren ||
- (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())) ||
- (child->isRenderBlock() && child->style()->height().isPercent()) ||
- (child->isBody() && child->style()->htmlHacks())))
- {
- child->setChildNeedsLayout(true);
- }
-
- // Handle the four types of special elements first. These include positioned content, floating content, compacts and
- // run-ins. When we encounter these four types of objects, we don't actually lay them out as normal flow blocks.
- bool handled = false;
- RenderObject* next = handleSpecialChild(child, marginInfo, compactInfo, handled);
- if (handled) { child = next; continue; }
-
- // The child is a normal flow object. Compute its vertical margins now.
- child->calcVerticalMargins();
-
-#ifdef APPLE_CHANGES /* margin-*-collapse not merged yet */
- // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
- if (child->style()->marginTopCollapse() == MSEPARATE) {
- marginInfo.setAtTopOfBlock(false);
- marginInfo.clearMargin();
- }
-#endif
-
- // Try to guess our correct y position. In most cases this guess will
- // be correct. Only if we're wrong (when we compute the real y position)
- // will we have to potentially relayout.
- int yPosEstimate = estimateVerticalPosition(child, marginInfo);
-
- // If an element might be affected by the presence of floats, then always mark it for
- // layout.
- if ( !child->flowAroundFloats() || child->usesLineWidth() ) {
- int fb = floatBottom();
- if (fb > m_height || fb > yPosEstimate)
- child->setChildNeedsLayout(true);
- }
-
- // Go ahead and position the child as though it didn't collapse with the top.
- child->setPos(child->xPos(), yPosEstimate);
- child->layoutIfNeeded();
-
- // Now determine the correct ypos based on examination of collapsing margin
- // values.
- collapseMargins(child, marginInfo, yPosEstimate);
-
- // Now check for clear.
- clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin);
-
- // We are no longer at the top of the block if we encounter a non-empty child.
- // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
- if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
- marginInfo.setAtTopOfBlock(false);
-
- // Now place the child in the correct horizontal position
- determineHorizontalPosition(child);
-
- adjustSizeForCompactIfNeeded(child, compactInfo);
- // Update our height now that the child has been placed in the correct position.
- m_height += child->height();
-
-#ifdef APPLE_CHANGES
- if (child->style()->marginBottomCollapse() == MSEPARATE) {
- m_height += child->marginBottom();
- marginInfo.clearMargin();
- }
-#endif
-
- // Check for page-breaks
- if (canvas()->pagedMode())
- clearChildOfPageBreaks(child, pageBreakInfo, marginInfo);
-
- if (child->hasOverhangingFloats() && !child->flowAroundFloats()) {
- // need to add the child's floats to our floating objects list, but not in the case where
- // overflow is auto/scroll
- addOverHangingFloats( static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos(), true );
- }
-
- // See if this child has made our overflow need to grow.
- int effX = child->effectiveXPos();
- int effY = child->effectiveYPos();
- m_overflowWidth = kMax(effX + child->effectiveWidth(), m_overflowWidth);
- m_overflowLeft = kMin(effX, m_overflowLeft);
- m_overflowHeight = kMax(effY + child->effectiveHeight(), m_overflowHeight);
- m_overflowTop = kMin(effY, m_overflowTop);
-
- // Insert our compact into the block margin if we have one.
- insertCompactIfNeeded(child, compactInfo);
-
- child = child->nextSibling();
- }
-
- // The last child had forced page-break-after
- if (pageBreakInfo.forcePageBreak())
- m_height = pageBreakInfo.pageBottom();
-
- // Now do the handling of the bottom of the block, adding in our bottom border/padding and
- // determining the correct collapsed bottom margin information.
- handleBottomOfBlock(top, bottom, marginInfo);
-
- setNeedsLayout(false);
-}
-
-void RenderBlock::clearChildOfPageBreaks(RenderObject *child, PageBreakInfo &pageBreakInfo, MarginInfo &marginInfo)
-{
- (void)marginInfo;
- int childTop = child->yPos();
- int childBottom = child->yPos()+child->height();
-#ifdef PAGE_DEBUG
- kdDebug(6040) << renderName() << " ChildTop: " << childTop << " ChildBottom: " << childBottom << endl;
-#endif
-
- bool forcePageBreak = pageBreakInfo.forcePageBreak() || child->style()->pageBreakBefore() == PBALWAYS;
-#ifdef PAGE_DEBUG
- if (forcePageBreak)
- kdDebug(6040) << renderName() << "Forced break required" << endl;
-#endif
-
- int xpage = crossesPageBreak(childTop, childBottom);
- if (xpage || forcePageBreak)
- {
- if (!forcePageBreak && child->containsPageBreak() && !child->needsPageClear()) {
-#ifdef PAGE_DEBUG
- kdDebug(6040) << renderName() << " Child contains page-break to page " << xpage << endl;
-#endif
- // ### Actually this assumes floating children are breaking/clearing
- // nicely as well.
- setContainsPageBreak(true);
- }
- else {
- bool doBreak = true;
- // don't break before the first child or when page-break-inside is avoid
- if (!forcePageBreak && (!style()->pageBreakInside() || m_avoidPageBreak || child == firstChild())) {
- if (parent()->canClear(this, (m_avoidPageBreak) ? PageBreakHarder : PageBreakNormal )) {
-#ifdef PAGE_DEBUG
- kdDebug(6040) << renderName() << "Avoid page-break inside" << endl;
-#endif
- child->setNeedsPageClear(false);
- setNeedsPageClear(true);
- doBreak = false;
- }
-#ifdef PAGE_DEBUG
- else
- kdDebug(6040) << renderName() << "Ignoring page-break avoid" << endl;
-#endif
- }
- if (doBreak) {
-#ifdef PAGE_DEBUG
- kdDebug(6040) << renderName() << " Clearing child of page-break" << endl;
- kdDebug(6040) << renderName() << " child top of page " << xpage << endl;
-#endif
- clearPageBreak(child, pageBreakInfo.pageBottom());
- child->setNeedsPageClear(false);
- setContainsPageBreak(true);
- }
- }
- pageBreakInfo.setPageBottom(pageBreakInfo.pageBottom() + canvas()->pageHeight());
- }
- else
- if (child->yPos() >= pageBreakInfo.pageBottom()) {
- bool doBreak = true;
-#ifdef PAGE_DEBUG
- kdDebug(6040) << "Page-break between children" << endl;
-#endif
- if (!style()->pageBreakInside() || m_avoidPageBreak) {
- if(parent()->canClear(this, (m_avoidPageBreak) ? PageBreakHarder : PageBreakNormal )) {
-#ifdef PAGE_DEBUG
- kdDebug(6040) << "Avoid page-break inside" << endl;
-#endif
- child->setNeedsPageClear(false);
- setNeedsPageClear(true);
- doBreak = false;
- }
-#ifdef PAGE_DEBUG
- else
- kdDebug(6040) << "Ignoring page-break avoid" << endl;
-#endif
- }
- if (doBreak) {
- // Break between children
- setContainsPageBreak(true);
- // ### Should collapse top-margin with page-margin
- }
- pageBreakInfo.setPageBottom(pageBreakInfo.pageBottom() + canvas()->pageHeight());
- }
-
- // Do we need a forced page-break before next child?
- pageBreakInfo.setForcePageBreak(false);
- if (child->style()->pageBreakAfter() == PBALWAYS)
- pageBreakInfo.setForcePageBreak(true);
-}
-
-void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
-{
- if (m_positionedObjects) {
- //kdDebug( 6040 ) << renderName() << " " << this << "::layoutPositionedObjects() start" << endl;
- RenderObject* r;
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- for ( ; (r = it.current()); ++it ) {
- //kdDebug(6040) << " have a positioned object" << endl;
- if (r->markedForRepaint()) {
- r->repaintDuringLayout();
- r->setMarkedForRepaint(false);
- }
- if ( relayoutChildren || r->style()->position() == FIXED ||
- ((r->hasStaticY()||r->hasStaticX()) && r->parent() != this && r->parent()->isBlockFlow()) ) {
- r->setChildNeedsLayout(true);
- r->dirtyFormattingContext(false);
- }
- r->layoutIfNeeded();
- }
- }
-}
-
-void RenderBlock::paint(PaintInfo& pI, int _tx, int _ty)
-{
- _tx += m_x;
- _ty += m_y;
-
- // check if we need to do anything at all...
- if (!isRoot() && !isInlineFlow() && !overhangingContents() && !isRelPositioned() && !isPositioned() )
- {
- int h = m_overflowHeight;
- int yPos = _ty;
- if (m_floatingObjects && floatBottom() > h)
- h = floatBottom();
-
- yPos += overflowTop();
-
- int os = maximalOutlineSize(pI.phase);
- if( (yPos > pI.r.bottom() + os) || (_ty + h <= pI.r.y() - os))
- return;
- }
-
- paintObject(pI, _tx, _ty);
-}
-
-void RenderBlock::paintObject(PaintInfo& pI, int _tx, int _ty, bool shouldPaintOutline)
-{
-#ifdef DEBUG_LAYOUT
- //kdDebug( 6040 ) << renderName() << "(RenderBlock) " << this << " ::paintObject() w/h = (" << width() << "/" << height() << ")" << endl;
-#endif
-
- // If we're a repositioned run-in, don't paint background/borders.
- bool inlineFlow = isInlineFlow();
-
- // 1. paint background, borders etc
- if (!inlineFlow &&
- (pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground ) &&
- shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE)
- paintBoxDecorations(pI, _tx, _ty);
-
- if ( pI.phase == PaintActionElementBackground )
- return;
- if ( pI.phase == PaintActionChildBackgrounds )
- pI.phase = PaintActionChildBackground;
-
- // 2. paint contents
- int scrolledX = _tx;
- int scrolledY = _ty;
- if (hasOverflowClip() && m_layer)
- m_layer->subtractScrollOffset(scrolledX, scrolledY);
-
- if (childrenInline())
- paintLines(pI, scrolledX, scrolledY);
- else {
- for(RenderObject *child = firstChild(); child; child = child->nextSibling())
- if(!child->layer() && !child->isFloating())
- child->paint(pI, scrolledX, scrolledY);
- }
-
- // 3. paint floats.
- if (!inlineFlow && (pI.phase == PaintActionFloat || pI.phase == PaintActionSelection))
- paintFloats(pI, scrolledX, scrolledY, pI.phase == PaintActionSelection);
-
- // 4. paint outline.
- if (shouldPaintOutline && !inlineFlow && pI.phase == PaintActionOutline &&
- style()->outlineWidth() && style()->visibility() == VISIBLE)
- paintOutline(pI.p, _tx, _ty, width(), height(), style());
-
-#ifdef BOX_DEBUG
- if ( style() && style()->visibility() == VISIBLE ) {
- if(isAnonymous())
- outlineBox(pI.p, _tx, _ty, "green");
- if(isFloating())
- outlineBox(pI.p, _tx, _ty, "yellow");
- else
- outlineBox(pI.p, _tx, _ty);
- }
-#endif
-}
-
-void RenderBlock::paintFloats(PaintInfo& pI, int _tx, int _ty, bool paintSelection)
-{
- if (!m_floatingObjects)
- return;
-
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it) {
- // Only paint the object if our noPaint flag isn't set.
- if (r->node->isFloating() && !r->noPaint && !r->node->layer()) {
- PaintAction oldphase = pI.phase;
- if (paintSelection) {
- pI.phase = PaintActionSelection;
- r->node->paint(pI, _tx + r->left - r->node->xPos() + r->node->marginLeft(),
- _ty + r->startY - r->node->yPos() + r->node->marginTop());
- }
- else {
- pI.phase = PaintActionElementBackground;
- r->node->paint(pI,
- _tx + r->left - r->node->xPos() + r->node->marginLeft(),
- _ty + r->startY - r->node->yPos() + r->node->marginTop());
- pI.phase = PaintActionChildBackgrounds;
- r->node->paint(pI,
- _tx + r->left - r->node->xPos() + r->node->marginLeft(),
- _ty + r->startY - r->node->yPos() + r->node->marginTop());
- pI.phase = PaintActionFloat;
- r->node->paint(pI,
- _tx + r->left - r->node->xPos() + r->node->marginLeft(),
- _ty + r->startY - r->node->yPos() + r->node->marginTop());
- pI.phase = PaintActionForeground;
- r->node->paint(pI,
- _tx + r->left - r->node->xPos() + r->node->marginLeft(),
- _ty + r->startY - r->node->yPos() + r->node->marginTop());
- pI.phase = PaintActionOutline;
- r->node->paint(pI,
- _tx + r->left - r->node->xPos() + r->node->marginLeft(),
- _ty + r->startY - r->node->yPos() + r->node->marginTop());
- }
- pI.phase = oldphase;
- }
- }
-}
-
-void RenderBlock::insertPositionedObject(RenderObject *o)
-{
- // Create the list of special objects if we don't aleady have one
- if (!m_positionedObjects) {
- m_positionedObjects = new TQPtrList<RenderObject>;
- m_positionedObjects->setAutoDelete(false);
- }
- else {
- // Don't insert the object again if it's already in the list
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- RenderObject* f;
- while ( (f = it.current()) ) {
- if (f == o) return;
- ++it;
- }
- }
-
- // Create the special object entry & append it to the list
- setOverhangingContents();
- m_positionedObjects->append(o);
-}
-
-void RenderBlock::removePositionedObject(RenderObject *o)
-{
- if (m_positionedObjects) {
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- while (it.current()) {
- if (it.current() == o)
- m_positionedObjects->removeRef(it.current());
- ++it;
- }
- if (m_positionedObjects->isEmpty()) {
- delete m_positionedObjects;
- m_positionedObjects = 0;
- }
- }
-}
-
-void RenderBlock::insertFloatingObject(RenderObject *o)
-{
- // Create the list of special objects if we don't aleady have one
- if (!m_floatingObjects) {
- m_floatingObjects = new TQPtrList<FloatingObject>;
- m_floatingObjects->setAutoDelete(true);
- }
- else {
- // Don't insert the object again if it's already in the list
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- FloatingObject* f;
- while ( (f = it.current()) ) {
- if (f->node == o) return;
- ++it;
- }
- }
-
- // Create the special object entry & append it to the list
-
- FloatingObject *newObj;
- if (o->isFloating()) {
- // floating object
- o->layoutIfNeeded();
-
- if(o->style()->floating() & FLEFT)
- newObj = new FloatingObject(FloatingObject::FloatLeft);
- else
- newObj = new FloatingObject(FloatingObject::FloatRight);
-
- newObj->startY = -500000;
- newObj->endY = -500000;
- newObj->width = o->width() + o->marginLeft() + o->marginRight();
- }
- else {
- // We should never get here, as insertFloatingObject() should only ever be called with floating
- // objects.
- KHTMLAssert(false);
- newObj = 0; // keep gcc's uninitialized variable warnings happy
- }
-
- newObj->node = o;
-
- m_floatingObjects->append(newObj);
-}
-
-void RenderBlock::removeFloatingObject(RenderObject *o)
-{
- if (m_floatingObjects) {
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- while (it.current()) {
- if (it.current()->node == o)
- m_floatingObjects->removeRef(it.current());
- ++it;
- }
- }
-}
-
-void RenderBlock::positionNewFloats()
-{
- if(!m_floatingObjects) return;
- FloatingObject *f = m_floatingObjects->getLast();
- if(!f || f->startY != -500000) return;
- FloatingObject *lastFloat;
- while(1)
- {
- lastFloat = m_floatingObjects->prev();
- if (!lastFloat || lastFloat->startY != -500000) {
- m_floatingObjects->next();
- break;
- }
- f = lastFloat;
- }
-
- int y = m_height;
-
-
- // the float can not start above the y position of the last positioned float.
- if(lastFloat && lastFloat->startY > y)
- y = lastFloat->startY;
-
- while(f)
- {
- //skip elements copied from elsewhere and positioned elements
- if (f->node->containingBlock()!=this)
- {
- f = m_floatingObjects->next();
- continue;
- }
-
- RenderObject *o = f->node;
- int _height = o->height() + o->marginTop() + o->marginBottom();
-
- // floats avoid page-breaks
- if(canvas()->pagedMode())
- {
- int top = y;
- int bottom = y + o->height();
- if (crossesPageBreak(top, bottom) && o->height() < canvas()->pageHeight() ) {
- int newY = pageTopAfter(top);
-#ifdef PAGE_DEBUG
- kdDebug(6040) << renderName() << " clearing float " << newY - y << "px" << endl;
-#endif
- y = newY;
- }
- }
-
- int ro = rightOffset(); // Constant part of right offset.
- int lo = leftOffset(); // Constant part of left offset.
- int fwidth = f->width; // The width we look for.
- //kdDebug( 6040 ) << " Object width: " << fwidth << " available width: " << ro - lo << endl;
-
- // in quirk mode, floated auto-width tables try to fit within remaining linewidth
- bool ftQuirk = o->isTable() && style()->htmlHacks() && o->style()->width().isVariable();
- if (ftQuirk)
- fwidth = kMin( o->minWidth()+o->marginLeft()+o->marginRight(), fwidth );
-
- if (ro - lo < fwidth)
- fwidth = ro - lo; // Never look for more than what will be available.
-
- if ( o->style()->clear() & CLEFT )
- y = kMax( leftBottom(), y );
- if ( o->style()->clear() & CRIGHT )
- y = kMax( rightBottom(), y );
-
- bool canClearLine;
- if (o->style()->floating() & FLEFT)
- {
- int heightRemainingLeft = 1;
- int heightRemainingRight = 1;
- int fx = leftRelOffset(y,lo, false, &heightRemainingLeft, &canClearLine);
- if (canClearLine)
- {
- while (rightRelOffset(y,ro, false, &heightRemainingRight)-fx < fwidth)
- {
- y += kMin( heightRemainingLeft, heightRemainingRight );
- fx = leftRelOffset(y,lo, false, &heightRemainingLeft);
- }
- }
- if (ftQuirk && (rightRelOffset(y,ro, false)-fx < f->width)) {
- o->setPos( o->xPos(), y + o->marginTop() );
- o->setChildNeedsLayout(true, false);
- o->layoutIfNeeded();
- _height = o->height() + o->marginTop() + o->marginBottom();
- f->width = o->width() + o->marginLeft() + o->marginRight();
- }
- f->left = fx;
- //kdDebug( 6040 ) << "positioning left aligned float at (" << fx + o->marginLeft() << "/" << y + o->marginTop() << ") fx=" << fx << endl;
- o->setPos(fx + o->marginLeft(), y + o->marginTop());
- }
- else
- {
- int heightRemainingLeft = 1;
- int heightRemainingRight = 1;
- int fx = rightRelOffset(y,ro, false, &heightRemainingRight, &canClearLine);
- if (canClearLine)
- {
- while (fx - leftRelOffset(y,lo, false, &heightRemainingLeft) < fwidth)
- {
- y += kMin(heightRemainingLeft, heightRemainingRight);
- fx = rightRelOffset(y,ro, false, &heightRemainingRight);
- }
- }
- if (ftQuirk && (fx - leftRelOffset(y,lo, false) < f->width)) {
- o->setPos( o->xPos(), y + o->marginTop() );
- o->setChildNeedsLayout(true, false);
- o->layoutIfNeeded();
- _height = o->height() + o->marginTop() + o->marginBottom();
- f->width = o->width() + o->marginLeft() + o->marginRight();
- }
- f->left = fx - f->width;
- //kdDebug( 6040 ) << "positioning right aligned float at (" << fx - o->marginRight() - o->width() << "/" << y + o->marginTop() << ")" << endl;
- o->setPos(fx - o->marginRight() - o->width(), y + o->marginTop());
- }
-
- if ( m_layer && hasOverflowClip()) {
- if (o->xPos()+o->width() > m_overflowWidth)
- m_overflowWidth = o->xPos()+o->width();
- else
- if (o->xPos() < m_overflowLeft)
- m_overflowLeft = o->xPos();
- }
-
- f->startY = y;
- f->endY = f->startY + _height;
-
-
- //kdDebug( 6040 ) << "floatingObject x/y= (" << f->left << "/" << f->startY << "-" << f->width << "/" << f->endY - f->startY << ")" << endl;
-
- f = m_floatingObjects->next();
- }
-}
-
-void RenderBlock::newLine()
-{
- positionNewFloats();
- // set y position
- int newY = 0;
- switch(m_clearStatus)
- {
- case CLEFT:
- newY = leftBottom();
- break;
- case CRIGHT:
- newY = rightBottom();
- break;
- case CBOTH:
- newY = floatBottom();
- default:
- break;
- }
- if(m_height < newY)
- {
- // kdDebug( 6040 ) << "adjusting y position" << endl;
- m_height = newY;
- }
- m_clearStatus = CNONE;
-}
-
-int
-RenderBlock::leftOffset() const
-{
- return borderLeft()+paddingLeft();
-}
-
-int
-RenderBlock::leftRelOffset(int y, int fixedOffset, bool applyTextIndent, int *heightRemaining, bool *canClearLine ) const
-{
- int left = fixedOffset;
- if (canClearLine) *canClearLine = true;
-
- if (m_floatingObjects) {
- if ( heightRemaining ) *heightRemaining = 1;
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- {
- //kdDebug( 6040 ) <<(void *)this << " left: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
- if (r->startY <= y && r->endY > y &&
- r->type == FloatingObject::FloatLeft &&
- r->left + r->width > left) {
- left = r->left + r->width;
- if ( heightRemaining ) *heightRemaining = r->endY - y;
- if ( canClearLine ) *canClearLine = (r->node->style()->floating() != FLEFT_ALIGN);
- }
- }
- }
-
- if (applyTextIndent && m_firstLine && style()->direction() == LTR ) {
- int cw=0;
- if (style()->textIndent().isPercent())
- cw = containingBlock()->contentWidth();
- left += style()->textIndent().minWidth(cw);
- }
-
- //kdDebug( 6040 ) << "leftOffset(" << y << ") = " << left << endl;
- return left;
-}
-
-int
-RenderBlock::rightOffset() const
-{
- int right = m_width - borderRight() - paddingRight();
- if (m_layer && scrollsOverflowY())
- right -= m_layer->verticalScrollbarWidth();
- return right;
-}
-
-int
-RenderBlock::rightRelOffset(int y, int fixedOffset, bool applyTextIndent, int *heightRemaining, bool *canClearLine ) const
-{
- int right = fixedOffset;
- if (canClearLine) *canClearLine = true;
-
- if (m_floatingObjects) {
- if (heightRemaining) *heightRemaining = 1;
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- {
- //kdDebug( 6040 ) << "right: sy, ey, x, w " << r->startY << "," << r->endY << "," << r->left << "," << r->width << " " << endl;
- if (r->startY <= y && r->endY > y &&
- r->type == FloatingObject::FloatRight &&
- r->left < right) {
- right = r->left;
- if ( heightRemaining ) *heightRemaining = r->endY - y;
- if ( canClearLine ) *canClearLine = (r->node->style()->floating() != FRIGHT_ALIGN);
- }
- }
- }
-
- if (applyTextIndent && m_firstLine && style()->direction() == RTL ) {
- int cw=0;
- if (style()->textIndent().isPercent())
- cw = containingBlock()->contentWidth();
- right -= style()->textIndent().minWidth(cw);
- }
-
- //kdDebug( 6040 ) << "rightOffset(" << y << ") = " << right << endl;
- return right;
-}
-
-unsigned short
-RenderBlock::lineWidth(int y, bool *canClearLine) const
-{
- //kdDebug( 6040 ) << "lineWidth(" << y << ")=" << rightOffset(y) - leftOffset(y) << endl;
- int result;
- if (canClearLine) {
- bool rightCanClearLine;
- bool leftCanClearLine;
- result = rightOffset(y, &rightCanClearLine) - leftOffset(y, &leftCanClearLine);
- *canClearLine = rightCanClearLine && leftCanClearLine;
- } else
- result = rightOffset(y) - leftOffset(y);
- return (result < 0) ? 0 : result;
-}
-
-int
-RenderBlock::nearestFloatBottom(int height) const
-{
- if (!m_floatingObjects) return 0;
- int bottom = 0;
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- if (r->endY>height && (r->endY<bottom || bottom==0))
- bottom=r->endY;
- return kMax(bottom, height);
-}
-
-int RenderBlock::floatBottom() const
-{
- if (!m_floatingObjects) return 0;
- int bottom=0;
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- if (r->endY>bottom)
- bottom=r->endY;
- return bottom;
-}
-
-int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int bottom = RenderFlow::lowestPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return bottom;
- if (includeSelf && m_overflowHeight > bottom)
- bottom = m_overflowHeight;
-
- if (m_floatingObjects) {
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it ) {
- if (!r->noPaint) {
- int lp = r->startY + r->node->marginTop() + r->node->lowestPosition(false);
- bottom = kMax(bottom, lp);
- }
- }
- }
- bottom = kMax(bottom, lowestAbsolutePosition());
-
- if (!includeSelf && lastLineBox()) {
- int lp = lastLineBox()->yPos() + lastLineBox()->height();
- bottom = kMax(bottom, lp);
- }
-
- return bottom;
-}
-
-int RenderBlock::lowestAbsolutePosition() const
-{
- if (!m_positionedObjects)
- return 0;
-
- // Fixed positioned objects do not scroll and thus should not constitute
- // part of the lowest position.
- int bottom = 0;
- RenderObject* r;
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- for ( ; (r = it.current()); ++it ) {
- if (r->style()->position() == FIXED)
- continue;
- int lp = r->yPos() + r->lowestPosition(false);
- bottom = kMax(bottom, lp);
- }
- return bottom;
-}
-
-int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int right = RenderFlow::rightmostPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return right;
- if (includeSelf && m_overflowWidth > right)
- right = m_overflowWidth;
-
- if (m_floatingObjects) {
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it ) {
- if (!r->noPaint) {
- int rp = r->left + r->node->marginLeft() + r->node->rightmostPosition(false);
- right = kMax(right, rp);
- }
- }
- }
- right = kMax(right, rightmostAbsolutePosition());
-
- if (!includeSelf && firstLineBox()) {
- for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox()) {
- int rp = currBox->xPos() + currBox->width();
- right = kMax(right, rp);
- }
- }
-
- return right;
-}
-
-int RenderBlock::rightmostAbsolutePosition() const
-{
- if (!m_positionedObjects)
- return 0;
- int right = 0;
- RenderObject* r;
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- for ( ; (r = it.current()); ++it ) {
- if (r->style()->position() == FIXED)
- continue;
- int rp = r->xPos() + r->rightmostPosition(false);
- right = kMax(right, rp);
- }
- return right;
-}
-
-int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int left = RenderFlow::leftmostPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return left;
-
- if (includeSelf && m_overflowLeft < left)
- left = m_overflowLeft;
-
- if (m_floatingObjects) {
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it ) {
- if (!r->noPaint) {
- int lp = r->left + r->node->marginLeft() + r->node->leftmostPosition(false);
- left = kMin(left, lp);
- }
- }
- }
- left = kMin(left, leftmostAbsolutePosition());
-
- if (!includeSelf && firstLineBox()) {
- for (InlineRunBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
- left = kMin(left, (int)currBox->xPos());
- }
-
- return left;
-}
-
-int RenderBlock::leftmostAbsolutePosition() const
-{
- if (!m_positionedObjects)
- return 0;
- int left = 0;
- RenderObject* r;
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- for ( ; (r = it.current()); ++it ) {
- if (r->style()->position() == FIXED)
- continue;
- int lp = r->xPos() + r->leftmostPosition(false);
- left = kMin(left, lp);
- }
- return left;
-}
-
-int RenderBlock::highestPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int top = RenderFlow::highestPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return top;
-
- if (includeSelf && m_overflowTop < top)
- top = m_overflowTop;
-
- if (m_floatingObjects) {
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it ) {
- if (!r->noPaint) {
- int hp = r->startY + r->node->marginTop() + r->node->highestPosition(false);
- top = kMin(top, hp);
- }
- }
- }
- top = kMin(top, highestAbsolutePosition());
-
- if (!includeSelf && firstLineBox()) {
- top = kMin(top, (int)firstLineBox()->yPos());
- }
-
- return top;
-}
-
-int RenderBlock::highestAbsolutePosition() const
-{
- if (!m_positionedObjects)
- return 0;
- int top = 0;
- RenderObject* r;
- TQPtrListIterator<RenderObject> it(*m_positionedObjects);
- for ( ; (r = it.current()); ++it ) {
- if (r->style()->position() == FIXED)
- continue;
- int hp = r->yPos() + r->highestPosition(false);
- hp = kMin(top, hp);
- }
- return top;
-}
-
-int
-RenderBlock::leftBottom()
-{
- if (!m_floatingObjects) return 0;
- int bottom=0;
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- if (r->endY>bottom && r->type == FloatingObject::FloatLeft)
- bottom=r->endY;
-
- return bottom;
-}
-
-int
-RenderBlock::rightBottom()
-{
- if (!m_floatingObjects) return 0;
- int bottom=0;
- FloatingObject* r;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- if (r->endY>bottom && r->type == FloatingObject::FloatRight)
- bottom=r->endY;
-
- return bottom;
-}
-
-void
-RenderBlock::clearFloats()
-{
- if (m_floatingObjects)
- m_floatingObjects->clear();
-
- // we are done if the element defines a new block formatting context
- if (flowAroundFloats() || isRoot() || isCanvas() || isFloatingOrPositioned() || isTableCell()) return;
-
- RenderObject *prev = previousSibling();
-
- // find the element to copy the floats from
- // pass non-flows
- // pass fAF's
- bool parentHasFloats = false;
- while (prev) {
- if (!prev->isRenderBlock() || prev->isFloatingOrPositioned() || prev->flowAroundFloats()) {
- if ( prev->isFloating() && parent()->isRenderBlock() ) {
- parentHasFloats = true;
- }
- prev = prev->previousSibling();
- } else
- break;
- }
-
- int offset = m_y;
- if (parentHasFloats)
- {
- addOverHangingFloats( static_cast<RenderBlock *>( parent() ),
- parent()->borderLeft() + parent()->paddingLeft(), offset, false );
- }
-
- int xoffset = 0;
- if (prev) {
- if(prev->isTableCell()) return;
- offset -= prev->yPos();
- } else {
- prev = parent();
- if(!prev) return;
- xoffset += prev->borderLeft() + prev->paddingLeft();
- }
- //kdDebug() << "RenderBlock::clearFloats found previous "<< (void *)this << " prev=" << (void *)prev<< endl;
-
- // add overhanging special objects from the previous RenderBlock
- if(!prev->isRenderBlock()) return;
- RenderBlock * flow = static_cast<RenderBlock *>(prev);
- if(!flow->m_floatingObjects) return;
- if(flow->floatBottom() > offset)
- addOverHangingFloats( flow, xoffset, offset, false );
-}
-
-void RenderBlock::addOverHangingFloats( RenderBlock *flow, int xoff, int offset, bool child )
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << (void *)this << ": adding overhanging floats xoff=" << xoff << " offset=" << offset << " child=" << child << endl;
-#endif
-
- // Prevent floats from being added to the canvas by the root element, e.g., <html>.
- if ( !flow->m_floatingObjects || (child && flow->isRoot()) )
- return;
-
- // if I am clear of my floats, don't add them
- // the CSS spec also mentions that child floats
- // are not cleared.
- if (!child && style()->clear() == CBOTH)
- {
- return;
- }
-
- TQPtrListIterator<FloatingObject> it(*flow->m_floatingObjects);
- FloatingObject *r;
- for ( ; (r = it.current()); ++it ) {
-
- if (!child && r->type == FloatingObject::FloatLeft && style()->clear() == CLEFT )
- continue;
- if (!child && r->type == FloatingObject::FloatRight && style()->clear() == CRIGHT )
- continue;
-
- if ( ( !child && r->endY > offset ) ||
- ( child && flow->yPos() + r->endY > height() ) ) {
- if (child && !r->crossedLayer) {
- if (flow->enclosingLayer() == enclosingLayer()) {
- // Set noPaint to true only if we didn't cross layers.
- r->noPaint = true;
- } else {
- r->crossedLayer = true;
- }
- }
-
- FloatingObject* f = 0;
- // don't insert it twice!
- if (m_floatingObjects) {
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- while ( (f = it.current()) ) {
- if (f->node == r->node) break;
- ++it;
- }
- }
- if ( !f ) {
- FloatingObject *floatingObj = new FloatingObject(r->type);
- floatingObj->startY = r->startY - offset;
- floatingObj->endY = r->endY - offset;
- floatingObj->left = r->left - xoff;
- // Applying the child's margin makes no sense in the case where the child was passed in.
- // since his own margin was added already through the subtraction of the |xoff| variable
- // above. |xoff| will equal -flow->marginLeft() in this case, so it's already been taken
- // into account. Only apply this code if |child| is false, since otherwise the left margin
- // will get applied twice. -dwh
- if (!child && flow != parent())
- floatingObj->left += flow->marginLeft();
- if ( !child ) {
- floatingObj->left -= marginLeft();
- floatingObj->noPaint = true;
- }
- else {
- floatingObj->noPaint = (r->crossedLayer || !r->noPaint);
- floatingObj->crossedLayer = r->crossedLayer;
- }
-
- floatingObj->width = r->width;
- floatingObj->node = r->node;
- if (!m_floatingObjects) {
- m_floatingObjects = new TQPtrList<FloatingObject>;
- m_floatingObjects->setAutoDelete(true);
- }
- m_floatingObjects->append(floatingObj);
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "addOverHangingFloats x/y= (" << floatingObj->left << "/" << floatingObj->startY << "-" << floatingObj->width << "/" << floatingObj->endY - floatingObj->startY << ")" << endl;
-#endif
- }
- }
- }
-}
-
-bool RenderBlock::containsFloat(RenderObject* o) const
-{
- if (m_floatingObjects) {
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- while (it.current()) {
- if (it.current()->node == o)
- return true;
- ++it;
- }
- }
- return false;
-}
-
-void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove)
-{
- dirtyFormattingContext(false);
- setChildNeedsLayout(true);
-
- if (floatToRemove)
- removeFloatingObject(floatToRemove);
-
- // Iterate over our children and mark them as needed.
- if (!childrenInline()) {
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (isBlockFlow() && !child->isFloatingOrPositioned() &&
- ((floatToRemove ? child->containsFloat(floatToRemove) : child->hasFloats()) || child->usesLineWidth()))
- child->markAllDescendantsWithFloatsForLayout(floatToRemove);
- }
- }
-}
-
-int RenderBlock::getClearDelta(RenderObject *child)
-{
- if (!hasFloats())
- return 0;
-
- //kdDebug( 6040 ) << "getClearDelta on child " << child << " oldheight=" << m_height << endl;
- bool clearSet = child->style()->clear() != CNONE;
- int bottom = 0;
- switch(child->style()->clear())
- {
- case CNONE:
- break;
- case CLEFT:
- bottom = leftBottom();
- break;
- case CRIGHT:
- bottom = rightBottom();
- break;
- case CBOTH:
- bottom = floatBottom();
- break;
- }
-
- // We also clear floats if we are too big to sit on the same line as a float, and happen to flow around floats.
- // FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed
- // to fit) and not all (we should be using nearestFloatBottom and looping).
-
- int result = clearSet ? kMax(0, bottom - child->yPos()) : 0;
- if (!result && child->flowAroundFloats() && !style()->width().isVariable()) {
- bool canClearLine;
- int lw = lineWidth(child->yPos(), &canClearLine);
- if (((child->style()->width().isPercent() && child->width() > lw) ||
- (child->style()->width().isFixed() && child->minWidth() > lw)) &&
- child->minWidth() <= contentWidth() && canClearLine)
- result = kMax(0, floatBottom() - child->yPos());
- }
- return result;
-}
-
-bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
-{
- if (!scrollsOverflow() || !m_layer)
- return false;
-
- if (m_layer->verticalScrollbarWidth()) {
- TQRect vertRect(_tx + width() - borderRight() - m_layer->verticalScrollbarWidth(),
- _ty + borderTop() - borderTopExtra(),
- m_layer->verticalScrollbarWidth(),
- height() + borderTopExtra() + borderBottomExtra()-borderTop()-borderBottom());
- if (vertRect.contains(_x, _y)) {
-#ifdef APPLE_CHANGES
- RenderLayer::gScrollBar = m_layer->verticalScrollbar();
-#endif
- return true;
- }
- }
-
- if (m_layer->horizontalScrollbarHeight()) {
- TQRect horizRect(_tx + borderLeft(),
- _ty + height() + borderTop() + borderBottomExtra() - borderBottom() - m_layer->horizontalScrollbarHeight(),
- width()-borderLeft()-borderRight(),
- m_layer->horizontalScrollbarHeight());
- if (horizRect.contains(_x, _y)) {
-#ifdef APPLE_CHANGES
- RenderLayer::gScrollBar = m_layer->horizontalScrollbar();
-#endif
- return true;
- }
- }
-
- return false;
-}
-
-bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inBox)
-{
- bool inScrollbar = isPointInScrollbar(_x, _y, _tx+xPos(), _ty+yPos());
- if (inScrollbar && hitTestAction != HitTestChildrenOnly)
- inBox = true;
-
- if (hitTestAction != HitTestSelfOnly && m_floatingObjects && !inScrollbar) {
- int stx = _tx + xPos();
- int sty = _ty + yPos();
- if (hasOverflowClip() && m_layer)
- m_layer->subtractScrollOffset(stx, sty);
- FloatingObject* o;
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for (it.toLast(); (o = it.current()); --it)
- if (!o->noPaint && !o->node->layer())
- inBox |= o->node->nodeAtPoint(info, _x, _y,
- stx+o->left + o->node->marginLeft() - o->node->xPos(),
- sty+o->startY + o->node->marginTop() - o->node->yPos(), HitTestAll ) ;
- }
-
- inBox |= RenderFlow::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
- return inBox;
-}
-
-void RenderBlock::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(RenderBlock)::calcMinMaxWidth() this=" << this << endl;
-#endif
-
- m_minWidth = 0;
- m_maxWidth = 0;
-
- bool noWrap = !style()->autoWrap();
- if (childrenInline())
- calcInlineMinMaxWidth();
- else
- calcBlockMinMaxWidth();
-
- if(m_maxWidth < m_minWidth) m_maxWidth = m_minWidth;
-
- if (noWrap && childrenInline()) {
- m_minWidth = m_maxWidth;
-
- // A horizontal marquee with inline children has no minimum width.
- if (style()->overflowX() == OMARQUEE && m_layer && m_layer->marquee() &&
- m_layer->marquee()->isHorizontal() && !m_layer->marquee()->isUnfurlMarquee())
- m_minWidth = 0;
- }
-
- if (isTableCell()) {
- Length w = static_cast<RenderTableCell*>(this)->styleOrColWidth();
- if (w.isFixed() && w.value() > 0)
- m_maxWidth = kMax((int)m_minWidth, calcContentWidth(w.value()));
- } else if (style()->width().isFixed() && style()->width().value() > 0)
- m_minWidth = m_maxWidth = calcContentWidth(style()->width().value());
-
- if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
- m_maxWidth = kMax(m_maxWidth, (int)calcContentWidth(style()->minWidth().value()));
- m_minWidth = kMax(m_minWidth, (short)calcContentWidth(style()->minWidth().value()));
- }
-
- if (style()->maxWidth().isFixed() && style()->maxWidth().value() != UNDEFINED) {
- m_maxWidth = kMin(m_maxWidth, (int)calcContentWidth(style()->maxWidth().value()));
- m_minWidth = kMin(m_minWidth, (short)calcContentWidth(style()->maxWidth().value()));
- }
-
- int toAdd = 0;
- toAdd = borderLeft() + borderRight() + paddingLeft() + paddingRight();
-
- m_minWidth += toAdd;
- m_maxWidth += toAdd;
-
- setMinMaxKnown();
-
- //kdDebug( 6040 ) << "Text::calcMinMaxWidth(" << this << "): min = " << m_minWidth << " max = " << m_maxWidth << endl;
- // ### compare with min/max width set in style sheet...
-}
-
-// bidi.cpp defines the following functions too.
-// Maybe these should not be static, after all...
-
-#ifndef KDE_USE_FINAL
-
-static int getBPMWidth(int childValue, Length cssUnit)
-{
- if (!cssUnit.isVariable())
- return (cssUnit.isFixed() ? cssUnit.value() : childValue);
- return 0;
-}
-
-static int getBorderPaddingMargin(RenderObject* child, bool endOfInline)
-{
- RenderStyle* cstyle = child->style();
- int result = 0;
- bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
- result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
- (leftSide ? cstyle->marginLeft() :
- cstyle->marginRight()));
- result += getBPMWidth((leftSide ? child->paddingLeft() : child->paddingRight()),
- (leftSide ? cstyle->paddingLeft() :
- cstyle->paddingRight()));
- result += leftSide ? child->borderLeft() : child->borderRight();
- return result;
-}
-#endif
-
-static void stripTrailingSpace(bool preserveWS,
- int& inlineMax, int& inlineMin,
- RenderObject* trailingSpaceChild)
-{
- if (!preserveWS && trailingSpaceChild && trailingSpaceChild->isText()) {
- // Collapse away the trailing space at the end of a block.
- RenderText* t = static_cast<RenderText *>(trailingSpaceChild);
- const Font *f = t->htmlFont( false );
- TQChar space[1]; space[0] = ' ';
- int spaceWidth = f->width(space, 1, 0);
- inlineMax -= spaceWidth;
- if (inlineMin > inlineMax)
- inlineMin = inlineMax;
- }
-}
-
-void RenderBlock::calcInlineMinMaxWidth()
-{
- int inlineMax=0;
- int inlineMin=0;
-
- int cw = containingBlock()->contentWidth();
- int floatMaxWidth = 0;
-
- // If we are at the start of a line, we want to ignore all white-space.
- // Also strip spaces if we previously had text that ended in a trailing space.
- bool stripFrontSpaces = true;
-
- bool isTcQuirk = isTableCell() && style()->htmlHacks() && style()->width().isVariable();
-
- RenderObject* trailingSpaceChild = 0;
-
- bool autoWrap, oldAutoWrap;
- autoWrap = oldAutoWrap = style()->autoWrap();
-
- InlineMinMaxIterator childIterator(this, this);
- bool addedTextIndent = false; // Only gets added in once.
- RenderObject* prevFloat = 0;
- while (RenderObject* child = childIterator.next())
- {
- autoWrap = child->style()->autoWrap();
-
- if( !child->isBR() )
- {
- // Step One: determine whether or not we need to go ahead and
- // terminate our current line. Each discrete chunk can become
- // the new min-width, if it is the widest chunk seen so far, and
- // it can also become the max-width.
-
- // Children fall into three categories:
- // (1) An inline flow object. These objects always have a min/max of 0,
- // and are included in the iteration solely so that their margins can
- // be added in.
- //
- // (2) An inline non-text non-flow object, e.g., an inline replaced element.
- // These objects can always be on a line by themselves, so in this situation
- // we need to go ahead and break the current line, and then add in our own
- // margins and min/max width on its own line, and then terminate the line.
- //
- // (3) A text object. Text runs can have breakable characters at the start,
- // the middle or the end. They may also lose whitespace off the front if
- // we're already ignoring whitespace. In order to compute accurate min-width
- // information, we need three pieces of information.
- // (a) the min-width of the first non-breakable run. Should be 0 if the text string
- // starts with whitespace.
- // (b) the min-width of the last non-breakable run. Should be 0 if the text string
- // ends with whitespace.
- // (c) the min/max width of the string (trimmed for whitespace).
- //
- // If the text string starts with whitespace, then we need to go ahead and
- // terminate our current line (unless we're already in a whitespace stripping
- // mode.
- //
- // If the text string has a breakable character in the middle, but didn't start
- // with whitespace, then we add the width of the first non-breakable run and
- // then end the current line. We then need to use the intermediate min/max width
- // values (if any of them are larger than our current min/max). We then look at
- // the width of the last non-breakable run and use that to start a new line
- // (unless we end in whitespace).
- RenderStyle* cstyle = child->style();
- short childMin = 0;
- short childMax = 0;
-
- if (!child->isText()) {
- // Case (1) and (2). Inline replaced and inline flow elements.
- if (child->isInlineFlow()) {
- // Add in padding/border/margin from the appropriate side of
- // the element.
- int bpm = getBorderPaddingMargin(child, childIterator.endOfInline);
- childMin += bpm;
- childMax += bpm;
-
- inlineMin += childMin;
- inlineMax += childMax;
- }
- else {
- // Inline replaced elements add in their margins to their min/max values.
- int margins = 0;
- LengthType type = cstyle->marginLeft().type();
- if ( type != Variable )
- margins += (type == Fixed ? cstyle->marginLeft().value() : child->marginLeft());
- type = cstyle->marginRight().type();
- if ( type != Variable )
- margins += (type == Fixed ? cstyle->marginRight().value() : child->marginRight());
- childMin += margins;
- childMax += margins;
- }
- }
-
- if (!child->isRenderInline() && !child->isText()) {
-
- bool qBreak = isTcQuirk && !child->isFloatingOrPositioned();
- // Case (2). Inline replaced elements and floats.
- // Go ahead and terminate the current line as far as
- // minwidth is concerned.
- childMin += child->minWidth();
- childMax += child->maxWidth();
-
- if (!qBreak && (autoWrap || oldAutoWrap)) {
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- inlineMin = 0;
- }
-
- // Check our "clear" setting. If we're supposed to clear the previous float, then
- // go ahead and terminate maxwidth as well.
- if (child->isFloating()) {
- if (prevFloat &&
- ((inlineMax + childMax > floatMaxWidth) ||
- ((prevFloat->style()->floating() & FLEFT) && (child->style()->clear() & CLEFT)) ||
- ((prevFloat->style()->floating() & FRIGHT) && (child->style()->clear() & CRIGHT)))) {
- m_maxWidth = kMax(inlineMax, (int)m_maxWidth);
- inlineMax = 0;
- }
- prevFloat = child;
- if (!floatMaxWidth)
- floatMaxWidth = availableWidth();
- }
-
- // Add in text-indent. This is added in only once.
- int ti = 0;
- if ( !addedTextIndent ) {
- addedTextIndent = true;
- ti = style()->textIndent().minWidth( cw );
- childMin+=ti;
- childMax+=ti;
- }
-
- // Add our width to the max.
- inlineMax += childMax;
-
- if (!autoWrap||qBreak)
- inlineMin += childMin;
- else {
- // Now check our line.
- inlineMin = childMin;
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
-
- // Now start a new line.
- inlineMin = 0;
- }
-
- // We are no longer stripping whitespace at the start of
- // a line.
- if (!child->isFloating()) {
- stripFrontSpaces = false;
- trailingSpaceChild = 0;
- }
- }
- else if (child->isText())
- {
- // Case (3). Text.
- RenderText* t = static_cast<RenderText *>(child);
-
- // Determine if we have a breakable character. Pass in
- // whether or not we should ignore any spaces at the front
- // of the string. If those are going to be stripped out,
- // then they shouldn't be considered in the breakable char
- // check.
- bool hasBreakableChar, hasBreak;
- short beginMin, endMin;
- bool beginWS, endWS;
- short beginMax, endMax;
- t->trimmedMinMaxWidth(beginMin, beginWS, endMin, endWS, hasBreakableChar,
- hasBreak, beginMax, endMax,
- childMin, childMax, stripFrontSpaces);
-
- // This text object is insignificant and will not be rendered. Just
- // continue.
- if (!hasBreak && childMax == 0) continue;
-
- if (stripFrontSpaces)
- trailingSpaceChild = child;
- else
- trailingSpaceChild = 0;
-
- // Add in text-indent. This is added in only once.
- int ti = 0;
- if (!addedTextIndent) {
- addedTextIndent = true;
- ti = style()->textIndent().minWidth(cw);
- childMin+=ti; beginMin += ti;
- childMax+=ti; beginMax += ti;
- }
-
- // If we have no breakable characters at all,
- // then this is the easy case. We add ourselves to the current
- // min and max and continue.
- if (!hasBreakableChar) {
- inlineMin += childMin;
- }
- else {
- // We have a breakable character. Now we need to know if
- // we start and end with whitespace.
- if (beginWS) {
- // Go ahead and end the current line.
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- }
- else {
- inlineMin += beginMin;
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- childMin -= ti;
- }
-
- inlineMin = childMin;
-
- if (endWS) {
- // We end in whitespace, which means we can go ahead
- // and end our current line.
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- inlineMin = 0;
- }
- else {
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- inlineMin = endMin;
- }
- }
-
- if (hasBreak) {
- inlineMax += beginMax;
- if (m_maxWidth < inlineMax) m_maxWidth = inlineMax;
- if (m_maxWidth < childMax) m_maxWidth = childMax;
- inlineMax = endMax;
- }
- else
- inlineMax += childMax;
- }
- }
- else
- {
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
- inlineMin = inlineMax = 0;
- stripFrontSpaces = true;
- trailingSpaceChild = 0;
- }
-
- oldAutoWrap = autoWrap;
- }
-
- stripTrailingSpace(style()->preserveWS(), inlineMax, inlineMin, trailingSpaceChild);
-
- if(m_minWidth < inlineMin) m_minWidth = inlineMin;
- if(m_maxWidth < inlineMax) m_maxWidth = inlineMax;
- // kdDebug( 6040 ) << "m_minWidth=" << m_minWidth
- // << " m_maxWidth=" << m_maxWidth << endl;
-}
-
-// Use a very large value (in effect infinite).
-#define BLOCK_MAX_WIDTH 15000
-
-void RenderBlock::calcBlockMinMaxWidth()
-{
- bool nowrap = !style()->autoWrap();
-
- RenderObject *child = firstChild();
- RenderObject* prevFloat = 0;
- int floatWidths = 0;
- int floatMaxWidth = 0;
-
- while(child != 0)
- {
- // positioned children don't affect the minmaxwidth
- if (child->isPositioned()) {
- child = child->nextSibling();
- continue;
- }
-
- if (prevFloat && (!child->isFloating() ||
- ((prevFloat->style()->floating() & FLEFT) && (child->style()->clear() & CLEFT)) ||
- ((prevFloat->style()->floating() & FRIGHT) && (child->style()->clear() & CRIGHT)))) {
- m_maxWidth = kMax(floatWidths, m_maxWidth);
- floatWidths = 0;
- }
-
- Length ml = child->style()->marginLeft();
- Length mr = child->style()->marginRight();
-
- // Call calcWidth on the child to ensure that our margins are
- // up to date. This method can be called before the child has actually
- // calculated its margins (which are computed inside calcWidth).
- if (ml.isPercent() || mr.isPercent())
- calcWidth();
-
- // A margin basically has three types: fixed, percentage, and auto (variable).
- // Auto margins simply become 0 when computing min/max width.
- // Fixed margins can be added in as is.
- // Percentage margins are computed as a percentage of the width we calculated in
- // the calcWidth call above. In this case we use the actual cached margin values on
- // the RenderObject itself.
- int margin = 0;
- if (ml.isFixed())
- margin += ml.value();
- else if (ml.isPercent())
- margin += child->marginLeft();
-
- if (mr.isFixed())
- margin += mr.value();
- else if (mr.isPercent())
- margin += child->marginRight();
-
- if (margin < 0) margin = 0;
-
- int w = child->minWidth() + margin;
- if(m_minWidth < w) m_minWidth = w;
- // IE ignores tables for calculation of nowrap. Makes some sense.
- if ( nowrap && !child->isTable() && m_maxWidth < w )
- m_maxWidth = w;
-
- w = child->maxWidth() + margin;
-
- if(m_maxWidth < w) m_maxWidth = w;
-
- if (child->isFloating()) {
- if (prevFloat && (floatWidths + w > floatMaxWidth)) {
- m_maxWidth = kMax(floatWidths, m_maxWidth);
- floatWidths = w;
- } else
- floatWidths += w;
- } else if (m_maxWidth < w)
- m_maxWidth = w;
-
- // A very specific WinIE quirk.
- // Example:
- /*
- <div style="position:absolute; width:100px; top:50px;">
- <div style="position:absolute;left:0px;top:50px;height:50px;background-color:green">
- <table style="width:100%"><tr><td></table>
- </div>
- </div>
- */
- // In the above example, the inner absolute positioned block should have a computed width
- // of 100px because of the table.
- // We can achieve this effect by making the maxwidth of blocks that contain tables
- // with percentage widths be infinite (as long as they are not inside a table cell).
- if (style()->htmlHacks() && child->style()->width().isPercent() &&
- !isTableCell() && child->isTable() && m_maxWidth < BLOCK_MAX_WIDTH) {
- RenderBlock* cb = containingBlock();
- while (!cb->isCanvas() && !cb->isTableCell())
- cb = cb->containingBlock();
- if (!cb->isTableCell())
- m_maxWidth = BLOCK_MAX_WIDTH;
- }
- if (child->isFloating()) {
- prevFloat = child;
- if (!floatMaxWidth)
- floatMaxWidth = availableWidth();
- }
- child = child->nextSibling();
- }
- m_maxWidth = kMax(floatWidths, m_maxWidth);
-}
-
-void RenderBlock::close()
-{
- if (lastChild() && lastChild()->isAnonymousBlock())
- lastChild()->close();
- updateFirstLetter();
- RenderFlow::close();
-}
-
-int RenderBlock::getBaselineOfFirstLineBox()
-{
- if (m_firstLineBox)
- return m_firstLineBox->yPos() + m_firstLineBox->baseline();
-
- if (isInline())
- return -1; // We're inline and had no line box, so we have no baseline we can return.
-
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- int result = curr->getBaselineOfFirstLineBox();
- if (result != -1)
- return curr->yPos() + result; // Translate to our coordinate space.
- }
-
- return -1;
-}
-
-InlineFlowBox* RenderBlock::getFirstLineBox()
-{
- if (m_firstLineBox)
- return m_firstLineBox;
-
- if (isInline())
- return 0; // We're inline and had no line box, so we have no baseline we can return.
-
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- InlineFlowBox* result = curr->getFirstLineBox();
- if (result)
- return result;
- }
-
- return 0;
-}
-
-bool RenderBlock::inRootBlockContext() const
-{
- if (isTableCell() || isFloatingOrPositioned() || hasOverflowClip())
- return false;
-
- if (isRoot() || isCanvas())
- return true;
-
- return containingBlock()->inRootBlockContext();
-}
-
-const char *RenderBlock::renderName() const
-{
- if (isFloating())
- return "RenderBlock (floating)";
- if (isPositioned())
- return "RenderBlock (positioned)";
- if (isAnonymousBlock() && m_avoidPageBreak)
- return "RenderBlock (avoidPageBreak)";
- if (isAnonymousBlock())
- return "RenderBlock (anonymous)";
- else if (isAnonymous())
- return "RenderBlock (generated)";
- if (isRelPositioned())
- return "RenderBlock (relative positioned)";
- if (style() && style()->display() == COMPACT)
- return "RenderBlock (compact)";
- if (style() && style()->display() == RUN_IN)
- return "RenderBlock (run-in)";
- return "RenderBlock";
-}
-
-#ifdef ENABLE_DUMP
-void RenderBlock::printTree(int indent) const
-{
- RenderFlow::printTree(indent);
-
- if (m_floatingObjects)
- {
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- FloatingObject *r;
- for ( ; (r = it.current()); ++it )
- {
- TQString s;
- s.fill(' ', indent);
- kdDebug() << s << renderName() << ": " <<
- (r->type == FloatingObject::FloatLeft ? "FloatLeft" : "FloatRight" ) <<
- "[" << r->node->renderName() << ": " << (void*)r->node << "] (" << r->startY << " - " << r->endY << ")" << "width: " << r->width <<
- endl;
- }
- }
-}
-
-void RenderBlock::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderFlow::dump(stream,ind);
-
- if (m_childrenInline) { stream << " childrenInline"; }
- // FIXME: currently only print pre to not mess up regression
- if (style()->preserveWS()) { stream << " pre"; }
- if (m_firstLine) { stream << " firstLine"; }
-
- if (m_floatingObjects && !m_floatingObjects->isEmpty())
- {
- stream << " special(";
- TQPtrListIterator<FloatingObject> it(*m_floatingObjects);
- FloatingObject *r;
- bool first = true;
- for ( ; (r = it.current()); ++it )
- {
- if (!first)
- stream << ",";
- stream << r->node->renderName();
- first = false;
- }
- stream << ")";
- }
-
- // ### EClear m_clearStatus
-}
-#endif
-
-#undef DEBUG
-#undef DEBUG_LAYOUT
-#undef BOX_DEBUG
-
-} // namespace khtml
-
diff --git a/khtml/rendering/render_block.h b/khtml/rendering/render_block.h
deleted file mode 100644
index 2b0e49398..000000000
--- a/khtml/rendering/render_block.h
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * This file is part of the render object implementation for KHTML.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef RENDER_BLOCK_H
-#define RENDER_BLOCK_H
-
-#include <tqptrlist.h>
-
-#include "render_flow.h"
-
-namespace khtml {
-
-class RenderBlock : public RenderFlow
-{
-public:
- RenderBlock(DOM::NodeImpl* node);
- virtual ~RenderBlock();
-
- virtual const char *renderName() const;
-
- virtual bool isRenderBlock() const { return true; }
- virtual bool isBlockFlow() const { return !isInline() && !isTable(); }
- virtual bool isInlineFlow() const { return isInline() && !isReplaced(); }
- virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
-
- virtual bool childrenInline() const { return m_childrenInline; }
- virtual void setChildrenInline(bool b) { m_childrenInline = b; }
- void makeChildrenNonInline(RenderObject* insertionPoint = 0);
-
- void makePageBreakAvoidBlocks();
-
- // The height (and width) of a block when you include overflow spillage out of the bottom
- // of the block (e.g., a <div style="height:25px"> that has a 100px tall image inside
- // it would have an overflow height of borderTop() + paddingTop() + 100px.
- virtual int overflowHeight() const { return m_overflowHeight; }
- virtual int overflowWidth() const { return m_overflowWidth; }
- virtual int overflowLeft() const { return m_overflowLeft; }
- virtual int overflowTop() const { return m_overflowTop; }
- virtual void setOverflowHeight(int h) { m_overflowHeight = h; }
- virtual void setOverflowWidth(int w) { m_overflowWidth = w; }
- virtual void setOverflowLeft(int l) { m_overflowLeft = l; }
- virtual void setOverflowTop(int t) { m_overflowTop = t; }
-
- virtual bool isSelfCollapsingBlock() const;
- virtual bool isTopMarginQuirk() const { return m_topMarginQuirk; }
- virtual bool isBottomMarginQuirk() const { return m_bottomMarginQuirk; }
-
- virtual short maxTopMargin(bool positive) const {
- if (positive)
- return m_maxTopPosMargin;
- else
- return m_maxTopNegMargin;
- }
- virtual short maxBottomMargin(bool positive) const {
- if (positive)
- return m_maxBottomPosMargin;
- else
- return m_maxBottomNegMargin;
- }
-
- void initMaxMarginValues() {
- if (m_marginTop >= 0)
- m_maxTopPosMargin = m_marginTop;
- else
- m_maxTopNegMargin = -m_marginTop;
- if (m_marginBottom >= 0)
- m_maxBottomPosMargin = m_marginBottom;
- else
- m_maxBottomNegMargin = -m_marginBottom;
- }
-
- virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
- virtual void removeChild(RenderObject *oldChild);
-
- virtual void setStyle(RenderStyle* _style);
- virtual void attach();
- void updateFirstLetter();
-
- virtual void layout();
- void layoutBlock( bool relayoutChildren );
- void layoutBlockChildren( bool relayoutChildren );
- void layoutInlineChildren( bool relayoutChildren, int breakBeforeLine = 0);
-
- void layoutPositionedObjects( bool relayoutChildren );
- void insertPositionedObject(RenderObject *o);
- void removePositionedObject(RenderObject *o);
-
- // Called to lay out the legend for a fieldset.
- virtual RenderObject* layoutLegend(bool /*relayoutChildren*/) { return 0; };
-
- // the implementation of the following functions is in bidi.cpp
- void bidiReorderLine(const BidiIterator &start, const BidiIterator &end, BidiState &bidi );
- BidiIterator findNextLineBreak(BidiIterator &start, BidiState &info );
- InlineFlowBox* constructLine(const BidiIterator& start, const BidiIterator& end);
- InlineFlowBox* createLineBoxes(RenderObject* obj);
- void computeHorizontalPositionsForLine(InlineFlowBox* lineBox, BidiState &bidi);
- void computeVerticalPositionsForLine(InlineFlowBox* lineBox);
- bool clearLineOfPageBreaks(InlineFlowBox* lineBox);
- void checkLinesForOverflow();
- void deleteEllipsisLineBoxes();
- void checkLinesForTextOverflow();
- // end bidi.cpp functions
-
- virtual void paint(PaintInfo& i, int tx, int ty);
- void paintObject(PaintInfo& i, int tx, int ty, bool paintOutline = true);
- void paintFloats(PaintInfo& i, int _tx, int _ty, bool paintSelection = false);
-
- void insertFloatingObject(RenderObject *o);
- void removeFloatingObject(RenderObject *o);
-
- // called from lineWidth, to position the floats added in the last line.
- void positionNewFloats();
- void clearFloats();
- int getClearDelta(RenderObject *child);
- virtual void markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove = 0);
-
- // FIXME: containsFloats() should not return true if the floating objects list
- // is empty. However, layoutInlineChildren() relies on the current behavior.
- // http://bugzilla.opendarwin.org/show_bug.cgi?id=7395#c3
- virtual bool hasFloats() const { return m_floatingObjects!=0; }
- virtual bool containsFloat(RenderObject* o) const;
-
- virtual bool hasOverhangingFloats() const { return floatBottom() > m_height; }
- void addOverHangingFloats( RenderBlock *block, int xoffset, int yoffset, bool child );
-
- int nearestFloatBottom(int height) const;
- int floatBottom() const;
- inline int leftBottom();
- inline int rightBottom();
-
- virtual unsigned short lineWidth(int y, bool *canClearLine = 0) const;
- virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int leftmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int highestPosition(bool includeOverflowInterior, bool includeSelf) const;
- int lowestAbsolutePosition() const;
- int leftmostAbsolutePosition() const;
- int rightmostAbsolutePosition() const;
- int highestAbsolutePosition() const;
-
- int rightOffset() const;
- int rightRelOffset(int y, int fixedOffset, bool applyTextIndent=true, int *heightRemaining = 0, bool *canClearLine = 0) const;
- int rightOffset(int y, bool *canClearLine = 0) const { return rightRelOffset(y, rightOffset(), true, 0, canClearLine); }
-
- int leftOffset() const;
- int leftRelOffset(int y, int fixedOffset, bool applyTextIndent=true, int *heightRemaining = 0, bool *canClearLine = 0) const;
- int leftOffset(int y, bool *canClearLine = 0) const { return leftRelOffset(y, leftOffset(), true, 0, canClearLine); }
-
- virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int _tx, int _ty, HitTestAction hitTestAction = HitTestAll, bool inside=false);
-
- bool isPointInScrollbar(int x, int y, int tx, int ty);
-
- virtual void calcMinMaxWidth();
- void calcInlineMinMaxWidth();
- void calcBlockMinMaxWidth();
-
- virtual void close();
-
- virtual int getBaselineOfFirstLineBox();
- virtual InlineFlowBox* getFirstLineBox();
-
- RootInlineBox* firstRootBox() { return static_cast<RootInlineBox*>(m_firstLineBox); }
- RootInlineBox* lastRootBox() { return static_cast<RootInlineBox*>(m_lastLineBox); }
-
- bool inRootBlockContext() const;
-
-#ifdef ENABLE_DUMP
- virtual void printTree(int indent=0) const;
- virtual void dump(TQTextStream &stream, const TQString &ind) const;
-#endif
-
-protected:
- void newLine();
-
-protected:
- struct FloatingObject {
- enum Type {
- FloatLeft,
- FloatRight
- };
-
- FloatingObject(Type _type) {
- node = 0;
- startY = 0;
- endY = 0;
- type = _type;
- left = 0;
- width = 0;
- noPaint = false;
- crossedLayer = false;
-
- }
- RenderObject* node;
- int startY;
- int endY;
- short left;
- short width;
- Type type : 1; // left or right aligned
- bool noPaint : 1;
- bool crossedLayer : 1; // lock noPaint flag
- };
-
- // The following helper functions and structs are used by layoutBlockChildren.
- class CompactInfo {
- // A compact child that needs to be collapsed into the margin of the following block.
- RenderObject* m_compact;
-
- // The block with the open margin that the compact child is going to place itself within.
- RenderObject* m_block;
- bool m_treatAsBlock : 1;
-
- public:
- RenderObject* compact() const { return m_compact; }
- RenderObject* block() const { return m_block; }
- void setTreatAsBlock(bool b) { m_treatAsBlock = b; }
- bool treatAsBlock() const { return m_treatAsBlock; }
- bool matches(RenderObject* child) const { return m_compact && m_block == child; }
-
- void clear() { set(0, 0); }
- void set(RenderObject* c, RenderObject* b) { m_compact = c; m_block = b; }
-
- CompactInfo() { clear(); }
- };
-
- class MarginInfo {
- // Collapsing flags for whether we can collapse our margins with our children's margins.
- bool m_canCollapseWithChildren : 1;
- bool m_canCollapseTopWithChildren : 1;
- bool m_canCollapseBottomWithChildren : 1;
-
- // Whether or not we are a quirky container, i.e., do we collapse away top and bottom
- // margins in our container. Table cells and the body are the common examples. We
- // also have a custom style property for Safari RSS to deal with TypePad blog articles.
- bool m_quirkContainer : 1;
-
- // This flag tracks whether we are still looking at child margins that can all collapse together at the beginning of a block.
- // They may or may not collapse with the top margin of the block (|m_canCollapseTopWithChildren| tells us that), but they will
- // always be collapsing with one another. This variable can remain set to true through multiple iterations
- // as long as we keep encountering self-collapsing blocks.
- bool m_atTopOfBlock : 1;
-
- // This flag is set when we know we're examining bottom margins and we know we're at the bottom of the block.
- bool m_atBottomOfBlock : 1;
-
- // If our last normal flow child was a self-collapsing block that cleared a float,
- // we track it in this variable.
- bool m_selfCollapsingBlockClearedFloat : 1;
-
- // These variables are used to detect quirky margins that we need to collapse away (in table cells
- // and in the body element).
- bool m_topQuirk : 1;
- bool m_bottomQuirk : 1;
- bool m_determinedTopQuirk : 1;
-
- // These flags track the previous maximal positive and negative margins.
- int m_posMargin;
- int m_negMargin;
-
- public:
- MarginInfo(RenderBlock* b, int top, int bottom);
-
- void setAtTopOfBlock(bool b) { m_atTopOfBlock = b; }
- void setAtBottomOfBlock(bool b) { m_atBottomOfBlock = b; }
- void clearMargin() { m_posMargin = m_negMargin = 0; }
- void setSelfCollapsingBlockClearedFloat(bool b) { m_selfCollapsingBlockClearedFloat = b; }
- void setTopQuirk(bool b) { m_topQuirk = b; }
- void setBottomQuirk(bool b) { m_bottomQuirk = b; }
- void setDeterminedTopQuirk(bool b) { m_determinedTopQuirk = b; }
- void setPosMargin(int p) { m_posMargin = p; }
- void setNegMargin(int n) { m_negMargin = n; }
- void setPosMarginIfLarger(int p) { if (p > m_posMargin) m_posMargin = p; }
- void setNegMarginIfLarger(int n) { if (n > m_negMargin) m_negMargin = n; }
-
- void setMargin(int p, int n) { m_posMargin = p; m_negMargin = n; }
-
- bool atTopOfBlock() const { return m_atTopOfBlock; }
- bool canCollapseWithTop() const { return m_atTopOfBlock && m_canCollapseTopWithChildren; }
- bool canCollapseWithBottom() const { return m_atBottomOfBlock && m_canCollapseBottomWithChildren; }
- bool canCollapseTopWithChildren() const { return m_canCollapseTopWithChildren; }
- bool canCollapseBottomWithChildren() const { return m_canCollapseBottomWithChildren; }
- bool selfCollapsingBlockClearedFloat() const { return m_selfCollapsingBlockClearedFloat; }
- bool quirkContainer() const { return m_quirkContainer; }
- bool determinedTopQuirk() const { return m_determinedTopQuirk; }
- bool topQuirk() const { return m_topQuirk; }
- bool bottomQuirk() const { return m_bottomQuirk; }
- int posMargin() const { return m_posMargin; }
- int negMargin() const { return m_negMargin; }
- int margin() const { return m_posMargin - m_negMargin; }
- };
-
- class PageBreakInfo {
- int m_pageBottom; // Next calculated page-break
- bool m_forcePageBreak : 1; // Must break before next block
- // ### to do better "page-break-after/before: avoid" this struct
- // should keep a pagebreakAvoid block and gather children in it
- public:
- PageBreakInfo(int pageBottom) : m_pageBottom(pageBottom), m_forcePageBreak(false) {};
- bool forcePageBreak() { return m_forcePageBreak; }
- void setForcePageBreak(bool b) { m_forcePageBreak = b; }
- int pageBottom() { return m_pageBottom; };
- void setPageBottom(int bottom) { m_pageBottom = bottom; }
- };
-
- virtual bool canClear(RenderObject *child, PageBreakLevel level);
- void clearPageBreak(RenderObject* child, int pageBottom);
-
- void adjustPositionedBlock(RenderObject* child, const MarginInfo& marginInfo);
- void adjustFloatingBlock(const MarginInfo& marginInfo);
- RenderObject* handleSpecialChild(RenderObject* child, const MarginInfo& marginInfo, CompactInfo& compactInfo, bool& handled);
- RenderObject* handleFloatingChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled);
- RenderObject* handlePositionedChild(RenderObject* child, const MarginInfo& marginInfo, bool& handled);
- RenderObject* handleCompactChild(RenderObject* child, CompactInfo& compactInfo, const MarginInfo& marginInfo, bool& handled);
- RenderObject* handleRunInChild(RenderObject* child, bool& handled);
- void collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate);
- void clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin);
- void adjustSizeForCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo);
- void insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo);
- int estimateVerticalPosition(RenderObject* child, const MarginInfo& info);
- void determineHorizontalPosition(RenderObject* child);
- void handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo);
- void setCollapsedBottomMargin(const MarginInfo& marginInfo);
- void clearChildOfPageBreaks(RenderObject* child, PageBreakInfo &pageBreakInfo, MarginInfo &marginInfo);
- // End helper functions and structs used by layoutBlockChildren.
-
-protected:
- // How much content overflows out of our block vertically or horizontally (all we support
- // for now is spillage out of the bottom and the right, which are the common cases).
- int m_overflowHeight;
- int m_overflowWidth;
-
- // Left and top overflow.
- int m_overflowTop;
- int m_overflowLeft;
-
-private:
- TQPtrList<FloatingObject>* m_floatingObjects;
- TQPtrList<RenderObject>* m_positionedObjects;
-
- bool m_childrenInline : 1;
- bool m_firstLine : 1; // used in inline layouting
- EClear m_clearStatus : 2; // used during layuting of paragraphs
- bool m_avoidPageBreak : 1; // anonymous avoid page-break block
- bool m_topMarginQuirk : 1;
- bool m_bottomMarginQuirk : 1;
-
- short m_maxTopPosMargin;
- short m_maxTopNegMargin;
- short m_maxBottomPosMargin;
- short m_maxBottomNegMargin;
-
-};
-
-} // namespace
-
-#endif // RENDER_BLOCK_H
-
diff --git a/khtml/rendering/render_body.cpp b/khtml/rendering/render_body.cpp
deleted file mode 100644
index 541c9676d..000000000
--- a/khtml/rendering/render_body.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include "rendering/render_body.h"
-#include "rendering/render_canvas.h"
-#include "html/html_baseimpl.h"
-#include "xml/dom_docimpl.h"
-#include "khtmlview.h"
-
-#include <kglobal.h>
-#include <kdebug.h>
-
-using namespace khtml;
-using namespace DOM;
-
-RenderBody::RenderBody(HTMLBodyElementImpl* element)
- : RenderBlock(element)
-{
- scrollbarsStyled = false;
-}
-
-RenderBody::~RenderBody()
-{
-}
-
-void RenderBody::setStyle(RenderStyle* style)
-{
-// tqDebug("RenderBody::setStyle()");
- // ignore position: fixed on body
- if (style->htmlHacks() && style->position() == FIXED)
- style->setPosition(STATIC);
-
- RenderBlock::setStyle(style);
- document()->setTextColor( style->color() );
- scrollbarsStyled = false;
-}
-
-void RenderBody::paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty)
-{
- //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl;
- TQColor bgColor;
- const BackgroundLayer *bgLayer = 0;
-
- if( parent()->style()->hasBackground() ) {
- // the root element already has a non-transparent background of its own
- // so we must fork our own. (CSS2.1 - 14.2 §4)
- bgColor = style()->backgroundColor();
- bgLayer = style()->backgroundLayers();
- }
-
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- _ty -= borderTopExtra();
-
- int my = kMax(_ty, paintInfo.r.y());
- int end = kMin( paintInfo.r.y()+paintInfo.r.height(), _ty + h );
- int mh = end - my;
-
- paintBackgrounds(paintInfo.p, bgColor, bgLayer, my, mh, _tx, _ty, w, h);
-
- if(style()->hasBorder())
- paintBorder( paintInfo.p, _tx, _ty, w, h, style() );
-
-}
-
-void RenderBody::repaint(Priority p)
-{
- RenderObject *cb = containingBlock();
- if(cb)
- cb->repaint(p);
-}
-
-void RenderBody::layout()
-{
- // in quirk mode, we'll need to have our margins determined
- // for percentage height calculations
- if (style()->htmlHacks())
- calcHeight();
- RenderBlock::layout();
-
- if (!scrollbarsStyled)
- {
- RenderCanvas* canvas = this->canvas();
- if (canvas->view())
- {
- canvas->view()->horizontalScrollBar()->setPalette(style()->palette());
- canvas->view()->verticalScrollBar()->setPalette(style()->palette());
- }
- scrollbarsStyled=true;
- }
-}
-
-int RenderBody::availableHeight() const
-{
- int h = RenderBlock::availableHeight();
-
- if( style()->marginTop().isFixed() )
- h -= style()->marginTop().value();
- if( style()->marginBottom().isFixed() )
- h -= style()->marginBottom().value();
-
- return kMax(0, h);
-}
diff --git a/khtml/rendering/render_body.h b/khtml/rendering/render_body.h
deleted file mode 100644
index 7951f73e1..000000000
--- a/khtml/rendering/render_body.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_BODY
-#define RENDER_BODY
-
-#include "rendering/render_block.h"
-
-namespace DOM
-{
- class HTMLBodyElementImpl;
-}
-
-namespace khtml {
-
-class RenderBody : public RenderBlock
-{
-public:
- RenderBody(DOM::HTMLBodyElementImpl* node);
- virtual ~RenderBody();
-
- virtual bool isBody() const { return true; }
-
- virtual const char *renderName() const { return "RenderBody"; }
- virtual void repaint(Priority p=NormalPriority);
-
- virtual void layout();
- virtual void setStyle(RenderStyle* style);
-
- virtual int availableHeight() const;
-
-protected:
- virtual void paintBoxDecorations(PaintInfo&, int _tx, int _ty);
- bool scrollbarsStyled;
-};
-
-} // end namespace
-#endif
diff --git a/khtml/rendering/render_box.cpp b/khtml/rendering/render_box.cpp
deleted file mode 100644
index 7400752ac..000000000
--- a/khtml/rendering/render_box.cpp
+++ /dev/null
@@ -1,2325 +0,0 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Apple Computer, Inc.
- * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- * (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-// -------------------------------------------------------------------------
-//#define DEBUG_LAYOUT
-//#define CLIP_DEBUG
-
-
-#include <tqpainter.h>
-
-#include "misc/loader.h"
-#include "rendering/render_replaced.h"
-#include "rendering/render_canvas.h"
-#include "rendering/render_table.h"
-#include "rendering/render_inline.h"
-#include "rendering/render_block.h"
-#include "rendering/render_line.h"
-#include "rendering/render_layer.h"
-#include "misc/htmlhashes.h"
-#include "xml/dom_nodeimpl.h"
-#include "xml/dom_docimpl.h"
-#include "html/html_elementimpl.h"
-
-#include <khtmlview.h>
-#include <kdebug.h>
-#include <kglobal.h>
-#include <assert.h>
-
-
-using namespace DOM;
-using namespace khtml;
-
-#define TABLECELLMARGIN -0x4000
-
-RenderBox::RenderBox(DOM::NodeImpl* node)
- : RenderContainer(node)
-{
- m_minWidth = -1;
- m_maxWidth = -1;
- m_width = m_height = 0;
- m_x = 0;
- m_y = 0;
- m_marginTop = 0;
- m_marginBottom = 0;
- m_marginLeft = 0;
- m_marginRight = 0;
- m_staticX = 0;
- m_staticY = 0;
-
- m_placeHolderBox = 0;
- m_layer = 0;
-}
-
-RenderBlock* RenderBox::createAnonymousBlock()
-{
- RenderStyle *newStyle = new RenderStyle();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(BLOCK);
-
- RenderBlock *newBox = new (renderArena()) RenderBlock(document() /* anonymous*/);
- newBox->setStyle(newStyle);
- return newBox;
-}
-
-void RenderBox::restructureParentFlow() {
- if (!parent() || parent()->childrenInline() == isInline())
- return;
- // We have gone from not affecting the inline status of the parent flow to suddenly
- // having an impact. See if there is a mismatch between the parent flow's
- // childrenInline() state and our state.
- if (!isInline()) {
- if (parent()->isRenderInline()) {
- // We have to split the parent flow.
- RenderInline* parentInline = static_cast<RenderInline*>(parent());
- RenderBlock* newBox = parentInline->createAnonymousBlock();
-
- RenderFlow* oldContinuation = parent()->continuation();
- parentInline->setContinuation(newBox);
-
- RenderObject* beforeChild = nextSibling();
- parent()->removeChildNode(this);
- parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
- }
- else if (parent()->isRenderBlock())
- static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
- }
- else {
- // An anonymous block must be made to wrap this inline.
- RenderBlock* box = createAnonymousBlock();
- parent()->insertChildNode(box, this);
- box->appendChildNode(parent()->removeChildNode(this));
- }
-}
-
-static inline bool overflowAppliesTo(RenderObject* o)
-{
- // css 2.1-11.1.1
- // 1) overflow only applies to non-replaced block-level elements, table cells, and inline-block elements
- if (o->isRenderBlock() || o->isTableRow() || o->isTableSection())
- // 2) overflow on root applies to the viewport (cf. KHTMLView::layout)
- if (!o->isRoot())
- // 3) overflow on body may apply to the viewport...
- if (!o->isBody()
- // ...but only for HTML documents...
- || !o->document()->isHTMLDocument()
- // ...and only when the root has a visible overflow
- || !o->document()->documentElement()->renderer()
- || !o->document()->documentElement()->renderer()->style()
- || o->document()->documentElement()->renderer()->style()->hidesOverflow())
- return true;
-
- return false;
-}
-
-void RenderBox::setStyle(RenderStyle *_style)
-{
- bool affectsParent = style() && isFloatingOrPositioned() &&
- (!_style->isFloating() && _style->position() != ABSOLUTE && _style->position() != FIXED) &&
- parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
-
- RenderContainer::setStyle(_style);
-
- // The root always paints its background/border.
- if (isRoot())
- setShouldPaintBackgroundOrBorder(true);
-
- switch(_style->display())
- {
- case INLINE:
- case INLINE_BLOCK:
- case INLINE_TABLE:
- setInline(true);
- break;
- case RUN_IN:
- if (isInline() && parent() && parent()->childrenInline())
- break;
- default:
- setInline(false);
- }
-
- switch(_style->position())
- {
- case ABSOLUTE:
- case FIXED:
- setPositioned(true);
- break;
- default:
- setPositioned(false);
- if( !isTableCell() && _style->isFloating() )
- setFloating(true);
-
- if( _style->position() == RELATIVE )
- setRelPositioned(true);
- }
-
- if (overflowAppliesTo(this) && _style->hidesOverflow())
- setHasOverflowClip();
-
- if (requiresLayer()) {
- if (!m_layer) {
- m_layer = new (renderArena()) RenderLayer(this);
- m_layer->insertOnlyThisLayer();
- if (parent() && containingBlock())
- m_layer->updateLayerPosition();
- }
- }
- else if (m_layer && !isCanvas()) {
- m_layer->removeOnlyThisLayer();
- m_layer = 0;
- }
-
- if (m_layer)
- m_layer->styleChanged();
-
- if (style()->outlineWidth() > 0 && style()->outlineSize() > maximalOutlineSize(PaintActionOutline))
- static_cast<RenderCanvas*>(document()->renderer())->setMaximalOutlineSize(style()->outlineSize());
- if (affectsParent)
- restructureParentFlow();
-}
-
-RenderBox::~RenderBox()
-{
- //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;
-}
-
-void RenderBox::detach()
-{
- RenderLayer* layer = m_layer;
- RenderArena* arena = renderArena();
-
- RenderContainer::detach();
-
- if (layer)
- layer->detach(arena);
-}
-
-InlineBox* RenderBox::createInlineBox(bool /*makePlaceHolderBox*/, bool /*isRootLineBox*/)
-{
- if (m_placeHolderBox)
- m_placeHolderBox->detach(renderArena());
- return (m_placeHolderBox = new (renderArena()) InlineBox(this));
-}
-
-void RenderBox::deleteInlineBoxes(RenderArena* arena)
-{
- if (m_placeHolderBox) {
- m_placeHolderBox->detach( arena ? arena : renderArena() );
- m_placeHolderBox = 0;
- }
-}
-
-short RenderBox::contentWidth() const
-{
- short w = m_width - style()->borderLeftWidth() - style()->borderRightWidth();
- w -= paddingLeft() + paddingRight();
-
- if (m_layer && scrollsOverflowY())
- w -= m_layer->verticalScrollbarWidth();
-
- //kdDebug( 6040 ) << "RenderBox::contentWidth(2) = " << w << endl;
- return w;
-}
-
-int RenderBox::contentHeight() const
-{
- int h = m_height - style()->borderTopWidth() - style()->borderBottomWidth();
- h -= paddingTop() + paddingBottom();
-
- if (m_layer && scrollsOverflowX())
- h -= m_layer->horizontalScrollbarHeight();
-
- return h;
-}
-
-void RenderBox::setPos( int xPos, int yPos )
-{
- m_x = xPos; m_y = yPos;
-}
-
-short RenderBox::width() const
-{
- return m_width;
-}
-
-int RenderBox::height() const
-{
- return m_height;
-}
-
-void RenderBox::setWidth( int width )
-{
- m_width = width;
-}
-
-void RenderBox::setHeight( int height )
-{
- m_height = height;
-}
-
-int RenderBox::calcBoxHeight(int h) const
-{
- if (style()->boxSizing() == CONTENT_BOX)
- h += borderTop() + borderBottom() + paddingTop() + paddingBottom();
-
- return h;
-}
-
-int RenderBox::calcBoxWidth(int w) const
-{
- if (style()->boxSizing() == CONTENT_BOX)
- w += borderLeft() + borderRight() + paddingLeft() + paddingRight();
-
- return w;
-}
-
-int RenderBox::calcContentHeight(int h) const
-{
- if (style()->boxSizing() == BORDER_BOX)
- h -= borderTop() + borderBottom() + paddingTop() + paddingBottom();
-
- return kMax(0, h);
-}
-
-int RenderBox::calcContentWidth(int w) const
-{
- if (style()->boxSizing() == BORDER_BOX)
- w -= borderLeft() + borderRight() + paddingLeft() + paddingRight();
-
- return kMax(0, w);
-}
-
-// --------------------- painting stuff -------------------------------
-
-void RenderBox::paint(PaintInfo& i, int _tx, int _ty)
-{
- _tx += m_x;
- _ty += m_y;
-
- if (hasOverflowClip() && m_layer)
- m_layer->subtractScrollOffset(_tx, _ty);
-
- // default implementation. Just pass things through to the children
- for(RenderObject* child = firstChild(); child; child = child->nextSibling())
- child->paint(i, _tx, _ty);
-}
-
-void RenderBox::paintRootBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty)
-{
- //kdDebug( 6040 ) << renderName() << "::paintRootBoxDecorations()" << _tx << "/" << _ty << endl;
- const BackgroundLayer* bgLayer = style()->backgroundLayers();
- TQColor bgColor = style()->backgroundColor();
- if (document()->isHTMLDocument() && !style()->hasBackground()) {
- // Locate the <body> element using the DOM. This is easier than trying
- // to crawl around a render tree with potential :before/:after content and
- // anonymous blocks created by inline <body> tags etc. We can locate the <body>
- // render object very easily via the DOM.
- HTMLElementImpl* body = document()->body();
- RenderObject* bodyObject = (body && body->id() == ID_BODY) ? body->renderer() : 0;
-
- if (bodyObject) {
- bgLayer = bodyObject->style()->backgroundLayers();
- bgColor = bodyObject->style()->backgroundColor();
- }
- }
-
- if( !bgColor.isValid() && canvas()->view())
- bgColor = canvas()->view()->palette().active().color(TQColorGroup::Base);
-
- int w = width();
- int h = height();
-
- // kdDebug(0) << "width = " << w <<endl;
-
- int rw, rh;
- if (canvas()->view()) {
- rw = canvas()->view()->contentsWidth();
- rh = canvas()->view()->contentsHeight();
- } else {
- rw = canvas()->docWidth();
- rh = canvas()->docHeight();
- }
-
- // kdDebug(0) << "rw = " << rw <<endl;
-
- int bx = _tx - marginLeft();
- int by = _ty - marginTop();
- int bw = QMAX(w + marginLeft() + marginRight() + borderLeft() + borderRight(), rw);
- int bh = QMAX(h + marginTop() + marginBottom() + borderTop() + borderBottom(), rh);
-
- // CSS2 14.2:
- // " The background of the box generated by the root element covers the entire canvas."
- // hence, paint the background even in the margin areas (unlike for every other element!)
- // I just love these little inconsistencies .. :-( (Dirk)
- int my = kMax(by, paintInfo.r.y());
-
- paintBackgrounds(paintInfo.p, bgColor, bgLayer, my, paintInfo.r.height(), bx, by, bw, bh);
-
- if(style()->hasBorder())
- paintBorder( paintInfo.p, _tx, _ty, w, h, style() );
-}
-
-void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty)
-{
- //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl;
-
- if(isRoot())
- return paintRootBoxDecorations(paintInfo, _tx, _ty);
-
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- _ty -= borderTopExtra();
-
- int my = kMax(_ty,paintInfo.r.y());
- int end = kMin( paintInfo.r.y() + paintInfo.r.height(), _ty + h );
- int mh = end - my;
-
- // The <body> only paints its background if the root element has defined a background
- // independent of the body. Go through the DOM to get to the root element's render object,
- // since the root could be inline and wrapped in an anonymous block.
-
- if (!isBody() || !document()->isHTMLDocument() || document()->documentElement()->renderer()->style()->hasBackground())
- paintBackgrounds(paintInfo.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h);
-
- if(style()->hasBorder()) {
- paintBorder(paintInfo.p, _tx, _ty, w, h, style());
- }
-}
-
-void RenderBox::paintBackgrounds(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int height)
- {
- if (!bgLayer) return;
- paintBackgrounds(p, c, bgLayer->next(), clipy, cliph, _tx, _ty, w, height);
- paintBackground(p, c, bgLayer, clipy, cliph, _tx, _ty, w, height);
-}
-
-void RenderBox::paintBackground(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int height)
-{
- paintBackgroundExtended(p, c, bgLayer, clipy, cliph, _tx, _ty, w, height,
- borderLeft(), borderRight(), paddingLeft(), paddingRight());
-}
-
-static void calculateBackgroundSize(const BackgroundLayer* bgLayer, int& scaledWidth, int& scaledHeight)
-{
- CachedImage* bg = bgLayer->backgroundImage();
-
- if (bgLayer->isBackgroundSizeSet()) {
- Length bgWidth = bgLayer->backgroundSize().width;
- Length bgHeight = bgLayer->backgroundSize().height;
-
- if (bgWidth.isPercent())
- scaledWidth = scaledWidth * bgWidth.value() / 100;
- else if (bgWidth.isFixed())
- scaledWidth = bgWidth.value();
- else if (bgWidth.isVariable()) {
- // If the width is auto and the height is not, we have to use the appropriate
- // scale to maintain our aspect ratio.
- if (bgHeight.isPercent()) {
- int scaledH = scaledHeight * bgHeight.value() / 100;
- scaledWidth = bg->pixmap_size().width() * scaledH / bg->pixmap_size().height();
- } else if (bgHeight.isFixed())
- scaledWidth = bg->pixmap_size().width() * bgHeight.value() / bg->pixmap_size().height();
- }
-
- if (bgHeight.isPercent())
- scaledHeight = scaledHeight * bgHeight.value() / 100;
- else if (bgHeight.isFixed())
- scaledHeight = bgHeight.value();
- else if (bgHeight.isVariable()) {
- // If the height is auto and the width is not, we have to use the appropriate
- // scale to maintain our aspect ratio.
- if (bgWidth.isPercent())
- scaledHeight = bg->pixmap_size().height() * scaledWidth / bg->pixmap_size().width();
- else if (bgWidth.isFixed())
- scaledHeight = bg->pixmap_size().height() * bgWidth.value() / bg->pixmap_size().width();
- else if (bgWidth.isVariable()) {
- // If both width and height are auto, we just want to use the image's
- // intrinsic size.
- scaledWidth = bg->pixmap_size().width();
- scaledHeight = bg->pixmap_size().height();
- }
- }
- } else {
- scaledWidth = bg->pixmap_size().width();
- scaledHeight = bg->pixmap_size().height();
- }
-}
-
-void RenderBox::paintBackgroundExtended(TQPainter *p, const TQColor &c, const BackgroundLayer* bgLayer, int clipy, int cliph,
- int _tx, int _ty, int w, int h,
- int bleft, int bright, int pleft, int pright)
-{
- if ( cliph < 0 )
- return;
-
- if (bgLayer->backgroundClip() != BGBORDER) {
- // Clip to the padding or content boxes as necessary.
- bool includePadding = bgLayer->backgroundClip() == BGCONTENT;
- int x = _tx + bleft + (includePadding ? pleft : 0);
- int y = _ty + borderTop() + (includePadding ? paddingTop() : 0);
- int width = w - bleft - bright - (includePadding ? pleft + pright : 0);
- int height = h - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : 0);
- p->save();
- p->setClipRect(TQRect(x, y, width, height), TQPainter::CoordPainter);
- }
-
- CachedImage* bg = bgLayer->backgroundImage();
- bool shouldPaintBackgroundImage = bg && bg->pixmap_size() == bg->valid_rect().size() && !bg->isTransparent() && !bg->isErrorImage();
- TQColor bgColor = c;
-
- // Paint the color first underneath all images.
- if (!bgLayer->next() && bgColor.isValid() && tqAlpha(bgColor.rgb()) > 0)
- p->fillRect(_tx, clipy, w, cliph, bgColor);
-
- // no progressive loading of the background image
- if (shouldPaintBackgroundImage) {
- int sx = 0;
- int sy = 0;
- int cw,ch;
- int cx,cy;
- int scaledImageWidth, scaledImageHeight;
-
- // CSS2 chapter 14.2.1
-
- if (bgLayer->backgroundAttachment()) {
- //scroll
- int hpab = 0, vpab = 0, left = 0, top = 0; // Init to 0 for background-origin of 'border'
- if (bgLayer->backgroundOrigin() != BGBORDER) {
- hpab += bleft + bright;
- vpab += borderTop() + borderBottom();
- left += bleft;
- top += borderTop();
- if (bgLayer->backgroundOrigin() == BGCONTENT) {
- hpab += pleft + pright;
- vpab += paddingTop() + paddingBottom();
- left += pleft;
- top += paddingTop();
- }
- }
-
- int pw = w - hpab;
- int ph = h - vpab;
- scaledImageWidth = pw;
- scaledImageHeight = ph;
- calculateBackgroundSize(bgLayer, scaledImageWidth, scaledImageHeight);
-
- EBackgroundRepeat bgr = bgLayer->backgroundRepeat();
- if (bgr == NO_REPEAT || bgr == REPEAT_Y) {
- cw = scaledImageWidth;
- int xPosition = bgLayer->backgroundXPosition().minWidth(pw-scaledImageWidth);
- if ( xPosition >= 0 ) {
- cx = _tx + xPosition;
- cw = kMin(scaledImageWidth, pw - xPosition);
- }
- else {
- cx = _tx;
- if (scaledImageWidth > 0) {
- sx = -xPosition;
- cw = kMin(scaledImageWidth+xPosition, pw);
- }
- }
- cx += left;
- } else {
- // repeat over x
- cw = w;
- cx = _tx;
- if (scaledImageWidth > 0) {
- int xPosition = bgLayer->backgroundXPosition().minWidth(pw-scaledImageWidth);
- sx = scaledImageWidth - (xPosition % scaledImageWidth);
- sx -= left % scaledImageWidth;
- }
- }
- if (bgr == NO_REPEAT || bgr == REPEAT_X) {
- ch = scaledImageHeight;
- int yPosition = bgLayer->backgroundYPosition().minWidth(ph - scaledImageHeight);
- if ( yPosition >= 0 ) {
- cy = _ty + yPosition;
- ch = kMin(ch, ph - yPosition);
- }
- else {
- cy = _ty;
- if (scaledImageHeight > 0) {
- sy = -yPosition;
- ch = kMin(scaledImageHeight+yPosition, ph);
- }
- }
-
- cy += top;
- } else {
- // repeat over y
- ch = h;
- cy = _ty;
- if (scaledImageHeight > 0) {
- int yPosition = bgLayer->backgroundYPosition().minWidth(ph - scaledImageHeight);
- sy = scaledImageHeight - (yPosition % scaledImageHeight);
- sy -= top % scaledImageHeight;
- }
- }
- if (layer())
- layer()->scrollOffset(sx, sy);
- }
- else
- {
- //fixed
- TQRect vr = viewRect();
- int pw = vr.width();
- int ph = vr.height();
- scaledImageWidth = pw;
- scaledImageHeight = ph;
- calculateBackgroundSize(bgLayer, scaledImageWidth, scaledImageHeight);
- EBackgroundRepeat bgr = bgLayer->backgroundRepeat();
-
- int xPosition = bgLayer->backgroundXPosition().minWidth(pw-scaledImageWidth);
- if (bgr == NO_REPEAT || bgr == REPEAT_Y) {
- cw = kMin(scaledImageWidth, pw - xPosition);
- cx = vr.x() + xPosition;
- } else {
- cw = pw;
- cx = vr.x();
- if (scaledImageWidth > 0)
- sx = scaledImageWidth - xPosition % scaledImageWidth;
- }
-
- int yPosition = bgLayer->backgroundYPosition().minWidth(ph-scaledImageHeight);
- if (bgr == NO_REPEAT || bgr == REPEAT_X) {
- ch = kMin(scaledImageHeight, ph - yPosition);
- cy = vr.y() + yPosition;
- } else {
- ch = ph;
- cy = vr.y();
- if (scaledImageHeight > 0)
- sy = scaledImageHeight - yPosition % scaledImageHeight;
- }
-
- TQRect fix(cx, cy, cw, ch);
- TQRect ele(_tx, _ty, w, h);
- TQRect b = fix.intersect(ele);
-
- //kdDebug() <<" ele is " << ele << " b is " << b << " fix is " << fix << endl;
- sx+=b.x()-cx;
- sy+=b.y()-cy;
- cx=b.x();cy=b.y();cw=b.width();ch=b.height();
- }
- // restrict painting to repaint-clip
- if (cy < clipy) {
- ch -= (clipy - cy);
- sy += (clipy - cy);
- cy = clipy;
- }
- ch = kMin(ch, cliph);
-
-// kdDebug() << " clipy, cliph: " << clipy << ", " << cliph << endl;
-// kdDebug() << " drawTiledPixmap(" << cx << ", " << cy << ", " << cw << ", " << ch << ", " << sx << ", " << sy << ")" << endl;
- if (cw>0 && ch>0)
- p->drawTiledPixmap(cx, cy, cw, ch, bg->tiled_pixmap(c, scaledImageWidth, scaledImageHeight), sx, sy);
-
- }
-
- if (bgLayer->backgroundClip() != BGBORDER)
- p->restore(); // Undo the background clip
-
-}
-
-void RenderBox::outlineBox(TQPainter *p, int _tx, int _ty, const char *color)
-{
- p->setPen(TQPen(TQColor(color), 1, Qt::DotLine));
- p->setBrush( Qt::NoBrush );
- p->drawRect(_tx, _ty, m_width, m_height);
-}
-
-TQRect RenderBox::getOverflowClipRect(int tx, int ty)
-{
- // XXX When overflow-clip (CSS3) is implemented, we'll obtain the property
- // here.
- int bl=borderLeft(),bt=borderTop(),bb=borderBottom(),br=borderRight();
- int clipx = tx+bl;
- int clipy = ty+bt;
- int clipw = m_width-bl-br;
- int cliph = m_height-bt-bb+borderTopExtra()+borderBottomExtra();
-
- // Substract out scrollbars if we have them.
- if (m_layer) {
- clipw -= m_layer->verticalScrollbarWidth();
- cliph -= m_layer->horizontalScrollbarHeight();
- }
-
- return TQRect(clipx,clipy,clipw,cliph);
-}
-
-TQRect RenderBox::getClipRect(int tx, int ty)
-{
- int bl=borderLeft(),bt=borderTop(),bb=borderBottom(),br=borderRight();
- // ### what about paddings?
- int clipw = m_width-bl-br;
- int cliph = m_height-bt-bb;
-
- bool rtl = (style()->direction() == RTL);
-
- int clipleft = 0;
- int clipright = clipw;
- int cliptop = 0;
- int clipbottom = cliph;
-
- if ( style()->hasClip() && style()->position() == ABSOLUTE ) {
- // the only case we use the clip property according to CSS 2.1
- if (!style()->clipLeft().isVariable()) {
- int c = style()->clipLeft().width(clipw);
- if ( rtl )
- clipleft = clipw - c;
- else
- clipleft = c;
- }
- if (!style()->clipRight().isVariable()) {
- int w = style()->clipRight().width(clipw);
- if ( rtl ) {
- clipright = clipw - w;
- } else {
- clipright = w;
- }
- }
- if (!style()->clipTop().isVariable())
- cliptop = style()->clipTop().width(cliph);
- if (!style()->clipBottom().isVariable())
- clipbottom = style()->clipBottom().width(cliph);
- }
- int clipx = tx + clipleft;
- int clipy = ty + cliptop;
- clipw = clipright-clipleft;
- cliph = clipbottom-cliptop;
-
- //kdDebug( 6040 ) << "setting clip("<<clipx<<","<<clipy<<","<<clipw<<","<<cliph<<")"<<endl;
-
- return TQRect(clipx,clipy,clipw,cliph);
-}
-
-void RenderBox::close()
-{
- setNeedsLayoutAndMinMaxRecalc();
-}
-
-short RenderBox::containingBlockWidth() const
-{
- if (isCanvas() && canvas()->view())
- {
- if (canvas()->pagedMode())
- return canvas()->width();
- else
- return canvas()->view()->visibleWidth();
- }
-
- RenderBlock* cb = containingBlock();
- if (isRenderBlock() && cb->isTable() && static_cast<RenderTable*>(cb)->caption() == this) {
- //captions are not affected by table border or padding
- return cb->width();
- }
- if (usesLineWidth())
- return cb->lineWidth(m_y);
- else
- return cb->contentWidth();
-}
-
-bool RenderBox::absolutePosition(int &_xPos, int &_yPos, bool f) const
-{
- if ( style()->position() == FIXED )
- f = true;
- RenderObject *o = container();
- if( o && o->absolutePosition(_xPos, _yPos, f))
- {
- if ( o->layer() ) {
- if (o->hasOverflowClip())
- o->layer()->subtractScrollOffset( _xPos, _yPos );
- if (isPositioned())
- o->layer()->checkInlineRelOffset(this, _xPos, _yPos);
- }
-
- if(!isInline() || isReplaced()) {
- _xPos += xPos(),
- _yPos += yPos();
- }
-
- if(isRelPositioned())
- relativePositionOffset(_xPos, _yPos);
- return true;
- }
- else
- {
- _xPos = 0;
- _yPos = 0;
- return false;
- }
-}
-
-void RenderBox::position(InlineBox* box, int /*from*/, int /*len*/, bool /*reverse*/)
-{
- if (isPositioned()) {
- // Cache the x position only if we were an INLINE type originally.
- bool wasInline = style()->isOriginalDisplayInlineType();
-
- if (wasInline && hasStaticX()) {
- // The value is cached in the xPos of the box. We only need this value if
- // our object was inline originally, since otherwise it would have ended up underneath
- // the inlines.
- m_staticX = box->xPos();
- }
- else if (!wasInline && hasStaticY()) {
- // Our object was a block originally, so we make our normal flow position be
- // just below the line box (as though all the inlines that came before us got
- // wrapped in an anonymous block, which is what would have happened had we been
- // in flow). This value was cached in the yPos() of the box.
- m_staticY = box->yPos();
- }
- }
- else if (isReplaced())
- setPos( box->xPos(), box->yPos() );
-}
-
-void RenderBox::repaint(Priority prior)
-{
- int ow = style() ? style()->outlineSize() : 0;
- if( isInline() && !isReplaced() )
- {
- RenderObject* p = parent();
- Q_ASSERT(p);
- while( p->isInline() && !p->isReplaced() )
- p = p->parent();
- int xoff = p->hasOverflowClip() ? 0 : p->overflowLeft();
- int yoff = p->hasOverflowClip() ? 0 : p->overflowTop();
- p->repaintRectangle( -ow + xoff, -ow + yoff, p->effectiveWidth()+ow*2, p->effectiveHeight()+ow*2, prior);
- }
- else
- {
- int xoff = hasOverflowClip() ? 0 : overflowLeft();
- int yoff = hasOverflowClip() ? 0 : overflowTop();
- repaintRectangle( -ow + xoff, -ow + yoff, effectiveWidth()+ow*2, effectiveHeight()+ow*2, prior);
- }
-}
-
-void RenderBox::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
-{
- x += m_x;
- y += m_y;
-
- // Apply the relative position offset when invalidating a rectangle. The layer
- // is translated, but the render box isn't, so we need to do this to get the
- // right dirty rect. Since this is called from RenderObject::setStyle, the relative position
- // flag on the RenderObject has been cleared, so use the one on the style().
- if (style()->position() == RELATIVE && m_layer)
- relativePositionOffset(x,y);
-
- if (style()->position() == FIXED) f=true;
-
- // kdDebug( 6040 ) << "RenderBox(" <<this << ", " << renderName() << ")::repaintRectangle (" << x << "/" << y << ") (" << w << "/" << h << ")" << endl;
- RenderObject *o = container();
- if( o ) {
- if (o->layer()) {
- if (o->style()->hidesOverflow() && o->layer() && !o->isInlineFlow())
- o->layer()->subtractScrollOffset(x,y); // For overflow:auto/scroll/hidden.
- if (style()->position() == ABSOLUTE)
- o->layer()->checkInlineRelOffset(this,x,y);
- }
- o->repaintRectangle(x, y, w, h, p, f);
- }
-}
-
-void RenderBox::relativePositionOffset(int &tx, int &ty) const
-{
- if(!style()->left().isVariable())
- tx += style()->left().width(containingBlockWidth());
- else if(!style()->right().isVariable())
- tx -= style()->right().width(containingBlockWidth());
- if(!style()->top().isVariable())
- {
- if (!style()->top().isPercent()
- || containingBlock()->style()->height().isFixed())
- ty += style()->top().width(containingBlockHeight());
- }
- else if(!style()->bottom().isVariable())
- {
- if (!style()->bottom().isPercent()
- || containingBlock()->style()->height().isFixed())
- ty -= style()->bottom().width(containingBlockHeight());
- }
-}
-
-void RenderBox::calcWidth()
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "RenderBox("<<renderName()<<")::calcWidth()" << endl;
-#endif
- if (isPositioned())
- {
- calcAbsoluteHorizontal();
- }
- else
- {
- bool treatAsReplaced = isReplaced() && !isInlineBlockOrInlineTable();
- Length w;
- if (treatAsReplaced)
- w = Length( calcReplacedWidth(), Fixed );
- else
- w = style()->width();
-
- Length ml = style()->marginLeft();
- Length mr = style()->marginRight();
-
- int cw = containingBlockWidth();
- if (cw<0) cw = 0;
-
- m_marginLeft = 0;
- m_marginRight = 0;
-
- if (isInline() && !isInlineBlockOrInlineTable())
- {
- // just calculate margins
- m_marginLeft = ml.minWidth(cw);
- m_marginRight = mr.minWidth(cw);
- if (treatAsReplaced)
- {
- m_width = calcBoxWidth(w.width(cw));
- m_width = KMAX(m_width, m_minWidth);
- }
-
- return;
- }
- else
- {
- LengthType widthType, minWidthType, maxWidthType;
- if (treatAsReplaced) {
- m_width = calcBoxWidth(w.width(cw));
- widthType = w.type();
- } else {
- m_width = calcWidthUsing(Width, cw, widthType);
- int minW = calcWidthUsing(MinWidth, cw, minWidthType);
- int maxW = style()->maxWidth().value() == UNDEFINED ?
- m_width : calcWidthUsing(MaxWidth, cw, maxWidthType);
-
- if (m_width > maxW) {
- m_width = maxW;
- widthType = maxWidthType;
- }
- if (m_width < minW) {
- m_width = minW;
- widthType = minWidthType;
- }
- }
-
- if (widthType == Variable) {
- // kdDebug( 6040 ) << "variable" << endl;
- m_marginLeft = ml.minWidth(cw);
- m_marginRight = mr.minWidth(cw);
- }
- else
- {
-// kdDebug( 6040 ) << "non-variable " << w.type << ","<< w.value << endl;
- calcHorizontalMargins(ml,mr,cw);
- }
- }
-
- if (cw && cw != m_width + m_marginLeft + m_marginRight && !isFloating() && !isInline())
- {
- if (containingBlock()->style()->direction()==LTR)
- m_marginRight = cw - m_width - m_marginLeft;
- else
- m_marginLeft = cw - m_width - m_marginRight;
- }
- }
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "RenderBox::calcWidth(): m_width=" << m_width << " containingBlockWidth()=" << containingBlockWidth() << endl;
- kdDebug( 6040 ) << "m_marginLeft=" << m_marginLeft << " m_marginRight=" << m_marginRight << endl;
-#endif
-}
-
-int RenderBox::calcWidthUsing(WidthType widthType, int cw, LengthType& lengthType)
-{
- int width = m_width;
- Length w;
- if (widthType == Width)
- w = style()->width();
- else if (widthType == MinWidth)
- w = style()->minWidth();
- else
- w = style()->maxWidth();
-
- lengthType = w.type();
-
- if (lengthType == Variable) {
- int marginLeft = style()->marginLeft().minWidth(cw);
- int marginRight = style()->marginRight().minWidth(cw);
- if (cw) width = cw - marginLeft - marginRight;
-
- // size to max width?
- if (sizesToMaxWidth()) {
- width = KMAX(width, (int)m_minWidth);
- width = KMIN(width, (int)m_maxWidth);
- }
- }
- else
- {
- width = calcBoxWidth(w.width(cw));
- }
-
- return width;
-}
-
-void RenderBox::calcHorizontalMargins(const Length& ml, const Length& mr, int cw)
-{
- if (isFloating() || isInline()) // Inline blocks/tables and floats don't have their margins increased.
- {
- m_marginLeft = ml.minWidth(cw);
- m_marginRight = mr.minWidth(cw);
- }
- else
- {
- if ( (ml.isVariable() && mr.isVariable() && m_width<cw) ||
- (!ml.isVariable() && !mr.isVariable() &&
- containingBlock()->style()->textAlign() == KHTML_CENTER) )
- {
- m_marginLeft = (cw - m_width)/2;
- if (m_marginLeft<0) m_marginLeft=0;
- m_marginRight = cw - m_width - m_marginLeft;
- }
- else if ( (mr.isVariable() && m_width<cw) ||
- (!ml.isVariable() && containingBlock()->style()->direction() == RTL &&
- containingBlock()->style()->textAlign() == KHTML_LEFT))
- {
- m_marginLeft = ml.width(cw);
- m_marginRight = cw - m_width - m_marginLeft;
- }
- else if ( (ml.isVariable() && m_width<cw) ||
- (!mr.isVariable() && containingBlock()->style()->direction() == LTR &&
- containingBlock()->style()->textAlign() == KHTML_RIGHT))
- {
- m_marginRight = mr.width(cw);
- m_marginLeft = cw - m_width - m_marginRight;
- }
- else
- {
- // this makes auto margins 0 if we failed a m_width<cw test above (css2.1, 10.3.3)
- m_marginLeft = ml.minWidth(cw);
- m_marginRight = mr.minWidth(cw);
- }
- }
-}
-
-void RenderBox::calcHeight()
-{
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "RenderBox::calcHeight()" << endl;
-#endif
-
- //cell height is managed by table, inline elements do not have a height property.
- if ( isTableCell() || (isInline() && !isReplaced()) )
- return;
-
- if (isPositioned())
- calcAbsoluteVertical();
- else
- {
- calcVerticalMargins();
-
- // For tables, calculate margins only
- if (isTable())
- return;
-
- Length h;
- bool treatAsReplaced = isReplaced() && !isInlineBlockOrInlineTable();
- bool checkMinMaxHeight = false;
-
- if ( treatAsReplaced )
- h = Length( calcReplacedHeight(), Fixed );
- else {
- h = style()->height();
- checkMinMaxHeight = true;
- }
-
- int height;
- if (checkMinMaxHeight) {
- height = calcHeightUsing(style()->height());
- if (height == -1)
- height = m_height;
- int minH = calcHeightUsing(style()->minHeight()); // Leave as -1 if unset.
- int maxH = style()->maxHeight().value() == UNDEFINED ? height : calcHeightUsing(style()->maxHeight());
- if (maxH == -1)
- maxH = height;
- height = kMin(maxH, height);
- height = kMax(minH, height);
- }
- else {
- // The only times we don't check min/max height are when a fixed length has
- // been given as an override. Just use that.
- height = calcBoxHeight(h.value());
- }
-
- if (height<m_height && !overhangingContents() && !hasOverflowClip())
- setOverhangingContents();
-
- m_height = height;
- }
-
- // Unfurling marquees override with the furled height.
- if (style()->overflowX() == OMARQUEE && m_layer && m_layer->marquee() &&
- m_layer->marquee()->isUnfurlMarquee() && !m_layer->marquee()->isHorizontal()) {
- m_layer->marquee()->setEnd(m_height);
- m_height = kMin(m_height, m_layer->marquee()->unfurlPos());
- }
-
-}
-
-int RenderBox::calcHeightUsing(const Length& h)
-{
- int height = -1;
- if (!h.isVariable()) {
- if (h.isFixed())
- height = h.value();
- else if (h.isPercent())
- height = calcPercentageHeight(h);
- if (height != -1) {
- height = calcBoxHeight(height);
- return height;
- }
- }
- return height;
-}
-
-int RenderBox::calcImplicitHeight() const {
- assert(hasImplicitHeight());
-
- RenderBlock* cb = containingBlock();
- // padding-box height
- int ch = cb->height() - cb->borderTop() + cb->borderBottom();
- int top = style()->top().width(ch);
- int bottom = style()->bottom().width(ch);
-
- return ch - top - bottom;
-}
-
-int RenderBox::calcPercentageHeight(const Length& height, bool treatAsReplaced) const
-{
- int result = -1;
- RenderBlock* cb = containingBlock();
- // In quirk mode, table cells violate what the CSS spec says to do with heights.
- if (cb->isTableCell() && style()->htmlHacks()) {
- result = static_cast<RenderTableCell*>(cb)->cellPercentageHeight();
- }
-
- // Otherwise we only use our percentage height if our containing block had a specified
- // height.
- else if (cb->style()->height().isFixed())
- result = cb->calcContentHeight(cb->style()->height().value());
- else if (cb->style()->height().isPercent()) {
- // We need to recur and compute the percentage height for our containing block.
- result = cb->calcPercentageHeight(cb->style()->height(), treatAsReplaced);
- if (result != -1)
- result = cb->calcContentHeight(result);
- }
- else if (cb->isCanvas()) {
- if (!canvas()->pagedMode())
- result = static_cast<RenderCanvas*>(cb)->viewportHeight();
- else
- result = static_cast<RenderCanvas*>(cb)->height();
- result -= cb->style()->borderTopWidth() - cb->style()->borderBottomWidth();
- result -= cb->paddingTop() + cb->paddingBottom();
- }
- else if (cb->isBody() && style()->htmlHacks() &&
- cb->style()->height().isVariable() && !cb->isFloatingOrPositioned()) {
- int margins = cb->collapsedMarginTop() + cb->collapsedMarginBottom();
- int visHeight = canvas()->viewportHeight();
- RenderObject* p = cb->parent();
- result = visHeight - (margins + p->marginTop() + p->marginBottom() +
- p->borderTop() + p->borderBottom() +
- p->paddingTop() + p->paddingBottom());
- }
- else if (cb->isRoot() && style()->htmlHacks() && cb->style()->height().isVariable()) {
- int visHeight = canvas()->viewportHeight();
- result = visHeight - (marginTop() + marginBottom() +
- borderTop() + borderBottom() +
- paddingTop() + paddingBottom());
- }
- else if (cb->isAnonymousBlock() || treatAsReplaced && style()->htmlHacks()) {
- // IE quirk.
- result = cb->calcPercentageHeight(cb->style()->height(), treatAsReplaced);
- }
- else if (cb->hasImplicitHeight()) {
- result = cb->calcImplicitHeight();
- }
-
- if (result != -1) {
- result = height.width(result);
- if (cb->isTableCell() && style()->boxSizing() != BORDER_BOX) {
- result -= (borderTop() + paddingTop() + borderBottom() + paddingBottom());
- result = kMax(0, result);
- }
- }
- return result;
-}
-
-short RenderBox::calcReplacedWidth() const
-{
- int width = calcReplacedWidthUsing(Width);
- int minW = calcReplacedWidthUsing(MinWidth);
- int maxW = style()->maxWidth().value() == UNDEFINED ? width : calcReplacedWidthUsing(MaxWidth);
-
- if (width > maxW)
- width = maxW;
-
- if (width < minW)
- width = minW;
-
- return width;
-}
-
-int RenderBox::calcReplacedWidthUsing(WidthType widthType) const
-{
- Length w;
- if (widthType == Width)
- w = style()->width();
- else if (widthType == MinWidth)
- w = style()->minWidth();
- else
- w = style()->maxWidth();
-
- switch (w.type()) {
- case Fixed:
- return w.value();
- case Percent:
- {
- const int cw = containingBlockWidth();
- if (cw > 0) {
- int result = w.minWidth(cw);
- return result;
- }
- }
- // fall through
- default:
- return intrinsicWidth();
- }
-}
-
-int RenderBox::calcReplacedHeight() const
-{
- int height = calcReplacedHeightUsing(Height);
- int minH = calcReplacedHeightUsing(MinHeight);
- int maxH = style()->maxHeight().value() == UNDEFINED ? height : calcReplacedHeightUsing(MaxHeight);
-
- if (height > maxH)
- height = maxH;
-
- if (height < minH)
- height = minH;
-
- return height;
-}
-
-int RenderBox::calcReplacedHeightUsing(HeightType heightType) const
-{
- Length h;
- if (heightType == Height)
- h = style()->height();
- else if (heightType == MinHeight)
- h = style()->minHeight();
- else
- h = style()->maxHeight();
- switch( h.type() ) {
- case Fixed:
- return h.value();
- case Percent:
- {
- int th = calcPercentageHeight(h, true);
- if (th != -1)
- return th;
- // fall through
- }
- default:
- return intrinsicHeight();
- };
-}
-
-int RenderBox::availableHeight() const
-{
- return availableHeightUsing(style()->height());
-}
-
-int RenderBox::availableHeightUsing(const Length& h) const
-{
- if (h.isFixed())
- return calcContentHeight(h.value());
-
- if (isCanvas())
- if (static_cast<const RenderCanvas*>(this)->pagedMode())
- return static_cast<const RenderCanvas*>(this)->pageHeight();
- else
- return static_cast<const RenderCanvas*>(this)->viewportHeight();
-
- // We need to stop here, since we don't want to increase the height of the table
- // artificially. We're going to rely on this cell getting expanded to some new
- // height, and then when we lay out again we'll use the calculation below.
- if (isTableCell() && (h.isVariable() || h.isPercent())) {
- const RenderTableCell* tableCell = static_cast<const RenderTableCell*>(this);
- return tableCell->cellPercentageHeight() -
- (borderTop()+borderBottom()+paddingTop()+paddingBottom());
- }
-
- if (h.isPercent())
- return calcContentHeight(h.width(containingBlock()->availableHeight()));
-
- // Check for implicit height
- if (hasImplicitHeight())
- return calcImplicitHeight();
-
- return containingBlock()->availableHeight();
-}
-
-int RenderBox::availableWidth() const
-{
- return availableWidthUsing(style()->width());
-}
-
-int RenderBox::availableWidthUsing(const Length& w) const
-{
- if (w.isFixed())
- return calcContentWidth(w.value());
-
- if (isCanvas())
- return static_cast<const RenderCanvas*>(this)->viewportWidth();
-
- if (w.isPercent())
- return calcContentWidth(w.width(containingBlock()->availableWidth()));
-
- return containingBlock()->availableWidth();
-}
-
-void RenderBox::calcVerticalMargins()
-{
- if( isTableCell() ) {
- // table margins are basically infinite
- m_marginTop = TABLECELLMARGIN;
- m_marginBottom = TABLECELLMARGIN;
- return;
- }
-
- Length tm = style()->marginTop();
- Length bm = style()->marginBottom();
-
- // margins are calculated with respect to the _width_ of
- // the containing block (8.3)
- int cw = containingBlock()->contentWidth();
-
- m_marginTop = tm.minWidth(cw);
- m_marginBottom = bm.minWidth(cw);
-}
-
-void RenderBox::setStaticX(short staticX)
-{
- m_staticX = staticX;
-}
-
-void RenderBox::setStaticY(int staticY)
-{
- m_staticY = staticY;
-}
-
-void RenderBox::calcAbsoluteHorizontal()
-{
- if (isReplaced()) {
- calcAbsoluteHorizontalReplaced();
- return;
- }
-
- // QUESTIONS
- // FIXME 1: Which RenderObject's 'direction' property should used: the
- // containing block (cb) as the spec seems to imply, the parent (parent()) as
- // was previously done in calculating the static distances, or ourself, which
- // was also previously done for deciding what to override when you had
- // over-constrained margins? Also note that the container block is used
- // in similar situations in other parts of the RenderBox class (see calcWidth()
- // and calcHorizontalMargins()). For now we are using the parent for quirks
- // mode and the containing block for strict mode.
-
- // FIXME 2: Can perhaps optimize out cases when max-width/min-width are greater
- // than or less than the computed m_width. Be careful of box-sizing and
- // percentage issues.
-
- // The following is based off of the W3C Working Draft from April 11, 2006 of
- // CSS 2.1: Section 10.3.7 "Absolutely positioned, non-replaced elements"
- // <http://www.w3.org/TR/CSS21/visudet.html#abs-non-replaced-width>
- // (block-style-comments in this function and in calcAbsoluteHorizontalValues()
- // correspond to text from the spec)
-
-
- // We don't use containingBlock(), since we may be positioned by an enclosing
- // relative positioned inline.
- const RenderObject* containerBlock = container();
-
- // FIXME: This is incorrect for cases where the container block is a relatively
- // positioned inline.
- const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight();
-
- // To match WinIE, in quirks mode use the parent's 'direction' property
- // instead of the the container block's.
- EDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction();
-
- const int bordersPlusPadding = borderLeft() + borderRight() + paddingLeft() + paddingRight();
- const Length marginLeft = style()->marginLeft();
- const Length marginRight = style()->marginRight();
- Length left = style()->left();
- Length right = style()->right();
-
- /*---------------------------------------------------------------------------*\
- * For the purposes of this section and the next, the term "static position"
- * (of an element) refers, roughly, to the position an element would have had
- * in the normal flow. More precisely:
- *
- * * The static position for 'left' is the distance from the left edge of the
- * containing block to the left margin edge of a hypothetical box that would
- * have been the first box of the element if its 'position' property had
- * been 'static' and 'float' had been 'none'. The value is negative if the
- * hypothetical box is to the left of the containing block.
- * * The static position for 'right' is the distance from the right edge of the
- * containing block to the right margin edge of the same hypothetical box as
- * above. The value is positive if the hypothetical box is to the left of the
- * containing block's edge.
- *
- * But rather than actually calculating the dimensions of that hypothetical box,
- * user agents are free to make a guess at its probable position.
- *
- * For the purposes of calculating the static position, the containing block of
- * fixed positioned elements is the initial containing block instead of the
- * viewport, and all scrollable boxes should be assumed to be scrolled to their
- * origin.
- \*---------------------------------------------------------------------------*/
-
- // Calculate the static distance if needed.
- if (left.isVariable() && right.isVariable()) {
- if (containerDirection == LTR) {
- // 'm_staticX' should already have been set through layout of the parent.
- int staticPosition = m_staticX - containerBlock->borderLeft();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
- staticPosition += po->xPos();
- left = Length(staticPosition, Fixed);
- } else {
- RenderObject* po = parent();
- // 'm_staticX' should already have been set through layout of the parent.
- int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width();
- for (; po && po != containerBlock; po = po->parent())
- staticPosition -= po->xPos();
- right = Length(staticPosition, Fixed);
- }
- }
-
- // Calculate constraint equation values for 'width' case.
- calcAbsoluteHorizontalValues(style()->width(), containerBlock, containerDirection,
- containerWidth, bordersPlusPadding,
- left, right, marginLeft, marginRight,
- m_width, m_marginLeft, m_marginRight, m_x);
- // Calculate constraint equation values for 'max-width' case.calcContentWidth(width.width(containerWidth));
- if (style()->maxWidth().value() != UNDEFINED) {
- short maxWidth;
- short maxMarginLeft;
- short maxMarginRight;
- short maxXPos;
-
- calcAbsoluteHorizontalValues(style()->maxWidth(), containerBlock, containerDirection,
- containerWidth, bordersPlusPadding,
- left, right, marginLeft, marginRight,
- maxWidth, maxMarginLeft, maxMarginRight, maxXPos);
-
- if (m_width > maxWidth) {
- m_width = maxWidth;
- m_marginLeft = maxMarginLeft;
- m_marginRight = maxMarginRight;
- m_x = maxXPos;
- }
- }
-
- // Calculate constraint equation values for 'min-width' case.
- if (style()->minWidth().value()) {
- short minWidth;
- short minMarginLeft;
- short minMarginRight;
- short minXPos;
-
- calcAbsoluteHorizontalValues(style()->minWidth(), containerBlock, containerDirection,
- containerWidth, bordersPlusPadding,
- left, right, marginLeft, marginRight,
- minWidth, minMarginLeft, minMarginRight, minXPos);
-
- if (m_width < minWidth) {
- m_width = minWidth;
- m_marginLeft = minMarginLeft;
- m_marginRight = minMarginRight;
- m_x = minXPos;
- }
- }
-
- // Put m_width into correct form.
- m_width += bordersPlusPadding;
-}
-
-void RenderBox::calcAbsoluteHorizontalValues(Length width, const RenderObject* containerBlock, EDirection containerDirection,
- const int containerWidth, const int bordersPlusPadding,
- const Length left, const Length right, const Length marginLeft, const Length marginRight,
- short& widthValue, short& marginLeftValue, short& marginRightValue, short& xPos)
-{
- // 'left' and 'right' cannot both be 'auto' because one would of been
- // converted to the static postion already
- assert(!(left.isVariable() && right.isVariable()));
-
- int leftValue = 0;
-
- bool widthIsAuto = width.isVariable();
- bool leftIsAuto = left.isVariable();
- bool rightIsAuto = right.isVariable();
-
- if (!leftIsAuto && !widthIsAuto && !rightIsAuto) {
- /*-----------------------------------------------------------------------*\
- * If none of the three is 'auto': If both 'margin-left' and 'margin-
- * right' are 'auto', solve the equation under the extra constraint that
- * the two margins get equal values, unless this would make them negative,
- * in which case when direction of the containing block is 'ltr' ('rtl'),
- * set 'margin-left' ('margin-right') to zero and solve for 'margin-right'
- * ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto',
- * solve the equation for that value. If the values are over-constrained,
- * ignore the value for 'left' (in case the 'direction' property of the
- * containing block is 'rtl') or 'right' (in case 'direction' is 'ltr')
- * and solve for that value.
- \*-----------------------------------------------------------------------*/
- // NOTE: It is not necessary to solve for 'right' in the over constrained
- // case because the value is not used for any further calculations.
-
- leftValue = left.width(containerWidth);
- widthValue = calcContentWidth(width.width(containerWidth));
-
- const int availableSpace = containerWidth - (leftValue + widthValue + right.width(containerWidth) + bordersPlusPadding);
-
- // Margins are now the only unknown
- if (marginLeft.isVariable() && marginRight.isVariable()) {
- // Both margins auto, solve for equality
- if (availableSpace >= 0) {
- marginLeftValue = availableSpace / 2; // split the diference
- marginRightValue = availableSpace - marginLeftValue; // account for odd valued differences
- } else {
- // see FIXME 1
- if (containerDirection == LTR) {
- marginLeftValue = 0;
- marginRightValue = availableSpace; // will be negative
- } else {
- marginLeftValue = availableSpace; // will be negative
- marginRightValue = 0;
- }
- }
- } else if (marginLeft.isVariable()) {
- // Solve for left margin
- marginRightValue = marginRight.width(containerWidth);
- marginLeftValue = availableSpace - marginRightValue;
- } else if (marginRight.isVariable()) {
- // Solve for right margin
- marginLeftValue = marginLeft.width(containerWidth);
- marginRightValue = availableSpace - marginLeftValue;
- } else {
- // Over-constrained, solve for left if direction is RTL
- marginLeftValue = marginLeft.width(containerWidth);
- marginRightValue = marginRight.width(containerWidth);
-
- // see FIXME 1 -- used to be "this->style()->direction()"
- if (containerDirection == RTL)
- leftValue = (availableSpace + leftValue) - marginLeftValue - marginRightValue;
- }
- } else {
- /*--------------------------------------------------------------------*\
- * Otherwise, set 'auto' values for 'margin-left' and 'margin-right'
- * to 0, and pick the one of the following six rules that applies.
- *
- * 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the
- * width is shrink-to-fit. Then solve for 'left'
- *
- * OMIT RULE 2 AS IT SHOULD NEVER BE HIT
- * ------------------------------------------------------------------
- * 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if
- * the 'direction' property of the containing block is 'ltr' set
- * 'left' to the static position, otherwise set 'right' to the
- * static position. Then solve for 'left' (if 'direction is 'rtl')
- * or 'right' (if 'direction' is 'ltr').
- * ------------------------------------------------------------------
- *
- * 3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the
- * width is shrink-to-fit . Then solve for 'right'
- * 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve
- * for 'left'
- * 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve
- * for 'width'
- * 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve
- * for 'right'
- *
- * Calculation of the shrink-to-fit width is similar to calculating the
- * width of a table cell using the automatic table layout algorithm.
- * Roughly: calculate the preferred width by formatting the content
- * without breaking lines other than where explicit line breaks occur,
- * and also calculate the preferred minimum width, e.g., by trying all
- * possible line breaks. CSS 2.1 does not define the exact algorithm.
- * Thirdly, calculate the available width: this is found by solving
- * for 'width' after setting 'left' (in case 1) or 'right' (in case 3)
- * to 0.
- *
- * Then the shrink-to-fit width is:
- * kMin(kMax(preferred minimum width, available width), preferred width).
- \*--------------------------------------------------------------------*/
- // NOTE: For rules 3 and 6 it is not necessary to solve for 'right'
- // because the value is not used for any further calculations.
-
- // Calculate margins, 'auto' margins are ignored.
- marginLeftValue = marginLeft.minWidth(containerWidth);
- marginRightValue = marginRight.minWidth(containerWidth);
-
- const int availableSpace = containerWidth - (marginLeftValue + marginRightValue + bordersPlusPadding);
-
- // FIXME: Is there a faster way to find the correct case?
- // Use rule/case that applies.
- if (leftIsAuto && widthIsAuto && !rightIsAuto) {
- // RULE 1: (use shrink-to-fit for width, and solve of left)
- int rightValue = right.width(containerWidth);
-
- // FIXME: would it be better to have shrink-to-fit in one step?
- int preferredWidth = m_maxWidth - bordersPlusPadding;
- int preferredMinWidth = m_minWidth - bordersPlusPadding;
- int availableWidth = availableSpace - rightValue;
- widthValue = kMin(kMax(preferredMinWidth, availableWidth), preferredWidth);
- leftValue = availableSpace - (widthValue + rightValue);
- } else if (!leftIsAuto && widthIsAuto && rightIsAuto) {
- // RULE 3: (use shrink-to-fit for width, and no need solve of right)
- leftValue = left.width(containerWidth);
-
- // FIXME: would it be better to have shrink-to-fit in one step?
- int preferredWidth = m_maxWidth - bordersPlusPadding;
- int preferredMinWidth = m_minWidth - bordersPlusPadding;
- int availableWidth = availableSpace - leftValue;
- widthValue = kMin(kMax(preferredMinWidth, availableWidth), preferredWidth);
- } else if (leftIsAuto && !width.isVariable() && !rightIsAuto) {
- // RULE 4: (solve for left)
- widthValue = calcContentWidth(width.width(containerWidth));
- leftValue = availableSpace - (widthValue + right.width(containerWidth));
- } else if (!leftIsAuto && widthIsAuto && !rightIsAuto) {
- // RULE 5: (solve for width)
- leftValue = left.width(containerWidth);
- widthValue = availableSpace - (leftValue + right.width(containerWidth));
- } else if (!leftIsAuto&& !widthIsAuto && rightIsAuto) {
- // RULE 6: (no need solve for right)
- leftValue = left.width(containerWidth);
- widthValue = calcContentWidth(width.width(containerWidth));
- }
- }
-
- // Use computed values to calculate the horizontal position.
- xPos = leftValue + marginLeftValue + containerBlock->borderLeft();
-}
-
-
-void RenderBox::calcAbsoluteVertical()
-{
- if (isReplaced()) {
- calcAbsoluteVerticalReplaced();
- return;
- }
-
- // The following is based off of the W3C Working Draft from April 11, 2006 of
- // CSS 2.1: Section 10.6.4 "Absolutely positioned, non-replaced elements"
- // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-non-replaced-height>
- // (block-style-comments in this function and in calcAbsoluteVerticalValues()
- // correspond to text from the spec)
-
-
- // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
- const RenderObject* containerBlock = container();
- const int containerHeight = containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom();
-
- const int bordersPlusPadding = borderTop() + borderBottom() + paddingTop() + paddingBottom();
- const Length marginTop = style()->marginTop();
- const Length marginBottom = style()->marginBottom();
- Length top = style()->top();
- Length bottom = style()->bottom();
-
- /*---------------------------------------------------------------------------*\
- * For the purposes of this section and the next, the term "static position"
- * (of an element) refers, roughly, to the position an element would have had
- * in the normal flow. More precisely, the static position for 'top' is the
- * distance from the top edge of the containing block to the top margin edge
- * of a hypothetical box that would have been the first box of the element if
- * its 'position' property had been 'static' and 'float' had been 'none'. The
- * value is negative if the hypothetical box is above the containing block.
- *
- * But rather than actually calculating the dimensions of that hypothetical
- * box, user agents are free to make a guess at its probable position.
- *
- * For the purposes of calculating the static position, the containing block
- * of fixed positioned elements is the initial containing block instead of
- * the viewport.
- \*---------------------------------------------------------------------------*/
-
- // Calculate the static distance if needed.
- if (top.isVariable() && bottom.isVariable()) {
- // m_staticY should already have been set through layout of the parent()
- int staticTop = m_staticY - containerBlock->borderTop();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
- staticTop += po->yPos();
- }
- top.setValue(Fixed, staticTop);
- }
-
-
- int height; // Needed to compute overflow.
-
- // Calculate constraint equation values for 'height' case.
- calcAbsoluteVerticalValues(style()->height(), containerBlock, containerHeight, bordersPlusPadding,
- top, bottom, marginTop, marginBottom,
- height, m_marginTop, m_marginBottom, m_y);
-
- // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
- // see FIXME 2
-
- // Calculate constraint equation values for 'max-height' case.
- if (style()->maxHeight().value() != UNDEFINED) {
- int maxHeight;
- short maxMarginTop;
- short maxMarginBottom;
- int maxYPos;
-
- calcAbsoluteVerticalValues(style()->maxHeight(), containerBlock, containerHeight, bordersPlusPadding,
- top, bottom, marginTop, marginBottom,
- maxHeight, maxMarginTop, maxMarginBottom, maxYPos);
-
- if (height > maxHeight) {
- height = maxHeight;
- m_marginTop = maxMarginTop;
- m_marginBottom = maxMarginBottom;
- m_y = maxYPos;
- }
- }
-
- // Calculate constraint equation values for 'min-height' case.
- if (style()->minHeight().value()) {
- int minHeight;
- short minMarginTop;
- short minMarginBottom;
- int minYPos;
-
- calcAbsoluteVerticalValues(style()->minHeight(), containerBlock, containerHeight, bordersPlusPadding,
- top, bottom, marginTop, marginBottom,
- minHeight, minMarginTop, minMarginBottom, minYPos);
-
- if (height < minHeight) {
- height = minHeight;
- m_marginTop = minMarginTop;
- m_marginBottom = minMarginBottom;
- m_y = minYPos;
- }
- }
-
- height += bordersPlusPadding;
-
- // Set final height value.
- m_height = height;
-}
-
-void RenderBox::calcAbsoluteVerticalValues(Length height, const RenderObject* containerBlock,
- const int containerHeight, const int bordersPlusPadding,
- const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
- int& heightValue, short& marginTopValue, short& marginBottomValue, int& yPos)
-{
- // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
- // converted to the static position in calcAbsoluteVertical()
- assert(!(top.isVariable() && bottom.isVariable()));
-
- int contentHeight = m_height - bordersPlusPadding;
-
- int topValue = 0;
-
- bool heightIsAuto = height.isVariable();
- bool topIsAuto = top.isVariable();
- bool bottomIsAuto = bottom.isVariable();
-
- if (isTable() && heightIsAuto) {
- // Height is never unsolved for tables. "auto" means shrink to fit.
- // Use our height instead.
- heightValue = contentHeight;
- heightIsAuto = false;
- } else if (!heightIsAuto) {
- heightValue = calcContentHeight(height.width(containerHeight));
- if (contentHeight > heightValue) {
- if (!isTable())
- contentHeight = heightValue;
- else
- heightValue = contentHeight;
- }
- }
-
-
- if (!topIsAuto && !heightIsAuto && !bottomIsAuto) {
- /*-----------------------------------------------------------------------*\
- * If none of the three are 'auto': If both 'margin-top' and 'margin-
- * bottom' are 'auto', solve the equation under the extra constraint that
- * the two margins get equal values. If one of 'margin-top' or 'margin-
- * bottom' is 'auto', solve the equation for that value. If the values
- * are over-constrained, ignore the value for 'bottom' and solve for that
- * value.
- \*-----------------------------------------------------------------------*/
- // NOTE: It is not necessary to solve for 'bottom' in the over constrained
- // case because the value is not used for any further calculations.
-
- topValue = top.width(containerHeight);
-
- const int availableSpace = containerHeight - (topValue + heightValue + bottom.width(containerHeight) + bordersPlusPadding);
-
- // Margins are now the only unknown
- if (marginTop.isVariable() && marginBottom.isVariable()) {
- // Both margins auto, solve for equality
- // NOTE: This may result in negative values.
- marginTopValue = availableSpace / 2; // split the diference
- marginBottomValue = availableSpace - marginTopValue; // account for odd valued differences
- } else if (marginTop.isVariable()) {
- // Solve for top margin
- marginBottomValue = marginBottom.width(containerHeight);
- marginTopValue = availableSpace - marginBottomValue;
- } else if (marginBottom.isVariable()) {
- // Solve for bottom margin
- marginTopValue = marginTop.width(containerHeight);
- marginBottomValue = availableSpace - marginTopValue;
- } else {
- // Over-constrained, (no need solve for bottom)
- marginTopValue = marginTop.width(containerHeight);
- marginBottomValue = marginBottom.width(containerHeight);
- }
- } else {
- /*--------------------------------------------------------------------*\
- * Otherwise, set 'auto' values for 'margin-top' and 'margin-bottom'
- * to 0, and pick the one of the following six rules that applies.
- *
- * 1. 'top' and 'height' are 'auto' and 'bottom' is not 'auto', then
- * the height is based on the content, and solve for 'top'.
- *
- * OMIT RULE 2 AS IT SHOULD NEVER BE HIT
- * ------------------------------------------------------------------
- * 2. 'top' and 'bottom' are 'auto' and 'height' is not 'auto', then
- * set 'top' to the static position, and solve for 'bottom'.
- * ------------------------------------------------------------------
- *
- * 3. 'height' and 'bottom' are 'auto' and 'top' is not 'auto', then
- * the height is based on the content, and solve for 'bottom'.
- * 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', and
- * solve for 'top'.
- * 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', and
- * solve for 'height'.
- * 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', and
- * solve for 'bottom'.
- \*--------------------------------------------------------------------*/
- // NOTE: For rules 3 and 6 it is not necessary to solve for 'bottom'
- // because the value is not used for any further calculations.
-
- // Calculate margins, 'auto' margins are ignored.
- marginTopValue = marginTop.minWidth(containerHeight);
- marginBottomValue = marginBottom.minWidth(containerHeight);
-
- const int availableSpace = containerHeight - (marginTopValue + marginBottomValue + bordersPlusPadding);
-
- // Use rule/case that applies.
- if (topIsAuto && heightIsAuto && !bottomIsAuto) {
- // RULE 1: (height is content based, solve of top)
- heightValue = contentHeight;
- topValue = availableSpace - (heightValue + bottom.width(containerHeight));
- }
- else if (topIsAuto && !heightIsAuto && bottomIsAuto) {
- // RULE 2: (shouldn't happen)
- }
- else if (!topIsAuto && heightIsAuto && bottomIsAuto) {
- // RULE 3: (height is content based, no need solve of bottom)
- heightValue = contentHeight;
- topValue = top.width(containerHeight);
- } else if (topIsAuto && !heightIsAuto && !bottomIsAuto) {
- // RULE 4: (solve of top)
- topValue = availableSpace - (heightValue + bottom.width(containerHeight));
- } else if (!topIsAuto && heightIsAuto && !bottomIsAuto) {
- // RULE 5: (solve of height)
- topValue = top.width(containerHeight);
- heightValue = kMax(0, availableSpace - (topValue + bottom.width(containerHeight)));
- } else if (!topIsAuto && !heightIsAuto && bottomIsAuto) {
- // RULE 6: (no need solve of bottom)
- topValue = top.width(containerHeight);
- }
- }
-
- // Use computed values to calculate the vertical position.
- yPos = topValue + marginTopValue + containerBlock->borderTop();
-}
-
-void RenderBox::calcAbsoluteHorizontalReplaced()
-{
- // The following is based off of the W3C Working Draft from April 11, 2006 of
- // CSS 2.1: Section 10.3.8 "Absolutly positioned, replaced elements"
- // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
- // (block-style-comments in this function correspond to text from the spec and
- // the numbers correspond to numbers in spec)
-
- // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
- const RenderObject* containerBlock = container();
-
- // FIXME: This is incorrect for cases where the container block is a relatively
- // positioned inline.
- const int containerWidth = containingBlockWidth() + containerBlock->paddingLeft() + containerBlock->paddingRight();
-
- // To match WinIE, in quirks mode use the parent's 'direction' property
- // instead of the the container block's.
- EDirection containerDirection = (style()->htmlHacks()) ? parent()->style()->direction() : containerBlock->style()->direction();
-
- // Variables to solve.
- Length left = style()->left();
- Length right = style()->right();
- Length marginLeft = style()->marginLeft();
- Length marginRight = style()->marginRight();
-
-
- /*-----------------------------------------------------------------------*\
- * 1. The used value of 'width' is determined as for inline replaced
- * elements.
- \*-----------------------------------------------------------------------*/
- // NOTE: This value of width is FINAL in that the min/max width calculations
- // are dealt with in calcReplacedWidth(). This means that the steps to produce
- // correct max/min in the non-replaced version, are not necessary.
- m_width = calcReplacedWidth() + borderLeft() + borderRight() + paddingLeft() + paddingRight();
- const int availableSpace = containerWidth - m_width;
-
- /*-----------------------------------------------------------------------*\
- * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
- * of the containing block is 'ltr', set 'left' to the static position;
- * else if 'direction' is 'rtl', set 'right' to the static position.
- \*-----------------------------------------------------------------------*/
- if (left.isVariable() && right.isVariable()) {
- // see FIXME 1
- if (containerDirection == LTR) {
- // 'm_staticX' should already have been set through layout of the parent.
- int staticPosition = m_staticX - containerBlock->borderLeft();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent())
- staticPosition += po->xPos();
- left.setValue(Fixed, staticPosition);
- } else {
- RenderObject* po = parent();
- // 'm_staticX' should already have been set through layout of the parent.
- int staticPosition = m_staticX + containerWidth + containerBlock->borderRight() - po->width();
- for (; po && po != containerBlock; po = po->parent())
- staticPosition -= po->xPos();
- right.setValue(Fixed, staticPosition);
- }
- }
-
- /*-----------------------------------------------------------------------*\
- * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
- * or 'margin-right' with '0'.
- \*-----------------------------------------------------------------------*/
- if (left.isVariable() || right.isVariable()) {
- if (marginLeft.isVariable())
- marginLeft.setValue(Fixed, 0);
- if (marginRight.isVariable())
- marginRight.setValue(Fixed, 0);
- }
-
- /*-----------------------------------------------------------------------*\
- * 4. If at this point both 'margin-left' and 'margin-right' are still
- * 'auto', solve the equation under the extra constraint that the two
- * margins must get equal values, unless this would make them negative,
- * in which case when the direction of the containing block is 'ltr'
- * ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
- * 'margin-right' ('margin-left').
- \*-----------------------------------------------------------------------*/
- int leftValue = 0;
- int rightValue = 0;
-
- if (marginLeft.isVariable() && marginRight.isVariable()) {
- // 'left' and 'right' cannot be 'auto' due to step 3
- assert(!(left.isVariable() && right.isVariable()));
-
- leftValue = left.width(containerWidth);
- rightValue = right.width(containerWidth);
-
- int difference = availableSpace - (leftValue + rightValue);
- if (difference > 0) {
- m_marginLeft = difference / 2; // split the diference
- m_marginRight = difference - m_marginLeft; // account for odd valued differences
- } else {
- // see FIXME 1
- if (containerDirection == LTR) {
- m_marginLeft = 0;
- m_marginRight = difference; // will be negative
- } else {
- m_marginLeft = difference; // will be negative
- m_marginRight = 0;
- }
- }
-
- /*-----------------------------------------------------------------------*\
- * 5. If at this point there is an 'auto' left, solve the equation for
- * that value.
- \*-----------------------------------------------------------------------*/
- } else if (left.isVariable()) {
- m_marginLeft = marginLeft.width(containerWidth);
- m_marginRight = marginRight.width(containerWidth);
- rightValue = right.width(containerWidth);
-
- // Solve for 'left'
- leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight);
- } else if (right.isVariable()) {
- m_marginLeft = marginLeft.width(containerWidth);
- m_marginRight = marginRight.width(containerWidth);
- leftValue = left.width(containerWidth);
-
- // Solve for 'right'
- rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight);
- } else if (marginLeft.isVariable()) {
- m_marginRight = marginRight.width(containerWidth);
- leftValue = left.width(containerWidth);
- rightValue = right.width(containerWidth);
-
- // Solve for 'margin-left'
- m_marginLeft = availableSpace - (leftValue + rightValue + m_marginRight);
- } else if (marginRight.isVariable()) {
- m_marginLeft = marginLeft.width(containerWidth);
- leftValue = left.width(containerWidth);
- rightValue = right.width(containerWidth);
-
- // Solve for 'margin-right'
- m_marginRight = availableSpace - (leftValue + rightValue + m_marginLeft);
- }
-
- /*-----------------------------------------------------------------------*\
- * 6. If at this point the values are over-constrained, ignore the value
- * for either 'left' (in case the 'direction' property of the
- * containing block is 'rtl') or 'right' (in case 'direction' is
- * 'ltr') and solve for that value.
- \*-----------------------------------------------------------------------*/
- else {
- m_marginLeft = marginLeft.width(containerWidth);
- m_marginRight = marginRight.width(containerWidth);
- if (containerDirection == LTR) {
- leftValue = left.width(containerWidth);
- rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight);
- }
- else {
- rightValue = right.width(containerWidth);
- leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight);
- }
- }
-
- int totalWidth = m_width + leftValue + rightValue + m_marginLeft + m_marginRight;
- if (totalWidth > containerWidth && (containerDirection == RTL))
- leftValue = containerWidth - (totalWidth - leftValue);
-
- // Use computed values to calculate the horizontal position.
- m_x = leftValue + m_marginLeft + containerBlock->borderLeft();
-}
-
-void RenderBox::calcAbsoluteVerticalReplaced()
-{
- // The following is based off of the W3C Working Draft from April 11, 2006 of
- // CSS 2.1: Section 10.6.5 "Absolutly positioned, replaced elements"
- // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
- // (block-style-comments in this function correspond to text from the spec and
- // the numbers correspond to numbers in spec)
-
- // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
- const RenderObject* containerBlock = container();
- const int containerHeight = containerBlock->height() - containerBlock->borderTop() - containerBlock->borderBottom();
-
- // Variables to solve.
- Length top = style()->top();
- Length bottom = style()->bottom();
- Length marginTop = style()->marginTop();
- Length marginBottom = style()->marginBottom();
-
-
- /*-----------------------------------------------------------------------*\
- * 1. The used value of 'height' is determined as for inline replaced
- * elements.
- \*-----------------------------------------------------------------------*/
- // NOTE: This value of height is FINAL in that the min/max height calculations
- // are dealt with in calcReplacedHeight(). This means that the steps to produce
- // correct max/min in the non-replaced version, are not necessary.
- m_height = calcReplacedHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom();
- const int availableSpace = containerHeight - m_height;
-
- /*-----------------------------------------------------------------------*\
- * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
- * with the element's static position.
- \*-----------------------------------------------------------------------*/
- if (top.isVariable() && bottom.isVariable()) {
- // m_staticY should already have been set through layout of the parent().
- int staticTop = m_staticY - containerBlock->borderTop();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
- staticTop += po->yPos();
- }
- top.setValue(Fixed, staticTop);
- }
-
- /*-----------------------------------------------------------------------*\
- * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
- * 'margin-bottom' with '0'.
- \*-----------------------------------------------------------------------*/
- // FIXME: The spec. says that this step should only be taken when bottom is
- // auto, but if only top is auto, this makes step 4 impossible.
- if (top.isVariable() || bottom.isVariable()) {
- if (marginTop.isVariable())
- marginTop.setValue(Fixed, 0);
- if (marginBottom.isVariable())
- marginBottom.setValue(Fixed, 0);
- }
-
- /*-----------------------------------------------------------------------*\
- * 4. If at this point both 'margin-top' and 'margin-bottom' are still
- * 'auto', solve the equation under the extra constraint that the two
- * margins must get equal values.
- \*-----------------------------------------------------------------------*/
- int topValue = 0;
- int bottomValue = 0;
-
- if (marginTop.isVariable() && marginBottom.isVariable()) {
- // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combinded.
- assert(!(top.isVariable() || bottom.isVariable()));
-
- topValue = top.width(containerHeight);
- bottomValue = bottom.width(containerHeight);
-
- int difference = availableSpace - (topValue + bottomValue);
- // NOTE: This may result in negative values.
- m_marginTop = difference / 2; // split the difference
- m_marginBottom = difference - m_marginTop; // account for odd valued differences
-
- /*-----------------------------------------------------------------------*\
- * 5. If at this point there is only one 'auto' left, solve the equation
- * for that value.
- \*-----------------------------------------------------------------------*/
- } else if (top.isVariable()) {
- m_marginTop = marginTop.width(containerHeight);
- m_marginBottom = marginBottom.width(containerHeight);
- bottomValue = bottom.width(containerHeight);
-
- // Solve for 'top'
- topValue = availableSpace - (bottomValue + m_marginTop + m_marginBottom);
- } else if (bottom.isVariable()) {
- m_marginTop = marginTop.width(containerHeight);
- m_marginBottom = marginBottom.width(containerHeight);
- topValue = top.width(containerHeight);
-
- // Solve for 'bottom'
- // NOTE: It is not necessary to solve for 'bottom' because we don't ever
- // use the value.
- } else if (marginTop.isVariable()) {
- m_marginBottom = marginBottom.width(containerHeight);
- topValue = top.width(containerHeight);
- bottomValue = bottom.width(containerHeight);
-
- // Solve for 'margin-top'
- m_marginTop = availableSpace - (topValue + bottomValue + m_marginBottom);
- } else if (marginBottom.isVariable()) {
- m_marginTop = marginTop.width(containerHeight);
- topValue = top.width(containerHeight);
- bottomValue = bottom.width(containerHeight);
-
- // Solve for 'margin-bottom'
- m_marginBottom = availableSpace - (topValue + bottomValue + m_marginTop);
- }
-
- /*-----------------------------------------------------------------------*\
- * 6. If at this point the values are over-constrained, ignore the value
- * for 'bottom' and solve for that value.
- \*-----------------------------------------------------------------------*/
- else {
- m_marginTop = marginTop.width(containerHeight);
- m_marginBottom = marginBottom.width(containerHeight);
- topValue = top.width(containerHeight);
-
- // Solve for 'bottom'
- // NOTE: It is not necessary to solve for 'bottom' because we don't ever
- // use the value.
- }
-
- // Use computed values to calculate the vertical position.
- m_y = topValue + m_marginTop + containerBlock->borderTop();
-}
-
-int RenderBox::highestPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
-{
- return includeSelf ? 0 : m_height;
-}
-
-int RenderBox::lowestPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
-{
- return includeSelf ? m_height : 0;
-}
-
-int RenderBox::rightmostPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
-{
- return includeSelf ? m_width : 0;
-}
-
-int RenderBox::leftmostPosition(bool /*includeOverflowInterior*/, bool includeSelf) const
-{
- return includeSelf ? 0 : m_width;
-}
-
-int RenderBox::pageTopAfter(int y) const
-{
- RenderObject* cb = container();
- if (cb)
- return cb->pageTopAfter(y+yPos()) - yPos();
- else
- return 0;
-}
-
-int RenderBox::crossesPageBreak(int t, int b) const
-{
- RenderObject* cb = container();
- if (cb)
- return cb->crossesPageBreak(yPos()+t, yPos()+b);
- else
- return false;
-}
-
-void RenderBox::caretPos(int /*offset*/, int flags, int &_x, int &_y, int &width, int &height)
-{
-#if 0
- _x = -1;
-
- // propagate it downwards to its children, someone will feel responsible
- RenderObject *child = firstChild();
-// if (child) kdDebug(6040) << "delegating caretPos to " << child->renderName() << endl;
- if (child) child->caretPos(offset, override, _x, _y, width, height);
-
- // if not, use the extents of this box. offset 0 means left, offset 1 means
- // right
- if (_x == -1) {
- //kdDebug(6040) << "no delegation" << endl;
- _x = xPos() + (offset == 0 ? 0 : m_width);
- _y = yPos();
- height = m_height;
- width = override && offset == 0 ? m_width : 1;
-
- // If height of box is smaller than font height, use the latter one,
- // otherwise the caret might become invisible.
- // FIXME: ignoring :first-line, missing good reason to take care of
- int fontHeight = style()->fontMetrics().height();
- if (fontHeight > height)
- height = fontHeight;
-
- int absx, absy;
-
- RenderObject *cb = containingBlock();
-
- if (cb && cb != this && cb->absolutePosition(absx,absy)) {
- //kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
- _x += absx;
- _y += absy;
- } else {
- // we don't know our absolute position, and there is no point returning
- // just a relative one
- _x = _y = -1;
- }
- }
-#endif
-
- _x = xPos();
- _y = yPos();
-// kdDebug(6040) << "_x " << _x << " _y " << _y << endl;
- width = 1; // no override is indicated in boxes
-
- RenderBlock *cb = containingBlock();
-
- // Place caret outside the border
- if (flags & CFOutside) {
-
- RenderStyle *s = element() && element()->parent()
- && element()->parent()->renderer()
- ? element()->parent()->renderer()->style()
- : cb->style();
-
- const TQFontMetrics &fm = s->fontMetrics();
- height = fm.height();
-
- bool rtl = s->direction() == RTL;
- bool outsideEnd = flags & CFOutsideEnd;
-
- if (outsideEnd) {
- _x += this->width();
- } else {
- _x--;
- }
-
- int hl = fm.leading() / 2;
- if (!isReplaced() || style()->display() == BLOCK) {
- if (!outsideEnd ^ rtl)
- _y -= hl;
- else
- _y += kMax(this->height() - fm.ascent() - hl, 0);
- } else {
- _y += baselinePosition(false) - fm.ascent() - hl;
- }
-
- // Place caret inside the element
- } else {
- const TQFontMetrics &fm = style()->fontMetrics();
- height = fm.height();
-
- RenderStyle *s = style();
-
- _x += borderLeft() + paddingLeft();
- _y += borderTop() + paddingTop();
-
- // ### regard direction
- switch (s->textAlign()) {
- case LEFT:
- case KHTML_LEFT:
- case TAAUTO: // ### find out what this does
- case JUSTIFY:
- break;
- case CENTER:
- case KHTML_CENTER:
- _x += contentWidth() / 2;
- break;
- case KHTML_RIGHT:
- case RIGHT:
- _x += contentWidth();
- break;
- }
- }
-
- int absx, absy;
- if (cb && cb != this && cb->absolutePosition(absx,absy)) {
-// kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
- _x += absx;
- _y += absy;
- } else {
- // we don't know our absolute position, and there is no point returning
- // just a relative one
- _x = _y = -1;
- }
-}
-
-#undef DEBUG_LAYOUT
diff --git a/khtml/rendering/render_box.h b/khtml/rendering/render_box.h
deleted file mode 100644
index c0c618d5c..000000000
--- a/khtml/rendering/render_box.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_BOX_H
-#define RENDER_BOX_H
-
-#include "render_container.h"
-
-namespace khtml {
-
-enum WidthType { Width, MinWidth, MaxWidth };
-enum HeightType { Height, MinHeight, MaxHeight };
-
-class RenderBlock;
-
-class RenderBox : public RenderContainer
-{
-
-
-// combines ElemImpl & PosElImpl (all rendering objects are positioned)
-// should contain all border and padding handling
-
-public:
- RenderBox(DOM::NodeImpl* node);
- virtual ~RenderBox();
-
- virtual const char *renderName() const { return "RenderBox"; }
- virtual bool isBox() const { return true; }
-
- virtual void setStyle(RenderStyle *style);
- virtual void paint(PaintInfo& i, int _tx, int _ty);
-
- virtual void close();
-
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
- virtual void deleteInlineBoxes(RenderArena* arena=0);
-
- virtual void detach();
-
- virtual short minWidth() const { return m_minWidth; }
- virtual int maxWidth() const { return m_maxWidth; }
-
- virtual short contentWidth() const;
- virtual int contentHeight() const;
-
- virtual bool absolutePosition(int &xPos, int &yPos, bool f = false) const;
-
- virtual void setPos( int xPos, int yPos );
-
- virtual int xPos() const { return m_x; }
- virtual int yPos() const { return m_y; }
- virtual short width() const;
- virtual int height() const;
-
- virtual short marginTop() const { return m_marginTop; }
- virtual short marginBottom() const { return m_marginBottom; }
- virtual short marginLeft() const { return m_marginLeft; }
- virtual short marginRight() const { return m_marginRight; }
-
- virtual void setWidth( int width );
- virtual void setHeight( int height );
-
- virtual void position(InlineBox* box, int from, int len, bool reverse);
-
- virtual int highestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int leftmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
-
- virtual void repaint(Priority p=NormalPriority);
-
- virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
-
- virtual short containingBlockWidth() const;
- void relativePositionOffset(int &tx, int &ty) const;
-
- virtual void calcWidth();
- virtual void calcHeight();
-
- virtual short calcReplacedWidth() const;
- virtual int calcReplacedHeight() const;
-
- virtual int availableHeight() const;
- virtual int availableWidth() const;
-
- void calcVerticalMargins();
-
- virtual RenderLayer* layer() const { return m_layer; }
-
- void setStaticX(short staticX);
- void setStaticY(int staticY);
- int staticX() const { return m_staticX; }
- int staticY() const { return m_staticY; }
-
- virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
-
- void calcHorizontalMargins(const Length& ml, const Length& mr, int cw);
- RenderBlock* createAnonymousBlock();
-
- virtual int pageTopAfter(int y) const;
- virtual int crossesPageBreak(int t, int b) const;
-
- int calcBoxWidth(int w) const;
- int calcBoxHeight(int h) const;
- int calcContentWidth(int w) const;
- int calcContentHeight(int h) const;
-
-protected:
- int calcWidthUsing(WidthType widthType, int cw, LengthType& lengthType);
- int calcHeightUsing(const Length& height);
- int calcReplacedWidthUsing(WidthType widthType) const;
- int calcReplacedHeightUsing(HeightType heightType) const;
- int calcPercentageHeight(const Length& height, bool treatAsReplaced = false) const;
- int availableHeightUsing(const Length& h) const;
- int availableWidthUsing(const Length& w) const;
- int calcImplicitHeight() const;
- bool hasImplicitHeight() const {
- return isPositioned() && !style()->top().isVariable() && !style()->bottom().isVariable();
- }
-
-protected:
- virtual void paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty);
- void paintRootBoxDecorations( PaintInfo& paintInfo, int _tx, int _ty);
-
- void paintBackgrounds(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int h);
- void paintBackground(TQPainter *p, const TQColor& c, const BackgroundLayer* bgLayer, int clipy, int cliph, int _tx, int _ty, int w, int h);
-
- virtual void paintBackgroundExtended(TQPainter* /*p*/, const TQColor& /*c*/, const BackgroundLayer* /*bgLayer*/,
- int /*clipy*/, int /*cliph*/, int /*_tx*/, int /*_ty*/,
- int /*w*/, int /*height*/, int /*bleft*/, int /*bright*/, int /*pleft*/, int /*pright*/ );
-
- void outlineBox(TQPainter *p, int _tx, int _ty, const char *color = "red");
-
- void calcAbsoluteHorizontal();
- void calcAbsoluteVertical();
- void calcAbsoluteHorizontalValues(Length width, const RenderObject* cb, EDirection containerDirection,
- const int containerWidth, const int bordersPlusPadding,
- const Length left, const Length right, const Length marginLeft, const Length marginRight,
- short& widthValue, short& marginLeftValue, short& marginRightValue, short& xPos);
- void calcAbsoluteVerticalValues(Length height, const RenderObject* cb,
- const int containerHeight, const int bordersPlusPadding,
- const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
- int& heightValue, short& marginTopValue, short& marginBottomValue, int& yPos);
-
- void calcAbsoluteVerticalReplaced();
- void calcAbsoluteHorizontalReplaced();
-
- TQRect getOverflowClipRect(int tx, int ty);
- TQRect getClipRect(int tx, int ty);
-
- void restructureParentFlow();
-
-
- // the actual height of the contents + borders + padding (border-box)
- int m_height;
- int m_y;
-
- short m_width;
- short m_x;
-
- short m_marginTop;
- short m_marginBottom;
-
- short m_marginLeft;
- short m_marginRight;
-
- /*
- * the minimum width the element needs, to be able to render
- * its content without clipping
- */
- short m_minWidth;
- /* The maximum width the element can fill horizontally
- * ( = the width of the element with line breaking disabled)
- */
- int m_maxWidth;
-
- // Cached normal flow values for absolute positioned elements with static left/top values.
- short m_staticX;
- int m_staticY;
-
- RenderLayer *m_layer;
-
- /* A box used to represent this object on a line
- * when its inner content isn't contextually relevant
- * (e.g replaced or positioned elements)
- */
- InlineBox *m_placeHolderBox;
-};
-
-
-} //namespace
-
-#endif
diff --git a/khtml/rendering/render_br.cpp b/khtml/rendering/render_br.cpp
deleted file mode 100644
index 69984b760..000000000
--- a/khtml/rendering/render_br.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include "render_br.h"
-
-using namespace khtml;
-
-
-RenderBR::RenderBR(DOM::NodeImpl* node)
- : RenderText(node, new DOM::DOMStringImpl(TQChar('\n')))
-{
- m_hasReturn = true;
-}
-
-RenderBR::~RenderBR()
-{
-}
-
-#if 0
-void RenderBR::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
-{
- RenderText::caretPos(offset,flags,_x,_y,width,height);
- return;
-#if 0
- if (previousSibling() && !previousSibling()->isBR() && !previousSibling()->isFloating()) {
- int offset = 0;
- if (previousSibling()->isText())
- offset = static_cast<RenderText*>(previousSibling())->maxOffset();
-
- // FIXME: this won't return a big width in override mode (LS)
- previousSibling()->caretPos(offset,override,_x,_y,width,height);
- return;
- }
-
- int absx, absy;
- absolutePosition(absx,absy);
- if (absx == -1) {
- // we don't know out absolute position, and there is no point returning
- // just a relative one
- _x = _y = -1;
- }
- else {
- _x += absx;
- _y += absy;
- }
- height = RenderText::verticalPositionHint( false );
- width = override ? height / 2 : 1;
-#endif
-}
-#endif
-
-FindSelectionResult RenderBR::checkSelectionPoint(int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int &offset, SelPointState &state)
-{
- // Simply take result of previous one
- RenderText *prev = static_cast<RenderText *>(previousSibling());
- if (!prev || !prev->isText() || !prev->inlineTextBoxCount() || prev->isBR())
- prev = this;
-
- //kdDebug(6040) << "delegated to " << prev->renderName() << "@" << prev << endl;
- return prev->RenderText::checkSelectionPoint(_x, _y, _tx, _ty, node, offset, state);
-}
diff --git a/khtml/rendering/render_br.h b/khtml/rendering/render_br.h
deleted file mode 100644
index f4175015f..000000000
--- a/khtml/rendering/render_br.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_BR_H
-#define RENDER_BR_H
-
-#include "render_text.h"
-
-/*
- * The whole class here is a hack to get <br> working, as long as we don't have support for
- * CSS2 :before and :after pseudo elements
- */
-namespace khtml {
-
-class RenderBR : public RenderText
-{
-public:
- RenderBR(DOM::NodeImpl* node);
- virtual ~RenderBR();
-
- virtual const char *renderName() const { return "RenderBR"; }
-
- virtual void paint( PaintInfo&, int, int) {}
-
- virtual unsigned int width(unsigned int, unsigned int, const Font *) const { return 0; }
- virtual unsigned int width( unsigned int, unsigned int, bool) const { return 0; }
- virtual short width() const { return RenderText::width(); }
-
- virtual int height() const { return 0; }
-
- // overrides
- virtual void calcMinMaxWidth() {}
- virtual short minWidth() const { return 0; }
- virtual int maxWidth() const { return 0; }
-
- virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
- DOM::NodeImpl*& node, int & offset,
- SelPointState & );
-
- virtual bool isBR() const { return true; }
-#if 0
- virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
-#endif
- /** returns the lowest possible value the caret offset may have to
- * still point to a valid position.
- *
- * Returns 0.
- */
- virtual long minOffset() const { return 0; }
- /** returns the highest possible value the caret offset may have to
- * still point to a valid position.
- *
- * Returns also 0, as BRs have no width.
- */
- virtual long maxOffset() const { return 0; }
-};
-
-}
-#endif
diff --git a/khtml/rendering/render_canvas.cpp b/khtml/rendering/render_canvas.cpp
deleted file mode 100644
index e8540eba6..000000000
--- a/khtml/rendering/render_canvas.cpp
+++ /dev/null
@@ -1,780 +0,0 @@
-/**
- * This file is part of the HTML widget for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 2003 Apple Computer, Inc.
- * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-
-#include "rendering/render_canvas.h"
-#include "rendering/render_layer.h"
-#include "xml/dom_docimpl.h"
-
-#include "khtmlview.h"
-#include "khtml_part.h"
-#include <kdebug.h>
-#include <kglobal.h>
-
-using namespace khtml;
-
-//#define BOX_DEBUG
-//#define SPEED_DEBUG
-
-RenderCanvas::RenderCanvas(DOM::NodeImpl* node, KHTMLView *view)
- : RenderBlock(node)
-{
- // init RenderObject attributes
- setInline(false);
- setIsAnonymous(false);
-
- m_view = view;
- // try to contrain the width to the views width
-
- m_minWidth = 0;
- m_height = 0;
-
- m_width = m_minWidth;
- m_maxWidth = m_minWidth;
-
- m_rootWidth = m_rootHeight = 0;
- m_viewportWidth = m_viewportHeight = 0;
- m_cachedDocWidth = m_cachedDocHeight = -1;
-
- setPositioned(true); // to 0,0 :)
-
- m_staticMode = false;
- m_pagedMode = false;
- m_printImages = true;
-
- m_pageTop = 0;
- m_pageBottom = 0;
-
- m_page = 0;
-
- m_maximalOutlineSize = 0;
-
- m_selectionStart = 0;
- m_selectionEnd = 0;
- m_selectionStartPos = -1;
- m_selectionEndPos = -1;
-
- m_needsWidgetMasks = false;
-
- // Create a new root layer for our layer hierarchy.
- m_layer = new (node->getDocument()->renderArena()) RenderLayer(this);
-}
-
-RenderCanvas::~RenderCanvas()
-{
- delete m_page;
-}
-
-void RenderCanvas::setStyle(RenderStyle* style)
-{
- /*
- if (m_pagedMode)
- style->setOverflow(OHIDDEN); */
- RenderBlock::setStyle(style);
-}
-
-void RenderCanvas::calcHeight()
-{
- if (m_pagedMode || !m_view)
- m_height = m_rootHeight;
- else
- m_height = m_view->visibleHeight();
-}
-
-void RenderCanvas::calcWidth()
-{
- // the width gets set by KHTMLView::print when printing to a printer.
- if(m_pagedMode || !m_view)
- {
- m_width = m_rootWidth;
- return;
- }
-
- m_width = m_view ? m_view->frameWidth() : m_minWidth;
-
- if (style()->marginLeft().isFixed())
- m_marginLeft = style()->marginLeft().value();
- else
- m_marginLeft = 0;
-
- if (style()->marginRight().isFixed())
- m_marginRight = style()->marginRight().value();
- else
- m_marginRight = 0;
-}
-
-void RenderCanvas::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- RenderBlock::calcMinMaxWidth();
-
- m_maxWidth = m_minWidth;
-
- setMinMaxKnown();
-}
-
-//#define SPEED_DEBUG
-
-void RenderCanvas::layout()
-{
- if (m_pagedMode) {
- m_minWidth = m_width;
-// m_maxWidth = m_width;
- }
-
- m_needsFullRepaint = markedForRepaint() || !view() || view()->needsFullRepaint() || m_pagedMode;
-
- setChildNeedsLayout(true);
- setMinMaxKnown(false);
- for(RenderObject* c = firstChild(); c; c = c->nextSibling())
- c->setChildNeedsLayout(true);
-
- int oldWidth = m_width;
- int oldHeight = m_height;
-
- m_cachedDocWidth = m_cachedDocHeight = -1;
-
- if (m_pagedMode || !m_view) {
- m_width = m_rootWidth;
- m_height = m_rootHeight;
- }
- else
- {
- m_viewportWidth = m_width = m_view->visibleWidth();
- m_viewportHeight = m_height = m_view->visibleHeight();
- }
-
-#ifdef SPEED_DEBUG
- TQTime qt;
- qt.start();
-#endif
-
- if ( recalcMinMax() )
- recalcMinMaxWidths();
-
-#ifdef SPEED_DEBUG
- kdDebug() << "RenderCanvas::calcMinMax time used=" << qt.elapsed() << endl;
- qt.start();
-#endif
-
- bool relayoutChildren = (oldWidth != m_width) || (oldHeight != m_height);
-
- RenderBlock::layoutBlock( relayoutChildren );
-
-#ifdef SPEED_DEBUG
- kdDebug() << "RenderCanvas::layout time used=" << qt.elapsed() << endl;
- qt.start();
-#endif
-
- updateDocumentSize();
-
- layer()->updateLayerPositions( layer(), needsFullRepaint(), true );
-
- if (!m_pagedMode && m_needsWidgetMasks)
- layer()->updateWidgetMasks(layer());
-
- scheduleDeferredRepaints();
- setNeedsLayout(false);
-
-#ifdef SPEED_DEBUG
- kdDebug() << "RenderCanvas::end time used=" << qt.elapsed() << endl;
-#endif
-}
-
-void RenderCanvas::updateDocumentSize()
-{
- // update our cached document size
- int hDocH = m_cachedDocHeight = docHeight();
- int hDocW = m_cachedDocWidth = docWidth();
-
- if (!m_pagedMode && m_view) {
-
- bool vss = m_view->verticalScrollBar()->isShown();
- bool hss = m_view->horizontalScrollBar()->isShown();
- TQSize s = m_view->viewportSize(m_cachedDocWidth, m_cachedDocHeight);
-
- // if we are about to show a scrollbar, and the document is sized to the viewport w or h,
- // then reserve the scrollbar space so that it doesn't trigger the _other_ scrollbar
-
- if (!vss && m_width - m_view->verticalScrollBar()->sizeHint().width() == s.width() &&
- m_cachedDocWidth <= m_width)
- hDocW = kMin( m_cachedDocWidth, s.width() );
-
- if (!hss && m_height - m_view->horizontalScrollBar()->sizeHint().height() == s.height() &&
- m_cachedDocHeight <= m_height)
- hDocH = kMin( m_cachedDocHeight, s.height() );
-
- // likewise, if a scrollbar is shown, and we have a cunning plan to turn it off,
- // think again if we are falling downright in the hysteresis zone
-
- if (vss && s.width() > m_cachedDocWidth && m_cachedDocWidth > m_view->visibleWidth())
- hDocW = s.width()+1;
-
- if (hss && s.height() > m_cachedDocHeight && m_cachedDocHeight > m_view->visibleHeight())
- hDocH = s.height()+1;
-
- m_view->resizeContents(hDocW, hDocH);
-
- setWidth( m_viewportWidth = s.width() );
- setHeight( m_viewportHeight = s.height() );
- }
- layer()->resize( kMax( m_cachedDocWidth,int( m_width ) ), kMax( m_cachedDocHeight,m_height ) );
-}
-
-void RenderCanvas::updateDocSizeAfterLayerTranslation( RenderObject* o, bool posXOffset, bool posYOffset )
-{
- if (needsLayout())
- return;
- int rightmost, lowest;
- o->absolutePosition( rightmost, lowest );
- if (posXOffset) {
- rightmost += o->rightmostPosition(false, true);
- setCachedDocWidth( kMax(docWidth(), rightmost) );
- } else {
- setCachedDocWidth( -1 );
- }
- if (posYOffset) {
- lowest += o->lowestPosition(false, true);
- setCachedDocHeight( kMax(docHeight(), lowest) );
- } else {
- setCachedDocHeight( -1 );
- }
-// kdDebug() << " posXOffset: " << posXOffset << " posYOffset " << posYOffset << " m_cachedDocWidth " << m_cachedDocWidth << " m_cachedDocHeight " << m_cachedDocHeight << endl;
- updateDocumentSize();
-}
-
-bool RenderCanvas::needsFullRepaint() const
-{
- return m_needsFullRepaint || m_pagedMode;
-}
-
-void RenderCanvas::repaintViewRectangle(int x, int y, int w, int h, bool asap)
-{
- KHTMLAssert( view() );
- view()->scheduleRepaint( x, y, w, h, asap );
-}
-
-bool RenderCanvas::absolutePosition(int &xPos, int &yPos, bool f) const
-{
- if ( f && m_pagedMode) {
- xPos = 0;
- yPos = m_pageTop;
- }
- else if ( f && m_view) {
- xPos = m_view->contentsX();
- yPos = m_view->contentsY();
- }
- else {
- xPos = yPos = 0;
- }
- return true;
-}
-
-void RenderCanvas::paint(PaintInfo& paintInfo, int _tx, int _ty)
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << this << " ::paintObject() w/h = (" << width() << "/" << height() << ")" << endl;
-#endif
-
- // 1. paint background, borders etc
- if(paintInfo.phase == PaintActionElementBackground) {
- paintBoxDecorations(paintInfo, _tx, _ty);
- return;
- }
-
- // 2. paint contents
- for( RenderObject *child = firstChild(); child; child=child->nextSibling())
- if(!child->layer() && !child->isFloating())
- child->paint(paintInfo, _tx, _ty);
-
- // 3. paint floats.
- if (paintInfo.phase == PaintActionFloat)
- paintFloats(paintInfo, _tx, _ty);
-
-#ifdef BOX_DEBUG
- if (m_view)
- {
- _tx += m_view->contentsX();
- _ty += m_view->contentsY();
- }
-
- outlineBox(p, _tx, _ty);
-#endif
-
-}
-
-void RenderCanvas::paintBoxDecorations(PaintInfo& paintInfo, int /*_tx*/, int /*_ty*/)
-{
- if ((firstChild() && firstChild()->style()->visibility() == VISIBLE) || !view())
- return;
-
- paintInfo.p->fillRect(paintInfo.r, view()->palette().active().color(TQColorGroup::Base));
-}
-
-void RenderCanvas::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
-{
- if (m_staticMode) return;
-// kdDebug( 6040 ) << "updating views contents (" << x << "/" << y << ") (" << w << "/" << h << ")" << endl;
-
- if (f && m_pagedMode) {
- y += m_pageTop;
- } else
- if ( f && m_view ) {
- x += m_view->contentsX();
- y += m_view->contentsY();
- }
-
- TQRect vr = viewRect();
- TQRect ur(x, y, w, h);
-
- if (m_view && ur.intersects(vr)) {
-
- if (p == RealtimePriority)
- // ### KWQ's updateContents has an additional parameter "now".
- // It's not clear what the difference between updateContents(...,true)
- // and repaintContents(...) is. As Qt doesn't have this, I'm leaving it out. (LS)
- m_view->updateContents(ur/*, true*/);
- else if (p == HighPriority)
- m_view->scheduleRepaint(x, y, w, h, true /*asap*/);
- else
- m_view->scheduleRepaint(x, y, w, h);
- }
-}
-
-void RenderCanvas::deferredRepaint( RenderObject* o )
-{
- m_dirtyChildren.append( o );
-}
-
-void RenderCanvas::scheduleDeferredRepaints()
-{
- if (!needsFullRepaint()) {
- TQValueList<RenderObject*>::const_iterator it;
- for ( it = m_dirtyChildren.begin(); it != m_dirtyChildren.end(); ++it )
- (*it)->repaint();
- }
- //kdDebug(6040) << "scheduled deferred repaints: " << m_dirtyChildren.count() << " needed full repaint: " << needsFullRepaint() << endl;
- m_dirtyChildren.clear();
-}
-
-void RenderCanvas::repaint(Priority p)
-{
- if (m_view && !m_staticMode) {
- if (p == RealtimePriority) {
- //m_view->resizeContents(docWidth(), docHeight());
- m_view->unscheduleRepaint();
- if (needsLayout()) {
- m_view->scheduleRelayout();
- return;
- }
- // ### same as in repaintRectangle
- m_view->updateContents(m_view->contentsX(), m_view->contentsY(),
- m_view->visibleWidth(), m_view->visibleHeight()/*, true*/);
- }
- else if (p == HighPriority)
- m_view->scheduleRepaint(m_view->contentsX(), m_view->contentsY(),
- m_view->visibleWidth(), m_view->visibleHeight(), true /*asap*/);
- else
- m_view->scheduleRepaint(m_view->contentsX(), m_view->contentsY(),
- m_view->visibleWidth(), m_view->visibleHeight());
- }
-}
-
-static TQRect enclosingPositionedRect (RenderObject *n)
-{
- RenderObject *enclosingParent = n->containingBlock();
- TQRect rect(0,0,0,0);
- if (enclosingParent) {
- int ox, oy;
- enclosingParent->absolutePosition(ox, oy);
- int off = 0;
- if (!enclosingParent->hasOverflowClip()) {
- ox += enclosingParent->overflowLeft();
- oy += enclosingParent->overflowTop();
- }
- rect.setX(ox);
- rect.setY(oy);
- rect.setWidth(enclosingParent->effectiveWidth());
- rect.setHeight(enclosingParent->effectiveHeight());
- }
- return rect;
-}
-
-TQRect RenderCanvas::selectionRect() const
-{
- RenderObject *r = m_selectionStart;
- if (!r)
- return TQRect();
-
- TQRect selectionRect = enclosingPositionedRect(r);
-
- while (r && r != m_selectionEnd)
- {
- RenderObject* n;
- if ( !(n = r->firstChild()) ){
- if ( !(n = r->nextSibling()) )
- {
- n = r->parent();
- while (n && !n->nextSibling())
- n = n->parent();
- if (n)
- n = n->nextSibling();
- }
- }
- r = n;
- if (r) {
- selectionRect = selectionRect.unite(enclosingPositionedRect(r));
- }
- }
-
- return selectionRect;
-}
-
-void RenderCanvas::setSelection(RenderObject *s, int sp, RenderObject *e, int ep)
-{
- // Check we got valid renderobjects. www.msnbc.com and clicking
- // around, to find the case where this happened.
- if ( !s || !e )
- {
- kdWarning(6040) << "RenderCanvas::setSelection() called with start=" << s << " end=" << e << endl;
- return;
- }
-// kdDebug( 6040 ) << "RenderCanvas::setSelection(" << s << "," << sp << "," << e << "," << ep << ")" << endl;
-
- bool changedSelectionBorder = ( s != m_selectionStart || e != m_selectionEnd );
-
- // Cut out early if the selection hasn't changed.
- if ( !changedSelectionBorder && m_selectionStartPos == sp && m_selectionEndPos == ep )
- return;
-
- // Record the old selected objects. Will be used later
- // to delta against the selected objects.
-
- RenderObject *oldStart = m_selectionStart;
- int oldStartPos = m_selectionStartPos;
- RenderObject *oldEnd = m_selectionEnd;
- int oldEndPos = m_selectionEndPos;
- TQPtrList<RenderObject> oldSelectedInside;
- TQPtrList<RenderObject> newSelectedInside;
- RenderObject *os = oldStart;
-
- while (os && os != oldEnd)
- {
- RenderObject* no;
- if ( !(no = os->firstChild()) ){
- if ( !(no = os->nextSibling()) )
- {
- no = os->parent();
- while (no && !no->nextSibling())
- no = no->parent();
- if (no)
- no = no->nextSibling();
- }
- }
- if (os->selectionState() == SelectionInside && !oldSelectedInside.containsRef(os))
- oldSelectedInside.append(os);
-
- os = no;
- }
- if (changedSelectionBorder)
- clearSelection(false);
-
- while (s->firstChild())
- s = s->firstChild();
- while (e->lastChild())
- e = e->lastChild();
-
-#if 0
- bool changedSelectionBorder = ( s != m_selectionStart || e != m_selectionEnd );
-
- if ( !changedSelectionBorder && m_selectionStartPos == sp && m_selectionEndPos = ep )
- return;
-#endif
-
- // set selection start
- if (m_selectionStart)
- m_selectionStart->setIsSelectionBorder(false);
- m_selectionStart = s;
- if (m_selectionStart)
- m_selectionStart->setIsSelectionBorder(true);
- m_selectionStartPos = sp;
-
- // set selection end
- if (m_selectionEnd)
- m_selectionEnd->setIsSelectionBorder(false);
- m_selectionEnd = e;
- if (m_selectionEnd)
- m_selectionEnd->setIsSelectionBorder(true);
- m_selectionEndPos = ep;
-
-#if 0
- kdDebug( 6040 ) << "old selection (" << oldStart << "," << oldStartPos << "," << oldEnd << "," << oldEndPos << ")" << endl;
- kdDebug( 6040 ) << "new selection (" << s << "," << sp << "," << e << "," << ep << ")" << endl;
-#endif
-
- // update selection status of all objects between m_selectionStart and m_selectionEnd
- RenderObject* o = s;
-
- while (o && o!=e)
- {
- o->setSelectionState(SelectionInside);
-// kdDebug( 6040 ) << "setting selected " << o << ", " << o->isText() << endl;
- RenderObject* no;
- if ( !(no = o->firstChild()) )
- if ( !(no = o->nextSibling()) )
- {
- no = o->parent();
- while (no && !no->nextSibling())
- no = no->parent();
- if (no)
- no = no->nextSibling();
- }
- if (o->selectionState() == SelectionInside && !newSelectedInside.containsRef(o))
- newSelectedInside.append(o);
-
- o=no;
- }
- s->setSelectionState(SelectionStart);
- e->setSelectionState(SelectionEnd);
- if(s == e) s->setSelectionState(SelectionBoth);
-
- if (!m_view)
- return;
-
- newSelectedInside.removeRef(s);
- newSelectedInside.removeRef(e);
-
- TQRect updateRect;
-
- // Don't use repaint() because it will cause all rects to
- // be united (see khtmlview::scheduleRepaint()). Instead
- // just draw damage rects for objects that have a change
- // in selection state.
- // ### for Qt, updateContents will unite them, too. This has to be
- // circumvented somehow (LS)
-
- // Are any of the old fully selected objects not in the new selection?
- // If so we have to draw them.
- // Could be faster by building list of non-intersecting rectangles rather
- // than unioning rectangles.
- TQPtrListIterator<RenderObject> oldIterator(oldSelectedInside);
- bool firstRect = true;
- for (; oldIterator.current(); ++oldIterator){
- if (!newSelectedInside.containsRef(oldIterator.current())){
- if (firstRect){
- updateRect = enclosingPositionedRect(oldIterator.current());
- firstRect = false;
- }
- else
- updateRect = updateRect.unite(enclosingPositionedRect(oldIterator.current()));
- }
- }
- if (!firstRect){
- m_view->updateContents( updateRect );
- }
-
- // Are any of the new fully selected objects not in the previous selection?
- // If so we have to draw them.
- // Could be faster by building list of non-intersecting rectangles rather
- // than unioning rectangles.
- TQPtrListIterator<RenderObject> newIterator(newSelectedInside);
- firstRect = true;
- for (; newIterator.current(); ++newIterator){
- if (!oldSelectedInside.containsRef(newIterator.current())){
- if (firstRect){
- updateRect = enclosingPositionedRect(newIterator.current());
- firstRect = false;
- }
- else
- updateRect = updateRect.unite(enclosingPositionedRect(newIterator.current()));
- }
- }
- if (!firstRect) {
- m_view->updateContents( updateRect );
- }
-
- // Is the new starting object different, or did the position in the starting
- // element change? If so we have to draw it.
- if (oldStart != m_selectionStart ||
- (oldStart == oldEnd && (oldStartPos != m_selectionStartPos || oldEndPos != m_selectionEndPos)) ||
- (oldStart == m_selectionStart && oldStartPos != m_selectionStartPos)){
- m_view->updateContents( enclosingPositionedRect(m_selectionStart) );
- }
-
- // Draw the old selection start object if it's different than the new selection
- // start object.
- if (oldStart && oldStart != m_selectionStart){
- m_view->updateContents( enclosingPositionedRect(oldStart) );
- }
-
- // Does the selection span objects and is the new end object different, or did the position
- // in the end element change? If so we have to draw it.
- if (/*(oldStart != oldEnd || !oldEnd) &&*/
- (oldEnd != m_selectionEnd ||
- (oldEnd == m_selectionEnd && oldEndPos != m_selectionEndPos))){
- m_view->updateContents( enclosingPositionedRect(m_selectionEnd) );
- }
-
- // Draw the old selection end object if it's different than the new selection
- // end object.
- if (oldEnd && oldEnd != m_selectionEnd){
- m_view->updateContents( enclosingPositionedRect(oldEnd) );
- }
-}
-
-void RenderCanvas::clearSelection(bool doRepaint)
-{
- // update selection status of all objects between m_selectionStart and m_selectionEnd
- RenderObject* o = m_selectionStart;
- while (o && o!=m_selectionEnd)
- {
- if (o->selectionState()!=SelectionNone)
- if (doRepaint)
- o->repaint();
- o->setSelectionState(SelectionNone);
- o->repaint();
- RenderObject* no;
- if ( !(no = o->firstChild()) )
- if ( !(no = o->nextSibling()) )
- {
- no = o->parent();
- while (no && !no->nextSibling())
- no = no->parent();
- if (no)
- no = no->nextSibling();
- }
- o=no;
- }
- if (m_selectionEnd) {
- m_selectionEnd->setSelectionState(SelectionNone);
- if (doRepaint)
- m_selectionEnd->repaint();
- }
-
- // set selection start & end to 0
- if (m_selectionStart)
- m_selectionStart->setIsSelectionBorder(false);
- m_selectionStart = 0;
- m_selectionStartPos = -1;
-
- if (m_selectionEnd)
- m_selectionEnd->setIsSelectionBorder(false);
- m_selectionEnd = 0;
- m_selectionEndPos = -1;
-}
-
-void RenderCanvas::selectionStartEnd(int& spos, int& epos)
-{
- spos = m_selectionStartPos;
- epos = m_selectionEndPos;
-}
-
-TQRect RenderCanvas::viewRect() const
-{
- if (m_pagedMode)
- if (m_pageTop == m_pageBottom) {
- kdDebug(6040) << "viewRect: " << TQRect(0, m_pageTop, m_width, m_height) << endl;
- return TQRect(0, m_pageTop, m_width, m_height);
- }
- else {
- kdDebug(6040) << "viewRect: " << TQRect(0, m_pageTop, m_width, m_pageBottom - m_pageTop) << endl;
- return TQRect(0, m_pageTop, m_width, m_pageBottom - m_pageTop);
- }
- else if (m_view)
- return TQRect(m_view->contentsX(),
- m_view->contentsY(),
- m_view->visibleWidth(),
- m_view->visibleHeight());
- else
- return TQRect(0,0,m_rootWidth,m_rootHeight);
-}
-
-int RenderCanvas::docHeight() const
-{
- if (m_cachedDocHeight != -1)
- return m_cachedDocHeight;
-
- int h;
- if (m_pagedMode || !m_view)
- h = m_height;
- else
- h = 0;
-
- RenderObject *fc = firstChild();
- if(fc) {
- int dh = fc->overflowHeight() + fc->marginTop() + fc->marginBottom();
- int lowestPos = fc->lowestPosition(false);
-// kdDebug(6040) << "h " << h << " lowestPos " << lowestPos << " dh " << dh << " fc->rh " << fc->effectiveHeight() << " fc->height() " << fc->height() << endl;
- if( lowestPos > dh )
- dh = lowestPos;
- lowestPos = lowestAbsolutePosition();
- if( lowestPos > dh )
- dh = lowestPos;
- if( dh > h )
- h = dh;
- }
-
- RenderLayer *layer = m_layer;
- h = kMax( h, layer->yPos() + layer->height() );
-// kdDebug(6040) << "h " << h << " layer(" << layer->renderer()->renderName() << "@" << layer->renderer() << ")->height " << layer->height() << " lp " << (layer->yPos() + layer->height()) << " height() " << layer->renderer()->height() << " rh " << layer->renderer()->effectiveHeight() << endl;
- return h;
-}
-
-int RenderCanvas::docWidth() const
-{
- if (m_cachedDocWidth != -1)
- return m_cachedDocWidth;
-
- int w;
- if (m_pagedMode || !m_view)
- w = m_width;
- else
- w = 0;
-
- RenderObject *fc = firstChild();
- if(fc) {
- // ow: like effectiveWidth() but without the negative
- const int ow = fc->hasOverflowClip() ? fc->width() : fc->overflowWidth();
- int dw = ow + fc->marginLeft() + fc->marginRight();
- int rightmostPos = fc->rightmostPosition(false);
-// kdDebug(6040) << "w " << w << " rightmostPos " << rightmostPos << " dw " << dw << " fc->rw " << fc->effectiveWidth() << " fc->width() " << fc->width() << endl;
- if( rightmostPos > dw )
- dw = rightmostPos;
- rightmostPos = rightmostAbsolutePosition();
- if ( rightmostPos > dw )
- dw = rightmostPos;
- if( dw > w )
- w = dw;
- }
-
- RenderLayer *layer = m_layer;
- w = kMax( w, layer->xPos() + layer->width() );
-// kdDebug(6040) << "w " << w << " layer(" << layer->renderer()->renderName() << ")->width " << layer->width() << " rm " << (layer->xPos() + layer->width()) << " width() " << layer->renderer()->width() << " rw " << layer->renderer()->effectiveWidth() << endl;
- return w;
-}
-
-RenderPage* RenderCanvas::page() {
- if (!m_page) m_page = new RenderPage(this);
- return m_page;
-}
diff --git a/khtml/rendering/render_canvas.h b/khtml/rendering/render_canvas.h
deleted file mode 100644
index 17f279d7b..000000000
--- a/khtml/rendering/render_canvas.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * This file is part of the HTML widget for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef render_canvas_h
-#define render_canvas_h
-
-#include "render_block.h"
-
-class KHTMLView;
-class TQScrollView;
-
-namespace khtml {
-
-class RenderPage;
-class RenderStyle;
-
-enum CanvasMode {
- CanvasViewPort, // Paints inside a viewport
- CanvasPage, // Paints one page
- CanvasDocument // Paints the whole document
-};
-
-class RenderCanvas : public RenderBlock
-{
-public:
- RenderCanvas(DOM::NodeImpl* node, KHTMLView *view);
- ~RenderCanvas();
-
- virtual const char *renderName() const { return "RenderCanvas"; }
-
- virtual bool isCanvas() const { return true; }
-
- virtual void setStyle(RenderStyle *style);
- virtual void layout();
- virtual void calcWidth();
- virtual void calcHeight();
- virtual void calcMinMaxWidth();
- virtual bool absolutePosition(int &xPos, int&yPos, bool f = false) const;
-
- int docHeight() const;
- int docWidth() const;
-
- KHTMLView *view() const { return m_view; }
-
- virtual void repaint(Priority p=NormalPriority);
- virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
- void repaintViewRectangle(int x, int y, int w, int h, bool asap=false);
- bool needsFullRepaint() const;
- void deferredRepaint( RenderObject* o );
- void scheduleDeferredRepaints();
-
- virtual void paint(PaintInfo&, int tx, int ty);
- virtual void paintBoxDecorations(PaintInfo& paintInfo, int _tx, int _ty);
- virtual void setSelection(RenderObject *s, int sp, RenderObject *e, int ep);
- virtual void clearSelection(bool doRepaint=true);
- virtual RenderObject *selectionStart() const { return m_selectionStart; }
- virtual RenderObject *selectionEnd() const { return m_selectionEnd; }
-
- void setPrintImages(bool enable) { m_printImages = enable; }
- bool printImages() const { return m_printImages; }
-
- void setCanvasMode(CanvasMode mode) { m_canvasMode = mode; }
- CanvasMode canvasMode() const { return m_canvasMode; }
-
- void setPagedMode(bool b) { m_pagedMode = b; }
- void setStaticMode(bool b) { m_staticMode = b; }
-
- bool pagedMode() const { return m_pagedMode; }
- bool staticMode() const { return m_staticMode; }
-
- void setPageTop(int top) {
- m_pageTop = top;
-// m_y = top;
- }
- void setPageBottom(int bottom) { m_pageBottom = bottom; }
- int pageTop() const { return m_pageTop; }
- int pageBottom() const { return m_pageBottom; }
-
- int pageTopAfter(int y) const {
- if (pageHeight() == 0) return 0;
- return (y / pageHeight() + 1) * pageHeight() ;
- }
-
- int crossesPageBreak(int top, int bottom) const {
- if (pageHeight() == 0) return false;
- int pT = top / pageHeight();
- // bottom is actually the first line not in the box
- int pB = (bottom-1) / pageHeight();
- return (pT == pB) ? 0 : (pB + 1);
- }
-
- void setPageNumber(int number) { m_pageNr = number; }
- int pageNumber() const { return m_pageNr; }
-
-public:
- virtual void setWidth( int width ) { m_rootWidth = m_width = width; }
- virtual void setHeight( int height ) { m_rootHeight = m_height = height; }
-
-// void setPageHeight( int height ) { m_viewportHeight = m_pageHeight = height; }
- int pageHeight() const { return m_pageBottom - m_pageTop; }
-
- int viewportWidth() const { return m_viewportWidth; }
- int viewportHeight() const { return m_viewportHeight; }
-
- RenderPage* page();
-
- TQRect selectionRect() const;
-
- void setMaximalOutlineSize(int o) { m_maximalOutlineSize = o; }
- int maximalOutlineSize() const { return m_maximalOutlineSize; }
-
- void setNeedsWidgetMasks( bool b=true) { m_needsWidgetMasks = b; }
- bool needsWidgetMasks() const { return m_needsWidgetMasks; }
-
- void updateDocSizeAfterLayerTranslation( RenderObject* o, bool posXOffset, bool posYOffset );
-protected:
- // makes sure document, scrollbars and viewport size are accurate
- void updateDocumentSize();
-
- // internal setters for cached values of document width/height
- // Setting to -1/-1 invalidates the cache.
- void setCachedDocWidth(int w ) { m_cachedDocWidth = w; }
- void setCachedDocHeight(int h) { m_cachedDocHeight = h; }
-
- virtual void selectionStartEnd(int& spos, int& epos);
-
- virtual TQRect viewRect() const;
-
- KHTMLView *m_view;
-
- RenderObject* m_selectionStart;
- RenderObject* m_selectionEnd;
- int m_selectionStartPos;
- int m_selectionEndPos;
-
- CanvasMode m_canvasMode;
-
- int m_rootWidth;
- int m_rootHeight;
-
- int m_viewportWidth;
- int m_viewportHeight;
-
- int m_cachedDocWidth;
- int m_cachedDocHeight;
-
- bool m_printImages;
- bool m_needsFullRepaint;
-
- // Canvas is not interactive
- bool m_staticMode;
- // Canvas is paged
- bool m_pagedMode;
- // Canvas contains overlaid widgets
- bool m_needsWidgetMasks;
-
- short m_pageNr;
-
- int m_pageTop;
- int m_pageBottom;
-
- RenderPage* m_page;
-
- int m_maximalOutlineSize; // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
- TQValueList<RenderObject*> m_dirtyChildren;
-};
-
-inline RenderCanvas* RenderObject::canvas() const
-{
- return static_cast<RenderCanvas*>(document()->renderer());
-}
-
-// Represents the page-context of CSS
-class RenderPage
-{
-public:
- RenderPage(RenderCanvas* canvas) : m_canvas(canvas),
- m_marginTop(0), m_marginBottom(0),
- m_marginLeft(0), m_marginRight(0),
- m_pageWidth(0), m_pageHeight(0),
- m_fixedSize(false)
- {
- m_style = new RenderPageStyle();
- }
- virtual ~RenderPage()
- {
- delete m_style;
- }
-
- int marginTop() const { return m_marginTop; }
- int marginBottom() const { return m_marginBottom; }
- int marginLeft() const { return m_marginLeft; }
- int marginRight() const { return m_marginRight; }
-
- void setMarginTop(int margin) { m_marginTop = margin; }
- void setMarginBottom(int margin) { m_marginBottom = margin; }
- void setMarginLeft(int margin) { m_marginLeft = margin; }
- void setMarginRight(int margin) { m_marginRight = margin; }
-
- int pageWidth() const { return m_pageWidth; }
- int pageHeight() const { return m_pageHeight; }
-
- void setPageSize(int width, int height) {
- m_pageWidth = width;
- m_pageHeight = height;
- }
-
- // Returns true if size was set by document, false if set by user-agent
- bool fixedSize() const { return m_fixedSize; }
- void setFixedSize(bool b) { m_fixedSize = b; }
-
- RenderPageStyle* style() { return m_style; }
- const RenderPageStyle* style() const { return m_style; }
-
-protected:
- RenderCanvas* m_canvas;
- RenderPageStyle* m_style;
-
- int m_marginTop;
- int m_marginBottom;
- int m_marginLeft;
- int m_marginRight;
-
- int m_pageWidth;
- int m_pageHeight;
-
- bool m_fixedSize;
-};
-
-}
-#endif
diff --git a/khtml/rendering/render_container.cpp b/khtml/rendering/render_container.cpp
deleted file mode 100644
index 69f987477..000000000
--- a/khtml/rendering/render_container.cpp
+++ /dev/null
@@ -1,597 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2001-2003 Lars Knoll (knoll@kde.org)
- * (C) 2001 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2002-2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-//#define DEBUG_LAYOUT
-
-#include "rendering/render_container.h"
-#include "rendering/render_table.h"
-#include "rendering/render_text.h"
-#include "rendering/render_image.h"
-#include "rendering/render_canvas.h"
-#include "rendering/render_generated.h"
-#include "rendering/render_inline.h"
-#include "xml/dom_docimpl.h"
-#include "css/css_valueimpl.h"
-
-#include <kdebug.h>
-#include <assert.h>
-
-using namespace khtml;
-
-RenderContainer::RenderContainer(DOM::NodeImpl* node)
- : RenderObject(node)
-{
- m_first = 0;
- m_last = 0;
-}
-
-void RenderContainer::detach()
-{
- if (continuation())
- continuation()->detach();
-
- // We simulate removeNode calls for all our children
- // and set parent to 0 to avoid removeNode from being called.
- // First call removeLayers and removeFromObjectLists since they assume
- // a valid render-tree
- for(RenderObject* n = m_first; n; n = n->nextSibling() ) {
- n->removeLayers(enclosingLayer());
- n->removeFromObjectLists();
- }
-
- RenderObject* next;
- for(RenderObject* n = m_first; n; n = next ) {
- n->setParent(0);
- next = n->nextSibling();
- n->detach();
- }
- m_first = 0;
- m_last = 0;
-
- RenderObject::detach();
-}
-
-void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << this << ": " << renderName() << "(RenderObject)::addChild( " << newChild << ": " <<
- newChild->renderName() << ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
-#endif
- // protect ourselves from deletion
- setDoNotDelete(true);
-
- bool needsTable = false;
-
- if(!newChild->isText() && !newChild->isReplaced()) {
- switch(newChild->style()->display()) {
- case INLINE:
- case BLOCK:
- case LIST_ITEM:
- case RUN_IN:
- case COMPACT:
- case INLINE_BLOCK:
- case TABLE:
- case INLINE_TABLE:
- break;
- case TABLE_COLUMN:
- if ( isTableCol() )
- break;
- // nobreak
- case TABLE_COLUMN_GROUP:
- case TABLE_CAPTION:
- case TABLE_ROW_GROUP:
- case TABLE_HEADER_GROUP:
- case TABLE_FOOTER_GROUP:
-
- //kdDebug( 6040 ) << "adding section" << endl;
- if ( !isTable() )
- needsTable = true;
- break;
- case TABLE_ROW:
- //kdDebug( 6040 ) << "adding row" << endl;
- if ( !isTableSection() )
- needsTable = true;
- break;
- case TABLE_CELL:
- //kdDebug( 6040 ) << "adding cell" << endl;
- if ( !isTableRow() )
- needsTable = true;
- // I'm not 100% sure this is the best way to fix this, but without this
- // change we recurse infinitely when trying to render the CSS2 test page:
- // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
- if ( isTableCell() && !firstChild() && !newChild->isTableCell() )
- needsTable = false;
-
- break;
- case NONE:
- // RenderHtml and some others can have display:none
- // KHTMLAssert(false);
- break;
- }
- }
-
- if ( needsTable ) {
- RenderTable *table;
- RenderObject *last = beforeChild ? beforeChild->previousSibling() : lastChild();
- if ( last && last->isTable() && last->isAnonymous() ) {
- table = static_cast<RenderTable *>(last);
- } else {
- //kdDebug( 6040 ) << "creating anonymous table, before=" << beforeChild << endl;
- table = new (renderArena()) RenderTable(document() /* is anonymous */);
- RenderStyle *newStyle = new RenderStyle();
- newStyle->inheritFrom(style());
- newStyle->setDisplay( TABLE );
- newStyle->setFlowAroundFloats( true );
- table->setParent( this ); // so it finds the arena
- table->setStyle(newStyle);
- table->setParent( 0 );
- addChild(table, beforeChild);
- }
- table->addChild(newChild);
- } else {
- // just add it...
- insertChildNode(newChild, beforeChild);
- }
-
- if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
- DOM::DOMStringImpl* textToTransform = static_cast<RenderText*>(newChild)->originalString();
- if (textToTransform)
- static_cast<RenderText*>(newChild)->setText(textToTransform, true);
- }
- newChild->attach();
-
- setDoNotDelete(false);
-}
-
-RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild)
-{
- KHTMLAssert(oldChild->parent() == this);
-
- // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
- // that a positioned child got yanked). We also repaint, so that the area exposed when the child
- // disappears gets repainted properly.
- if ( document()->renderer() ) {
- oldChild->setNeedsLayoutAndMinMaxRecalc();
- oldChild->repaint();
-
- // Keep our layer hierarchy updated.
- oldChild->removeLayers(enclosingLayer());
- // remove the child from any special layout lists
- oldChild->removeFromObjectLists();
-
- // if oldChild is the start or end of the selection, then clear
- // the selection to avoid problems of invalid pointers
-
- // ### This is not the "proper" solution... ideally the selection
- // ### should be maintained based on DOM Nodes and a Range, which
- // ### gets adjusted appropriately when nodes are deleted/inserted
- // ### near etc. But this at least prevents crashes caused when
- // ### the start or end of the selection is deleted and then
- // ### accessed when the user next selects something.
-
- if (oldChild->isSelectionBorder()) {
- RenderObject *root = oldChild;
- while (root->parent())
- root = root->parent();
- if (root->isCanvas()) {
- static_cast<RenderCanvas*>(root)->clearSelection();
- }
- }
- }
-
- // remove the child from the render-tree
- if (oldChild->previousSibling())
- oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
- if (oldChild->nextSibling())
- oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
-
- if (m_first == oldChild)
- m_first = oldChild->nextSibling();
- if (m_last == oldChild)
- m_last = oldChild->previousSibling();
-
- oldChild->setPreviousSibling(0);
- oldChild->setNextSibling(0);
- oldChild->setParent(0);
-
- return oldChild;
-}
-
-void RenderContainer::setStyle(RenderStyle* _style)
-{
- RenderObject::setStyle(_style);
-
- // If we are a pseudo-container we need to restyle the children
- if (style()->isGenerated())
- {
- // ### we could save this call when the change only affected
- // non inherited properties
- RenderStyle *pseudoStyle = new RenderStyle();
- pseudoStyle->inheritFrom(style());
- pseudoStyle->ref();
- RenderObject *child = firstChild();
- while (child != 0)
- {
- child->setStyle(pseudoStyle);
- child = child->nextSibling();
- }
- pseudoStyle->deref();
- }
-}
-
-void RenderContainer::updatePseudoChildren()
-{
- // In CSS2, before/after pseudo-content cannot nest. Check this first.
- // Remove when CSS 3 Generated Content becomes Candidate Recommendation
- if (style()->styleType() == RenderStyle::BEFORE
- || style()->styleType() == RenderStyle::AFTER)
- return;
-
- updatePseudoChild(RenderStyle::BEFORE);
- updatePseudoChild(RenderStyle::AFTER);
- // updatePseudoChild(RenderStyle::MARKER, marker());
-}
-
-void RenderContainer::updatePseudoChild(RenderStyle::PseudoId type)
-{
- // The head manages generated content for its continuations
- if (isInlineContinuation()) return;
-
- RenderStyle* pseudo = style()->getPseudoStyle(type);
-
- RenderObject* child = pseudoContainer(type);
-
- // Whether or not we currently have generated content attached.
- bool oldContentPresent = child && (child->style()->styleType() == type);
-
- // Whether or not we now want generated content.
- bool newContentWanted = pseudo && pseudo->display() != NONE;
-
- // No generated content
- if (!oldContentPresent && !newContentWanted)
- return;
-
- bool movedContent = (type == RenderStyle::AFTER && isRenderInline() && continuation());
-
- // Whether or not we want the same old content.
- bool sameOldContent = oldContentPresent && newContentWanted && !movedContent
- && (child->style()->contentDataEquivalent(pseudo));
-
- // No change in content, update style
- if( sameOldContent ) {
- child->setStyle(pseudo);
- return;
- }
-
- // If we don't want generated content any longer, or if we have generated content,
- // but it's no longer identical to the new content data we want to build
- // render objects for, then we nuke all of the old generated content.
- if (oldContentPresent && (!newContentWanted || !sameOldContent))
- {
- // The child needs to be removed.
- oldContentPresent = false;
- child->detach();
- child = 0;
- }
-
- // If we have no pseudo-style or if the pseudo's display type is NONE, then we
- // have no generated content and can now return.
- if (!newContentWanted)
- return;
-
- // Generated content consists of a single container that houses multiple children (specified
- // by the content property). This pseudo container gets the pseudo style set on it.
- RenderContainer* pseudoContainer = 0;
- pseudoContainer = RenderFlow::createFlow(element(), pseudo, renderArena());
- pseudoContainer->setIsAnonymous( true );
- pseudoContainer->createGeneratedContent();
-
- // Only add the container if it had content
- if (pseudoContainer->firstChild()) {
- addPseudoContainer(pseudoContainer);
- pseudoContainer->close();
- }
-}
-
-void RenderContainer::createGeneratedContent()
-{
- RenderStyle* pseudo = style();
- RenderStyle* style = new RenderStyle();
- style->ref();
- style->inheritFrom(pseudo);
-
- // Now walk our list of generated content and create render objects for every type
- // we encounter.
- for (ContentData* contentData = pseudo->contentData();
- contentData; contentData = contentData->_nextContent)
- {
- if (contentData->_contentType == CONTENT_TEXT)
- {
- RenderText* t = new (renderArena()) RenderText( node(), 0);
- t->setIsAnonymous( true );
- t->setStyle(style);
- t->setText(contentData->contentText());
- addChild(t);
- }
- else if (contentData->_contentType == CONTENT_OBJECT)
- {
- RenderImage* img = new (renderArena()) RenderImage(node());
- img->setIsAnonymous( true );
- img->setStyle(style);
- img->setContentObject(contentData->contentObject());
- addChild(img);
- }
- else if (contentData->_contentType == CONTENT_COUNTER)
- {
- // really a counter or just a glyph?
- EListStyleType type = (EListStyleType)contentData->contentCounter()->listStyle();
- RenderObject *t = 0;
- if (isListStyleCounted(type)) {
- t = new (renderArena()) RenderCounter( node(), contentData->contentCounter() );
- }
- else {
- t = new (renderArena()) RenderGlyph( node(), type );
- }
- t->setIsAnonymous( true );
- t->setStyle(style);
- addChild(t);
- }
- else if (contentData->_contentType == CONTENT_QUOTE)
- {
- RenderQuote* t = new (renderArena()) RenderQuote( node(), contentData->contentQuote() );
- t->setIsAnonymous( true );
- t->setStyle(style);
- addChild(t);
- }
- }
- style->deref();
-}
-
-RenderContainer* RenderContainer::pseudoContainer(RenderStyle::PseudoId type) const
-{
- RenderObject *child = 0;
- switch (type) {
- case RenderStyle::AFTER:
- child = lastChild();
- break;
- case RenderStyle::BEFORE:
- child = firstChild();
- break;
- case RenderStyle::REPLACED:
- child = lastChild();
- if (child && child->style()->styleType() == RenderStyle::AFTER)
- child = child->previousSibling();
- break;
- default:
- child = 0;
- }
-
- if (child && child->style()->styleType() == type) {
- assert(child->isRenderBlock() || child->isRenderInline());
- return static_cast<RenderContainer*>(child);
- }
- if (type == RenderStyle::AFTER) {
- // check continuations
- if (continuation())
- return continuation()->pseudoContainer(type);
- }
- if (child && child->isAnonymousBlock())
- return static_cast<RenderBlock*>(child)->pseudoContainer(type);
- return 0;
-}
-
-void RenderContainer::addPseudoContainer(RenderObject* child)
-{
- RenderStyle::PseudoId type = child->style()->styleType();
- switch (type) {
- case RenderStyle::AFTER: {
- RenderObject *o = this;
- while (o->continuation()) o = o->continuation();
-
- // Coalesce inlines
- if (child->style()->display() == INLINE && o->lastChild() && o->lastChild()->isAnonymousBlock()) {
- o->lastChild()->addChild(child, 0);
- } else
- o->addChild(child, 0);
- break;
- }
- case RenderStyle::BEFORE:
- // Coalesce inlines
- if (child->style()->display() == INLINE && firstChild() && firstChild()->isAnonymousBlock()) {
- firstChild()->addChild(child, firstChild()->firstChild());
- } else
- addChild(child, firstChild());
- break;
- case RenderStyle::REPLACED:
- addChild(child, pseudoContainer(RenderStyle::AFTER));
- break;
- default:
- break;
- }
-}
-
-void RenderContainer::updateReplacedContent()
-{
- // Only for normal elements
- if (!style() || style()->styleType() != RenderStyle::NOPSEUDO)
- return;
-
- // delete old generated content
- RenderContainer *container = pseudoContainer(RenderStyle::REPLACED);
- if (container) {
- container->detach();
- }
-
- if (style()->useNormalContent()) return;
-
- // create generated content
- RenderStyle* pseudo = style()->getPseudoStyle(RenderStyle::REPLACED);
- if (!pseudo) {
- pseudo = new RenderStyle();
- pseudo->inheritFrom(style());
- pseudo->setStyleType(RenderStyle::REPLACED);
- }
- if (pseudo->useNormalContent())
- pseudo->setContentData(style()->contentData());
-
- container = RenderFlow::createFlow(node(), pseudo, renderArena());
- container->setIsAnonymous( true );
- container->createGeneratedContent();
-
- addChild(container, pseudoContainer(RenderStyle::AFTER));
-}
-
-void RenderContainer::appendChildNode(RenderObject* newChild)
-{
- KHTMLAssert(newChild->parent() == 0);
-
- newChild->setParent(this);
- RenderObject* lChild = lastChild();
-
- if(lChild)
- {
- newChild->setPreviousSibling(lChild);
- lChild->setNextSibling(newChild);
- }
- else
- setFirstChild(newChild);
-
- setLastChild(newChild);
-
- // Keep our layer hierarchy updated. Optimize for the common case where we don't have any children
- // and don't have a layer attached to ourselves.
- if (newChild->firstChild() || newChild->layer()) {
- RenderLayer* layer = enclosingLayer();
- newChild->addLayers(layer, newChild);
- }
-
- newChild->setNeedsLayoutAndMinMaxRecalc(); // Goes up the containing block hierarchy.
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-}
-
-void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild)
-{
- if(!beforeChild) {
- appendChildNode(child);
- return;
- }
-
- KHTMLAssert(!child->parent());
- while ( beforeChild->parent() != this && beforeChild->parent()->isAnonymousBlock() )
- beforeChild = beforeChild->parent();
- KHTMLAssert(beforeChild->parent() == this);
-
- if(beforeChild == firstChild())
- setFirstChild(child);
-
- RenderObject* prev = beforeChild->previousSibling();
- child->setNextSibling(beforeChild);
- beforeChild->setPreviousSibling(child);
- if(prev) prev->setNextSibling(child);
- child->setPreviousSibling(prev);
- child->setParent(this);
-
- // Keep our layer hierarchy updated.
- RenderLayer* layer = enclosingLayer();
- child->addLayers(layer, child);
-
- child->setNeedsLayoutAndMinMaxRecalc();
- if (!normalChildNeedsLayout())
- setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
-}
-
-
-void RenderContainer::layout()
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
- const bool pagedMode = canvas()->pagedMode();
- RenderObject *child = firstChild();
- while( child ) {
- if (pagedMode) child->setNeedsLayout(true);
- child->layoutIfNeeded();
- if (child->containsPageBreak()) setContainsPageBreak(true);
- if (child->needsPageClear()) setNeedsPageClear(true);
- child = child->nextSibling();
- }
- setNeedsLayout(false);
-}
-
-void RenderContainer::removeLeftoverAnonymousBoxes()
-{
- // we have to go over all child nodes and remove anonymous boxes, that do _not_
- // have inline children to keep the tree flat
- RenderObject *child = firstChild();
- while( child ) {
- RenderObject *next = child->nextSibling();
-
- if ( child->isRenderBlock() && child->isAnonymousBlock() && !child->continuation() &&
- !child->childrenInline() && !child->isTableCell() && !child->doNotDelete()) {
- RenderObject *firstAnChild = child->firstChild();
- RenderObject *lastAnChild = child->lastChild();
- if ( firstAnChild ) {
- RenderObject *o = firstAnChild;
- while( o ) {
- o->setParent( this );
- o = o->nextSibling();
- }
- firstAnChild->setPreviousSibling( child->previousSibling() );
- lastAnChild->setNextSibling( child->nextSibling() );
- if ( child->previousSibling() )
- child->previousSibling()->setNextSibling( firstAnChild );
- if ( child->nextSibling() )
- child->nextSibling()->setPreviousSibling( lastAnChild );
- if ( child == firstChild() )
- m_first = firstAnChild;
- if ( child == lastChild() )
- m_last = lastAnChild;
- } else {
- if ( child->previousSibling() )
- child->previousSibling()->setNextSibling( child->nextSibling() );
- if ( child->nextSibling() )
- child->nextSibling()->setPreviousSibling( child->previousSibling() );
- if ( child == firstChild() )
- m_first = child->nextSibling();
- if ( child == lastChild() )
- m_last = child->previousSibling();
- }
- child->setParent( 0 );
- child->setPreviousSibling( 0 );
- child->setNextSibling( 0 );
- if ( !child->isText() ) {
- RenderContainer *c = static_cast<RenderContainer *>(child);
- c->m_first = 0;
- c->m_next = 0;
- }
- child->detach();
- }
- child = next;
- }
- if ( parent() )
- parent()->removeLeftoverAnonymousBoxes();
-}
-
-#undef DEBUG_LAYOUT
diff --git a/khtml/rendering/render_container.h b/khtml/rendering/render_container.h
deleted file mode 100644
index 4cf386140..000000000
--- a/khtml/rendering/render_container.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2001 Antti Koivisto (koivisto@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef render_container_h
-#define render_container_h
-
-#include "render_object.h"
-
-namespace khtml
-{
-
-
-/**
- * Base class for rendering objects that can have children
- */
-class RenderContainer : public RenderObject
-{
-public:
- RenderContainer(DOM::NodeImpl* node);
-
- void detach();
-
- RenderObject *firstChild() const { return m_first; }
- RenderObject *lastChild() const { return m_last; }
-
- virtual bool childAllowed() const {
- // Prevent normal children when we are replaced by generated content
- if (style()) return style()->useNormalContent();
- return true;
- }
-
- virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
-
- virtual RenderObject* removeChildNode(RenderObject* child);
- virtual void appendChildNode(RenderObject* child);
- virtual void insertChildNode(RenderObject* child, RenderObject* before);
-
- virtual void layout();
- virtual void calcMinMaxWidth() { setMinMaxKnown( true ); }
-
- virtual void removeLeftoverAnonymousBoxes();
-
- virtual void setStyle(RenderStyle* _style);
-
-protected:
- // Generate CSS content
- void createGeneratedContent();
- void updateReplacedContent();
-
- void updatePseudoChildren();
- void updatePseudoChild(RenderStyle::PseudoId type);
-
- RenderContainer* pseudoContainer( RenderStyle::PseudoId type ) const;
- void addPseudoContainer(RenderObject* child);
-private:
-
- void setFirstChild(RenderObject *first) { m_first = first; }
- void setLastChild(RenderObject *last) { m_last = last; }
-
-protected:
-
- RenderObject *m_first;
- RenderObject *m_last;
-};
-
-}
-#endif
diff --git a/khtml/rendering/render_flow.cpp b/khtml/rendering/render_flow.cpp
deleted file mode 100644
index ae579bd46..000000000
--- a/khtml/rendering/render_flow.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003-2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-// -------------------------------------------------------------------------
-
-#include <kdebug.h>
-#include <assert.h>
-#include <tqpainter.h>
-#include <kglobal.h>
-
-#include "rendering/render_flow.h"
-#include "rendering/render_text.h"
-#include "rendering/render_table.h"
-#include "rendering/render_canvas.h"
-#include "rendering/render_inline.h"
-#include "rendering/render_block.h"
-#include "rendering/render_arena.h"
-#include "rendering/render_line.h"
-#include "xml/dom_nodeimpl.h"
-#include "xml/dom_docimpl.h"
-#include "misc/htmltags.h"
-#include "html/html_formimpl.h"
-
-#include "khtmlview.h"
-
-using namespace DOM;
-using namespace khtml;
-
-RenderFlow* RenderFlow::createFlow(DOM::NodeImpl* node, RenderStyle* style, RenderArena* arena)
-{
- RenderFlow* result;
- if (style->display() == INLINE)
- result = new (arena) RenderInline(node);
- else
- result = new (arena) RenderBlock(node);
- result->setStyle(style);
- return result;
-}
-
-RenderFlow* RenderFlow::continuationBefore(RenderObject* beforeChild)
-{
- if (beforeChild && beforeChild->parent() == this)
- return this;
-
- RenderFlow* curr = continuation();
- RenderFlow* nextToLast = this;
- RenderFlow* last = this;
- while (curr) {
- if (beforeChild && beforeChild->parent() == curr) {
- if (curr->firstChild() == beforeChild)
- return last;
- return curr;
- }
-
- nextToLast = last;
- last = curr;
- curr = curr->continuation();
- }
-
- if (!beforeChild && !last->firstChild())
- return nextToLast;
- return last;
-}
-
-void RenderFlow::addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild)
-{
- RenderFlow* flow = continuationBefore(beforeChild);
- while(beforeChild && beforeChild->parent() != flow && !beforeChild->parent()->isAnonymousBlock()) {
- // skip implicit containers around beforeChild
- beforeChild = beforeChild->parent();
- }
- RenderFlow* beforeChildParent = beforeChild ? static_cast<RenderFlow*>(beforeChild->parent()) :
- (flow->continuation() ? flow->continuation() : flow);
-
- if (newChild->isFloatingOrPositioned())
- return beforeChildParent->addChildToFlow(newChild, beforeChild);
-
- // A continuation always consists of two potential candidates: an inline or an anonymous
- // block box holding block children.
- bool childInline = newChild->isInline();
- bool bcpInline = beforeChildParent->isInline();
- bool flowInline = flow->isInline();
-
- if (flow == beforeChildParent)
- return flow->addChildToFlow(newChild, beforeChild);
- else {
- // The goal here is to match up if we can, so that we can coalesce and create the
- // minimal # of continuations needed for the inline.
- if (childInline == bcpInline)
- return beforeChildParent->addChildToFlow(newChild, beforeChild);
- else if (flowInline == childInline)
- return flow->addChildToFlow(newChild, 0); // Just treat like an append.
- else
- return beforeChildParent->addChildToFlow(newChild, beforeChild);
- }
-}
-
-void RenderFlow::addChild(RenderObject *newChild, RenderObject *beforeChild)
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(RenderFlow)::addChild( " << newChild->renderName() <<
- ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
- kdDebug( 6040 ) << "current height = " << m_height << endl;
-#endif
-
- if (continuation())
- return addChildWithContinuation(newChild, beforeChild);
- return addChildToFlow(newChild, beforeChild);
-}
-
-void RenderFlow::deleteInlineBoxes(RenderArena* arena)
-{
- RenderBox::deleteInlineBoxes(arena); //In case we upcalled
- //during construction
- if (m_firstLineBox) {
- if (!arena)
- arena = renderArena();
- InlineRunBox *curr=m_firstLineBox, *next=0;
- while (curr) {
- next = curr->nextLineBox();
- curr->detach(arena);
- curr = next;
- }
- m_firstLineBox = 0;
- m_lastLineBox = 0;
- }
-}
-
-void RenderFlow::deleteLastLineBox(RenderArena* arena)
-{
- if (m_lastLineBox) {
- if (!arena)
- arena = renderArena();
- InlineRunBox *curr=m_lastLineBox, *prev = m_lastLineBox;
- if (m_firstLineBox == m_lastLineBox)
- m_firstLineBox = m_lastLineBox = 0;
- else {
- prev = curr->prevLineBox();
- while (!prev->isInlineFlowBox()) {
- prev = prev->prevLineBox();
- prev->detach(arena);
- }
- m_lastLineBox = static_cast<InlineFlowBox*>(prev);
- prev->setNextLineBox(0);
- }
- if (curr->parent()) {
- curr->parent()->removeFromLine(curr);
- }
- curr->detach(arena);
- }
-}
-
-InlineBox* RenderFlow::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox)
-{
- if ( !isRootLineBox &&
- (isReplaced() || makePlaceHolderBox) ) // Inline tables and inline blocks
- return RenderBox::createInlineBox(false, false); // (or positioned element placeholders).
-
- InlineFlowBox* flowBox = 0;
- if (isInlineFlow())
- flowBox = new (renderArena()) InlineFlowBox(this);
- else
- flowBox = new (renderArena()) RootInlineBox(this);
-
- if (!m_firstLineBox) {
- m_firstLineBox = m_lastLineBox = flowBox;
- } else {
- m_lastLineBox->setNextLineBox(flowBox);
- flowBox->setPreviousLineBox(m_lastLineBox);
- m_lastLineBox = flowBox;
- }
-
- return flowBox;
-}
-
-void RenderFlow::paintLines(PaintInfo& i, int _tx, int _ty)
-{
- // Only paint during the foreground/selection phases.
- if (i.phase != PaintActionForeground && i.phase != PaintActionSelection && i.phase != PaintActionOutline)
- return;
-
- if (!firstLineBox())
- return;
-
- // We can check the first box and last box and avoid painting if we don't
- // intersect. This is a quick short-circuit that we can take to avoid walking any lines.
- // FIXME: This check is flawed in two extremely obscure ways.
- // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
- // (2) The overflow from an inline block on a line is not reported to the line.
- int maxOutlineSize = maximalOutlineSize(i.phase);
- int yPos = firstLineBox()->root()->topOverflow() - maxOutlineSize;
- int h = maxOutlineSize + lastLineBox()->root()->bottomOverflow() - yPos;
- yPos += _ty;
- if ((yPos >= i.r.y() + i.r.height()) || (yPos + h <= i.r.y()))
- return;
- for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextFlowBox()) {
- yPos = curr->root()->topOverflow() - maxOutlineSize;
- h = curr->root()->bottomOverflow() + maxOutlineSize - yPos;
- yPos += _ty;
- if ((yPos < i.r.y() + i.r.height()) && (yPos + h > i.r.y()))
- curr->paint(i, _tx, _ty);
- }
-
- if (i.phase == PaintActionOutline && i.outlineObjects) {
- TQValueList<RenderFlow *>::iterator it;;
- for( it = (*i.outlineObjects).begin(); it != (*i.outlineObjects).end(); ++it )
- if ((*it)->isRenderInline())
- static_cast<RenderInline*>(*it)->paintOutlines(i.p, _tx, _ty);
- i.outlineObjects->clear();
- }
-}
-
-
-bool RenderFlow::hitTestLines(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction)
-{
- (void) hitTestAction;
- /*
- if (hitTestAction != HitTestForeground) // ### port hitTest
- return false;
- */
-
- if (!firstLineBox())
- return false;
-
- // We can check the first box and last box and avoid hit testing if we don't
- // contain the point. This is a quick short-circuit that we can take to avoid walking any lines.
- // FIXME: This check is flawed in two extremely obscure ways.
- // (1) If some line in the middle has a huge overflow, it might actually extend below the last line.
- // (2) The overflow from an inline block on a line is not reported to the line.
- if ((y >= ty + lastLineBox()->root()->bottomOverflow()) || (y < ty + firstLineBox()->root()->topOverflow()))
- return false;
-
- // See if our root lines contain the point. If so, then we hit test
- // them further. Note that boxes can easily overlap, so we can't make any assumptions
- // based off positions of our first line box or our last line box.
- for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevFlowBox()) {
- if (y >= ty + curr->root()->topOverflow() && y < ty + curr->root()->bottomOverflow()) {
- bool inside = curr->nodeAtPoint(i, x, y, tx, ty);
- if (inside) {
- setInnerNode(i);
- return true;
- }
- }
- }
-
- return false;
-}
-
-
-void RenderFlow::repaint(Priority prior)
-{
- if (isInlineFlow()) {
- // Find our leftmost position.
- int left = 0;
- // root inline box not reliably availabe during relayout
- int top = firstLineBox() ? (
- needsLayout() ? firstLineBox()->xPos() : firstLineBox()->root()->topOverflow()
- ) : 0;
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
- if (curr == firstLineBox() || curr->xPos() < left)
- left = curr->xPos();
-
- // Now invalidate a rectangle.
- int ow = style() ? style()->outlineSize() : 0;
-
- // We need to add in the relative position offsets of any inlines (including us) up to our
- // containing block.
- RenderBlock* cb = containingBlock();
- for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isInlineFlow() && inlineFlow != cb;
- inlineFlow = inlineFlow->parent()) {
- if (inlineFlow->style() && inlineFlow->style()->position() == RELATIVE && inlineFlow->layer()) {
- KHTMLAssert(inlineFlow->isBox());
- static_cast<RenderBox*>(inlineFlow)->relativePositionOffset(left, top);
- }
- }
-
- RootInlineBox *lastRoot = lastLineBox() && !needsLayout() ? lastLineBox()->root() : 0;
- containingBlock()->repaintRectangle(-ow+left, -ow+top,
- width()+ow*2,
- (lastRoot ? lastRoot->bottomOverflow() - top : height())+ow*2, prior);
- }
- else {
- if (firstLineBox() && firstLineBox()->topOverflow() < 0) {
- int ow = style() ? style()->outlineSize() : 0;
- repaintRectangle(-ow, -ow+firstLineBox()->topOverflow(),
- effectiveWidth()+ow*2, effectiveHeight()+ow*2, prior);
- }
- else
- return RenderBox::repaint(prior);
- }
-}
-
-int
-RenderFlow::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int bottom = RenderBox::lowestPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return bottom;
-
- // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
- // For now, we have to descend into all the children, since we may have a huge abs div inside
- // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
- // the abs div.
- for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
- if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
- int lp = c->yPos() + c->lowestPosition(false);
- bottom = kMax(bottom, lp);
- }
- }
-
- if (isRelPositioned()) {
- int x;
- relativePositionOffset(x, bottom);
- }
-
- return bottom;
-}
-
-int RenderFlow::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int right = RenderBox::rightmostPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return right;
-
- // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
- // For now, we have to descend into all the children, since we may have a huge abs div inside
- // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
- // the abs div.
- for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
- if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
- int rp = c->xPos() + c->rightmostPosition(false);
- right = kMax(right, rp);
- }
- }
-
- if (isRelPositioned()) {
- int y;
- relativePositionOffset(right, y);
- }
-
- return right;
-}
-
-int RenderFlow::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int left = RenderBox::leftmostPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return left;
-
- // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
- // For now, we have to descend into all the children, since we may have a huge abs div inside
- // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
- // the abs div.
- for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
- if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
- int lp = c->xPos() + c->leftmostPosition(false);
- left = kMin(left, lp);
- }
- }
-
- if (isRelPositioned()) {
- int y;
- relativePositionOffset(left, y);
- }
-
- return left;
-}
-
-int RenderFlow::highestPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int top = RenderBox::highestPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return top;
-
- // FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
- // For now, we have to descend into all the children, since we may have a huge abs div inside
- // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
- // the abs div.
- for (RenderObject *c = firstChild(); c; c = c->nextSibling()) {
- if (!c->isFloatingOrPositioned() && !c->isText() && !c->isInlineFlow()) {
- int hp = c->yPos() + c->highestPosition(false);
- top = kMin(top, hp);
- }
- }
-
- if (isRelPositioned()) {
- int x;
- relativePositionOffset(x, top);
- }
-
- return top;
-}
diff --git a/khtml/rendering/render_flow.h b/khtml/rendering/render_flow.h
deleted file mode 100644
index 1e23822bb..000000000
--- a/khtml/rendering/render_flow.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_FLOW_H
-#define RENDER_FLOW_H
-
-#include "render_box.h"
-#include "bidi.h"
-#include "render_line.h"
-
-namespace khtml {
-
-/**
- * all geometry managing stuff is only in the block elements.
- *
- * Inline elements don't layout themselves, but the whole paragraph
- * gets flowed by the surrounding block element. This is, because
- * one needs to know the whole paragraph to calculate bidirectional
- * behaviour of text, so putting the layouting routines in the inline
- * elements is impossible.
- */
-class RenderFlow : public RenderBox
-{
-public:
- RenderFlow(DOM::NodeImpl* node)
- : RenderBox(node)
- { m_continuation = 0; m_firstLineBox = 0; m_lastLineBox = 0; }
-
- virtual RenderFlow* continuation() const { return m_continuation; }
- void setContinuation(RenderFlow* c) { m_continuation = c; }
- RenderFlow* continuationBefore(RenderObject* beforeChild);
-
- void addChildWithContinuation(RenderObject* newChild, RenderObject* beforeChild);
- virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild) = 0;
- virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
-
- static RenderFlow* createFlow(DOM::NodeImpl* node, RenderStyle* style, RenderArena* arena);
-
- virtual void deleteLastLineBox(RenderArena* arena=0);
- virtual void deleteInlineBoxes(RenderArena* arena=0);
-
-
- InlineFlowBox* firstLineBox() const { return m_firstLineBox; }
- InlineFlowBox* lastLineBox() const { return m_lastLineBox; }
-
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
-
- void paintLines(PaintInfo& i, int _tx, int _ty);
- bool hitTestLines(NodeInfo& i, int x, int y, int tx, int ty, HitTestAction hitTestAction);
-
- virtual void repaint(Priority p=NormalPriority);
-
- virtual int highestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int lowestPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int rightmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
- virtual int leftmostPosition(bool includeOverflowInterior=true, bool includeSelf=true) const;
-
-protected:
- // An inline can be split with blocks occurring in between the inline content.
- // When this occurs we need a pointer to our next object. We can basically be
- // split into a sequence of inlines and blocks. The continuation will either be
- // an anonymous block (that houses other blocks) or it will be an inline flow.
- RenderFlow* m_continuation;
-
- // For block flows, each box represents the root inline box for a line in the
- // paragraph.
- // For inline flows, each box represents a portion of that inline.
- InlineFlowBox* m_firstLineBox;
- InlineFlowBox* m_lastLineBox;
-};
-
-
-} //namespace
-
-#endif
diff --git a/khtml/rendering/render_form.cpp b/khtml/rendering/render_form.cpp
deleted file mode 100644
index 81005de85..000000000
--- a/khtml/rendering/render_form.cpp
+++ /dev/null
@@ -1,1914 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000 Dirk Mueller (mueller@kde.org)
- * (C) 2006 Maksim Orlovich (maksim@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include <kcompletionbox.h>
-#include <kcursor.h>
-#include <kdebug.h>
-#include <kfiledialog.h>
-#include <kfind.h>
-#include <kfinddialog.h>
-#include <kiconloader.h>
-#include <klocale.h>
-#include <kmessagebox.h>
-#include <kreplace.h>
-#include <kreplacedialog.h>
-#include <kspell.h>
-#include <kurlcompletion.h>
-#include <twin.h>
-
-#include <tqstyle.h>
-
-#include "misc/helper.h"
-#include "xml/dom2_eventsimpl.h"
-#include "html/html_formimpl.h"
-#include "misc/htmlhashes.h"
-
-#include "rendering/render_form.h"
-#include <assert.h>
-
-#include "khtmlview.h"
-#include "khtml_ext.h"
-#include "xml/dom_docimpl.h"
-
-#include <tqpopupmenu.h>
-#include <tqbitmap.h>
-
-using namespace khtml;
-
-RenderFormElement::RenderFormElement(HTMLGenericFormElementImpl *element)
- : RenderWidget(element)
-{
- // init RenderObject attributes
- setInline(true); // our object is Inline
-
- m_state = 0;
-}
-
-RenderFormElement::~RenderFormElement()
-{
-}
-
-short RenderFormElement::baselinePosition( bool f ) const
-{
- return RenderWidget::baselinePosition( f ) - 2 - style()->fontMetrics().descent();
-}
-
-void RenderFormElement::updateFromElement()
-{
- m_widget->setEnabled(!element()->disabled());
- RenderWidget::updateFromElement();
-}
-
-void RenderFormElement::layout()
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
-
- // minimum height
- m_height = 0;
-
- calcWidth();
- calcHeight();
-
- if ( m_widget )
- resizeWidget(m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
- m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom());
-
- setNeedsLayout(false);
-}
-
-TQ_Alignment RenderFormElement::textAlignment() const
-{
- switch (style()->textAlign()) {
- case LEFT:
- case KHTML_LEFT:
- return Qt::AlignLeft;
- case RIGHT:
- case KHTML_RIGHT:
- return Qt::AlignRight;
- case CENTER:
- case KHTML_CENTER:
- return Qt::AlignHCenter;
- case JUSTIFY:
- // Just fall into the auto code for justify.
- case TAAUTO:
- return style()->direction() == RTL ? Qt::AlignRight : Qt::AlignLeft;
- }
- assert(false); // Should never be reached.
- return Qt::AlignLeft;
-}
-
-// -------------------------------------------------------------------------
-
-RenderButton::RenderButton(HTMLGenericFormElementImpl *element)
- : RenderFormElement(element)
-{
-}
-
-short RenderButton::baselinePosition( bool f ) const
-{
- return RenderWidget::baselinePosition( f ) - 2;
-}
-
-// -------------------------------------------------------------------------------
-
-
-RenderCheckBox::RenderCheckBox(HTMLInputElementImpl *element)
- : RenderButton(element)
-{
- TQCheckBox* b = new TQCheckBox(view()->viewport(), "__khtml");
- b->setAutoMask(true);
- b->setMouseTracking(true);
- setQWidget(b);
-
- // prevent firing toggled() signals on initialization
- b->setChecked(element->checked());
-
- connect(b,TQT_SIGNAL(stateChanged(int)),this,TQT_SLOT(slotStateChanged(int)));
-}
-
-
-void RenderCheckBox::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- TQCheckBox *cb = static_cast<TQCheckBox *>( m_widget );
- TQSize s( cb->style().pixelMetric( TQStyle::PM_IndicatorWidth ),
- cb->style().pixelMetric( TQStyle::PM_IndicatorHeight ) );
- setIntrinsicWidth( s.width() );
- setIntrinsicHeight( s.height() );
-
- RenderButton::calcMinMaxWidth();
-}
-
-void RenderCheckBox::updateFromElement()
-{
- widget()->setChecked(element()->checked());
-
- RenderButton::updateFromElement();
-}
-
-void RenderCheckBox::slotStateChanged(int state)
-{
- element()->setChecked(state == TQButton::On);
- element()->setIndeterminate(state == TQButton::NoChange);
-
- ref();
- element()->onChange();
- deref();
-}
-
-// -------------------------------------------------------------------------------
-
-RenderRadioButton::RenderRadioButton(HTMLInputElementImpl *element)
- : RenderButton(element)
-{
- TQRadioButton* b = new TQRadioButton(view()->viewport(), "__khtml");
- b->setMouseTracking(true);
- setQWidget(b);
-
- // prevent firing toggled() signals on initialization
- b->setChecked(element->checked());
-
- connect(b,TQT_SIGNAL(toggled(bool)),this,TQT_SLOT(slotToggled(bool)));
-}
-
-void RenderRadioButton::updateFromElement()
-{
- widget()->setChecked(element()->checked());
-
- RenderButton::updateFromElement();
-}
-
-void RenderRadioButton::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- TQRadioButton *rb = static_cast<TQRadioButton *>( m_widget );
- TQSize s( rb->style().pixelMetric( TQStyle::PM_ExclusiveIndicatorWidth ),
- rb->style().pixelMetric( TQStyle::PM_ExclusiveIndicatorHeight ) );
- setIntrinsicWidth( s.width() );
- setIntrinsicHeight( s.height() );
-
- RenderButton::calcMinMaxWidth();
-}
-
-void RenderRadioButton::slotToggled(bool activated)
-{
- if(activated) {
- ref();
- element()->onChange();
- deref();
- }
-}
-
-// -------------------------------------------------------------------------------
-
-
-RenderSubmitButton::RenderSubmitButton(HTMLInputElementImpl *element)
- : RenderButton(element)
-{
- TQPushButton* p = new TQPushButton(view()->viewport(), "__khtml");
- setQWidget(p);
- p->setAutoMask(true);
- p->setMouseTracking(true);
-}
-
-TQString RenderSubmitButton::rawText()
-{
- TQString value = element()->valueWithDefault().string();
- value = value.stripWhiteSpace();
- TQString raw;
- for(unsigned int i = 0; i < value.length(); i++) {
- raw += value[i];
- if(value[i] == '&')
- raw += '&';
- }
- return raw;
-}
-
-void RenderSubmitButton::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- TQString raw = rawText();
- TQPushButton* pb = static_cast<TQPushButton*>(m_widget);
- pb->setText(raw);
- pb->setFont(style()->font());
-
- bool empty = raw.isEmpty();
- if ( empty )
- raw = TQString::fromLatin1("X");
- TQFontMetrics fm = pb->fontMetrics();
- TQSize ts = fm.size( ShowPrefix, raw);
- TQSize s(pb->style().tqsizeFromContents( TQStyle::CT_PushButton, pb, ts )
- .expandedTo(TQApplication::globalStrut()));
- int margin = pb->style().pixelMetric( TQStyle::PM_ButtonMargin, pb) +
- pb->style().pixelMetric( TQStyle::PM_DefaultFrameWidth, pb ) * 2;
- int w = ts.width() + margin;
- int h = s.height();
- if (pb->isDefault() || pb->autoDefault()) {
- int dbw = pb->style().pixelMetric( TQStyle::PM_ButtonDefaultIndicator, pb ) * 2;
- w += dbw;
- }
-
- // add 30% margins to the width (heuristics to make it look similar to IE)
- s = TQSize( w*13/10, h ).expandedTo(TQApplication::globalStrut());
-
- setIntrinsicWidth( s.width() );
- setIntrinsicHeight( s.height() );
-
- RenderButton::calcMinMaxWidth();
-}
-
-void RenderSubmitButton::updateFromElement()
-{
- TQString oldText = static_cast<TQPushButton*>(m_widget)->text();
- TQString newText = rawText();
- static_cast<TQPushButton*>(m_widget)->setText(newText);
- if ( oldText != newText )
- setNeedsLayoutAndMinMaxRecalc();
- RenderFormElement::updateFromElement();
-}
-
-short RenderSubmitButton::baselinePosition( bool f ) const
-{
- return RenderFormElement::baselinePosition( f );
-}
-
-// -------------------------------------------------------------------------------
-
-RenderResetButton::RenderResetButton(HTMLInputElementImpl *element)
- : RenderSubmitButton(element)
-{
-}
-
-// -------------------------------------------------------------------------------
-
-LineEditWidget::LineEditWidget(DOM::HTMLInputElementImpl* input, KHTMLView* view, TQWidget* parent)
- : KLineEdit(parent, "__khtml"), m_input(input), m_view(view), m_spell(0)
-{
- setMouseTracking(true);
- KActionCollection *ac = new KActionCollection(this);
- m_spellAction = KStdAction::spelling( TQT_TQOBJECT(this), TQT_SLOT( slotCheckSpelling() ), ac );
-}
-
-LineEditWidget::~LineEditWidget()
-{
- delete m_spell;
- m_spell = 0L;
-}
-
-void LineEditWidget::slotCheckSpelling()
-{
- if ( text().isEmpty() ) {
- return;
- }
-
- delete m_spell;
- m_spell = new KSpell( this, i18n( "Spell Checking" ), TQT_TQOBJECT(this), TQT_SLOT( slotSpellCheckReady( KSpell *) ), 0, true, true);
-
- connect( m_spell, TQT_SIGNAL( death() ),this, TQT_SLOT( spellCheckerFinished() ) );
- connect( m_spell, TQT_SIGNAL( misspelling( const TQString &, const TQStringList &, unsigned int ) ),this, TQT_SLOT( spellCheckerMisspelling( const TQString &, const TQStringList &, unsigned int ) ) );
- connect( m_spell, TQT_SIGNAL( corrected( const TQString &, const TQString &, unsigned int ) ),this, TQT_SLOT( spellCheckerCorrected( const TQString &, const TQString &, unsigned int ) ) );
-}
-
-void LineEditWidget::spellCheckerMisspelling( const TQString &_text, const TQStringList &, unsigned int pos)
-{
- highLightWord( _text.length(),pos );
-}
-
-void LineEditWidget::highLightWord( unsigned int length, unsigned int pos )
-{
- setSelection ( pos, length );
-}
-
-void LineEditWidget::spellCheckerCorrected( const TQString &old, const TQString &corr, unsigned int pos )
-{
- if( old!= corr )
- {
- setSelection ( pos, old.length() );
- insert( corr );
- setSelection ( pos, corr.length() );
- }
-}
-
-void LineEditWidget::spellCheckerFinished()
-{
-}
-
-void LineEditWidget::slotSpellCheckReady( KSpell *s )
-{
- s->check( text() );
- connect( s, TQT_SIGNAL( done( const TQString & ) ), this, TQT_SLOT( slotSpellCheckDone( const TQString & ) ) );
-}
-
-void LineEditWidget::slotSpellCheckDone( const TQString &s )
-{
- if( s != text() )
- setText( s );
-}
-
-
-TQPopupMenu *LineEditWidget::createPopupMenu()
-{
- TQPopupMenu *popup = KLineEdit::createPopupMenu();
-
- if ( !popup ) {
- return 0L;
- }
-
- connect( popup, TQT_SIGNAL( activated( int ) ),
- this, TQT_SLOT( extendedMenuActivated( int ) ) );
-
- if (m_input->autoComplete()) {
- popup->insertSeparator();
- int id = popup->insertItem( SmallIconSet("edit"), i18n("&Edit History..."), EditHistory );
- popup->setItemEnabled( id, (compObj() && !compObj()->isEmpty()) );
- id = popup->insertItem( SmallIconSet("history_clear"), i18n("Clear &History"), ClearHistory );
- popup->setItemEnabled( id, (compObj() && !compObj()->isEmpty()) );
- }
-
- if (echoMode() == TQLineEdit::Normal &&
- !isReadOnly()) {
- popup->insertSeparator();
-
- m_spellAction->plug(popup);
- m_spellAction->setEnabled( !text().isEmpty() );
- }
-
- return popup;
-}
-
-
-void LineEditWidget::extendedMenuActivated( int id)
-{
- switch ( id )
- {
- case ClearHistory:
- m_view->clearCompletionHistory(m_input->name().string());
- if (compObj())
- compObj()->clear();
- case EditHistory:
- {
- KHistoryComboEditor dlg( compObj() ? compObj()->items() : TQStringList(), this );
- connect( &dlg, TQT_SIGNAL( removeFromHistory(const TQString&) ), TQT_SLOT( slotRemoveFromHistory(const TQString&)) );
- dlg.exec();
- }
- default:
- break;
- }
-}
-
-void LineEditWidget::slotRemoveFromHistory(const TQString &entry)
-{
- m_view->removeFormCompletionItem(m_input->name().string(), entry);
- if (compObj())
- compObj()->removeItem(entry);
-}
-
-
-bool LineEditWidget::event( TQEvent *e )
-{
- if (KLineEdit::event(e))
- return true;
-
- if ( e->type() == TQEvent::AccelAvailable && isReadOnly() ) {
- TQKeyEvent* ke = (TQKeyEvent*) e;
- if ( ke->state() & ControlButton ) {
- switch ( ke->key() ) {
- case Key_Left:
- case Key_Right:
- case Key_Up:
- case Key_Down:
- case Key_Home:
- case Key_End:
- ke->accept();
- default:
- break;
- }
- }
- }
- return false;
-}
-
-void LineEditWidget::mouseMoveEvent(TQMouseEvent *e)
-{
- // hack to prevent Qt from calling setCursor on the widget
- setDragEnabled(false);
- KLineEdit::mouseMoveEvent(e);
- setDragEnabled(true);
-}
-
-
-// -----------------------------------------------------------------------------
-
-RenderLineEdit::RenderLineEdit(HTMLInputElementImpl *element)
- : RenderFormElement(element)
-{
- LineEditWidget *edit = new LineEditWidget(element, view(), view()->viewport());
- connect(edit,TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed()));
- connect(edit,TQT_SIGNAL(textChanged(const TQString &)),this,TQT_SLOT(slotTextChanged(const TQString &)));
-
- if(element->inputType() == HTMLInputElementImpl::PASSWORD)
- edit->setEchoMode( TQLineEdit::Password );
-
- if ( element->autoComplete() ) {
- TQStringList completions = view()->formCompletionItems(element->name().string());
- if (completions.count()) {
- edit->completionObject()->setItems(completions);
- edit->setContextMenuEnabled(true);
- edit->completionBox()->setTabHandling( false );
- }
- }
-
- setQWidget(edit);
-}
-
-void RenderLineEdit::setStyle(RenderStyle* _style)
-{
- RenderFormElement::setStyle( _style );
-
- widget()->setAlignment(textAlignment());
-}
-
-void RenderLineEdit::highLightWord( unsigned int length, unsigned int pos )
-{
- LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
- if ( w )
- w->highLightWord( length, pos );
-}
-
-
-void RenderLineEdit::slotReturnPressed()
-{
- // don't submit the form when return was pressed in a completion-popup
- KCompletionBox *box = widget()->completionBox(false);
-
- if ( box && box->isVisible() && box->currentItem() != -1 ) {
- box->hide();
- return;
- }
-
- // Emit onChange if necessary
- // Works but might not be enough, dirk said he had another solution at
- // hand (can't remember which) - David
- handleFocusOut();
-
- HTMLFormElementImpl* fe = element()->form();
- if ( fe )
- fe->submitFromKeyboard();
-}
-
-void RenderLineEdit::handleFocusOut()
-{
- if ( widget() && widget()->edited() ) {
- element()->onChange();
- widget()->setEdited( false );
- }
-}
-
-void RenderLineEdit::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- const TQFontMetrics &fm = style()->fontMetrics();
- TQSize s;
-
- int size = element()->size();
-
- int h = fm.lineSpacing();
- int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17); // "some"
- s = TQSize(w + 2 + 2*widget()->frameWidth(),
- kMax(h, 14) + 2 + 2*widget()->frameWidth())
- .expandedTo(TQApplication::globalStrut());
-
- setIntrinsicWidth( s.width() );
- setIntrinsicHeight( s.height() );
-
- RenderFormElement::calcMinMaxWidth();
-}
-
-void RenderLineEdit::updateFromElement()
-{
- int ml = element()->maxLength();
- if ( ml < 0 )
- ml = 32767;
-
- if ( widget()->maxLength() != ml ) {
- widget()->setMaxLength( ml );
- }
-
- if (element()->value().string() != widget()->text()) {
- widget()->blockSignals(true);
- int pos = widget()->cursorPosition();
- widget()->setText(element()->value().string());
-
- widget()->setEdited( false );
-
- widget()->setCursorPosition(pos);
- widget()->blockSignals(false);
- }
- widget()->setReadOnly(element()->readOnly());
-
- RenderFormElement::updateFromElement();
-}
-
-void RenderLineEdit::slotTextChanged(const TQString &string)
-{
- // don't use setValue here!
- element()->m_value = string;
- element()->m_unsubmittedFormChange = true;
-}
-
-void RenderLineEdit::select()
-{
- static_cast<LineEditWidget*>(m_widget)->selectAll();
-}
-
-long RenderLineEdit::selectionStart()
-{
- LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
- if (w->hasSelectedText())
- return w->selectionStart();
- else
- return w->cursorPosition();
-}
-
-
-long RenderLineEdit::selectionEnd()
-{
- LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
- if (w->hasSelectedText())
- return w->selectionStart() + w->selectedText().length();
- else
- return w->cursorPosition();
-}
-
-void RenderLineEdit::setSelectionStart(long pos)
-{
- LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
- //See whether we have a non-empty selection now.
- long end = selectionEnd();
- if (end > pos)
- w->setSelection(pos, end - pos);
- w->setCursorPosition(pos);
-}
-
-void RenderLineEdit::setSelectionEnd(long pos)
-{
- LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
- //See whether we have a non-empty selection now.
- long start = selectionStart();
- if (start < pos)
- w->setSelection(start, pos - start);
-
- w->setCursorPosition(pos);
-}
-
-void RenderLineEdit::setSelectionRange(long start, long end)
-{
- LineEditWidget* w = static_cast<LineEditWidget*>(m_widget);
- w->setCursorPosition(end);
- w->setSelection(start, end - start);
-}
-
-// ---------------------------------------------------------------------------
-
-RenderFieldset::RenderFieldset(HTMLGenericFormElementImpl *element)
- : RenderBlock(element)
-{
-}
-
-RenderObject* RenderFieldset::layoutLegend(bool relayoutChildren)
-{
- RenderObject* legend = findLegend();
- if (legend) {
- if (relayoutChildren)
- legend->setNeedsLayout(true);
- legend->layoutIfNeeded();
-
- int xPos = borderLeft() + paddingLeft() + legend->marginLeft();
- if (style()->direction() == RTL)
- xPos = m_width - paddingRight() - borderRight() - legend->width() - legend->marginRight();
- int b = borderTop();
- int h = legend->height();
- legend->setPos(xPos, kMax((b-h)/2, 0));
- m_height = kMax(b,h) + paddingTop();
- }
- return legend;
-}
-
-RenderObject* RenderFieldset::findLegend()
-{
- for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
- if (!legend->isFloatingOrPositioned() && legend->element() &&
- legend->element()->id() == ID_LEGEND)
- return legend;
- }
- return 0;
-}
-
-void RenderFieldset::paintBoxDecorations(PaintInfo& pI, int _tx, int _ty)
-{
- //kdDebug( 6040 ) << renderName() << "::paintDecorations()" << endl;
-
- RenderObject* legend = findLegend();
- if (!legend)
- return RenderBlock::paintBoxDecorations(pI, _tx, _ty);
-
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- int yOff = (legend->yPos() > 0) ? 0 : (legend->height()-borderTop())/2;
- h -= yOff;
- _ty += yOff - borderTopExtra();
-
- int my = kMax(_ty,pI.r.y());
- int end = kMin( pI.r.y() + pI.r.height(), _ty + h );
- int mh = end - my;
-
- paintBackground(pI.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h);
-
- if ( style()->hasBorder() )
- paintBorderMinusLegend(pI.p, _tx, _ty, w, h, style(), legend->xPos(), legend->width());
-}
-
-void RenderFieldset::paintBorderMinusLegend(TQPainter *p, int _tx, int _ty, int w, int h,
- const RenderStyle* style, int lx, int lw)
-{
-
- const TQColor& tc = style->borderTopColor();
- const TQColor& bc = style->borderBottomColor();
-
- EBorderStyle ts = style->borderTopStyle();
- EBorderStyle bs = style->borderBottomStyle();
- EBorderStyle ls = style->borderLeftStyle();
- EBorderStyle rs = style->borderRightStyle();
-
- bool render_t = ts > BHIDDEN;
- bool render_l = ls > BHIDDEN;
- bool render_r = rs > BHIDDEN;
- bool render_b = bs > BHIDDEN;
-
- if(render_t) {
- drawBorder(p, _tx, _ty, _tx + lx, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
- (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE)?style->borderLeftWidth():0), 0);
- drawBorder(p, _tx+lx+lw, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
- 0, (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE)?style->borderRightWidth():0));
- }
-
- if(render_b)
- drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
- (render_l && (ls == DOTTED || ls == DASHED || ls == DOUBLE)?style->borderLeftWidth():0),
- (render_r && (rs == DOTTED || rs == DASHED || rs == DOUBLE)?style->borderRightWidth():0));
-
- if(render_l)
- {
- const TQColor& lc = style->borderLeftColor();
-
- bool ignore_top =
- (tc == lc) &&
- (ls >= OUTSET) &&
- (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
-
- bool ignore_bottom =
- (bc == lc) &&
- (ls >= OUTSET) &&
- (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
-
- drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
- ignore_top?0:style->borderTopWidth(),
- ignore_bottom?0:style->borderBottomWidth());
- }
-
- if(render_r)
- {
- const TQColor& rc = style->borderRightColor();
-
- bool ignore_top =
- (tc == rc) &&
- (rs >= DOTTED || rs == INSET) &&
- (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
-
- bool ignore_bottom =
- (bc == rc) &&
- (rs >= DOTTED || rs == INSET) &&
- (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
-
- drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
- ignore_top?0:style->borderTopWidth(),
- ignore_bottom?0:style->borderBottomWidth());
- }
-}
-
-void RenderFieldset::setStyle(RenderStyle* _style)
-{
- RenderBlock::setStyle(_style);
-
- // WinIE renders fieldsets with display:inline like they're inline-blocks. For us,
- // an inline-block is just a block element with replaced set to true and inline set
- // to true. Ensure that if we ended up being inline that we set our replaced flag
- // so that we're treated like an inline-block.
- if (isInline())
- setReplaced(true);
-}
-
-// -------------------------------------------------------------------------
-
-RenderFileButton::RenderFileButton(HTMLInputElementImpl *element)
- : RenderFormElement(element)
-{
- KURLRequester* w = new KURLRequester( view()->viewport(), "__khtml" );
-
- w->setMode(KFile::File | KFile::ExistingOnly);
- w->completionObject()->setDir(TDEGlobalSettings::documentPath());
-
- connect(w->lineEdit(), TQT_SIGNAL(returnPressed()), this, TQT_SLOT(slotReturnPressed()));
- connect(w->lineEdit(), TQT_SIGNAL(textChanged(const TQString &)),this,TQT_SLOT(slotTextChanged(const TQString &)));
- connect(w, TQT_SIGNAL(urlSelected(const TQString &)),this,TQT_SLOT(slotUrlSelected(const TQString &)));
-
- setQWidget(w);
- m_haveFocus = false;
-}
-
-
-
-void RenderFileButton::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- const TQFontMetrics &fm = style()->fontMetrics();
- int size = element()->size();
-
- int h = fm.lineSpacing();
- int w = fm.width( 'x' ) * (size > 0 ? size+1 : 17); // "some"
- KLineEdit* edit = static_cast<KURLRequester*>( m_widget )->lineEdit();
- TQSize s = edit->style().tqsizeFromContents(TQStyle::CT_LineEdit,
- edit,
- TQSize(w + 2 + 2*edit->frameWidth(), kMax(h, 14) + 2 + 2*edit->frameWidth()))
- .expandedTo(TQApplication::globalStrut());
- TQSize bs = static_cast<KURLRequester*>( m_widget )->minimumSizeHint() - edit->minimumSizeHint();
-
- setIntrinsicWidth( s.width() + bs.width() );
- setIntrinsicHeight( kMax(s.height(), bs.height()) );
-
- RenderFormElement::calcMinMaxWidth();
-}
-
-void RenderFileButton::handleFocusOut()
-{
- if ( widget()->lineEdit() && widget()->lineEdit()->edited() ) {
- element()->onChange();
- widget()->lineEdit()->setEdited( false );
- }
-}
-
-void RenderFileButton::updateFromElement()
-{
- KLineEdit* edit = widget()->lineEdit();
- edit->blockSignals(true);
- edit->setText(element()->value().string());
- edit->blockSignals(false);
- edit->setEdited( false );
-
- RenderFormElement::updateFromElement();
-}
-
-void RenderFileButton::slotReturnPressed()
-{
- handleFocusOut();
-
- if (element()->form())
- element()->form()->submitFromKeyboard();
-}
-
-void RenderFileButton::slotTextChanged(const TQString &/*string*/)
-{
- element()->m_value = KURL( widget()->url() ).prettyURL( 0, KURL::StripFileProtocol );
-}
-
-void RenderFileButton::slotUrlSelected(const TQString &)
-{
- element()->onChange();
-}
-
-void RenderFileButton::select()
-{
- widget()->lineEdit()->selectAll();
-}
-
-// -------------------------------------------------------------------------
-
-RenderLabel::RenderLabel(HTMLGenericFormElementImpl *element)
- : RenderFormElement(element)
-{
-
-}
-
-// -------------------------------------------------------------------------
-
-RenderLegend::RenderLegend(HTMLGenericFormElementImpl *element)
- : RenderBlock(element)
-{
-}
-
-// -------------------------------------------------------------------------------
-
-ComboBoxWidget::ComboBoxWidget(TQWidget *parent)
- : KComboBox(false, parent, "__khtml")
-{
- setAutoMask(true);
- if (listBox()) listBox()->installEventFilter(this);
- setMouseTracking(true);
-}
-
-bool ComboBoxWidget::event(TQEvent *e)
-{
- if (KComboBox::event(e))
- return true;
- if (e->type()==TQEvent::KeyPress)
- {
- TQKeyEvent *ke = TQT_TQKEYEVENT(e);
- switch(ke->key())
- {
- case Key_Return:
- case Key_Enter:
- popup();
- ke->accept();
- return true;
- default:
- return false;
- }
- }
- return false;
-}
-
-bool ComboBoxWidget::eventFilter(TQObject *dest, TQEvent *e)
-{
- if (TQT_BASE_OBJECT(dest)==TQT_BASE_OBJECT(listBox()) && e->type()==TQEvent::KeyPress)
- {
- TQKeyEvent *ke = TQT_TQKEYEVENT(e);
- bool forward = false;
- switch(ke->key())
- {
- case Key_Tab:
- forward=true;
- case Key_BackTab:
- // ugly hack. emulate popdownlistbox() (private in TQComboBox)
- // we re-use ke here to store the reference to the generated event.
- ke = new TQKeyEvent(TQEvent::KeyPress, Key_Escape, 0, 0);
- TQApplication::sendEvent(dest,ke);
- focusNextPrevChild(forward);
- delete ke;
- return true;
- default:
- return KComboBox::eventFilter(dest, e);
- }
- }
- return KComboBox::eventFilter(dest, e);
-}
-
-// -------------------------------------------------------------------------
-
-RenderSelect::RenderSelect(HTMLSelectElementImpl *element)
- : RenderFormElement(element)
-{
- m_ignoreSelectEvents = false;
- m_multiple = element->multiple();
- m_size = element->size();
- m_useListBox = (m_multiple || m_size > 1);
- m_selectionChanged = true;
- m_optionsChanged = true;
-
- if(m_useListBox)
- setQWidget(createListBox());
- else
- setQWidget(createComboBox());
-}
-
-void RenderSelect::updateFromElement()
-{
- m_ignoreSelectEvents = true;
-
- // change widget type
- bool oldMultiple = m_multiple;
- unsigned oldSize = m_size;
- bool oldListbox = m_useListBox;
-
- m_multiple = element()->multiple();
- m_size = element()->size();
- m_useListBox = (m_multiple || m_size > 1);
-
- if (oldMultiple != m_multiple || oldSize != m_size) {
- if (m_useListBox != oldListbox) {
- // type of select has changed
- if(m_useListBox)
- setQWidget(createListBox());
- else
- setQWidget(createComboBox());
- }
-
- if (m_useListBox && oldMultiple != m_multiple) {
- static_cast<KListBox*>(m_widget)->setSelectionMode(m_multiple ? TQListBox::Extended : TQListBox::Single);
- }
- m_selectionChanged = true;
- m_optionsChanged = true;
- }
-
- // update contents listbox/combobox based on options in m_element
- if ( m_optionsChanged ) {
- if (element()->m_recalcListItems)
- element()->recalcListItems();
- TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
- int listIndex;
-
- if(m_useListBox) {
- static_cast<KListBox*>(m_widget)->clear();
- }
-
- else
- static_cast<KComboBox*>(m_widget)->clear();
-
- for (listIndex = 0; listIndex < int(listItems.size()); listIndex++) {
- if (listItems[listIndex]->id() == ID_OPTGROUP) {
- DOMString text = listItems[listIndex]->getAttribute(ATTR_LABEL);
- if (text.isNull())
- text = "";
-
- if(m_useListBox) {
- TQListBoxText *item = new TQListBoxText(TQString(text.implementation()->s, text.implementation()->l));
- static_cast<KListBox*>(m_widget)
- ->insertItem(item, listIndex);
- item->setSelectable(false);
- }
- else {
- static_cast<KComboBox*>(m_widget)
- ->insertItem(TQString(text.implementation()->s, text.implementation()->l), listIndex);
- static_cast<KComboBox*>(m_widget)->listBox()->item(listIndex)->setSelectable(false);
- }
- }
- else if (listItems[listIndex]->id() == ID_OPTION) {
- HTMLOptionElementImpl* optElem = static_cast<HTMLOptionElementImpl*>(listItems[listIndex]);
- TQString text = optElem->text().string();
- if (optElem->parentNode()->id() == ID_OPTGROUP)
- {
- // Prefer label if set
- DOMString label = optElem->getAttribute(ATTR_LABEL);
- if (!label.isEmpty())
- text = label.string();
- text = TQString::fromLatin1(" ")+text;
- }
-
- if(m_useListBox) {
- KListBox *l = static_cast<KListBox*>(m_widget);
- l->insertItem(text, listIndex);
- DOMString disabled = optElem->getAttribute(ATTR_DISABLED);
- if (!disabled.isNull() && l->item( listIndex )) {
- l->item( listIndex )->setSelectable( false );
- }
- } else
- static_cast<KComboBox*>(m_widget)->insertItem(text, listIndex);
- }
- else
- KHTMLAssert(false);
- m_selectionChanged = true;
- }
-
- // TQComboBox caches the size hint unless you call setFont (ref: TT docu)
- if(!m_useListBox) {
- KComboBox *that = static_cast<KComboBox*>(m_widget);
- that->setFont( that->font() );
- }
- setNeedsLayoutAndMinMaxRecalc();
- m_optionsChanged = false;
- }
-
- // update selection
- if (m_selectionChanged) {
- updateSelection();
- }
-
-
- m_ignoreSelectEvents = false;
-
- RenderFormElement::updateFromElement();
-}
-
-void RenderSelect::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- if (m_optionsChanged)
- updateFromElement();
-
- // ### ugly HACK FIXME!!!
- setMinMaxKnown();
- layoutIfNeeded();
- setNeedsLayoutAndMinMaxRecalc();
- // ### end FIXME
-
- RenderFormElement::calcMinMaxWidth();
-}
-
-void RenderSelect::layout( )
-{
- KHTMLAssert(needsLayout());
- KHTMLAssert(minMaxKnown());
-
- // ### maintain selection properly between type/size changes, and work
- // out how to handle multiselect->singleselect (probably just select
- // first selected one)
-
- // calculate size
- if(m_useListBox) {
- KListBox* w = static_cast<KListBox*>(m_widget);
-
- TQListBoxItem* p = w->firstItem();
- int width = 0;
- int height = 0;
- while(p) {
- width = kMax(width, p->width(p->listBox()));
- height = kMax(height, p->height(p->listBox()));
- p = p->next();
- }
- if ( !height )
- height = w->fontMetrics().height();
- if ( !width )
- width = w->fontMetrics().width( 'x' );
-
- int size = m_size;
- // check if multiple and size was not given or invalid
- // Internet Exploder sets size to kMin(number of elements, 4)
- // Netscape seems to simply set it to "number of elements"
- // the average of that is IMHO kMin(number of elements, 10)
- // so I did that ;-)
- if(size < 1)
- size = kMin(static_cast<KListBox*>(m_widget)->count(), 10u);
-
- width += 2*w->frameWidth() + w->verticalScrollBar()->sizeHint().width();
- height = size*height + 2*w->frameWidth();
-
- setIntrinsicWidth( width );
- setIntrinsicHeight( height );
- }
- else {
- TQSize s(m_widget->sizeHint());
- setIntrinsicWidth( s.width() );
- setIntrinsicHeight( s.height() );
- }
-
- /// uuh, ignore the following line..
- setNeedsLayout(true);
- RenderFormElement::layout();
-
- // and now disable the widget in case there is no <option> given
- TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
-
- bool foundOption = false;
- for (uint i = 0; i < listItems.size() && !foundOption; i++)
- foundOption = (listItems[i]->id() == ID_OPTION);
-
- m_widget->setEnabled(foundOption && ! element()->disabled());
-}
-
-void RenderSelect::slotSelected(int index) // emitted by the combobox only
-{
- if ( m_ignoreSelectEvents ) return;
-
- KHTMLAssert( !m_useListBox );
-
- TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
- if(index >= 0 && index < int(listItems.size()))
- {
- bool found = ( listItems[index]->id() == ID_OPTION );
-
- if ( !found ) {
- // this one is not selectable, we need to find an option element
- while ( ( unsigned ) index < listItems.size() ) {
- if ( listItems[index]->id() == ID_OPTION ) {
- found = true;
- break;
- }
- ++index;
- }
-
- if ( !found ) {
- while ( index >= 0 ) {
- if ( listItems[index]->id() == ID_OPTION ) {
- found = true;
- break;
- }
- --index;
- }
- }
- }
-
- if ( found ) {
- bool changed = false;
-
- for ( unsigned int i = 0; i < listItems.size(); ++i )
- if ( listItems[i]->id() == ID_OPTION && i != (unsigned int) index )
- {
- HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>( listItems[i] );
- changed |= (opt->m_selected == true);
- opt->m_selected = false;
- }
-
- HTMLOptionElementImpl* opt = static_cast<HTMLOptionElementImpl*>(listItems[index]);
- changed |= (opt->m_selected == false);
- opt->m_selected = true;
-
- if ( index != static_cast<ComboBoxWidget*>( m_widget )->currentItem() )
- static_cast<ComboBoxWidget*>( m_widget )->setCurrentItem( index );
-
- // When selecting an optgroup item, and we move forward to we
- // shouldn't emit onChange. Hence this bool, the if above doesn't do it.
- if ( changed )
- {
- ref();
- element()->onChange();
- deref();
- }
- }
- }
-}
-
-
-void RenderSelect::slotSelectionChanged() // emitted by the listbox only
-{
- if ( m_ignoreSelectEvents ) return;
-
- // don't use listItems() here as we have to avoid recalculations - changing the
- // option list will make use update options not in the way the user expects them
- TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->m_listItems;
- for ( unsigned i = 0; i < listItems.count(); i++ )
- // don't use setSelected() here because it will cause us to be called
- // again with updateSelection.
- if ( listItems[i]->id() == ID_OPTION )
- static_cast<HTMLOptionElementImpl*>( listItems[i] )
- ->m_selected = static_cast<KListBox*>( m_widget )->isSelected( i );
-
- ref();
- element()->onChange();
- deref();
-}
-
-void RenderSelect::setOptionsChanged(bool _optionsChanged)
-{
- m_optionsChanged = _optionsChanged;
-}
-
-KListBox* RenderSelect::createListBox()
-{
- KListBox *lb = new KListBox(view()->viewport(), "__khtml");
- lb->setSelectionMode(m_multiple ? TQListBox::Extended : TQListBox::Single);
- // ### looks broken
- //lb->setAutoMask(true);
- connect( lb, TQT_SIGNAL( selectionChanged() ), this, TQT_SLOT( slotSelectionChanged() ) );
-// connect( lb, TQT_SIGNAL( clicked( TQListBoxItem * ) ), this, TQT_SLOT( slotClicked() ) );
- m_ignoreSelectEvents = false;
- lb->setMouseTracking(true);
-
- return lb;
-}
-
-ComboBoxWidget *RenderSelect::createComboBox()
-{
- ComboBoxWidget *cb = new ComboBoxWidget(view()->viewport());
- connect(cb, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotSelected(int)));
- return cb;
-}
-
-void RenderSelect::updateSelection()
-{
- TQMemArray<HTMLGenericFormElementImpl*> listItems = element()->listItems();
- int i;
- if (m_useListBox) {
- // if multi-select, we select only the new selected index
- KListBox *listBox = static_cast<KListBox*>(m_widget);
- for (i = 0; i < int(listItems.size()); i++)
- listBox->setSelected(i,listItems[i]->id() == ID_OPTION &&
- static_cast<HTMLOptionElementImpl*>(listItems[i])->selected());
- }
- else {
- bool found = false;
- unsigned firstOption = listItems.size();
- i = listItems.size();
- while (i--)
- if (listItems[i]->id() == ID_OPTION) {
- if (found)
- static_cast<HTMLOptionElementImpl*>(listItems[i])->m_selected = false;
- else if (static_cast<HTMLOptionElementImpl*>(listItems[i])->selected()) {
- static_cast<KComboBox*>( m_widget )->setCurrentItem(i);
- found = true;
- }
- firstOption = i;
- }
-
- Q_ASSERT(firstOption == listItems.size() || found);
- }
-
- m_selectionChanged = false;
-}
-
-
-// -------------------------------------------------------------------------
-
-TextAreaWidget::TextAreaWidget(int wrap, TQWidget* parent)
- : KTextEdit(parent, "__khtml"), m_findDlg(0), m_find(0), m_repDlg(0), m_replace(0)
-{
- if(wrap != DOM::HTMLTextAreaElementImpl::ta_NoWrap) {
- setWordWrap(TQTextEdit::WidgetWidth);
- setHScrollBarMode( AlwaysOff );
- setVScrollBarMode( AlwaysOn );
- }
- else {
- setWordWrap(TQTextEdit::NoWrap);
- setHScrollBarMode( Auto );
- setVScrollBarMode( Auto );
- }
- KCursor::setAutoHideCursor(viewport(), true);
- setTextFormat(TQTextEdit::PlainText);
- setAutoMask(true);
- setMouseTracking(true);
-
- KActionCollection *ac = new KActionCollection(this);
- m_findAction = KStdAction::find( TQT_TQOBJECT(this), TQT_SLOT( slotFind() ), ac );
- m_findNextAction = KStdAction::findNext( TQT_TQOBJECT(this), TQT_SLOT( slotFindNext() ), ac );
- m_replaceAction = KStdAction::replace( TQT_TQOBJECT(this), TQT_SLOT( slotReplace() ), ac );
-}
-
-
-TextAreaWidget::~TextAreaWidget()
-{
- delete m_replace;
- m_replace = 0L;
- delete m_find;
- m_find = 0L;
- delete m_repDlg;
- m_repDlg = 0L;
- delete m_findDlg;
- m_findDlg = 0L;
-}
-
-
-TQPopupMenu *TextAreaWidget::createPopupMenu(const TQPoint& pos)
-{
- TQPopupMenu *popup = KTextEdit::createPopupMenu(pos);
-
- if ( !popup ) {
- return 0L;
- }
-
- if (!isReadOnly()) {
- popup->insertSeparator();
-
- m_findAction->plug(popup);
- m_findAction->setEnabled( !text().isEmpty() );
-
- m_findNextAction->plug(popup);
- m_findNextAction->setEnabled( m_find != 0 );
-
- m_replaceAction->plug(popup);
- m_replaceAction->setEnabled( !text().isEmpty() );
- }
-
- return popup;
-}
-
-
-void TextAreaWidget::slotFindHighlight(const TQString& text, int matchingIndex, int matchingLength)
-{
- Q_UNUSED(text)
- //kdDebug() << "Highlight: [" << text << "] mi:" << matchingIndex << " ml:" << matchingLength << endl;
- if (sender() == m_replace) {
- setSelection(m_repPara, matchingIndex, m_repPara, matchingIndex + matchingLength);
- setCursorPosition(m_repPara, matchingIndex);
- } else {
- setSelection(m_findPara, matchingIndex, m_findPara, matchingIndex + matchingLength);
- setCursorPosition(m_findPara, matchingIndex);
- }
- ensureCursorVisible();
-}
-
-
-void TextAreaWidget::slotReplaceText(const TQString &text, int replacementIndex, int /*replacedLength*/, int matchedLength) {
- Q_UNUSED(text)
- //kdDebug() << "Replace: [" << text << "] ri:" << replacementIndex << " rl:" << replacedLength << " ml:" << matchedLength << endl;
- setSelection(m_repPara, replacementIndex, m_repPara, replacementIndex + matchedLength);
- removeSelectedText();
- insertAt(m_repDlg->replacement(), m_repPara, replacementIndex);
- if (m_replace->options() & KReplaceDialog::PromptOnReplace) {
- ensureCursorVisible();
- }
-}
-
-
-void TextAreaWidget::slotDoReplace()
-{
- if (!m_repDlg) {
- // Should really assert()
- return;
- }
-
- delete m_replace;
- m_replace = new KReplace(m_repDlg->pattern(), m_repDlg->replacement(), m_repDlg->options(), this);
- if (m_replace->options() & KFindDialog::FromCursor) {
- getCursorPosition(&m_repPara, &m_repIndex);
- } else if (m_replace->options() & KFindDialog::FindBackwards) {
- m_repPara = paragraphs() - 1;
- m_repIndex = paragraphLength(m_repPara) - 1;
- } else {
- m_repPara = 0;
- m_repIndex = 0;
- }
-
- // Connect highlight signal to code which handles highlighting
- // of found text.
- connect(m_replace, TQT_SIGNAL(highlight(const TQString &, int, int)),
- this, TQT_SLOT(slotFindHighlight(const TQString &, int, int)));
- connect(m_replace, TQT_SIGNAL(findNext()), this, TQT_SLOT(slotReplaceNext()));
- connect(m_replace, TQT_SIGNAL(replace(const TQString &, int, int, int)),
- this, TQT_SLOT(slotReplaceText(const TQString &, int, int, int)));
-
- m_repDlg->close();
- slotReplaceNext();
-}
-
-
-void TextAreaWidget::slotReplaceNext()
-{
- if (!m_replace) {
- // assert?
- return;
- }
-
- if (!(m_replace->options() & KReplaceDialog::PromptOnReplace)) {
- viewport()->setUpdatesEnabled(false);
- }
-
- KFind::Result res = KFind::NoMatch;
- while (res == KFind::NoMatch) {
- // If we're done.....
- if (m_replace->options() & KFindDialog::FindBackwards) {
- if (m_repIndex == 0 && m_repPara == 0) {
- break;
- }
- } else {
- if (m_repPara == paragraphs() - 1 &&
- m_repIndex == paragraphLength(m_repPara) - 1) {
- break;
- }
- }
-
- if (m_replace->needData()) {
- m_replace->setData(text(m_repPara), m_repIndex);
- }
-
- res = m_replace->replace();
-
- if (res == KFind::NoMatch) {
- if (m_replace->options() & KFindDialog::FindBackwards) {
- if (m_repPara == 0) {
- m_repIndex = 0;
- } else {
- m_repPara--;
- m_repIndex = paragraphLength(m_repPara) - 1;
- }
- } else {
- if (m_repPara == paragraphs() - 1) {
- m_repIndex = paragraphLength(m_repPara) - 1;
- } else {
- m_repPara++;
- m_repIndex = 0;
- }
- }
- }
- }
-
- if (!(m_replace->options() & KReplaceDialog::PromptOnReplace)) {
- viewport()->setUpdatesEnabled(true);
- repaintChanged();
- }
-
- if (res == KFind::NoMatch) { // at end
- m_replace->displayFinalDialog();
- delete m_replace;
- m_replace = 0;
- ensureCursorVisible();
- //or if ( m_replace->shouldRestart() ) { reinit (w/o FromCursor) and call slotReplaceNext(); }
- } else {
- //m_replace->closeReplaceNextDialog();
- }
-}
-
-
-void TextAreaWidget::slotDoFind()
-{
- if (!m_findDlg) {
- // Should really assert()
- return;
- }
-
- delete m_find;
- m_find = new KFind(m_findDlg->pattern(), m_findDlg->options(), this);
- if (m_find->options() & KFindDialog::FromCursor) {
- getCursorPosition(&m_findPara, &m_findIndex);
- } else if (m_find->options() & KFindDialog::FindBackwards) {
- m_findPara = paragraphs() - 1;
- m_findIndex = paragraphLength(m_findPara) - 1;
- } else {
- m_findPara = 0;
- m_findIndex = 0;
- }
-
- // Connect highlight signal to code which handles highlighting
- // of found text.
- connect(m_find, TQT_SIGNAL(highlight(const TQString &, int, int)),
- this, TQT_SLOT(slotFindHighlight(const TQString &, int, int)));
- connect(m_find, TQT_SIGNAL(findNext()), this, TQT_SLOT(slotFindNext()));
-
- m_findDlg->close();
- m_find->closeFindNextDialog();
- slotFindNext();
-}
-
-
-void TextAreaWidget::slotFindNext()
-{
- if (!m_find) {
- // assert?
- return;
- }
-
- KFind::Result res = KFind::NoMatch;
- while (res == KFind::NoMatch) {
- // If we're done.....
- if (m_find->options() & KFindDialog::FindBackwards) {
- if (m_findIndex == 0 && m_findPara == 0) {
- break;
- }
- } else {
- if (m_findPara == paragraphs() - 1 &&
- m_findIndex == paragraphLength(m_findPara) - 1) {
- break;
- }
- }
-
- if (m_find->needData()) {
- m_find->setData(text(m_findPara), m_findIndex);
- }
-
- res = m_find->find();
-
- if (res == KFind::NoMatch) {
- if (m_find->options() & KFindDialog::FindBackwards) {
- if (m_findPara == 0) {
- m_findIndex = 0;
- } else {
- m_findPara--;
- m_findIndex = paragraphLength(m_findPara) - 1;
- }
- } else {
- if (m_findPara == paragraphs() - 1) {
- m_findIndex = paragraphLength(m_findPara) - 1;
- } else {
- m_findPara++;
- m_findIndex = 0;
- }
- }
- }
- }
-
- if (res == KFind::NoMatch) { // at end
- m_find->displayFinalDialog();
- delete m_find;
- m_find = 0;
- //or if ( m_find->shouldRestart() ) { reinit (w/o FromCursor) and call slotFindNext(); }
- } else {
- //m_find->closeFindNextDialog();
- }
-}
-
-
-void TextAreaWidget::slotFind()
-{
- if( text().isEmpty() ) // saves having to track the text changes
- return;
-
- if ( m_findDlg ) {
- KWin::activateWindow( m_findDlg->winId() );
- } else {
- m_findDlg = new KFindDialog(false, this, "KHTML Text Area Find Dialog");
- connect( m_findDlg, TQT_SIGNAL(okClicked()), this, TQT_SLOT(slotDoFind()) );
- }
- m_findDlg->show();
-}
-
-
-void TextAreaWidget::slotReplace()
-{
- if( text().isEmpty() ) // saves having to track the text changes
- return;
-
- if ( m_repDlg ) {
- KWin::activateWindow( m_repDlg->winId() );
- } else {
- m_repDlg = new KReplaceDialog(this, "KHTMLText Area Replace Dialog", 0,
- TQStringList(), TQStringList(), false);
- connect( m_repDlg, TQT_SIGNAL(okClicked()), this, TQT_SLOT(slotDoReplace()) );
- }
- m_repDlg->show();
-}
-
-
-bool TextAreaWidget::event( TQEvent *e )
-{
- if ( e->type() == TQEvent::AccelAvailable && isReadOnly() ) {
- TQKeyEvent* ke = (TQKeyEvent*) e;
- if ( ke->state() & ControlButton ) {
- switch ( ke->key() ) {
- case Key_Left:
- case Key_Right:
- case Key_Up:
- case Key_Down:
- case Key_Home:
- case Key_End:
- ke->accept();
- default:
- break;
- }
- }
- }
- return KTextEdit::event( e );
-}
-
-// -------------------------------------------------------------------------
-
-RenderTextArea::RenderTextArea(HTMLTextAreaElementImpl *element)
- : RenderFormElement(element)
-{
- scrollbarsStyled = false;
-
- TextAreaWidget *edit = new TextAreaWidget(element->wrap(), view());
- setQWidget(edit);
- const KHTMLSettings *settings = view()->part()->settings();
- edit->setCheckSpellingEnabled( settings->autoSpellCheck() );
- edit->setTabChangesFocus( ! settings->allowTabulation() );
-
- connect(edit,TQT_SIGNAL(textChanged()),this,TQT_SLOT(slotTextChanged()));
-}
-
-RenderTextArea::~RenderTextArea()
-{
- if ( element()->m_dirtyvalue ) {
- element()->m_value = text();
- element()->m_dirtyvalue = false;
- }
-}
-
-void RenderTextArea::handleFocusOut()
-{
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- if ( w && element()->m_dirtyvalue ) {
- element()->m_value = text();
- element()->m_dirtyvalue = false;
- }
-
- if ( w && element()->m_changed ) {
- element()->m_changed = false;
- element()->onChange();
- }
-}
-
-void RenderTextArea::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- const TQFontMetrics &m = style()->fontMetrics();
- w->setTabStopWidth(8 * m.width(" "));
- TQSize size( kMax(element()->cols(), 1L)*m.width('x') + w->frameWidth() +
- w->verticalScrollBar()->sizeHint().width(),
- kMax(element()->rows(), 1L)*m.lineSpacing() + w->frameWidth()*4 +
- (w->wordWrap() == TQTextEdit::NoWrap ?
- w->horizontalScrollBar()->sizeHint().height() : 0)
- );
-
- setIntrinsicWidth( size.width() );
- setIntrinsicHeight( size.height() );
-
- RenderFormElement::calcMinMaxWidth();
-}
-
-void RenderTextArea::setStyle(RenderStyle* _style)
-{
- bool unsubmittedFormChange = element()->m_unsubmittedFormChange;
-
- RenderFormElement::setStyle(_style);
-
- widget()->blockSignals(true);
- widget()->setAlignment(textAlignment());
- widget()->blockSignals(false);
-
- scrollbarsStyled = false;
-
- element()->m_unsubmittedFormChange = unsubmittedFormChange;
-}
-
-void RenderTextArea::layout()
-{
- KHTMLAssert( needsLayout() );
-
- RenderFormElement::layout();
-
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
-
- if (!scrollbarsStyled) {
- w->horizontalScrollBar()->setPalette(style()->palette());
- w->verticalScrollBar()->setPalette(style()->palette());
- scrollbarsStyled=true;
- }
-}
-
-void RenderTextArea::updateFromElement()
-{
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- w->setReadOnly(element()->readOnly());
- TQString elementText = element()->value().string();
- if ( elementText != text() )
- {
- w->blockSignals(true);
- int line, col;
- w->getCursorPosition( &line, &col );
- int cx = w->contentsX();
- int cy = w->contentsY();
- w->setText( elementText );
- w->setCursorPosition( line, col );
- w->scrollBy( cx, cy );
- w->blockSignals(false);
- }
- element()->m_dirtyvalue = false;
-
- RenderFormElement::updateFromElement();
-}
-
-void RenderTextArea::close( )
-{
- element()->setValue( element()->defaultValue() );
-
- RenderFormElement::close();
-}
-
-
-TQString RenderTextArea::text()
-{
- TQString txt;
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
-
- if(element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical) {
- // yeah, TQTextEdit has no accessor for getting the visually wrapped text
- for (int p=0; p < w->paragraphs(); ++p) {
- int ll = 0;
- int lindex = w->lineOfChar(p, 0);
- TQString paragraphText = w->text(p);
- int pl = w->paragraphLength(p);
- paragraphText = paragraphText.left(pl); //Snip invented space.
- for (int l = 0; l < pl; ++l) {
- if (lindex != w->lineOfChar(p, l)) {
- paragraphText.insert(l+ll++, TQString::fromLatin1("\n"));
- lindex = w->lineOfChar(p, l);
- }
- }
- txt += paragraphText;
- if (p < w->paragraphs() - 1)
- txt += TQString::fromLatin1("\n");
- }
- }
- else
- txt = w->text();
-
- return txt;
-}
-
-int RenderTextArea::queryParagraphInfo(int para, Mode m, int param) {
- /* We have to be a bit careful here, as we need to match up the positions
- to what our value returns here*/
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- int length = 0;
-
- bool physWrap = element()->wrap() == DOM::HTMLTextAreaElementImpl::ta_Physical;
-
- TQString paragraphText = w->text(para);
- int pl = w->paragraphLength(para);
- int physicalPL = pl;
- if (m == ParaPortionLength)
- pl = param;
-
- if (physWrap) {
- //Go through all the chars of paragraph, and count line changes, chars, etc.
- int lindex = w->lineOfChar(para, 0);
- for (int c = 0; c < pl; ++c) {
- ++length;
- // Is there a change after this char?
- if (c+1 < physicalPL && lindex != w->lineOfChar(para, c+1)) {
- lindex = w->lineOfChar(para, c+1);
- ++length;
- }
- if (m == ParaPortionOffset && length > param)
- return c;
- }
- } else {
- //Make sure to count the LF, CR as appropriate. ### this is stupid now, simplify
- for (int c = 0; c < pl; ++c) {
- ++length;
- if (m == ParaPortionOffset && length > param)
- return c;
- }
- }
- if (m == ParaPortionOffset)
- return pl;
- if (m == ParaPortionLength)
- return length;
- return length + 1;
-}
-
-long RenderTextArea::computeCharOffset(int para, int index) {
- if (para < 0)
- return 0;
-
- long pos = 0;
- for (int cp = 0; cp < para; ++cp)
- pos += queryParagraphInfo(cp, ParaLength);
-
- if (index >= 0)
- pos += queryParagraphInfo(para, ParaPortionLength, index);
- return pos;
-}
-
-void RenderTextArea::computeParagraphAndIndex(long offset, int* para, int* index) {
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
-
- if (!w->paragraphs()) {
- *para = -1;
- *index = -1;
- return;
- }
-
- //Find the paragraph that contains us..
- int containingPar = 0;
- long endPos = 0;
- long startPos = 0;
- for (int p = 0; p < w->paragraphs(); ++p) {
- int len = queryParagraphInfo(p, ParaLength);
- endPos += len;
- if (endPos > offset) {
- containingPar = p;
- break;
- }
- startPos += len;
- }
-
- *para = containingPar;
-
- //Now, scan within the paragraph to find the position..
- long localOffset = offset - startPos;
-
- *index = queryParagraphInfo(containingPar, ParaPortionOffset, localOffset);
-}
-
-void RenderTextArea::highLightWord( unsigned int length, unsigned int pos )
-{
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- if ( w )
- w->highLightWord( length, pos );
-}
-
-
-void RenderTextArea::slotTextChanged()
-{
- element()->m_dirtyvalue = true;
- element()->m_changed = true;
- if (element()->m_value != text())
- element()->m_unsubmittedFormChange = true;
-}
-
-void RenderTextArea::select()
-{
- static_cast<TextAreaWidget *>(m_widget)->selectAll();
-}
-
-long RenderTextArea::selectionStart()
-{
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- int para, index, dummy1, dummy2;
- w->getSelection(&para, &index, &dummy1, &dummy2);
- if (para == -1 || index == -1)
- w->getCursorPosition(&para, &index);
-
- return computeCharOffset(para, index);
-}
-
-long RenderTextArea::selectionEnd()
-{
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- int para, index, dummy1, dummy2;
- w->getSelection(&dummy1, &dummy2, &para, &index);
- if (para == -1 || index == -1)
- w->getCursorPosition(&para, &index);
-
- return computeCharOffset(para, index);
-}
-
-void RenderTextArea::setSelectionStart(long offset) {
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- int fromPara, fromIndex, toPara, toIndex;
- w->getSelection(&fromPara, &fromIndex, &toPara, &toIndex);
- computeParagraphAndIndex(offset, &fromPara, &fromIndex);
- if (toPara == -1 || toIndex == -1) {
- toPara = fromPara;
- toIndex = fromIndex;
- }
- w->setSelection(fromPara, fromIndex, toPara, toIndex);
-}
-
-void RenderTextArea::setSelectionEnd(long offset) {
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- int fromPara, fromIndex, toPara, toIndex;
- w->getSelection(&fromPara, &fromIndex, &toPara, &toIndex);
- computeParagraphAndIndex(offset, &toPara, &toIndex);
- w->setSelection(fromPara, fromIndex, toPara, toIndex);
-}
-
-void RenderTextArea::setSelectionRange(long start, long end) {
- TextAreaWidget* w = static_cast<TextAreaWidget*>(m_widget);
- int fromPara, fromIndex, toPara, toIndex;
- computeParagraphAndIndex(start, &fromPara, &fromIndex);
- computeParagraphAndIndex(end, &toPara, &toIndex);
- w->setSelection(fromPara, fromIndex, toPara, toIndex);
-}
-// ---------------------------------------------------------------------------
-
-#include "render_form.moc"
diff --git a/khtml/rendering/render_form.h b/khtml/rendering/render_form.h
deleted file mode 100644
index db5088d20..000000000
--- a/khtml/rendering/render_form.h
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_FORM_H
-#define RENDER_FORM_H
-
-#include "rendering/render_replaced.h"
-#include "rendering/render_image.h"
-#include "rendering/render_flow.h"
-#include "rendering/render_style.h"
-#include "html/html_formimpl.h"
-
-class TQWidget;
-class TQLineEdit;
-class QListboxItem;
-
-#include <ktextedit.h>
-#include <kurlrequester.h>
-#include <klineedit.h>
-#include <tqcheckbox.h>
-#include <tqradiobutton.h>
-#include <tqpushbutton.h>
-#include <tqhbox.h>
-#include <klistbox.h>
-#include <kcombobox.h>
-#include "dom/dom_misc.h"
-
-class KHTMLPartBrowserExtension;
-class KSpell;
-class KFindDialog;
-class KReplaceDialog;
-class KFind;
-class KReplace;
-class KAction;
-class KURLRequester;
-
-namespace DOM {
- class HTMLFormElementImpl;
- class HTMLInputElementImpl;
- class HTMLSelectElementImpl;
- class HTMLGenericFormElementImpl;
- class HTMLTextAreaElementImpl;
-}
-
-namespace khtml {
-
-class DocLoader;
-
-// -------------------------------------------------------------------------
-
-class RenderFormElement : public khtml::RenderWidget
-{
-public:
- RenderFormElement(DOM::HTMLGenericFormElementImpl* node);
- virtual ~RenderFormElement();
-
- virtual const char *renderName() const { return "RenderForm"; }
-
- virtual bool isFormElement() const { return true; }
-
- // form elements never have padding
- virtual int paddingTop() const { return 0; }
- virtual int paddingBottom() const { return 0; }
- virtual int paddingLeft() const { return 0; }
- virtual int paddingRight() const { return 0; }
-
- virtual void updateFromElement();
-
- virtual void layout();
- virtual short baselinePosition( bool ) const;
-
- DOM::HTMLGenericFormElementImpl *element() const
- { return static_cast<DOM::HTMLGenericFormElementImpl*>(RenderObject::element()); }
-
-protected:
- virtual bool isRenderButton() const { return false; }
- virtual bool isEditable() const { return false; }
- TQ_Alignment textAlignment() const;
-
- TQPoint m_mousePos;
- int m_state;
-};
-
-// -------------------------------------------------------------------------
-
-// generic class for all buttons
-class RenderButton : public RenderFormElement
-{
- Q_OBJECT
-public:
- RenderButton(DOM::HTMLGenericFormElementImpl* node);
-
- virtual const char *renderName() const { return "RenderButton"; }
-
- virtual short baselinePosition( bool ) const;
-
- // don't even think about making this method virtual!
- DOM::HTMLInputElementImpl* element() const
- { return static_cast<DOM::HTMLInputElementImpl*>(RenderObject::element()); }
-
-protected:
- virtual bool isRenderButton() const { return true; }
-};
-
-// -------------------------------------------------------------------------
-
-class RenderCheckBox : public RenderButton
-{
- Q_OBJECT
-public:
- RenderCheckBox(DOM::HTMLInputElementImpl* node);
-
- virtual const char *renderName() const { return "RenderCheckBox"; }
- virtual void updateFromElement();
- virtual void calcMinMaxWidth();
-
- virtual bool handleEvent(const DOM::EventImpl&) { return false; }
-
- TQCheckBox *widget() const { return static_cast<TQCheckBox*>(m_widget); }
-
-public slots:
- virtual void slotStateChanged(int state);
-};
-
-// -------------------------------------------------------------------------
-
-class RenderRadioButton : public RenderButton
-{
- Q_OBJECT
-public:
- RenderRadioButton(DOM::HTMLInputElementImpl* node);
-
- virtual const char *renderName() const { return "RenderRadioButton"; }
-
- virtual void calcMinMaxWidth();
- virtual void updateFromElement();
-
- virtual bool handleEvent(const DOM::EventImpl&) { return false; }
-
- TQRadioButton *widget() const { return static_cast<TQRadioButton*>(m_widget); }
-
-public slots:
- virtual void slotToggled(bool);
-};
-
-// -------------------------------------------------------------------------
-
-class RenderSubmitButton : public RenderButton
-{
-public:
- RenderSubmitButton(DOM::HTMLInputElementImpl *element);
-
- virtual const char *renderName() const { return "RenderSubmitButton"; }
-
- virtual void calcMinMaxWidth();
- virtual void updateFromElement();
- virtual short baselinePosition( bool ) const;
-private:
- TQString rawText();
-};
-
-// -------------------------------------------------------------------------
-
-class RenderImageButton : public RenderImage
-{
-public:
- RenderImageButton(DOM::HTMLInputElementImpl *element)
- : RenderImage(element) {}
-
- virtual const char *renderName() const { return "RenderImageButton"; }
-};
-
-
-// -------------------------------------------------------------------------
-
-class RenderResetButton : public RenderSubmitButton
-{
-public:
- RenderResetButton(DOM::HTMLInputElementImpl *element);
-
- virtual const char *renderName() const { return "RenderResetButton"; }
-
-};
-
-// -------------------------------------------------------------------------
-
-class RenderPushButton : public RenderSubmitButton
-{
-public:
- RenderPushButton(DOM::HTMLInputElementImpl *element)
- : RenderSubmitButton(element) {}
-
-};
-
-// -------------------------------------------------------------------------
-
-class RenderLineEdit : public RenderFormElement
-{
- Q_OBJECT
-public:
- RenderLineEdit(DOM::HTMLInputElementImpl *element);
-
- virtual void calcMinMaxWidth();
-
- virtual const char *renderName() const { return "RenderLineEdit"; }
- virtual void updateFromElement();
- virtual void setStyle(RenderStyle *style);
-
- void select();
-
- KLineEdit *widget() const { return static_cast<KLineEdit*>(m_widget); }
- DOM::HTMLInputElementImpl* element() const
- { return static_cast<DOM::HTMLInputElementImpl*>(RenderObject::element()); }
- void highLightWord( unsigned int length, unsigned int pos );
-
- long selectionStart();
- long selectionEnd();
- void setSelectionStart(long pos);
- void setSelectionEnd(long pos);
- void setSelectionRange(long start, long end);
-public slots:
- void slotReturnPressed();
- void slotTextChanged(const TQString &string);
-protected:
- virtual void handleFocusOut();
-
-private:
- virtual bool isEditable() const { return true; }
- virtual bool canHaveBorder() const { return true; }
-};
-
-// -------------------------------------------------------------------------
-
-class LineEditWidget : public KLineEdit
-{
- Q_OBJECT
-public:
- LineEditWidget(DOM::HTMLInputElementImpl* input,
- KHTMLView* view, TQWidget* parent);
- ~LineEditWidget();
- void highLightWord( unsigned int length, unsigned int pos );
-
-protected:
- virtual bool event( TQEvent *e );
- virtual void mouseMoveEvent(TQMouseEvent *e);
- virtual TQPopupMenu *createPopupMenu();
-private slots:
- void extendedMenuActivated( int id);
- void slotCheckSpelling();
- void slotSpellCheckReady( KSpell *s );
- void slotSpellCheckDone( const TQString &s );
- void spellCheckerMisspelling( const TQString &text, const TQStringList &, unsigned int pos);
- void spellCheckerCorrected( const TQString &, const TQString &, unsigned int );
- void spellCheckerFinished();
- void slotRemoveFromHistory( const TQString & );
-
-private:
- enum LineEditMenuID {
- ClearHistory,
- EditHistory
- };
- DOM::HTMLInputElementImpl* m_input;
- KHTMLView* m_view;
- KSpell *m_spell;
- KAction *m_spellAction;
-};
-
-// -------------------------------------------------------------------------
-
-class RenderFieldset : public RenderBlock
-{
-public:
- RenderFieldset(DOM::HTMLGenericFormElementImpl *element);
-
- virtual const char *renderName() const { return "RenderFieldSet"; }
- virtual RenderObject* layoutLegend(bool relayoutChildren);
- virtual void setStyle(RenderStyle* _style);
-
-protected:
- virtual void paintBoxDecorations(PaintInfo& pI, int _tx, int _ty);
- void paintBorderMinusLegend(TQPainter *p, int _tx, int _ty, int w,
- int h, const RenderStyle *style, int lx, int lw);
- RenderObject* findLegend();
-};
-
-// -------------------------------------------------------------------------
-
-class RenderFileButton : public RenderFormElement
-{
- Q_OBJECT
-public:
- RenderFileButton(DOM::HTMLInputElementImpl *element);
-
- virtual const char *renderName() const { return "RenderFileButton"; }
- virtual void calcMinMaxWidth();
- virtual void updateFromElement();
- void select();
-
- KURLRequester *widget() const { return static_cast<KURLRequester*>(m_widget); }
-
- DOM::HTMLInputElementImpl *element() const
- { return static_cast<DOM::HTMLInputElementImpl*>(RenderObject::element()); }
-
-public slots:
- void slotReturnPressed();
- void slotTextChanged(const TQString &string);
- void slotUrlSelected(const TQString &string);
-
-protected:
- virtual void handleFocusOut();
-
- virtual bool isEditable() const { return true; }
- virtual bool canHaveBorder() const { return true; }
- virtual bool acceptsSyntheticEvents() const { return false; }
-
- bool m_clicked;
- bool m_haveFocus;
-};
-
-
-// -------------------------------------------------------------------------
-
-class RenderLabel : public RenderFormElement
-{
-public:
- RenderLabel(DOM::HTMLGenericFormElementImpl *element);
-
- virtual const char *renderName() const { return "RenderLabel"; }
-
-protected:
- virtual bool canHaveBorder() const { return true; }
-};
-
-
-// -------------------------------------------------------------------------
-
-class RenderLegend : public RenderBlock
-{
-public:
- RenderLegend(DOM::HTMLGenericFormElementImpl *element);
-
- virtual const char *renderName() const { return "RenderLegend"; }
-};
-
-// -------------------------------------------------------------------------
-
-class ComboBoxWidget : public KComboBox
-{
-public:
- ComboBoxWidget(TQWidget *parent);
-
-protected:
- virtual bool event(TQEvent *);
- virtual bool eventFilter(TQObject *dest, TQEvent *e);
-};
-
-// -------------------------------------------------------------------------
-
-class RenderSelect : public RenderFormElement
-{
- Q_OBJECT
-public:
- RenderSelect(DOM::HTMLSelectElementImpl *element);
-
- virtual const char *renderName() const { return "RenderSelect"; }
-
- virtual void calcMinMaxWidth();
- virtual void layout();
-
- void setOptionsChanged(bool _optionsChanged);
-
- bool selectionChanged() { return m_selectionChanged; }
- void setSelectionChanged(bool _selectionChanged) { m_selectionChanged = _selectionChanged; }
- virtual void updateFromElement();
-
- void updateSelection();
-
- DOM::HTMLSelectElementImpl *element() const
- { return static_cast<DOM::HTMLSelectElementImpl*>(RenderObject::element()); }
-
-protected:
- KListBox *createListBox();
- ComboBoxWidget *createComboBox();
-
- unsigned m_size;
- bool m_multiple;
- bool m_useListBox;
- bool m_selectionChanged;
- bool m_ignoreSelectEvents;
- bool m_optionsChanged;
-
-protected slots:
- void slotSelected(int index);
- void slotSelectionChanged();
-};
-
-// -------------------------------------------------------------------------
-class TextAreaWidget : public KTextEdit
-{
- Q_OBJECT
-public:
- TextAreaWidget(int wrap, TQWidget* parent);
- virtual ~TextAreaWidget();
-
-protected:
- virtual bool event (TQEvent *e );
- virtual TQPopupMenu *createPopupMenu(const TQPoint& pos);
- virtual TQPopupMenu* createPopupMenu() { return KTextEdit::createPopupMenu(); }
-private slots:
- void slotFind();
- void slotDoFind();
- void slotFindNext();
- void slotReplace();
- void slotDoReplace();
- void slotReplaceNext();
- void slotReplaceText(const TQString&, int, int, int);
- void slotFindHighlight(const TQString&, int, int);
-private:
- KFindDialog *m_findDlg;
- KFind *m_find;
- KReplaceDialog *m_repDlg;
- KReplace *m_replace;
- KAction *m_findAction;
- KAction *m_findNextAction;
- KAction *m_replaceAction;
- int m_findIndex, m_findPara;
- int m_repIndex, m_repPara;
-};
-
-
-// -------------------------------------------------------------------------
-
-class RenderTextArea : public RenderFormElement
-{
- Q_OBJECT
-public:
- RenderTextArea(DOM::HTMLTextAreaElementImpl *element);
- ~RenderTextArea();
-
- virtual const char *renderName() const { return "RenderTextArea"; }
- virtual void calcMinMaxWidth();
- virtual void layout();
- virtual void setStyle(RenderStyle *style);
-
- virtual void close ( );
- virtual void updateFromElement();
-
- // don't even think about making this method virtual!
- TextAreaWidget *widget() const { return static_cast<TextAreaWidget*>(m_widget); }
- DOM::HTMLTextAreaElementImpl* element() const
- { return static_cast<DOM::HTMLTextAreaElementImpl*>(RenderObject::element()); }
-
- TQString text();
- void highLightWord( unsigned int length, unsigned int pos );
-
- void select();
-
- long selectionStart();
- long selectionEnd();
- void setSelectionStart(long pos);
- void setSelectionEnd(long pos);
- void setSelectionRange(long start, long end);
-protected slots:
- void slotTextChanged();
-
-protected:
- virtual void handleFocusOut();
-
- virtual bool isEditable() const { return true; }
- virtual bool canHaveBorder() const { return true; }
-
- bool scrollbarsStyled;
-private:
- //Convert para, index -> offset
- long computeCharOffset(int para, int index);
-
- //Convert offset -> para, index
- void computeParagraphAndIndex(long offset, int* para, int* index);
-
- //Helper for doing the conversion..
- enum Mode { ParaLength, //Returns the length of the entire paragraph
- ParaPortionLength, //Return length of paragraph portion set by threshold
- ParaPortionOffset }; //Return offset that matches the length threshold.
- int queryParagraphInfo(int para, Mode m, int param = -1);
-};
-
-// -------------------------------------------------------------------------
-
-} //namespace
-
-#endif
diff --git a/khtml/rendering/render_frames.cpp b/khtml/rendering/render_frames.cpp
deleted file mode 100644
index 2535b534e..000000000
--- a/khtml/rendering/render_frames.cpp
+++ /dev/null
@@ -1,1025 +0,0 @@
-/**
- * This file is part of the KDE project.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 2000 Simon Hausmann <hausmann@kde.org>
- * (C) 2000 Stefan Schimanski (1Stein@gmx.de)
- * (C) 2003 Apple Computer, Inc.
- * (C) 2005 Niels Leenheer <niels.leenheer@gmail.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-//#define DEBUG_LAYOUT
-
-#include "rendering/render_frames.h"
-#include "rendering/render_canvas.h"
-#include "html/html_baseimpl.h"
-#include "html/html_objectimpl.h"
-#include "html/htmltokenizer.h"
-#include "misc/htmlattrs.h"
-#include "xml/dom2_eventsimpl.h"
-#include "xml/dom_docimpl.h"
-#include "misc/htmltags.h"
-#include "khtmlview.h"
-#include "khtml_part.h"
-#include "misc/knsplugininstaller.h"
-
-#include <kapplication.h>
-#include <kmessagebox.h>
-#include <kmimetype.h>
-#include <klocale.h>
-#include <kdebug.h>
-#include <tqtimer.h>
-#include <tqpainter.h>
-#include <tqcursor.h>
-
-#include <assert.h>
-
-using namespace khtml;
-using namespace DOM;
-
-RenderFrameSet::RenderFrameSet( HTMLFrameSetElementImpl *frameSet)
- : RenderBox(frameSet)
-{
- // init RenderObject attributes
- setInline(false);
-
- for (int k = 0; k < 2; ++k) {
- m_gridLen[k] = -1;
- m_gridDelta[k] = 0;
- m_gridLayout[k] = 0;
- }
-
- m_resizing = m_clientresizing= false;
-
- m_cursor = Qt::ArrowCursor;
-
- m_hSplit = -1;
- m_vSplit = -1;
-
- m_hSplitVar = 0;
- m_vSplitVar = 0;
-}
-
-RenderFrameSet::~RenderFrameSet()
-{
- for (int k = 0; k < 2; ++k) {
- delete [] m_gridLayout[k];
- delete [] m_gridDelta[k];
- }
- delete [] m_hSplitVar;
- delete [] m_vSplitVar;
-}
-
-bool RenderFrameSet::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inBox)
-{
- RenderBox::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
-
- bool inside = m_resizing || canResize(_x, _y);
-
- if ( inside && element() && !element()->noResize() && !info.readonly()) {
- info.setInnerNode(element());
- info.setInnerNonSharedNode(element());
- }
-
- return inside || m_clientresizing;
-}
-
-void RenderFrameSet::layout( )
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
-
- if ( !parent()->isFrameSet() ) {
- KHTMLView* view = canvas()->view();
- m_width = view ? view->visibleWidth() : 0;
- m_height = view ? view->visibleHeight() : 0;
- }
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(FrameSet)::layout( ) width=" << width() << ", height=" << height() << endl;
-#endif
-
- int remainingLen[2];
- remainingLen[1] = m_width - (element()->totalCols()-1)*element()->border();
- if(remainingLen[1]<0) remainingLen[1]=0;
- remainingLen[0] = m_height - (element()->totalRows()-1)*element()->border();
- if(remainingLen[0]<0) remainingLen[0]=0;
-
- int availableLen[2];
- availableLen[0] = remainingLen[0];
- availableLen[1] = remainingLen[1];
-
- if (m_gridLen[0] != element()->totalRows() || m_gridLen[1] != element()->totalCols()) {
- // number of rows or cols changed
- // need to zero out the deltas
- m_gridLen[0] = element()->totalRows();
- m_gridLen[1] = element()->totalCols();
- for (int k = 0; k < 2; ++k) {
- delete [] m_gridDelta[k];
- m_gridDelta[k] = new int[m_gridLen[k]];
- delete [] m_gridLayout[k];
- m_gridLayout[k] = new int[m_gridLen[k]];
- for (int i = 0; i < m_gridLen[k]; ++i)
- m_gridDelta[k][i] = 0;
- }
- }
-
- for (int k = 0; k < 2; ++k) {
- int totalRelative = 0;
- int totalFixed = 0;
- int totalPercent = 0;
- int countRelative = 0;
- int countFixed = 0;
- int countPercent = 0;
- int gridLen = m_gridLen[k];
- int* gridDelta = m_gridDelta[k];
- khtml::Length* grid = k ? element()->m_cols : element()->m_rows;
- int* gridLayout = m_gridLayout[k];
-
- if (grid) {
- // First we need to investigate how many columns of each type we have and
- // how much space these columns are going to require.
- for (int i = 0; i < gridLen; ++i) {
- // Count the total length of all of the fixed columns/rows -> totalFixed
- // Count the number of columns/rows which are fixed -> countFixed
- if (grid[i].isFixed()) {
- gridLayout[i] = kMax(grid[i].value(), 0);
- totalFixed += gridLayout[i];
- countFixed++;
- }
-
- // Count the total percentage of all of the percentage columns/rows -> totalPercent
- // Count the number of columns/rows which are percentages -> countPercent
- if (grid[i].isPercent()) {
- gridLayout[i] = kMax(grid[i].width(availableLen[k]), 0);
- totalPercent += gridLayout[i];
- countPercent++;
- }
-
- // Count the total relative of all the relative columns/rows -> totalRelative
- // Count the number of columns/rows which are relative -> countRelative
- if (grid[i].isRelative()) {
- totalRelative += kMax(grid[i].value(), 1);
- countRelative++;
- }
- }
-
- // Fixed columns/rows are our first priority. If there is not enough space to fit all fixed
- // columns/rows we need to proportionally adjust their size.
- if (totalFixed > remainingLen[k]) {
- int remainingFixed = remainingLen[k];
-
- for (int i = 0; i < gridLen; ++i) {
- if (grid[i].isFixed()) {
- gridLayout[i] = (gridLayout[i] * remainingFixed) / totalFixed;
- remainingLen[k] -= gridLayout[i];
- }
- }
- } else {
- remainingLen[k] -= totalFixed;
- }
-
- // Percentage columns/rows are our second priority. Divide the remaining space proportionally
- // over all percentage columns/rows. IMPORTANT: the size of each column/row is not relative
- // to 100%, but to the total percentage. For example, if there are three columns, each of 75%,
- // and the available space is 300px, each column will become 100px in width.
- if (totalPercent > remainingLen[k]) {
- int remainingPercent = remainingLen[k];
-
- for (int i = 0; i < gridLen; ++i) {
- if (grid[i].isPercent()) {
- gridLayout[i] = (gridLayout[i] * remainingPercent) / totalPercent;
- remainingLen[k] -= gridLayout[i];
- }
- }
- } else {
- remainingLen[k] -= totalPercent;
- }
-
- // Relative columns/rows are our last priority. Divide the remaining space proportionally
- // over all relative columns/rows. IMPORTANT: the relative value of 0* is treated as 1*.
- if (countRelative) {
- int lastRelative = 0;
- int remainingRelative = remainingLen[k];
-
- for (int i = 0; i < gridLen; ++i) {
- if (grid[i].isRelative()) {
- gridLayout[i] = (kMax(grid[i].value(), 1) * remainingRelative) / totalRelative;
- remainingLen[k] -= gridLayout[i];
- lastRelative = i;
- }
- }
-
- // If we could not evently distribute the available space of all of the relative
- // columns/rows, the remainder will be added to the last column/row.
- // For example: if we have a space of 100px and three columns (*,*,*), the remainder will
- // be 1px and will be added to the last column: 33px, 33px, 34px.
- if (remainingLen[k]) {
- gridLayout[lastRelative] += remainingLen[k];
- remainingLen[k] = 0;
- }
- }
-
- // If we still have some left over space we need to divide it over the already existing
- // columns/rows
- if (remainingLen[k]) {
- // Our first priority is to spread if over the percentage columns. The remaining
- // space is spread evenly, for example: if we have a space of 100px, the columns
- // definition of 25%,25% used to result in two columns of 25px. After this the
- // columns will each be 50px in width.
- if (countPercent && totalPercent) {
- int remainingPercent = remainingLen[k];
- int changePercent = 0;
-
- for (int i = 0; i < gridLen; ++i) {
- if (grid[i].isPercent()) {
- changePercent = (remainingPercent * gridLayout[i]) / totalPercent;
- gridLayout[i] += changePercent;
- remainingLen[k] -= changePercent;
- }
- }
- } else if (totalFixed) {
- // Our last priority is to spread the remaining space over the fixed columns.
- // For example if we have 100px of space and two column of each 40px, both
- // columns will become exactly 50px.
- int remainingFixed = remainingLen[k];
- int changeFixed = 0;
-
- for (int i = 0; i < gridLen; ++i) {
- if (grid[i].isFixed()) {
- changeFixed = (remainingFixed * gridLayout[i]) / totalFixed;
- gridLayout[i] += changeFixed;
- remainingLen[k] -= changeFixed;
- }
- }
- }
- }
-
- // If we still have some left over space we probably ended up with a remainder of
- // a division. We can not spread it evenly anymore. If we have any percentage
- // columns/rows simply spread the remainder equally over all available percentage columns,
- // regardless of their size.
- if (remainingLen[k] && countPercent) {
- int remainingPercent = remainingLen[k];
- int changePercent = 0;
-
- for (int i = 0; i < gridLen; ++i) {
- if (grid[i].isPercent()) {
- changePercent = remainingPercent / countPercent;
- gridLayout[i] += changePercent;
- remainingLen[k] -= changePercent;
- }
- }
- }
-
- // If we don't have any percentage columns/rows we only have fixed columns. Spread
- // the remainder equally over all fixed columns/rows.
- else if (remainingLen[k] && countFixed) {
- int remainingFixed = remainingLen[k];
- int changeFixed = 0;
-
- for (int i = 0; i < gridLen; ++i) {
- if (grid[i].isFixed()) {
- changeFixed = remainingFixed / countFixed;
- gridLayout[i] += changeFixed;
- remainingLen[k] -= changeFixed;
- }
- }
- }
-
- // Still some left over... simply add it to the last column, because it is impossible
- // spread it evenly or equally.
- if (remainingLen[k]) {
- gridLayout[gridLen - 1] += remainingLen[k];
- }
-
- // now we have the final layout, distribute the delta over it
- bool worked = true;
- for (int i = 0; i < gridLen; ++i) {
- if (gridLayout[i] && gridLayout[i] + gridDelta[i] <= 0)
- worked = false;
- gridLayout[i] += gridDelta[i];
- }
- // now the delta's broke something, undo it and reset deltas
- if (!worked)
- for (int i = 0; i < gridLen; ++i) {
- gridLayout[i] -= gridDelta[i];
- gridDelta[i] = 0;
- }
- }
- else
- gridLayout[0] = remainingLen[k];
- }
-
- positionFrames();
-
- RenderObject *child = firstChild();
- if ( !child )
- goto end2;
-
- if(!m_hSplitVar && !m_vSplitVar)
- {
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << "calculationg fixed Splitters" << endl;
-#endif
- if(!m_vSplitVar && element()->totalCols() > 1)
- {
- m_vSplitVar = new bool[element()->totalCols()];
- for(int i = 0; i < element()->totalCols(); i++) m_vSplitVar[i] = true;
- }
- if(!m_hSplitVar && element()->totalRows() > 1)
- {
- m_hSplitVar = new bool[element()->totalRows()];
- for(int i = 0; i < element()->totalRows(); i++) m_hSplitVar[i] = true;
- }
-
- for(int r = 0; r < element()->totalRows(); r++)
- {
- for(int c = 0; c < element()->totalCols(); c++)
- {
- bool fixed = false;
-
- if ( child->isFrameSet() )
- fixed = static_cast<RenderFrameSet *>(child)->element()->noResize();
- else
- fixed = static_cast<RenderFrame *>(child)->element()->noResize();
-
- if(fixed)
- {
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << "found fixed cell " << r << "/" << c << "!" << endl;
-#endif
- if( element()->totalCols() > 1)
- {
- if(c>0) m_vSplitVar[c-1] = false;
- m_vSplitVar[c] = false;
- }
- if( element()->totalRows() > 1)
- {
- if(r>0) m_hSplitVar[r-1] = false;
- m_hSplitVar[r] = false;
- }
- child = child->nextSibling();
- if(!child) goto end2;
- }
-#ifdef DEBUG_LAYOUT
- else
- kdDebug( 6031 ) << "not fixed: " << r << "/" << c << "!" << endl;
-#endif
- }
- }
-
- }
- RenderContainer::layout();
- end2:
- setNeedsLayout(false);
-}
-
-void RenderFrameSet::positionFrames()
-{
- int r;
- int c;
-
- RenderObject *child = firstChild();
- if ( !child )
- return;
-
- // NodeImpl *child = _first;
- // if(!child) return;
-
- int yPos = 0;
-
- for(r = 0; r < element()->totalRows(); r++)
- {
- int xPos = 0;
- for(c = 0; c < element()->totalCols(); c++)
- {
- child->setPos( xPos, yPos );
-#ifdef DEBUG_LAYOUT
- kdDebug(6040) << "child frame at (" << xPos << "/" << yPos << ") size (" << m_gridLayout[1][c] << "/" << m_gridLayout[0][r] << ")" << endl;
-#endif
- // has to be resized and itself resize its contents
- if ((m_gridLayout[1][c] != child->width()) || (m_gridLayout[0][r] != child->height())) {
- child->setWidth( m_gridLayout[1][c] );
- child->setHeight( m_gridLayout[0][r] );
- child->setNeedsLayout(true);
- child->layout();
- }
-
- xPos += m_gridLayout[1][c] + element()->border();
- child = child->nextSibling();
-
- if ( !child )
- return;
-
- }
-
- yPos += m_gridLayout[0][r] + element()->border();
- }
-
- // all the remaining frames are hidden to avoid ugly
- // spurious unflowed frames
- while ( child ) {
- child->setWidth( 0 );
- child->setHeight( 0 );
- child->setNeedsLayout(false);
-
- child = child->nextSibling();
- }
-}
-
-bool RenderFrameSet::userResize( MouseEventImpl *evt )
-{
- if (needsLayout()) return false;
-
- bool res = false;
- int _x = evt->clientX();
- int _y = evt->clientY();
-
- if ( !m_resizing && evt->id() == EventImpl::MOUSEMOVE_EVENT || evt->id() == EventImpl::MOUSEDOWN_EVENT )
- {
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << "mouseEvent:check" << endl;
-#endif
-
- m_hSplit = -1;
- m_vSplit = -1;
- //bool resizePossible = true;
-
- // check if we're over a horizontal or vertical boundary
- int pos = m_gridLayout[1][0] + xPos();
- for(int c = 1; c < element()->totalCols(); c++)
- {
- if(_x >= pos && _x <= pos+element()->border())
- {
- if(m_vSplitVar && m_vSplitVar[c-1] == true) m_vSplit = c-1;
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << "vsplit!" << endl;
-#endif
- res = true;
- break;
- }
- pos += m_gridLayout[1][c] + element()->border();
- }
-
- pos = m_gridLayout[0][0] + yPos();
- for(int r = 1; r < element()->totalRows(); r++)
- {
- if( _y >= pos && _y <= pos+element()->border())
- {
- if(m_hSplitVar && m_hSplitVar[r-1] == true) m_hSplit = r-1;
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << "hsplitvar = " << m_hSplitVar << endl;
- kdDebug( 6031 ) << "hsplit!" << endl;
-#endif
- res = true;
- break;
- }
- pos += m_gridLayout[0][r] + element()->border();
- }
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << m_hSplit << "/" << m_vSplit << endl;
-#endif
- }
-
-
- m_cursor = Qt::ArrowCursor;
- if(m_hSplit != -1 && m_vSplit != -1)
- m_cursor = Qt::SizeAllCursor;
- else if( m_vSplit != -1 )
- m_cursor = Qt::SizeHorCursor;
- else if( m_hSplit != -1 )
- m_cursor = Qt::SizeVerCursor;
-
- if(!m_resizing && evt->id() == EventImpl::MOUSEDOWN_EVENT)
- {
- setResizing(true);
- TDEApplication::setOverrideCursor(TQCursor(m_cursor));
- m_vSplitPos = _x;
- m_hSplitPos = _y;
- m_oldpos = -1;
- }
-
- // ### check the resize is not going out of bounds.
- if(m_resizing && evt->id() == EventImpl::MOUSEUP_EVENT)
- {
- setResizing(false);
- TDEApplication::restoreOverrideCursor();
-
- if(m_vSplit != -1 )
- {
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << "split xpos=" << _x << endl;
-#endif
- int delta = m_vSplitPos - _x;
- m_gridDelta[1][m_vSplit] -= delta;
- m_gridDelta[1][m_vSplit+1] += delta;
- }
- if(m_hSplit != -1 )
- {
-#ifdef DEBUG_LAYOUT
- kdDebug( 6031 ) << "split ypos=" << _y << endl;
-#endif
- int delta = m_hSplitPos - _y;
- m_gridDelta[0][m_hSplit] -= delta;
- m_gridDelta[0][m_hSplit+1] += delta;
- }
-
- // this just schedules the relayout
- // important, otherwise the moving indicator is not correctly erased
- setNeedsLayout(true);
- }
-
- KHTMLView *view = canvas()->view();
- if ((m_resizing || evt->id() == EventImpl::MOUSEUP_EVENT) && view) {
- TQPainter paint( view );
- paint.setPen( Qt::gray );
- paint.setBrush( Qt::gray );
- paint.setRasterOp( TQt::XorROP );
- TQRect r(xPos(), yPos(), width(), height());
- const int rBord = 3;
- int sw = element()->border();
- int p = m_resizing ? (m_vSplit > -1 ? _x : _y) : -1;
- if (m_vSplit > -1) {
- if ( m_oldpos >= 0 )
- paint.drawRect( m_oldpos + sw/2 - rBord , r.y(),
- 2*rBord, r.height() );
- if ( p >= 0 )
- paint.drawRect( p + sw/2 - rBord, r.y(), 2*rBord, r.height() );
- } else {
- if ( m_oldpos >= 0 )
- paint.drawRect( r.x(), m_oldpos + sw/2 - rBord,
- r.width(), 2*rBord );
- if ( p >= 0 )
- paint.drawRect( r.x(), p + sw/2 - rBord, r.width(), 2*rBord );
- }
- m_oldpos = p;
- }
-
- return res;
-}
-
-void RenderFrameSet::setResizing(bool e)
-{
- m_resizing = e;
- for (RenderObject* p = parent(); p; p = p->parent())
- if (p->isFrameSet()) static_cast<RenderFrameSet*>(p)->m_clientresizing = m_resizing;
-}
-
-bool RenderFrameSet::canResize( int _x, int _y )
-{
- // if we haven't received a layout, then the gridLayout doesn't contain useful data yet
- if (needsLayout() || !m_gridLayout[0] || !m_gridLayout[1] ) return false;
-
- // check if we're over a horizontal or vertical boundary
- int pos = m_gridLayout[1][0];
- for(int c = 1; c < element()->totalCols(); c++)
- if(_x >= pos && _x <= pos+element()->border())
- return true;
-
- pos = m_gridLayout[0][0];
- for(int r = 1; r < element()->totalRows(); r++)
- if( _y >= pos && _y <= pos+element()->border())
- return true;
-
- return false;
-}
-
-#ifdef ENABLE_DUMP
-void RenderFrameSet::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderBox::dump(stream,ind);
- stream << " totalrows=" << element()->totalRows();
- stream << " totalcols=" << element()->totalCols();
-
- if ( m_hSplitVar )
- for (uint i = 0; i < (uint)element()->totalRows(); i++) {
- stream << " hSplitvar(" << i << ")=" << m_hSplitVar[i];
- }
-
- if ( m_vSplitVar )
- for (uint i = 0; i < (uint)element()->totalCols(); i++)
- stream << " vSplitvar(" << i << ")=" << m_vSplitVar[i];
-}
-#endif
-
-/**************************************************************************************/
-
-RenderPart::RenderPart(DOM::HTMLElementImpl* node)
- : RenderWidget(node)
-{
- // init RenderObject attributes
- setInline(false);
-}
-
-void RenderPart::setWidget( TQWidget *widget )
-{
-#ifdef DEBUG_LAYOUT
- kdDebug(6031) << "RenderPart::setWidget()" << endl;
-#endif
-
- setQWidget( widget );
- widget->setFocusPolicy(TQ_WheelFocus);
- if(widget->inherits("KHTMLView"))
- connect( widget, TQT_SIGNAL( cleared() ), this, TQT_SLOT( slotViewCleared() ) );
-
- setNeedsLayoutAndMinMaxRecalc();
-
- // make sure the scrollbars are set correctly for restore
- // ### find better fix
- slotViewCleared();
-}
-
-bool RenderPart::partLoadingErrorNotify(khtml::ChildFrame *, const KURL& , const TQString& )
-{
- return false;
-}
-
-short RenderPart::intrinsicWidth() const
-{
- return 300;
-}
-
-int RenderPart::intrinsicHeight() const
-{
- return 150;
-}
-
-void RenderPart::slotViewCleared()
-{
-}
-
-/***************************************************************************************/
-
-RenderFrame::RenderFrame( DOM::HTMLFrameElementImpl *frame )
- : RenderPart(frame)
-{
- setInline( false );
-}
-
-void RenderFrame::slotViewCleared()
-{
- if(m_widget->inherits(TQSCROLLVIEW_OBJECT_NAME_STRING)) {
-#ifdef DEBUG_LAYOUT
- kdDebug(6031) << "frame is a scrollview!" << endl;
-#endif
- TQScrollView *view = static_cast<TQScrollView *>(m_widget);
- if(!element()->frameBorder || !((static_cast<HTMLFrameSetElementImpl *>(element()->parentNode()))->frameBorder()))
- view->setFrameStyle(TQFrame::NoFrame);
- view->setVScrollBarMode(element()->scrolling );
- view->setHScrollBarMode(element()->scrolling );
- if(view->inherits("KHTMLView")) {
-#ifdef DEBUG_LAYOUT
- kdDebug(6031) << "frame is a KHTMLview!" << endl;
-#endif
- KHTMLView *htmlView = static_cast<KHTMLView *>(view);
- if(element()->marginWidth != -1) htmlView->setMarginWidth(element()->marginWidth);
- if(element()->marginHeight != -1) htmlView->setMarginHeight(element()->marginHeight);
- }
- }
-}
-
-/****************************************************************************************/
-
-RenderPartObject::RenderPartObject( DOM::HTMLElementImpl* element )
- : RenderPart( element )
-{
- // init RenderObject attributes
- setInline(true);
-}
-
-void RenderPartObject::updateWidget()
-{
- TQString url;
- KHTMLPart *part = m_view->part();
-
- setNeedsLayoutAndMinMaxRecalc();
-
- if (element()->id() == ID_IFRAME) {
-
- HTMLIFrameElementImpl *o = static_cast<HTMLIFrameElementImpl *>(element());
- url = o->url.string();
- if (!o->getDocument()->isURLAllowed(url)) return;
- part->requestFrame( this, url, o->name.string(), TQStringList(), true );
- // ### this should be constant true - move iframe to somewhere else
- } else {
-
- TQStringList params;
- HTMLObjectBaseElementImpl * objbase = static_cast<HTMLObjectBaseElementImpl *>(element());
- url = objbase->url;
-
- for (NodeImpl* child = element()->firstChild(); child; child=child->nextSibling()) {
- if ( child->id() == ID_PARAM ) {
- HTMLParamElementImpl *p = static_cast<HTMLParamElementImpl *>( child );
-
- TQString aStr = p->name();
- aStr += TQString::fromLatin1("=\"");
- aStr += p->value();
- aStr += TQString::fromLatin1("\"");
- TQString name_lower = p->name().lower();
- if (name_lower == TQString::fromLatin1("type") && objbase->id() != ID_APPLET) {
- objbase->setServiceType(p->value());
- } else if (url.isEmpty() &&
- (name_lower == TQString::fromLatin1("src") ||
- name_lower == TQString::fromLatin1("movie") ||
- name_lower == TQString::fromLatin1("code"))) {
- url = p->value();
- }
- params.append(aStr);
- }
- }
- if (element()->id() != ID_OBJECT) {
- // add all attributes set on the embed object
- NamedAttrMapImpl* a = objbase->attributes();
- if (a) {
- for (unsigned long i = 0; i < a->length(); ++i) {
- NodeImpl::Id id = a->idAt(i);
- DOMString value = a->valueAt(i);
- params.append(objbase->getDocument()->getName(NodeImpl::AttributeId, id).string() + "=\"" + value.string() + "\"");
- }
- }
- }
- params.append( TQString::fromLatin1("__KHTML__PLUGINEMBED=\"YES\"") );
- params.append( TQString::fromLatin1("__KHTML__PLUGINBASEURL=\"%1\"").arg(element()->getDocument()->baseURL().url()));
-
- HTMLEmbedElementImpl *embed = 0;
- TQString classId;
- TQString serviceType = objbase->serviceType;
- if ( element()->id() == ID_EMBED ) {
-
- embed = static_cast<HTMLEmbedElementImpl *>( objbase );
-
- }
- else { // if(element()->id() == ID_OBJECT || element()->id() == ID_APPLET)
-
- // check for embed child object
- for (NodeImpl *child = objbase->firstChild(); child; child = child->nextSibling())
- if ( child->id() == ID_EMBED ) {
- embed = static_cast<HTMLEmbedElementImpl *>( child );
- break;
- }
- classId = objbase->classId;
-
- params.append( TQString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( classId ) );
- params.append( TQString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( objbase->getAttribute(ATTR_CODEBASE).string() ) );
- if (!objbase->getAttribute(ATTR_WIDTH).isEmpty())
- params.append( TQString::fromLatin1("WIDTH=\"%1\"").arg( objbase->getAttribute(ATTR_WIDTH).string() ) );
- else if (embed && !embed->getAttribute(ATTR_WIDTH).isEmpty()) {
- params.append( TQString::fromLatin1("WIDTH=\"%1\"").arg( embed->getAttribute(ATTR_WIDTH).string() ) );
- objbase->setAttribute(ATTR_WIDTH, embed->getAttribute(ATTR_WIDTH));
- }
- if (!objbase->getAttribute(ATTR_HEIGHT).isEmpty())
- params.append( TQString::fromLatin1("HEIGHT=\"%1\"").arg( objbase->getAttribute(ATTR_HEIGHT).string() ) );
- else if (embed && !embed->getAttribute(ATTR_HEIGHT).isEmpty()) {
- params.append( TQString::fromLatin1("HEIGHT=\"%1\"").arg( embed->getAttribute(ATTR_HEIGHT).string() ) );
- objbase->setAttribute(ATTR_HEIGHT, embed->getAttribute(ATTR_HEIGHT));
- }
-
- if ( embed ) {
- // render embed object
- url = embed->url;
- if (!embed->serviceType.isEmpty())
- serviceType = embed->serviceType;
- } else if (url.isEmpty() && objbase->classId.startsWith("java:")) {
- serviceType = "application/x-java-applet";
- url = objbase->classId.mid(5);
- }
- if ( (serviceType.isEmpty() ||
- serviceType == "application/x-oleobject") &&
- !objbase->classId.isEmpty())
- {
-#if 0
- // We have a clsid, means this is activex (Niko)
- serviceType = "application/x-activex-handler";
-#endif
-
- if(classId.find(TQString::fromLatin1("D27CDB6E-AE6D-11cf-96B8-444553540000")) >= 0) {
- // It is ActiveX, but the nsplugin system handling
- // should also work, that's why we don't override the
- // serviceType with application/x-activex-handler
- // but let the KTrader in khtmlpart::createPart() detect
- // the user's preference: launch with activex viewer or
- // with nspluginviewer (Niko)
- serviceType = "application/x-shockwave-flash";
- }
- else if(classId.find(TQString::fromLatin1("CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA")) >= 0)
- serviceType = "audio/x-pn-realaudio-plugin";
- else if(classId.find(TQString::fromLatin1("8AD9C840-044E-11D1-B3E9-00805F499D93")) >= 0 ||
- objbase->classId.find(TQString::fromLatin1("CAFEEFAC-0014-0000-0000-ABCDEFFEDCBA")) >= 0)
- serviceType = "application/x-java-applet";
- // http://www.apple.com/quicktime/tools_tips/tutorials/activex.html
- else if(classId.find(TQString::fromLatin1("02BF25D5-8C17-4B23-BC80-D3488ABDDC6B")) >= 0)
- serviceType = "video/quicktime";
- // http://msdn.microsoft.com/library/en-us/dnwmt/html/adding_windows_media_to_web_pages__etse.asp?frame=true
- else if(objbase->classId.find(TQString::fromLatin1("6BF52A52-394A-11d3-B153-00C04F79FAA6")) >= 0 ||
- classId.find(TQString::fromLatin1("22D6f312-B0F6-11D0-94AB-0080C74C7E95")) >= 0)
- serviceType = "video/x-msvideo";
-
- else
- kdDebug(6031) << "ActiveX classId " << objbase->classId << endl;
-
- // TODO: add more plugins here
- }
- }
- if ((url.isEmpty() && !embed &&
- (serviceType.isEmpty() || classId.isEmpty())) ||
- !document()->isURLAllowed(url) ||
- !part->requestObject( this, url, serviceType, params ))
- objbase->renderAlternative();
- }
-}
-
-// ugly..
-void RenderPartObject::close()
-{
- RenderPart::close();
-
- if ( element()->id() != ID_IFRAME )
- updateWidget();
- // deleted here
-}
-
-
-bool RenderPartObject::partLoadingErrorNotify( khtml::ChildFrame *childFrame, const KURL& url, const TQString& serviceType )
-{
- KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
- kdDebug(6031) << "RenderPartObject::partLoadingErrorNotify serviceType=" << serviceType << endl;
- // Check if we just tried with e.g. nsplugin
- // and fallback to the activexhandler if there is a classid
- // and a codebase, where we may download the ocx if it's missing
- if( serviceType != "application/x-activex-handler" && element()->id()==ID_OBJECT ) {
-
- // check for embed child object
- HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
- HTMLEmbedElementImpl *embed = 0;
- NodeImpl *child = o->firstChild();
- while ( child ) {
- if ( child->id() == ID_EMBED )
- embed = static_cast<HTMLEmbedElementImpl *>( child );
-
- child = child->nextSibling();
- }
- if( embed && !o->classId.isEmpty() &&
- !( static_cast<ElementImpl *>(o)->getAttribute(ATTR_CODEBASE).string() ).isEmpty() )
- {
- KParts::URLArgs args;
- args.serviceType = "application/x-activex-handler";
- kdDebug(6031) << "set to activex" << endl;
- if (part->requestObject( childFrame, url, args ))
- return true; // success
-
- return false;
- }
- }
- // Dissociate ourselves from the current event loop (to prevent crashes
- // due to the message box staying up)
- TQTimer::singleShot( 0, this, TQT_SLOT( slotPartLoadingErrorNotify() ) );
-#if 0
- Tokenizer *tokenizer = static_cast<DOM::DocumentImpl *>(part->document().handle())->tokenizer();
- if (tokenizer) tokenizer->setOnHold( true );
- slotPartLoadingErrorNotify();
- if (tokenizer) tokenizer->setOnHold( false );
-#endif
- return false;
-}
-
-void RenderPartObject::slotPartLoadingErrorNotify()
-{
- // First we need to find out the servicetype - again - this code is too duplicated !
- HTMLEmbedElementImpl *embed = 0;
- TQString serviceType;
- if( element()->id()==ID_OBJECT ) {
-
- // check for embed child object
- HTMLObjectElementImpl *o = static_cast<HTMLObjectElementImpl *>(element());
- serviceType = o->serviceType;
- NodeImpl *child = o->firstChild();
- while ( child ) {
- if ( child->id() == ID_EMBED )
- embed = static_cast<HTMLEmbedElementImpl *>( child );
-
- child = child->nextSibling();
- }
-
- } else if( element()->id()==ID_EMBED ) {
- embed = static_cast<HTMLEmbedElementImpl *>(element());
- }
- if ( embed )
- serviceType = embed->serviceType;
-
- // prepare for the local eventloop in KMessageBox
- ref();
-
- KHTMLPart *part = static_cast<KHTMLView *>(m_view)->part();
- KParts::BrowserExtension *ext = part->browserExtension();
- if( embed && !embed->pluginPage.isEmpty() && ext ) {
- // Prepare the mimetype to show in the question (comment if available, name as fallback)
- TQString mimeName = serviceType;
- KMimeType::Ptr mime = KMimeType::mimeType(serviceType);
- if ( mime->name() != KMimeType::defaultMimeType() )
- mimeName = mime->comment();
-
- // Check if we already asked the user, for this page
- if (!mimeName.isEmpty() && part->docImpl() && !part->pluginPageQuestionAsked( serviceType ) )
- {
- part->setPluginPageQuestionAsked( serviceType );
- bool pluginAvailable;
- pluginAvailable = false;
- // check if a pluginList file is in the config
- if(KNSPluginInstallEngine::isActive())
- {
- KNSPluginWizard pluginWizard(m_view, "pluginInstaller", mime);
- if(pluginWizard.pluginAvailable()) {
- pluginAvailable = true;
- pluginWizard.exec();
- }
- }
- if(!pluginAvailable) {
- // Prepare the URL to show in the question (host only if http, to make it short)
- KURL pluginPageURL( embed->pluginPage );
- TQString shortURL = pluginPageURL.protocol() == "http" ? pluginPageURL.host() : pluginPageURL.prettyURL();
- int res = KMessageBox::questionYesNo( m_view,
- i18n("No plugin found for '%1'.\nDo you want to download one from %2?").arg(mimeName).arg(shortURL),
- i18n("Missing Plugin"), i18n("Download"), i18n("Do Not Download"), TQString("plugin-")+serviceType);
- if ( res == KMessageBox::Yes )
- {
- // Display vendor download page
- ext->createNewWindow( pluginPageURL );
- return;
- }
- }
- }
- }
-
- // didn't work, render alternative content.
- if ( element() && (
- element()->id() == ID_OBJECT || element()->id() == ID_EMBED || element()->id() == ID_APPLET))
- static_cast<HTMLObjectBaseElementImpl*>( element() )->renderAlternative();
-
- deref();
-}
-
-void RenderPartObject::layout( )
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
-
- calcWidth();
- calcHeight();
-
- RenderPart::layout();
-
- setNeedsLayout(false);
-}
-
-void RenderPartObject::slotViewCleared()
-{
- if(m_widget->inherits(TQSCROLLVIEW_OBJECT_NAME_STRING) ) {
-#ifdef DEBUG_LAYOUT
- kdDebug(6031) << "iframe is a scrollview!" << endl;
-#endif
- TQScrollView *view = static_cast<TQScrollView *>(m_widget);
- int frameStyle = TQFrame::NoFrame;
- TQScrollView::ScrollBarMode scroll = TQScrollView::Auto;
- int marginw = -1;
- int marginh = -1;
- if ( element()->id() == ID_IFRAME) {
- HTMLIFrameElementImpl *frame = static_cast<HTMLIFrameElementImpl *>(element());
- if(frame->frameBorder)
- frameStyle = TQFrame::Box;
- scroll = frame->scrolling;
- marginw = frame->marginWidth;
- marginh = frame->marginHeight;
- }
- view->setFrameStyle(frameStyle);
- view->setVScrollBarMode(scroll );
- view->setHScrollBarMode(scroll );
- if(view->inherits("KHTMLView")) {
-#ifdef DEBUG_LAYOUT
- kdDebug(6031) << "frame is a KHTMLview!" << endl;
-#endif
- KHTMLView *htmlView = static_cast<KHTMLView *>(view);
- htmlView->setIgnoreWheelEvents( element()->id() == ID_IFRAME );
- if(marginw != -1) htmlView->setMarginWidth(marginw);
- if(marginh != -1) htmlView->setMarginHeight(marginh);
- }
- }
-}
-
-
-#include "render_frames.moc"
diff --git a/khtml/rendering/render_frames.h b/khtml/rendering/render_frames.h
deleted file mode 100644
index 3dd7ed0d9..000000000
--- a/khtml/rendering/render_frames.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * This file is part of the KDE project.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- * (C) 2000 Simon Hausmann <hausmann@kde.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef __render_frames_h__
-#define __render_frames_h__
-
-#include "rendering/render_replaced.h"
-#include "xml/dom_nodeimpl.h"
-#include "html/html_baseimpl.h"
-class KHTMLView;
-
-namespace DOM
-{
- class HTMLFrameElementImpl;
- class HTMLElementImpl;
- class MouseEventImpl;
-}
-
-namespace khtml
-{
- class ChildFrame;
-
-class RenderFrameSet : public RenderBox
-{
- friend class DOM::HTMLFrameSetElementImpl;
-public:
- RenderFrameSet( DOM::HTMLFrameSetElementImpl *frameSet );
-
- virtual ~RenderFrameSet();
-
- virtual const char *renderName() const { return "RenderFrameSet"; }
- virtual bool isFrameSet() const { return true; }
-
- virtual void layout();
-
- void positionFrames( );
-
- bool resizing() const { return m_resizing; }
- bool noResize() const { return element()->noResize(); }
-
- bool userResize( DOM::MouseEventImpl *evt );
- bool canResize( int _x, int _y);
- void setResizing(bool e);
-
- Qt::CursorShape cursorShape() const { return m_cursor; }
-
- bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction hitTestAction, bool inside);
-
- DOM::HTMLFrameSetElementImpl *element() const
- { return static_cast<DOM::HTMLFrameSetElementImpl*>(RenderObject::element()); }
-
-#ifdef ENABLE_DUMP
- virtual void dump(TQTextStream &stream, const TQString &ind) const;
-#endif
-
-private:
- Qt::CursorShape m_cursor;
- int m_oldpos;
- int m_gridLen[2];
- int* m_gridDelta[2];
- int* m_gridLayout[2];
-
- bool *m_hSplitVar; // is this split variable?
- bool *m_vSplitVar;
-
- int m_hSplit; // the split currently resized
- int m_vSplit;
- int m_hSplitPos;
- int m_vSplitPos;
-
- bool m_resizing;
- bool m_clientresizing;
-};
-
-class RenderPart : public khtml::RenderWidget
-{
- Q_OBJECT
-public:
- RenderPart(DOM::HTMLElementImpl* node);
-
- virtual const char *renderName() const { return "RenderPart"; }
-
- virtual void setWidget( TQWidget *widget );
-
- /**
- * Called by KHTMLPart to notify the frame object that loading the
- * part was not successfuly. (called either asyncroniously after a
- * after the servicetype of the given url (the one passed with requestObject)
- * has been determined or syncroniously from within requestObject)
- *
- * The default implementation does nothing.
- *
- * Return false in the normal case, return true if a fallback was found
- * and the url was successfully opened.
- */
- virtual bool partLoadingErrorNotify( khtml::ChildFrame *childFrame, const KURL& url, const TQString& serviceType );
-
- virtual short intrinsicWidth() const;
- virtual int intrinsicHeight() const;
-
-public slots:
- virtual void slotViewCleared();
-};
-
-class RenderFrame : public khtml::RenderPart
-{
- Q_OBJECT
-public:
- RenderFrame( DOM::HTMLFrameElementImpl *frame );
-
- virtual const char *renderName() const { return "RenderFrame"; }
- virtual bool isFrame() const { return true; }
-
- // frames never have padding
- virtual int paddingTop() const { return 0; }
- virtual int paddingBottom() const { return 0; }
- virtual int paddingLeft() const { return 0; }
- virtual int paddingRight() const { return 0; }
-
- DOM::HTMLFrameElementImpl *element() const
- { return static_cast<DOM::HTMLFrameElementImpl*>(RenderObject::element()); }
-
-public slots:
- void slotViewCleared();
-};
-
-// I can hardly call the class RenderObject ;-)
-class RenderPartObject : public khtml::RenderPart
-{
- Q_OBJECT
-public:
- RenderPartObject( DOM::HTMLElementImpl * );
-
- virtual const char *renderName() const { return "RenderPartObject"; }
-
- virtual void close();
-
- virtual void layout( );
- virtual void updateWidget();
-
- virtual bool canHaveBorder() const { return true; }
-
- virtual bool partLoadingErrorNotify( khtml::ChildFrame *childFrame, const KURL& url, const TQString& serviceType );
-
-public slots:
- void slotViewCleared();
-private slots:
- void slotPartLoadingErrorNotify();
-};
-
-}
-
-#endif
diff --git a/khtml/rendering/render_generated.cpp b/khtml/rendering/render_generated.cpp
deleted file mode 100644
index 17c65fc9c..000000000
--- a/khtml/rendering/render_generated.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-/**
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "rendering/render_generated.h"
-#include "rendering/render_style.h"
-#include "rendering/enumerate.h"
-#include "rendering/counter_tree.h"
-#include "css/css_valueimpl.h"
-
-using namespace khtml;
-using namespace Enumerate;
-
-// -------------------------------------------------------------------------
-
-RenderCounterBase::RenderCounterBase(DOM::NodeImpl* node)
- : RenderText(node,0), m_counterNode(0)
-{
-}
-
-void RenderCounterBase::layout()
-{
- KHTMLAssert( needsLayout() );
-
- if ( !minMaxKnown() )
- calcMinMaxWidth();
-
- RenderText::layout();
-}
-
-void RenderCounterBase::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- generateContent();
-
- if (str) str->deref();
- str = new DOM::DOMStringImpl(m_item.unicode(), m_item.length());
- str->ref();
-
- RenderText::calcMinMaxWidth();
-}
-
-
-void RenderCounterBase::updateContent()
-{
- setMinMaxKnown(false);
-}
-
-// -------------------------------------------------------------------------
-
-RenderCounter::RenderCounter(DOM::NodeImpl* node, const DOM::CounterImpl* counter)
- : RenderCounterBase(node), m_counter(counter)
-{
-}
-
-TQString RenderCounter::toListStyleType(int value, int total, EListStyleType type)
-{
- TQString item;
- switch(type)
- {
- case LNONE:
- break;
-// Glyphs: (these values are not really used and instead handled by RenderGlyph)
- case LDISC:
- item = TQChar(0x2022);
- break;
- case LCIRCLE:
- item = TQChar(0x25e6);
- break;
- case LSQUARE:
- item = TQChar(0x25a0);
- break;
- case LBOX:
- item = TQChar(0x25a1);
- break;
- case LDIAMOND:
- item = TQChar(0x25c6);
- break;
-// Numeric:
- case LDECIMAL:
- item.setNum ( value );
- break;
- case DECIMAL_LEADING_ZERO: {
- int decimals = 2;
- int t = total/100;
- while (t>0) {
- t = t/10;
- decimals++;
- }
- decimals = kMax(decimals, 2);
- TQString num = TQString::number(value);
- item.fill('0',decimals-num.length());
- item.append(num);
- break;
- }
- case ARABIC_INDIC:
- item = toArabicIndic( value );
- break;
- case LAO:
- item = toLao( value );
- break;
- case PERSIAN:
- case URDU:
- item = toPersianUrdu( value );
- break;
- case THAI:
- item = toThai( value );
- break;
- case TIBETAN:
- item = toTibetan( value );
- break;
-// Algoritmic:
- case LOWER_ROMAN:
- item = toRoman( value, false );
- break;
- case UPPER_ROMAN:
- item = toRoman( value, true );
- break;
- case HEBREW:
- item = toHebrew( value );
- break;
- case ARMENIAN:
- item = toArmenian( value );
- break;
- case GEORGIAN:
- item = toGeorgian( value );
- break;
-// Alphabetic:
- case LOWER_ALPHA:
- case LOWER_LATIN:
- item = toLowerLatin( value );
- break;
- case UPPER_ALPHA:
- case UPPER_LATIN:
- item = toUpperLatin( value );
- break;
- case LOWER_GREEK:
- item = toLowerGreek( value );
- break;
- case UPPER_GREEK:
- item = toUpperGreek( value );
- break;
- case HIRAGANA:
- item = toHiragana( value );
- break;
- case HIRAGANA_IROHA:
- item = toHiraganaIroha( value );
- break;
- case KATAKANA:
- item = toKatakana( value );
- break;
- case KATAKANA_IROHA:
- item = toKatakanaIroha( value );
- break;
-// Ideographic:
- case JAPANESE_FORMAL:
- item = toJapaneseFormal( value );
- break;
- case JAPANESE_INFORMAL:
- item = toJapaneseInformal( value );
- break;
- case SIMP_CHINESE_FORMAL:
- item = toSimpChineseFormal( value );
- break;
- case SIMP_CHINESE_INFORMAL:
- item = toSimpChineseInformal( value );
- break;
- case TRAD_CHINESE_FORMAL:
- item = toTradChineseFormal( value );
- break;
- case CJK_IDEOGRAPHIC:
- // CSS 3 List says treat as trad-chinese-informal
- case TRAD_CHINESE_INFORMAL:
- item = toTradChineseInformal( value );
- break;
- default:
- item.setNum ( value );
- break;
- }
- return item;
-}
-
-void RenderCounter::generateContent()
-{
- bool counters;
- counters = !m_counter->separator().isNull();
-
- if (!m_counterNode)
- m_counterNode = getCounter(m_counter->identifier().string(), true, counters);
-
- int value = m_counterNode->count();
- if (m_counterNode->isReset()) value = m_counterNode->value();
- int total = value;
- if (m_counterNode->parent()) total = m_counterNode->parent()->total();
- m_item = toListStyleType(value, total, (EListStyleType)m_counter->listStyle());
-
- if (counters) {
- CounterNode *counter = m_counterNode->parent();
- // we deliberately do not render the root counter-node
- while(counter->parent() && !(counter->isReset() && counter->parent()->isRoot())) {
- value = counter->count();
- total = counter->parent()->total();
- m_item = toListStyleType(value, total, (EListStyleType)m_counter->listStyle()) + m_counter->separator().string() + m_item;
- counter = counter->parent();
- };
- }
-
-}
-
-// -------------------------------------------------------------------------
-
-RenderQuote::RenderQuote(DOM::NodeImpl* node, EQuoteContent type)
- : RenderCounterBase(node), m_quoteType(type)
-{
-}
-
-
-int RenderQuote::quoteCount() const
-{
- switch(m_quoteType) {
- case OPEN_QUOTE:
- case NO_OPEN_QUOTE:
- return 1;
- case CLOSE_QUOTE:
- case NO_CLOSE_QUOTE:
- return -1;
- case NO_QUOTE:
- return 0;
- }
- assert(false);
- return 0;
-}
-
-void RenderQuote::generateContent()
-{
- bool visual;
- if (m_quoteType == NO_CLOSE_QUOTE || m_quoteType == NO_OPEN_QUOTE)
- visual = false;
- else
- visual = true;
-
- if (!m_counterNode)
- m_counterNode = getCounter("-khtml-quotes", visual, false);
-
- int value = m_counterNode->count();
- if (m_counterNode->isReset()) value = m_counterNode->value();
- switch (m_quoteType) {
- case OPEN_QUOTE:
- m_item = style()->openQuote( value );
- break;
- case CLOSE_QUOTE:
- m_item = style()->closeQuote( value );
- break;
- case NO_OPEN_QUOTE:
- case NO_CLOSE_QUOTE:
- case NO_QUOTE:
- m_item = TQString();
- }
-}
-
-// -------------------------------------------------------------------------
-
-RenderGlyph::RenderGlyph(DOM::NodeImpl* node, EListStyleType type)
- : RenderBox(node), m_type(type)
-{
- setInline(true);
-// setReplaced(true);
-}
-
-void RenderGlyph::setStyle(RenderStyle *_style)
-{
- RenderBox::setStyle(_style);
-
- const TQFontMetrics &fm = style()->fontMetrics();
- TQRect xSize= fm.boundingRect('x');
- m_height = xSize.height();
- m_width = xSize.width();;
-
- switch(m_type) {
- // Glyphs:
- case LDISC:
- case LCIRCLE:
- case LSQUARE:
- case LBOX:
- case LDIAMOND:
- case LNONE:
- break;
- default:
- // not a glyph !
- assert(false);
- break;
- }
-}
-
-void RenderGlyph::calcMinMaxWidth()
-{
- m_minWidth = m_width;
- m_maxWidth = m_width;
-
- setMinMaxKnown();
-}
-
-short RenderGlyph::lineHeight(bool /*b*/) const
-{
- return height();
-}
-
-short RenderGlyph::baselinePosition(bool /*b*/) const
-{
- return height();
-}
-
-void RenderGlyph::paint(PaintInfo& paintInfo, int _tx, int _ty)
-{
- if (paintInfo.phase != PaintActionForeground)
- return;
-
- if (style()->visibility() != VISIBLE) return;
-
- _tx += m_x;
- _ty += m_y;
-
- if((_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top()))
- return;
-
- TQPainter* p = paintInfo.p;
-
- const TQColor color( style()->color() );
- p->setPen( color );
-
- int xHeight = m_height;
- int bulletWidth = (xHeight+1)/2;
- int yoff = (xHeight - 1)/4;
- TQRect marker(_tx, _ty + yoff, bulletWidth, bulletWidth);
-
- switch(m_type) {
- case LDISC:
- p->setBrush( color );
- p->drawEllipse( marker );
- return;
- case LCIRCLE:
- p->setBrush( Qt::NoBrush );
- p->drawEllipse( marker );
- return;
- case LSQUARE:
- p->setBrush( color );
- p->drawRect( marker );
- return;
- case LBOX:
- p->setBrush( Qt::NoBrush );
- p->drawRect( marker );
- return;
- case LDIAMOND: {
- static TQPointArray diamond(4);
- int x = marker.x();
- int y = marker.y();
- int s = bulletWidth/2;
- diamond[0] = TQPoint(x+s, y);
- diamond[1] = TQPoint(x+2*s, y+s);
- diamond[2] = TQPoint(x+s, y+2*s);
- diamond[3] = TQPoint(x, y+s);
- p->setBrush( color );
- p->drawConvexPolygon( diamond, 0, 4 );
- return;
- }
- case LNONE:
- return;
- default:
- // not a glyph
- assert(false);
- }
-}
-
diff --git a/khtml/rendering/render_generated.h b/khtml/rendering/render_generated.h
deleted file mode 100644
index 6fa20e7cd..000000000
--- a/khtml/rendering/render_generated.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2004,2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_GENERATED_H
-#define RENDER_GENERATED_H
-
-#include "rendering/render_text.h"
-#include "rendering/render_box.h"
-
-namespace DOM {
- class CounterImpl;
-}
-
-namespace khtml {
- class CounterNode;
-
-// -----------------------------------------------------------------------------
-
-class RenderCounterBase : public RenderText
-{
-public:
- RenderCounterBase(DOM::NodeImpl* node);
-
- virtual const char *renderName() const { return "RenderCounterBase"; }
-
- virtual void layout( );
- virtual void calcMinMaxWidth();
- virtual bool isCounter() const { return true; }
-
- virtual void generateContent() = 0;
- void updateContent();
-
-protected:
- TQString m_item;
- CounterNode *m_counterNode; // Cache of the counternode
-};
-
-// -----------------------------------------------------------------------------
-
-class RenderCounter : public RenderCounterBase
-{
-public:
- RenderCounter(DOM::NodeImpl* node, const DOM::CounterImpl* counter);
- virtual ~RenderCounter() {};
-
- virtual const char *renderName() const { return "RenderCounter"; }
-
- virtual void generateContent();
-
-protected:
- TQString toListStyleType(int value, int total, EListStyleType type);
-
- const DOM::CounterImpl* m_counter;
-};
-
-// -----------------------------------------------------------------------------
-
-class RenderQuote : public RenderCounterBase
-{
-public:
- RenderQuote(DOM::NodeImpl* node, EQuoteContent type);
- virtual ~RenderQuote() {};
-
- virtual const char *renderName() const { return "RenderQuote"; }
-
- virtual bool isQuote() const { return true; }
- virtual int quoteCount() const;
-
- virtual void generateContent();
-
-protected:
- EQuoteContent m_quoteType;
-};
-
-// -----------------------------------------------------------------------------
-
-// Is actually a special case of renderCounter for non-counted list-styles
-// These have traditionally been drawn rather than use Unicode characters
-class RenderGlyph : public RenderBox
-{
-public:
- RenderGlyph(DOM::NodeImpl* node, EListStyleType type);
- virtual ~RenderGlyph() {};
-
- virtual const char *renderName() const { return "RenderGlyph"; }
-
- virtual void paint(PaintInfo& paintInfo, int _tx, int _ty);
- virtual void calcMinMaxWidth();
-
- virtual void setStyle(RenderStyle *_style);
-
- virtual short lineHeight( bool firstLine ) const;
- virtual short baselinePosition( bool firstLine ) const;
-
- virtual bool isGlyph() const { return true; }
-
- virtual void position(InlineBox* box, int /*from*/, int /*len*/, bool /*reverse*/) {
- setPos( box->xPos(), box->yPos() );
- }
-
-protected:
- EListStyleType m_type;
-};
-
-} //namespace
-
-#endif
diff --git a/khtml/rendering/render_image.cpp b/khtml/rendering/render_image.cpp
deleted file mode 100644
index f931e9ca5..000000000
--- a/khtml/rendering/render_image.cpp
+++ /dev/null
@@ -1,604 +0,0 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-//#define DEBUG_LAYOUT
-
-#include "render_image.h"
-#include "render_canvas.h"
-
-#include <tqdrawutil.h>
-#include <tqpainter.h>
-
-#include <kapplication.h>
-#include <kdebug.h>
-#include <kglobalsettings.h>
-
-#include "css/csshelper.h"
-#include "misc/helper.h"
-#include "misc/htmlattrs.h"
-#include "misc/loader.h"
-#include "misc/htmltags.h"
-#include "html/html_formimpl.h"
-#include "html/html_imageimpl.h"
-#include "html/dtd.h"
-#include "xml/dom2_eventsimpl.h"
-#include "html/html_documentimpl.h"
-#include "html/html_objectimpl.h"
-#include "khtmlview.h"
-#include "khtml_part.h"
-#include <math.h>
-
-#include "loading_icon.cpp"
-
-using namespace DOM;
-using namespace khtml;
-
-// -------------------------------------------------------------------------
-
-RenderImage::RenderImage(NodeImpl *_element)
- : RenderReplaced(_element)
-{
- m_oldImage = m_cachedImage = 0;
-
- m_selectionState = SelectionNone;
- berrorPic = false;
-
- const KHTMLSettings *settings = _element->getDocument()->view()->part()->settings();
- bUnfinishedImageFrame = settings->unfinishedImageFrame();
-
- setIntrinsicWidth( 0 );
- setIntrinsicHeight( 0 );
-}
-
-RenderImage::~RenderImage()
-{
- if(m_cachedImage) m_cachedImage->deref( this );
- if(m_oldImage) m_oldImage->deref( this );
-}
-
-TQPixmap RenderImage::pixmap() const
-{
- return m_cachedImage ? m_cachedImage->pixmap() : TQPixmap();
-}
-
-void RenderImage::setStyle(RenderStyle* _style)
-{
- RenderReplaced::setStyle(_style);
- // init RenderObject attributes
- //setOverhangingContents(style()->height().isPercent());
- setShouldPaintBackgroundOrBorder(true);
-}
-
-void RenderImage::setContentObject(CachedObject* co )
-{
- if (co && m_cachedImage != co)
- updateImage( static_cast<CachedImage*>( co ) );
-}
-
-void RenderImage::setPixmap( const TQPixmap &p, const TQRect& r, CachedImage *o)
-{
- if ( o == m_oldImage )
- return;
-
- if(o != m_cachedImage) {
- RenderReplaced::setPixmap(p, r, o);
- return;
- }
-
- bool iwchanged = false;
-
- if(o->isErrorImage()) {
- int iw = p.width() + 8;
- int ih = p.height() + 8;
-
- // we have an alt and the user meant it (its not a text we invented)
- if ( element() && !alt.isEmpty() && !element()->getAttribute( ATTR_ALT ).isNull()) {
- const TQFontMetrics &fm = style()->fontMetrics();
- TQRect br = fm.boundingRect ( 0, 0, 1024, 256, TQt::AlignAuto|TQt::WordBreak, alt.string() );
- if ( br.width() > iw )
- iw = br.width();
- if ( br.height() > ih )
- ih = br.height();
- }
-
- if ( iw != intrinsicWidth() ) {
- setIntrinsicWidth( iw );
- iwchanged = true;
- }
- if ( ih != intrinsicHeight() ) {
- setIntrinsicHeight( ih );
- iwchanged = true;
- }
- if ( element() && element()->id() == ID_OBJECT ) {
- static_cast<HTMLObjectElementImpl*>( element() )->renderAlternative();
- return;
- }
- }
- berrorPic = o->isErrorImage();
-
- bool needlayout = false;
-
- // Image dimensions have been changed, see what needs to be done
- if( o->pixmap_size().width() != intrinsicWidth() ||
- o->pixmap_size().height() != intrinsicHeight() || iwchanged )
- {
-// tqDebug("image dimensions have been changed, old: %d/%d new: %d/%d",
-// intrinsicWidth(), intrinsicHeight(),
-// o->pixmap_size().width(), o->pixmap_size().height());
-
- if(!o->isErrorImage()) {
- setIntrinsicWidth( o->pixmap_size().width() );
- setIntrinsicHeight( o->pixmap_size().height() );
- }
-
- // lets see if we need to relayout at all..
- int oldwidth = m_width;
- int oldheight = m_height;
- int oldminwidth = m_minWidth;
- m_minWidth = 0;
-
- if ( parent() ) {
- calcWidth();
- calcHeight();
- }
-
- if(iwchanged || m_width != oldwidth || m_height != oldheight)
- needlayout = true;
-
- m_minWidth = oldminwidth;
- m_width = oldwidth;
- m_height = oldheight;
- }
-
- // we're not fully integrated in the tree yet.. we'll come back.
- if ( !parent() )
- return;
-
- if(needlayout)
- {
- if (!selfNeedsLayout())
- setNeedsLayout(true);
- if (minMaxKnown())
- setMinMaxKnown(false);
- }
- else
- {
- bool completeRepaint = !resizeCache.isNull();
- int cHeight = contentHeight();
- int scaledHeight = intrinsicHeight() ? ((o->valid_rect().height()*cHeight)/intrinsicHeight()) : 0;
-
- // don't bog down X server doing xforms
- if(completeRepaint && cHeight >= 5 && o->valid_rect().height() < intrinsicHeight() &&
- (scaledHeight / (cHeight/5) == resizeCache.height() / (cHeight/5)))
- return;
-
- resizeCache = TQPixmap(); // for resized animations
-
- if(completeRepaint)
- repaintRectangle(borderLeft()+paddingLeft(), borderTop()+paddingTop(), contentWidth(), contentHeight());
- else
- {
- repaintRectangle(r.x() + borderLeft() + paddingLeft(), r.y() + borderTop() + paddingTop(),
- r.width(), r.height());
- }
- }
-}
-
-void RenderImage::paint(PaintInfo& paintInfo, int _tx, int _ty)
-{
- if (paintInfo.phase == PaintActionOutline && style()->outlineWidth() && style()->visibility() == VISIBLE)
- paintOutline(paintInfo.p, _tx + m_x, _ty + m_y, width(), height(), style());
-
- if (paintInfo.phase != PaintActionForeground && paintInfo.phase != PaintActionSelection)
- return;
-
- // not visible or not even once layouted?
- if (style()->visibility() != VISIBLE || m_y <= -500000) return;
-
- _tx += m_x;
- _ty += m_y;
-
- if((_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top())) return;
-
- if(shouldPaintBackgroundOrBorder())
- paintBoxDecorations(paintInfo, _tx, _ty);
-
- int cWidth = contentWidth();
- int cHeight = contentHeight();
- int leftBorder = borderLeft();
- int topBorder = borderTop();
- int leftPad = paddingLeft();
- int topPad = paddingTop();
-
- if (!canvas()->printImages())
- return;
-
- CachedImage* i = m_oldImage && m_oldImage->valid_rect().size() == m_oldImage->pixmap_size() &&
- m_oldImage->pixmap_size().width() == intrinsicWidth() &&
- m_oldImage->pixmap_size().height() == intrinsicHeight()
- ? m_oldImage : m_cachedImage;
-
- // paint frame around image as long as it is not completely loaded from web.
- if (bUnfinishedImageFrame && paintInfo.phase == PaintActionForeground && cWidth > 2 && cHeight > 2 && !complete()) {
- static TQPixmap *loadingIcon;
- TQColor bg = khtml::retrieveBackgroundColor(this);
- TQColor fg = khtml::hasSufficientContrast(Qt::gray, bg) ? Qt::gray :
- (hasSufficientContrast(Qt::white, bg) ? Qt::white : Qt::black);
- paintInfo.p->setPen(TQPen(fg, 1));
- paintInfo.p->setBrush( Qt::NoBrush );
- paintInfo.p->drawRect(_tx, _ty, m_width, m_height);
- if (!(m_width <= 5 || m_height <= 5)) {
- if (!loadingIcon) {
- loadingIcon = new TQPixmap();
- loadingIcon->loadFromData(loading_icon_data, loading_icon_len);
- }
- paintInfo.p->drawPixmap(_tx + 4, _ty + 4, *loadingIcon, 0, 0, m_width - 5, m_height - 5);
- }
-
- }
-
- //kdDebug( 6040 ) << " contents (" << contentWidth << "/" << contentHeight << ") border=" << borderLeft() << " padding=" << paddingLeft() << endl;
- if ( !i || berrorPic)
- {
- if(cWidth > 2 && cHeight > 2)
- {
- if ( !berrorPic ) {
- //tqDebug("qDrawShadePanel %d/%d/%d/%d", _tx + leftBorder, _ty + topBorder, cWidth, cHeight);
- qDrawShadePanel( paintInfo.p, _tx + leftBorder + leftPad, _ty + topBorder + topPad, cWidth, cHeight,
- TDEApplication::palette().inactive(), true, 1 );
- }
- TQPixmap const* pix = i ? &i->pixmap() : 0;
- if(berrorPic && pix && (cWidth >= pix->width()+4) && (cHeight >= pix->height()+4) )
- {
- TQRect r(pix->rect());
- r = r.intersect(TQRect(0, 0, cWidth-4, cHeight-4));
- paintInfo.p->drawPixmap( TQPoint( _tx + leftBorder + leftPad+2, _ty + topBorder + topPad+2), *pix, r );
- }
- if(!alt.isEmpty()) {
- TQString text = alt.string();
- paintInfo.p->setFont(style()->font());
- paintInfo.p->setPen( style()->color() );
- int ax = _tx + leftBorder + leftPad + 2;
- int ay = _ty + topBorder + topPad + 2;
- const TQFontMetrics &fm = style()->fontMetrics();
- if (cWidth>5 && cHeight>=fm.height())
- paintInfo.p->drawText(ax, ay+1, cWidth - 4, cHeight - 4, TQt::WordBreak, text );
- }
- }
- }
- else if (i && !i->isTransparent())
- {
- paintInfo.p->setPen( Qt::black ); // used for bitmaps
- const TQPixmap& pix = i->pixmap();
- if ( (cWidth != intrinsicWidth() || cHeight != intrinsicHeight()) &&
- pix.width() > 0 && pix.height() > 0 && i->valid_rect().isValid())
- {
- if (resizeCache.isNull() && cWidth && cHeight && intrinsicWidth() && intrinsicHeight())
- {
- TQRect scaledrect(i->valid_rect());
-// kdDebug(6040) << "time elapsed: " << dt->elapsed() << endl;
-// kdDebug( 6040 ) << "have to scale: " << endl;
-// tqDebug("cw=%d ch=%d pw=%d ph=%d rcw=%d, rch=%d",
-// cWidth, cHeight, intrinsicWidth(), intrinsicHeight(), resizeCache.width(), resizeCache.height());
- TQWMatrix matrix;
- matrix.scale( (float)(cWidth)/intrinsicWidth(),
- (float)(cHeight)/intrinsicHeight() );
- resizeCache = pix.xForm( matrix );
- scaledrect.setWidth( ( cWidth*scaledrect.width() ) / intrinsicWidth() );
- scaledrect.setHeight( ( cHeight*scaledrect.height() ) / intrinsicHeight() );
-// tqDebug("resizeCache size: %d/%d", resizeCache.width(), resizeCache.height());
-// tqDebug("valid: %d/%d, scaled: %d/%d",
-// i->valid_rect().width(), i->valid_rect().height(),
-// scaledrect.width(), scaledrect.height());
-
- // sometimes scaledrect.width/height are off by one because
- // of rounding errors. if the i is fully loaded, we
- // make sure that we don't do unnecessary resizes during painting
- TQSize s(scaledrect.size());
- if(i->valid_rect().size() == TQSize( intrinsicWidth(), intrinsicHeight() )) // fully loaded
- s = TQSize(cWidth, cHeight);
- if(kAbs(s.width() - cWidth) < 2) // rounding errors
- s.setWidth(cWidth);
- if(resizeCache.size() != s)
- resizeCache.resize(s);
-
- paintInfo.p->drawPixmap( TQPoint( _tx + leftBorder + leftPad, _ty + topBorder + topPad),
- resizeCache, scaledrect );
- }
- else
- paintInfo.p->drawPixmap( TQPoint( _tx + leftBorder + leftPad, _ty + topBorder + topPad), resizeCache );
- }
- else
- {
- // we might be just about switching images
- TQRect rect(i->valid_rect().isValid() ? i->valid_rect()
- : TQRect(0, 0, intrinsicWidth(), intrinsicHeight()));
-
- TQPoint offs( _tx + leftBorder + leftPad, _ty + topBorder + topPad);
-// tqDebug("normal paint rect %d/%d/%d/%d", rect.x(), rect.y(), rect.width(), rect.height());
-// rect = rect & TQRect( 0 , y - offs.y() - 10, w, 10 + y + h - offs.y());
-
-// tqDebug("normal paint rect after %d/%d/%d/%d", rect.x(), rect.y(), rect.width(), rect.height());
-// tqDebug("normal paint: offs.y(): %d, y: %d, diff: %d", offs.y(), y, y - offs.y());
-// tqDebug("");
-
-// p->setClipRect(TQRect(x,y,w,h));
-
-
-// p->drawPixmap( offs.x(), y, pix, rect.x(), rect.y(), rect.width(), rect.height() );
- paintInfo.p->drawPixmap(offs, pix, rect);
-
- }
- }
- if (m_selectionState != SelectionNone) {
-// kdDebug(6040) << "_tx " << _tx << " _ty " << _ty << " _x " << _x << " _y " << _y << endl;
- // Draw in any case if inside selection. For selection borders, the
- // offset will decide whether to draw selection or not
- bool draw = true;
- if (m_selectionState != SelectionInside) {
- int startPos, endPos;
- selectionStartEnd(startPos, endPos);
- if(selectionState() == SelectionStart)
- endPos = 1;
- else if(selectionState() == SelectionEnd)
- startPos = 0;
- draw = endPos - startPos > 0;
- }
- if (draw) {
- // setting the brush origin is important for compatibility,
- // don't touch it unless you know what you're doing
- paintInfo.p->setBrushOrigin(_tx, _ty - paintInfo.r.y());
- paintInfo.p->fillRect(_tx, _ty, width(), height(),
- TQBrush(style()->palette().active().highlight(),
- Qt::Dense4Pattern));
- }
- }
-}
-
-void RenderImage::layout()
-{
- KHTMLAssert( needsLayout());
- KHTMLAssert( minMaxKnown() );
-
- short oldwidth = m_width;
- int oldheight = m_height;
-
- // minimum height
- m_height = m_cachedImage && m_cachedImage->isErrorImage() ? intrinsicHeight() : 0;
-
- calcWidth();
- calcHeight();
-
- // if they are variable width and we calculate a huge height or width, we assume they
- // actually wanted the intrinsic width.
- if ( m_width > 4096 && !style()->width().isFixed() )
- m_width = intrinsicWidth() + paddingLeft() + paddingRight() + borderLeft() + borderRight();
- if ( m_height > 2048 && !style()->height().isFixed() )
- m_height = intrinsicHeight() + paddingTop() + paddingBottom() + borderTop() + borderBottom();
-
- // limit total size to not run out of memory when doing the xform call.
- if ( ( m_width * m_height > 4096*2048 ) &&
- ( contentWidth() > intrinsicWidth() || contentHeight() > intrinsicHeight() ) ) {
- float scale = sqrt( m_width*m_height / ( 4096.*2048. ) );
- m_width = (int) (m_width/scale);
- m_height = (int) (m_height/scale);
- }
-
- if ( m_width != oldwidth || m_height != oldheight )
- resizeCache = TQPixmap();
-
- setNeedsLayout(false);
-}
-
-void RenderImage::notifyFinished(CachedObject *finishedObj)
-{
- if ( ( m_cachedImage == finishedObj || m_oldImage == finishedObj ) && m_oldImage ) {
- m_oldImage->deref( this );
- m_oldImage = 0;
- repaint();
- }
-
- RenderReplaced::notifyFinished(finishedObj);
-}
-
-bool RenderImage::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
-{
- inside |= RenderReplaced::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
-
- if (inside && element()) {
- int tx = _tx + m_x;
- int ty = _ty + m_y;
- if (isRelPositioned())
- relativePositionOffset(tx, ty);
-
- HTMLImageElementImpl* i = element()->id() == ID_IMG ? static_cast<HTMLImageElementImpl*>(element()) : 0;
- HTMLMapElementImpl* map;
- if (i && i->getDocument()->isHTMLDocument() &&
- (map = static_cast<HTMLDocumentImpl*>(i->getDocument())->getMap(i->imageMap()))) {
- // we're a client side image map
- inside = map->mapMouseEvent(_x - tx, _y - ty, contentWidth(), contentHeight(), info);
- info.setInnerNonSharedNode(element());
- }
- }
-
- return inside;
-}
-
-void RenderImage::updateImage(CachedImage* new_image)
-{
- CachedImage* tempimage = m_oldImage;
- m_oldImage = m_cachedImage;
- m_cachedImage = new_image;
- assert( m_cachedImage != m_oldImage );
-
- if ( m_cachedImage )
- m_cachedImage->ref(this);
-
- if ( tempimage )
- tempimage->deref(this);
-
- // if the loading finishes we might get an error and then the image is deleted
- if ( m_cachedImage )
- berrorPic = m_cachedImage->isErrorImage();
- else
- berrorPic = true;
-}
-
-void RenderImage::updateFromElement()
-{
- if (element()->id() == ID_INPUT)
- alt = static_cast<HTMLInputElementImpl*>(element())->altText();
- else if (element()->id() == ID_IMG)
- alt = static_cast<HTMLImageElementImpl*>(element())->altText();
-
- DOMString u = element()->id() == ID_OBJECT ?
- element()->getAttribute(ATTR_DATA) : element()->getAttribute(ATTR_SRC);
-
- if (!u.isEmpty() &&
- ( !m_cachedImage || m_cachedImage->url() != u ) ) {
- CachedImage *new_image = element()->getDocument()->docLoader()->
- requestImage(khtml::parseURL(u));
-
- if(new_image && new_image != m_cachedImage)
- updateImage( new_image );
- }
-}
-
-bool RenderImage::complete() const
-{
- // "complete" means that the image has been loaded
- // but also that its width/height (contentWidth(),contentHeight()) have been calculated.
- return m_cachedImage && m_cachedImage->valid_rect().size() == m_cachedImage->pixmap_size() && !needsLayout();
-}
-
-bool RenderImage::isWidthSpecified() const
-{
- switch (style()->width().type()) {
- case Fixed:
- case Percent:
- return true;
- default:
- return false;
- }
- assert(false);
- return false;
-}
-
-bool RenderImage::isHeightSpecified() const
-{
- switch (style()->height().type()) {
- case Fixed:
- case Percent:
- return true;
- default:
- return false;
- }
- assert(false);
- return false;
-}
-
-short RenderImage::calcAspectRatioWidth() const
-{
- if (intrinsicHeight() == 0)
- return 0;
- if (!m_cachedImage || m_cachedImage->isErrorImage())
- return intrinsicWidth(); // Don't bother scaling.
- return RenderReplaced::calcReplacedHeight() * intrinsicWidth() / intrinsicHeight();
-}
-
-int RenderImage::calcAspectRatioHeight() const
-{
- if (intrinsicWidth() == 0)
- return 0;
- if (!m_cachedImage || m_cachedImage->isErrorImage())
- return intrinsicHeight(); // Don't bother scaling.
- return RenderReplaced::calcReplacedWidth() * intrinsicHeight() / intrinsicWidth();
-}
-
-short RenderImage::calcReplacedWidth() const
-{
- int width;
- if (isWidthSpecified())
- width = calcReplacedWidthUsing(Width);
- else
- width = calcAspectRatioWidth();
- int minW = calcReplacedWidthUsing(MinWidth);
- int maxW = style()->maxWidth().value() == UNDEFINED ? width : calcReplacedWidthUsing(MaxWidth);
-
- if (width > maxW)
- width = maxW;
-
- if (width < minW)
- width = minW;
-
- return width;
-}
-
-int RenderImage::calcReplacedHeight() const
-{
- int height;
- if (isHeightSpecified())
- height = calcReplacedHeightUsing(Height);
- else
- height = calcAspectRatioHeight();
-
- int minH = calcReplacedHeightUsing(MinHeight);
- int maxH = style()->maxHeight().value() == UNDEFINED ? height : calcReplacedHeightUsing(MaxHeight);
-
- if (height > maxH)
- height = maxH;
-
- if (height < minH)
- height = minH;
-
- return height;
-}
-
-#if 0
-void RenderImage::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
-{
- RenderReplaced::caretPos(offset, flags, _x, _y, width, height);
-
-#if 0 // doesn't work reliably
- height = intrinsicHeight();
- width = override && offset == 0 ? intrinsicWidth() : 0;
- _x = xPos();
- _y = yPos();
- if (offset > 0) _x += intrinsicWidth();
-
- RenderObject *cb = containingBlock();
-
- int absx, absy;
- if (cb && cb != this && cb->absolutePosition(absx,absy))
- {
- _x += absx;
- _y += absy;
- } else {
- // we don't know our absolute position, and there is no point returning
- // just a relative one
- _x = _y = -1;
- }
-#endif
-}
-#endif
diff --git a/khtml/rendering/render_image.h b/khtml/rendering/render_image.h
deleted file mode 100644
index 8c8bb9bef..000000000
--- a/khtml/rendering/render_image.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_IMAGE_H
-#define RENDER_IMAGE_H
-
-#include "html/dtd.h"
-#include "html/html_elementimpl.h"
-#include "rendering/render_replaced.h"
-#include "dom/dom_string.h"
-
-#include <tqmap.h>
-#include <tqpixmap.h>
-
-namespace khtml {
-
-class DocLoader;
-class CachedObject;
-
-class RenderImage : public RenderReplaced
-{
-public:
- RenderImage(DOM::NodeImpl* _element);
- virtual ~RenderImage();
-
- virtual const char *renderName() const { return "RenderImage"; }
- virtual void paint( PaintInfo& i, int tx, int ty );
-
- virtual void layout();
-
- virtual void setPixmap( const TQPixmap &, const TQRect&, CachedImage *);
-
- // don't even think about making these methods virtual!
- TQPixmap pixmap() const;
- DOM::HTMLElementImpl* element() const
- { return static_cast<DOM::HTMLElementImpl*>(RenderObject::element()); }
-
- bool complete() const;
-
- CachedObject *contentObject() { return m_cachedImage; }
- void setContentObject( CachedObject* );
-
- // hook to keep RendeObject::m_inline() up to date
- virtual void setStyle(RenderStyle *style);
- virtual void updateFromElement();
-
- virtual void notifyFinished(CachedObject *finishedObj);
- virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction hitTestAction, bool inside);
-
- bool isWidthSpecified() const;
- bool isHeightSpecified() const;
-
- short calcAspectRatioWidth() const;
- int calcAspectRatioHeight() const;
-
- virtual short calcReplacedWidth() const;
- virtual int calcReplacedHeight() const;
-
- virtual SelectionState selectionState() const {return m_selectionState;}
- virtual void setSelectionState(SelectionState s) {m_selectionState = s; }
-#if 0
- virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
-#endif
-
-private:
- void updateImage(CachedImage* new_image);
- /*
- * Cache for images that need resizing
- */
- TQPixmap resizeCache;
-
- // text to display as long as the image isn't available
- DOM::DOMString alt;
-
- CachedImage *m_cachedImage;
- CachedImage *m_oldImage;
-
- bool berrorPic : 1;
- bool bUnfinishedImageFrame :1;
- SelectionState m_selectionState : 3; // FIXME: don't forget to enlarge this as the enum grows
-};
-
-
-} //namespace
-
-#endif
diff --git a/khtml/rendering/render_inline.cpp b/khtml/rendering/render_inline.cpp
deleted file mode 100644
index c3eb08d4b..000000000
--- a/khtml/rendering/render_inline.cpp
+++ /dev/null
@@ -1,935 +0,0 @@
-/*
- * This file is part of the render object implementation for KHTML.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include <kglobal.h>
-
-#include "rendering/render_arena.h"
-#include "rendering/render_inline.h"
-#include "rendering/render_block.h"
-#include "xml/dom_docimpl.h"
-
-#include <tqvaluevector.h>
-
-using namespace khtml;
-
-void RenderInline::setStyle(RenderStyle* _style)
-{
- RenderFlow::setStyle(_style);
- setInline(true);
-
- // Ensure that all of the split inlines pick up the new style. We
- // only do this if we're an inline, since we don't want to propagate
- // a block's style to the other inlines.
- // e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before
- // and after the block share the same style, but the block doesn't
- // need to pass its style on to anyone else.
- RenderFlow* currCont = continuation();
- while (currCont) {
- if (currCont->isInline()) {
- RenderFlow* nextCont = currCont->continuation();
- currCont->setContinuation(0);
- currCont->setStyle(style());
- currCont->setContinuation(nextCont);
- }
- currCont = currCont->continuation();
- }
-
- if (attached()) {
- // Update replaced content
- updateReplacedContent();
- // Update pseudos for ::before and ::after
- updatePseudoChildren();
- }
-}
-
-// Attach handles initial setStyle that requires parent nodes
-void RenderInline::attach()
-{
- RenderFlow::attach();
-
- updateReplacedContent();
- updatePseudoChildren();
-}
-
-bool RenderInline::isInlineContinuation() const
-{
- return m_isContinuation;
-}
-
-void RenderInline::addChildToFlow(RenderObject* newChild, RenderObject* beforeChild)
-{
- // Make sure we don't append things after :after-generated content if we have it.
- if (!beforeChild && lastChild() && lastChild()->style()->styleType() == RenderStyle::AFTER)
- beforeChild = lastChild();
-
- if (!newChild->isText() && newChild->style()->position() != STATIC)
- setOverhangingContents();
-
- if (!newChild->isInline() && !newChild->isFloatingOrPositioned() )
- {
- // We are placing a block inside an inline. We have to perform a split of this
- // inline into continuations. This involves creating an anonymous block box to hold
- // |newChild|. We then make that block box a continuation of this inline. We take all of
- // the children after |beforeChild| and put them in a clone of this object.
-
- RenderBlock *newBox = createAnonymousBlock();
- RenderFlow* oldContinuation = continuation();
- setContinuation(newBox);
-
- splitFlow(beforeChild, newBox, newChild, oldContinuation);
- return;
- }
-
- RenderBox::addChild(newChild,beforeChild);
-
- newChild->setNeedsLayoutAndMinMaxRecalc();
-}
-
-RenderInline* RenderInline::cloneInline(RenderFlow* src)
-{
- RenderInline *o = new (src->renderArena()) RenderInline(src->element());
- o->m_isContinuation = true;
- o->setStyle(src->style());
- return o;
-}
-
-void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
- RenderBlock* middleBlock,
- RenderObject* beforeChild, RenderFlow* oldCont)
-{
- // Create a clone of this inline.
- RenderInline* clone = cloneInline(this);
- clone->setContinuation(oldCont);
-
- // Now take all of the children from beforeChild to the end and remove
- // then from |this| and place them in the clone.
- RenderObject* o = beforeChild;
- while (o) {
- RenderObject* tmp = o;
- o = tmp->nextSibling();
- clone->addChildToFlow(removeChildNode(tmp), 0);
- tmp->setNeedsLayoutAndMinMaxRecalc();
- }
-
- // Hook |clone| up as the continuation of the middle block.
- middleBlock->setContinuation(clone);
-
- // We have been reparented and are now under the fromBlock. We need
- // to walk up our inline parent chain until we hit the containing block.
- // Once we hit the containing block we're done.
- RenderFlow* curr = static_cast<RenderFlow*>(parent());
- RenderFlow* currChild = this;
- while (curr && curr != fromBlock) {
- // Create a new clone.
- RenderInline* cloneChild = clone;
- clone = cloneInline(curr);
-
- // Insert our child clone as the first child.
- clone->addChildToFlow(cloneChild, 0);
-
- // Hook the clone up as a continuation of |curr|.
- RenderFlow* oldCont = curr->continuation();
- curr->setContinuation(clone);
- clone->setContinuation(oldCont);
-
- // Now we need to take all of the children starting from the first child
- // *after* currChild and append them all to the clone.
- o = currChild->nextSibling();
- while (o) {
- RenderObject* tmp = o;
- o = tmp->nextSibling();
- clone->appendChildNode(curr->removeChildNode(tmp));
- tmp->setNeedsLayoutAndMinMaxRecalc();
- }
-
- // Keep walking up the chain.
- currChild = curr;
- curr = static_cast<RenderFlow*>(curr->parent());
- }
-
- // Now we are at the block level. We need to put the clone into the toBlock.
- toBlock->appendChildNode(clone);
-
- // Now take all the children after currChild and remove them from the fromBlock
- // and put them in the toBlock.
- o = currChild->nextSibling();
- while (o) {
- RenderObject* tmp = o;
- o = tmp->nextSibling();
- toBlock->appendChildNode(fromBlock->removeChildNode(tmp));
- }
-}
-
-void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
- RenderObject* newChild, RenderFlow* oldCont)
-{
- RenderBlock* pre = 0;
- RenderBlock* block = containingBlock();
- bool madeNewBeforeBlock = false;
- if (block->isAnonymousBlock()) {
- // We can reuse this block and make it the preBlock of the next continuation.
- pre = block;
- block = block->containingBlock();
- }
- else {
- // No anonymous block available for use. Make one.
- pre = block->createAnonymousBlock();
- madeNewBeforeBlock = true;
- }
-
- RenderBlock* post = block->createAnonymousBlock();
-
- RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
- if (madeNewBeforeBlock)
- block->insertChildNode(pre, boxFirst);
- block->insertChildNode(newBlockBox, boxFirst);
- block->insertChildNode(post, boxFirst);
- block->setChildrenInline(false);
-
- if (madeNewBeforeBlock) {
- RenderObject* o = boxFirst;
- while (o)
- {
- RenderObject* no = o;
- o = no->nextSibling();
- pre->appendChildNode(block->removeChildNode(no));
- no->setNeedsLayoutAndMinMaxRecalc();
- }
- }
-
- splitInlines(pre, post, newBlockBox, beforeChild, oldCont);
-
- // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting
- // time in makeChildrenNonInline by just setting this explicitly up front.
- newBlockBox->setChildrenInline(false);
-
- // We don't just call addChild, since it would pass things off to the
- // continuation, so we call addChildToFlow explicitly instead. We delayed
- // adding the newChild until now so that the |newBlockBox| would be fully
- // connected, thus allowing newChild access to a renderArena should it need
- // to wrap itself in additional boxes (e.g., table construction).
- newBlockBox->addChildToFlow(newChild, 0);
-
- // XXXdwh is any of this even necessary? I don't think it is.
- pre->close();
- pre->setPos(0, -500000);
- pre->setNeedsLayout(true);
- newBlockBox->close();
- newBlockBox->setPos(0, -500000);
- newBlockBox->setNeedsLayout(true);
- post->close();
- post->setPos(0, -500000);
- post->setNeedsLayout(true);
-
- updatePseudoChildren();
-
- block->setNeedsLayoutAndMinMaxRecalc();
-}
-
-void RenderInline::paint(PaintInfo& i, int _tx, int _ty)
-{
- paintLines(i, _tx, _ty);
-}
-
-/**
- * Appends the given coordinate-pair to the point-array if it is not
- * equal to the last element.
- * @param pointArray point-array
- * @param pnt point to append
- * @return \c true if \c pnt has actually been appended
- */
-inline static bool appendIfNew(TQValueVector<TQPoint> &pointArray, const TQPoint &pnt)
-{
-// if (!pointArray.isEmpty()) kdDebug(6040) << "appifnew: " << pointArray.back() << " == " << pnt << ": " << (pointArray.back() == pnt) << endl;
-// else kdDebug(6040) << "appifnew: " << pnt << " (unconditional)" << endl;
- if (!pointArray.isEmpty() && pointArray.back() == pnt) return false;
- pointArray.append(pnt);
- return true;
-}
-
-/**
- * Does spike-reduction on the given point-array's stack-top.
- *
- * Spikes are path segments of which one goes forward, and the sucessor
- * goes backward on the predecessor's segment:
- *
- * 2 0 1
- * x------x<-----x
- * (0 is stack-top in point-array)
- *
- * This will be reduced to
- * 1 0
- * x------x
- *
- * Preconditions:
- * - No other spikes exist in the whole point-array except at most
- * one at the end
- * - No two succeeding points are ever equal
- * - For each two succeeding points either p1.x == p2.x or p1.y == p2.y holds
- * true
- * - No such spike exists where 2 is situated between 0 and 1.
- *
- * Postcondition:
- * - No spikes exist in the whole point-array
- *
- * If no spike is found, the point-array is left unchanged.
- * @return \c true if an actual reduction was done
- */
-inline static bool reduceSpike(TQValueVector<TQPoint> &pointArray)
-{
- if (pointArray.size() < 3) return false;
- TQValueVector<TQPoint>::Iterator it = pointArray.end();
- TQPoint p0 = *--it;
- TQPoint p1 = *--it;
- TQPoint p2 = *--it;
-
- bool elide = false;
-
- if (p0.x() == p1.x() && p1.x() == p2.x()
- && (p1.y() < p0.y() && p0.y() < p2.y()
- || p2.y() < p0.y() && p0.y() < p1.y()
- || p1.y() < p2.y() && p2.y() < p0.y()
- || p0.y() < p2.y() && p2.y() < p1.y()
- || (elide = p2.y() == p0.y() && p0.y() < p1.y())
- || (elide = p1.y() < p0.y() && p0.y() == p2.y()))
- || p0.y() == p1.y() && p1.y() == p2.y()
- && (p1.x() < p0.x() && p0.x() < p2.x()
- || p2.x() < p0.x() && p0.x() < p1.x()
- || p1.x() < p2.x() && p2.x() < p0.x()
- || p0.x() < p2.x() && p2.x() < p1.x()
- || (elide = p2.x() == p0.x() && p0.x() < p1.x())
- || (elide = p1.x() < p0.x() && p0.x() == p2.x())))
- {
-// kdDebug(6040) << "spikered p2" << (elide ? " (elide)" : "") << ": " << p2 << " p1: " << p1 << " p0: " << p0 << endl;
- pointArray.pop_back(); pointArray.pop_back();
- if (!elide)
- pointArray.push_back(p0);
- return true;
- }
- return false;
-}
-
-/**
- * Reduces segment separators.
- *
- * A segment separator separates a segment into two segments, thus causing
- * two adjacent segment with the same orientation.
- *
- * 2 1 0
- * x-------x---->x
- * (0 means stack-top)
- *
- * Here, 1 is a segment separator. As segment separators not only make
- * the line drawing algorithm inefficient, but also make the spike-reduction
- * fail, they must be eliminated:
- *
- * 1 0
- * x------------>x
- *
- * Preconditions:
- * - No other segment separators exist in the whole point-array except
- * at most one at the end
- * - No two succeeding points are ever equal
- * - For each two succeeding points either p1.x == p2.x or p1.y == p2.y holds
- * true
- * - No such spike exists where 2 is situated between 0 and 1.
- *
- * Postcondition:
- * - No segment separators exist in the whole point-array
- *
- * If no segment separator is found at the end of the point-array, it is
- * left unchanged.
- * @return \c true if a segment separator was actually reduced.
- */
-inline static bool reduceSegmentSeparator(TQValueVector<TQPoint> &pointArray)
-{
- if (pointArray.size() < 3) return false;
- TQValueVector<TQPoint>::Iterator it = pointArray.end();
- TQPoint p0 = *--it;
- TQPoint p1 = *--it;
- TQPoint p2 = *--it;
-// kdDebug(6040) << "checking p2: " << p2 << " p1: " << p1 << " p0: " << p0 << endl;
-
- if (p0.x() == p1.x() && p1.x() == p2.x()
- && (p2.y() < p1.y() && p1.y() < p0.y()
- || p0.y() < p1.y() && p1.y() < p2.y())
- || p0.y() == p1.y() && p1.y() == p2.y()
- && (p2.x() < p1.x() && p1.x() < p0.x()
- || p0.x() < p1.x() && p1.x() < p2.x()))
- {
-// kdDebug(6040) << "segred p2: " << p2 << " p1: " << p1 << " p0: " << p0 << endl;
- pointArray.pop_back(); pointArray.pop_back();
- pointArray.push_back(p0);
- return true;
- }
- return false;
-}
-
-/**
- * Appends the given point to the point-array, doing necessary reductions to
- * produce a path without spikes and segment separators.
- */
-static void appendPoint(TQValueVector<TQPoint> &pointArray, TQPoint &pnt)
-{
- if (!appendIfNew(pointArray, pnt)) return;
-// kdDebug(6040) << "appendPoint: appended " << pnt << endl;
- reduceSegmentSeparator(pointArray)
- || reduceSpike(pointArray);
-}
-
-/**
- * Traverses the horizontal inline boxes and appends the point coordinates to
- * the given array.
- * @param box inline box
- * @param pointArray array collecting coordinates
- * @param bottom \c true, collect bottom coordinates, \c false, collect top
- * coordinates.
- * @param limit lower limit that an y-coordinate must at least reach. Note
- * that limit designates the highest y-coordinate for \c bottom, and
- * the lowest for !\c bottom.
- */
-static void collectHorizontalBoxCoordinates(InlineBox *box,
- TQValueVector<TQPoint> &pointArray,
- bool bottom, int offset, int limit = -500000)
-{
-// kdDebug(6000) << "collectHorizontalBoxCoordinates: " << endl;
- offset = bottom ? offset:-offset;
- int y = box->yPos() + bottom*box->height() + offset;
- if (limit != -500000 && (bottom ? y < limit : y > limit))
- y = limit;
- int x = box->xPos() + bottom*box->width() + offset;
- TQPoint newPnt(x, y);
- // Add intersection point if point-array not empty.
- if (!pointArray.isEmpty()) {
- TQPoint lastPnt = pointArray.back();
- TQPoint insPnt(newPnt.x(), lastPnt.y());
- if (offset && ((bottom && lastPnt.y() > y) || (!bottom && lastPnt.y() < y))) {
- insPnt.rx() = lastPnt.x();
- insPnt.ry() = y;
- }
-// kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
- appendPoint(pointArray, insPnt);
- }
- // Insert starting point of box
- appendPoint(pointArray, newPnt);
-
- newPnt.rx() += (bottom ? -box->width() : box->width()) - 2*offset;
-
- if (box->isInlineFlowBox()) {
- InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(box);
- for (InlineBox *b = bottom ? flowBox->lastChild() : flowBox->firstChild(); b; b = bottom ? b->prevOnLine() : b->nextOnLine()) {
- // Don't let boxes smaller than this flow box' height influence
- // the vertical position of the outline if they have a different
- // x-coordinate
- int l2;
- if (b->xPos() != box->xPos() && b->xPos() + b->width() != box->xPos() + box->width())
- l2 = y;
- else
- l2 = limit;
- collectHorizontalBoxCoordinates(b, pointArray, bottom, kAbs(offset), l2);
- }
-
- // Add intersection point if flow box contained any children
- if (flowBox->firstChild()) {
- TQPoint lastPnt = pointArray.back();
- TQPoint insPnt(lastPnt.x(), newPnt.y());
-// kdDebug(6040) << "right: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
- appendPoint(pointArray, insPnt);
- }
- }
-
- // Insert ending point of box
- appendPoint(pointArray, newPnt);
-
-// kdDebug(6000) << "collectHorizontalBoxCoordinates: " << "ende" << endl;
-}
-
-/**
- * Checks whether the given line box' extents and the following line box'
- * extents are disjount (i. e. do not share the same x-coordinate range).
- * @param line line box
- * @param toBegin \c true, compare with preceding line box, \c false, with
- * succeeding
- * @return \c true if this and the next box are disjoint
- */
-inline static bool lineBoxesDisjoint(InlineRunBox *line, int offset, bool toBegin)
-{
- InlineRunBox *next = toBegin ? line->prevLineBox() : line->nextLineBox();
- return !next || next->xPos() + next->width() + 2*offset < line->xPos()
- || next->xPos() > line->xPos() + line->width() + 2*offset;
-}
-
-/**
- * Traverses the vertical outer borders of the given render flow's line
- * boxes and appends the point coordinates to the given point array.
- * @param line line box to begin traversal
- * @param pointArray point array
- * @param left \c true, traverse the left vertical coordinates,
- * \c false, traverse the right vertical coordinates.
- * @param lastline if not 0, returns the pointer to the last line box traversed
- */
-static void collectVerticalBoxCoordinates(InlineRunBox *line,
- TQValueVector<TQPoint> &pointArray,
- bool left, int offset, InlineRunBox **lastline = 0)
-{
- InlineRunBox *last = 0;
- offset = left ? -offset:offset;
- for (InlineRunBox* curr = line; curr && !last; curr = left ? curr->prevLineBox() : curr->nextLineBox()) {
- InlineBox *root = curr;
-
- bool isLast = lineBoxesDisjoint(curr, kAbs(offset), left);
- if (isLast) last = curr;
-
- if (root != line && !isLast)
- while (root->parent()) root = root->parent();
- TQPoint newPnt(curr->xPos() + !left*curr->width() + offset,
- (left ? root->topOverflow() : root->bottomOverflow()) + offset);
- if (!pointArray.isEmpty()) {
- TQPoint lastPnt = pointArray.back();
- if (newPnt.x()>lastPnt.x() && !left)
- pointArray.back().setY( kMin(lastPnt.y(), root->topOverflow()-offset) );
- else if (newPnt.x()<lastPnt.x() && left)
- pointArray.back().setY( kMax(lastPnt.y(), root->bottomOverflow()+offset) );
- TQPoint insPnt(newPnt.x(), pointArray.back().y());
-// kdDebug(6040) << "left: " << lastPnt << " == " << insPnt << ": " << (insPnt == lastPnt) << endl;
- appendPoint(pointArray, insPnt);
- }
- appendPoint(pointArray, newPnt);
- }
- if (lastline) *lastline = last;
-}
-
-/**
- * Links up the end of the given point-array such that the starting point
- * is not a segment separator.
- *
- * To achieve this, improper points are removed from the beginning of
- * the point-array (by changing the array's starting iterator), and
- * proper ones appended to the point-array's back.
- *
- * @param pointArray point-array
- * @return actual begin of point array
- */
-static TQPoint *linkEndToBegin(TQValueVector<TQPoint> &pointArray)
-{
- uint index = 0;
- assert(pointArray.size() >= 3);
-
- // if first and last points match, ignore the last one.
- bool linkup = false; TQPoint linkupPnt;
- if (pointArray.front() == pointArray.back()) {
- linkupPnt = pointArray.back();
- pointArray.pop_back();
- linkup = true;
- }
-
- const TQPoint *it = pointArray.begin() + index;
- TQPoint pfirst = *it;
- TQPoint pnext = *++it;
- TQPoint plast = pointArray.back();
-// kdDebug(6040) << "linkcheck plast: " << plast << " pfirst: " << pfirst << " pnext: " << pnext << endl;
-
- if (plast.x() == pfirst.x() && pfirst.x() == pnext.x()
- || plast.y() == pfirst.y() && pfirst.y() == pnext.y()) {
-
- ++index;
- appendPoint(pointArray, pfirst);
- appendPoint(pointArray, pnext);
- } else if (linkup)
- pointArray.push_back(linkupPnt);
- return pointArray.begin() + index;
-}
-
-void RenderInline::paintOutlines(TQPainter *p, int _tx, int _ty)
-{
- if (style()->outlineWidth() == 0 || style()->outlineStyle() <= BHIDDEN)
- return;
- int offset = style()->outlineOffset();
-
- // We may have to draw more than one outline path as they may be
- // disjoint.
- for (InlineRunBox *curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- TQValueVector<TQPoint> path;
-
- // collect topmost outline
- collectHorizontalBoxCoordinates(curr, path, false, offset);
- // collect right outline
- collectVerticalBoxCoordinates(curr, path, false, offset, &curr);
- // collect bottommost outline
- collectHorizontalBoxCoordinates(curr, path, true, offset);
- // collect left outline
- collectVerticalBoxCoordinates(curr, path, true, offset);
-
- if (path.size() < 3) continue;
-
- const TQPoint *begin = linkEndToBegin(path);
-
- // paint the outline
- paintOutlinePath(p, _tx, _ty, begin, path.end(), BSLeft, -1, BSTop);
- }
-}
-
-template<class T> inline void kSwap(T &a1, T &a2)
-{
- T tmp = a2;
- a2 = a1;
- a1 = tmp;
-}
-
-enum BSOrientation { BSHorizontal, BSVertical };
-
-/**
- * Returns the orientation of the given border side.
- */
-inline BSOrientation bsOrientation(RenderObject::BorderSide bs)
-{
- switch (bs) {
- case RenderObject::BSTop:
- case RenderObject::BSBottom:
- return BSHorizontal;
- case RenderObject::BSLeft:
- case RenderObject::BSRight:
- return BSVertical;
- }
- return BSHorizontal; // make gcc happy (sigh)
-}
-
-/**
- * Determines the new border side by evaluating the new direction as determined
- * by the given coordinates, the old border side, and the relative direction.
- *
- * The relative direction specifies whether the old border side meets with the
- * straight given by the coordinates from below (negative), or above (positive).
- */
-inline RenderObject::BorderSide newBorderSide(RenderObject::BorderSide oldBS, int direction, const TQPoint &last, const TQPoint &cur)
-{
- bool below = direction < 0;
- if (last.x() == cur.x()) { // new segment is vertical
- bool t = oldBS == RenderObject::BSTop;
- bool b = oldBS == RenderObject::BSBottom;
- if ((t || b) && last.y() != cur.y())
- return (cur.y() < last.y()) ^ (t && below || b && !below)
- ? RenderObject::BSLeft : RenderObject::BSRight;
- } else /*if (last.y() == cur.y())*/ { // new segment is horizontal
- bool l = oldBS == RenderObject::BSLeft;
- bool r = oldBS == RenderObject::BSRight;
- if ((l || r) && last.x() != cur.x())
- return (cur.x() < last.x()) ^ (l && below || r && !below)
- ? RenderObject::BSTop : RenderObject::BSBottom;
- }
- return oldBS; // same direction
-}
-
-/**
- * Draws an outline segment between the given two points.
- * @param o render object
- * @param p painter
- * @param tx absolute x-coordinate of containing block
- * @param ty absolute y-coordinate of containing block
- * @param p1 starting point
- * @param p2 end point
- * @param prevBS border side of previous segment
- * @param curBS border side of this segment
- * @param nextBS border side of next segment
- */
-static void paintOutlineSegment(RenderObject *o, TQPainter *p, int tx, int ty,
- const TQPoint &p1, const TQPoint &p2,
- RenderObject::BorderSide prevBS,
- RenderObject::BorderSide curBS,
- RenderObject::BorderSide nextBS)
-{
- int ow = o->style()->outlineWidth();
- EBorderStyle os = o->style()->outlineStyle();
- TQColor oc = o->style()->outlineColor();
-
- int x1 = tx + p1.x();
- int y1 = ty + p1.y();
- int x2 = tx + p2.x();
- int y2 = ty + p2.y();
- if (x1 > x2) {
- kSwap(x1, x2);
- if (bsOrientation(curBS) == BSHorizontal) kSwap(prevBS, nextBS);
- }
- if (y1 > y2) {
- kSwap(y1, y2);
- if (bsOrientation(curBS) == BSVertical) kSwap(prevBS, nextBS);
- }
-
-// kdDebug(6040) << "segment(" << x1 << "," << y1 << ") - (" << x2 << "," << y2 << ")" << endl;
-/* p->setPen(Qt::gray);
- p->drawLine(x1,y1,x2,y2);*/
- switch (curBS) {
- case RenderObject::BSLeft:
- case RenderObject::BSRight:
-/* p->setPen(TQColor("#ffe4dd"));
- p->drawLine(
- x1 - (curBS == RenderObject::BSLeft ? ow : 0),
- y1 - (prevBS == RenderObject::BSTop ? ow : 0),
- x2 + (curBS == RenderObject::BSRight ? ow : 0),
- y2 + (nextBS == RenderObject::BSBottom ? ow : 0)
- );*/
- o->drawBorder(p,
- x1 - (curBS == RenderObject::BSLeft ? ow : 0),
- y1 - (prevBS == RenderObject::BSTop ? ow : 0),
- x2 + (curBS == RenderObject::BSRight ? ow : 0),
- y2 + (nextBS == RenderObject::BSBottom ? ow : 0),
- curBS, oc, o->style()->color(), os,
- prevBS == RenderObject::BSTop ? ow
- : prevBS == RenderObject::BSBottom ? -ow : 0,
- nextBS == RenderObject::BSTop ? -ow
- : nextBS == RenderObject::BSBottom ? ow : 0,
- true);
- break;
- case RenderObject::BSBottom:
- case RenderObject::BSTop:
-// kdDebug(6040) << "BSTop/BSBottom: prevBS " << prevBS << " curBS " << curBS << " nextBS " << nextBS << endl;
- o->drawBorder(p,
- x1 - (prevBS == RenderObject::BSLeft ? ow : 0),
- y1 - (curBS == RenderObject::BSTop ? ow : 0),
- x2 + (nextBS == RenderObject::BSRight ? ow : 0),
- y2 + (curBS == RenderObject::BSBottom ? ow : 0),
- curBS, oc, o->style()->color(), os,
- prevBS == RenderObject::BSLeft ? ow
- : prevBS == RenderObject::BSRight ? -ow : 0,
- nextBS == RenderObject::BSLeft ? -ow
- : nextBS == RenderObject::BSRight ? ow : 0,
- true);
- break;
- }
-}
-
-void RenderInline::paintOutlinePath(TQPainter *p, int tx, int ty, const TQPoint *begin, const TQPoint *end, BorderSide bs, int direction, BorderSide endingBS)
-{
- int ow = style()->outlineWidth();
- if (ow == 0 || m_isContinuation) // Continuations get painted by the original inline.
- return;
-
- TQPoint last = *begin;
- BorderSide lastBS = bs;
- Q_ASSERT(begin != end);
- ++begin;
-
-// kdDebug(6040) << "last: " << last << endl;
-
- bs = newBorderSide(bs, direction, last, *begin);
-// kdDebug(6040) << "newBorderSide: " << lastBS << " " << direction << "d " << last << " - " << *begin << " => " << bs << endl;
-
- for (const TQPoint *it = begin; it != end; ++it) {
- TQPoint cur = *it;
-// kdDebug(6040) << "cur: " << cur << endl;
- BorderSide nextBS;
- if (it + 1 != end) {
- TQPoint diff = cur - last;
- direction = diff.x() + diff.y();
- nextBS = newBorderSide(bs, direction, cur, *(it + 1));
-// kdDebug(6040) << "newBorderSide*: " << bs << " " << direction << "d " << cur << " - " << *(it + 1) << " => " << nextBS << endl;
- } else
- nextBS = endingBS;
-
- Q_ASSERT(bsOrientation(bs) != bsOrientation(nextBS));
- paintOutlineSegment(this, p, tx, ty, last, cur,
- lastBS, bs, nextBS);
- lastBS = bs;
- last = cur;
- bs = nextBS;
- }
-
-}
-
-void RenderInline::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(RenderInline)::calcMinMaxWidth() this=" << this << endl;
-#endif
-
- // Irrelevant, since some enclosing block will actually measure us and our children.
- m_minWidth = 0;
- m_maxWidth = 0;
-
- setMinMaxKnown();
-}
-
-short RenderInline::width() const
-{
- // Return the width of the minimal left side and the maximal right side.
- short leftSide = 0;
- short rightSide = 0;
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
- if (curr == firstLineBox() || curr->xPos() < leftSide)
- leftSide = curr->xPos();
- if (curr == firstLineBox() || curr->xPos() + curr->width() > rightSide)
- rightSide = curr->xPos() + curr->width();
- }
-
- return rightSide - leftSide;
-}
-
-int RenderInline::height() const
-{
- int h = 0;
- if (firstLineBox())
- h = lastLineBox()->yPos() + lastLineBox()->height() - firstLineBox()->yPos();
- return h;
-}
-
-int RenderInline::offsetLeft() const
-{
- int x = RenderFlow::offsetLeft();
- if (firstLineBox())
- x += firstLineBox()->xPos();
- return x;
-}
-
-int RenderInline::offsetTop() const
-{
- int y = RenderFlow::offsetTop();
- if (firstLineBox())
- y += firstLineBox()->yPos();
- return y;
-}
-
-const char *RenderInline::renderName() const
-{
- if (isRelPositioned())
- return "RenderInline (relative positioned)";
- if (isAnonymous())
- return "RenderInline (anonymous)";
- return "RenderInline";
-}
-
-bool RenderInline::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
-{
-/*
- if ( hitTestAction != HitTestSelfOnly ) {
- for (RenderObject* child = lastChild(); child; child = child->previousSibling())
- if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, _tx, _ty, HitTestAll))
- inside = true;
- }
-*/
- // Check our line boxes if we're still not inside.
- if (/*hitTestAction != HitTestChildrenOnly &&*/ !inside && style()->visibility() != HIDDEN) {
- // See if we're inside one of our line boxes.
- inside = hitTestLines(info, _x, _y, _tx, _ty, hitTestAction);
- }
-
- if (inside && element()) {
- if (info.innerNode() && info.innerNode()->renderer() &&
- !info.innerNode()->renderer()->isInline()) {
- // Within the same layer, inlines are ALWAYS fully above blocks. Change inner node.
- info.setInnerNode(element());
-
- // Clear everything else.
- info.setInnerNonSharedNode(0);
- info.setURLElement(0);
- }
-
- if (!info.innerNode())
- info.setInnerNode(element());
-
- if(!info.innerNonSharedNode())
- info.setInnerNonSharedNode(element());
- }
-
- return inside;
-}
-
-void RenderInline::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
-{
- _x = -1;
-
- RenderBlock *cb = containingBlock();
- bool rtl = cb->style()->direction() == RTL;
- bool outsideEnd = flags & CFOutsideEnd;
- // I need to explain that: outsideEnd contains a meaningful value if
- // and only if flags & CFOutside is set. If it is not, then randomly
- // either the first or the last line box is returned.
- // This doesn't matter because the only case this can happen is on an
- // empty inline element, whose first and last line boxes are actually
- // the same.
- InlineFlowBox *line = !outsideEnd ^ rtl ? firstLineBox() : lastLineBox();
-
- if (!line) { // umpf, handle "gracefully"
- RenderFlow::caretPos(offset, flags, _x, _y, width, height);
- return;
- }
-
- _x = line->xPos();
- width = 1; // ### regard CFOverride
-
- // Place caret outside the border
- if (flags & CFOutside) {
- RenderStyle *s = element() && element()->parent()
- && element()->parent()->renderer()
- ? element()->parent()->renderer()->style()
- : style();
- const TQFontMetrics &fm = s->fontMetrics();
- _y = line->yPos() + line->baseline() - fm.ascent();
- height = fm.height();
-
- if (!outsideEnd ^ rtl) {
- _x -= line->marginBorderPaddingLeft();
- } else {
- _x += line->width() + line->marginBorderPaddingRight();
- }
-
- } else {
- const TQFontMetrics &fm = style()->fontMetrics();
- _y = line->yPos() + line->baseline() - fm.ascent();
- height = fm.height();
- }
-
- int absx, absy;
- if (cb && cb->absolutePosition(absx,absy)) {
- //kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
- _x += absx;
- _y += absy;
- } else {
- // we don't know our absolute position, and there is no point returning
- // just a relative one
- _x = _y = -1;
- }
-}
-
-inline int minXPos(const RenderInline *o)
-{
- int retval=6666666;
- if (!o->firstLineBox()) return 0;
- for (InlineRunBox* curr = o->firstLineBox(); curr; curr = curr->nextLineBox())
- retval = kMin( retval, int( curr->m_x ));
- return retval;
-}
-
-int RenderInline::inlineXPos() const
-{
- return minXPos(this);
-}
-
-int RenderInline::inlineYPos() const
-{
- return firstLineBox() ? firstLineBox()->yPos() : 0;
-}
-
diff --git a/khtml/rendering/render_inline.h b/khtml/rendering/render_inline.h
deleted file mode 100644
index 5f4bf7b29..000000000
--- a/khtml/rendering/render_inline.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * This file is part of the render object implementation for KHTML.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999-2003 Antti Koivisto (koivisto@kde.org)
- * (C) 2002-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef RENDER_INLINE_H
-#define RENDER_INLINE_H
-
-#include "render_flow.h"
-
-namespace khtml {
-
-class RenderInline : public RenderFlow
-{
-public:
- RenderInline(DOM::NodeImpl* node) : RenderFlow( node ), m_isContinuation( false ) {}
-
- virtual const char *renderName() const;
-
- virtual bool isRenderInline() const { return true; }
- virtual bool isInlineFlow() const { return true; }
- virtual bool childrenInline() const { return true; }
-
- virtual bool isInlineContinuation() const;
-
- virtual void addChildToFlow(RenderObject* newChild, RenderObject* beforeChild);
-
- void splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
- RenderObject* beforeChild, RenderFlow* oldCont);
-
- void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
- RenderObject* newChild, RenderFlow* oldCont);
-
- virtual void setStyle(RenderStyle* _style);
- virtual void attach();
-
- virtual void layout() {} // Do nothing for layout()
-
- virtual void paint(PaintInfo&, int tx, int ty);
-
- virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside);
-
- virtual void calcMinMaxWidth();
-
- // overrides RenderObject
- virtual bool requiresLayer() const { return isRelPositioned(); }
-
- virtual short width() const;
- virtual int height() const;
-
- virtual int inlineXPos() const;
- virtual int inlineYPos() const;
-
- // used to calculate offsetWidth/Height. Overridden by inlines (render_flow) to return
- // the remaining width on a given line (and the height of a single line).
- virtual int offsetLeft() const;
- virtual int offsetTop() const;
-
- virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
- void paintOutlines(TQPainter *p, int tx, int ty);
-
-protected:
- static RenderInline* cloneInline(RenderFlow* src);
- void paintOutlinePath(TQPainter *p, int tx, int ty, const TQPoint *begin, const TQPoint *end, BorderSide startingBS, int initialDirection, BorderSide endingBS);
-
-private:
- bool m_isContinuation : 1; // Whether or not we're a continuation of an inline.
-
-};
-
-} // namespace
-
-#endif // RENDER_BLOCK_H
-
diff --git a/khtml/rendering/render_layer.cpp b/khtml/rendering/render_layer.cpp
deleted file mode 100644
index 2b7e93f1f..000000000
--- a/khtml/rendering/render_layer.cpp
+++ /dev/null
@@ -1,1830 +0,0 @@
-/*
- * Copyright (C) 2003 Apple Computer, Inc.
- * (C) 2006 Germain Garand <germain@ebooksfrance.org>
- * (C) 2006 Allan Sandfeld Jense <kde@carewolf.com>
- *
- * Portions are Copyright (C) 1998 Netscape Communications Corporation.
- *
- * Other contributors:
- * Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
- * Christian Biesinger <cbiesinger@web.de>
- * Randall Jesup <rjesup@wgate.com>
- * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
- * Josh Soref <timeless@mac.com>
- * Boris Zbarsky <bzbarsky@mit.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Alternatively, the contents of this file may be used under the terms
- * of either the Mozilla Public License Version 1.1, found at
- * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
- * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
- * (the "GPL"), in which case the provisions of the MPL or the GPL are
- * applicable instead of those above. If you wish to allow use of your
- * version of this file only under the terms of one of those two
- * licenses (the MPL or the GPL) and not to allow others to use your
- * version of this file under the LGPL, indicate your decision by
- * deletingthe provisions above and replace them with the notice and
- * other provisions required by the MPL or the GPL, as the case may be.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under any of the LGPL, the MPL or the GPL.
- */
-
-//#define BOX_DEBUG
-
-#include "render_layer.h"
-#include <kdebug.h>
-#include <assert.h>
-#include "khtmlview.h"
-#include "render_canvas.h"
-#include "render_arena.h"
-#include "render_replaced.h"
-#include "xml/dom_docimpl.h"
-#include "xml/dom2_eventsimpl.h"
-#include "misc/htmltags.h"
-#include "html/html_blockimpl.h"
-#include "xml/dom_restyler.h"
-
-#include <tqscrollbar.h>
-#include <tqptrvector.h>
-#include <tqstyle.h>
-
-using namespace DOM;
-using namespace khtml;
-
-#ifdef APPLE_CHANGES
-TQScrollBar* RenderLayer::gScrollBar = 0;
-#endif
-
-#ifndef NDEBUG
-static bool inRenderLayerDetach;
-#endif
-
-void
-RenderScrollMediator::slotValueChanged()
-{
- m_layer->updateScrollPositionFromScrollbars();
-}
-
-RenderLayer::RenderLayer(RenderObject* object)
-: m_object( object ),
-m_parent( 0 ),
-m_previous( 0 ),
-m_next( 0 ),
-m_first( 0 ),
-m_last( 0 ),
-m_x( 0 ),
-m_y( 0 ),
-m_scrollX( 0 ),
-m_scrollY( 0 ),
-m_scrollWidth( 0 ),
-m_scrollHeight( 0 ),
-m_hBar( 0 ),
-m_vBar( 0 ),
-m_scrollMediator( 0 ),
-m_posZOrderList( 0 ),
-m_negZOrderList( 0 ),
-m_overflowList(0),
-m_zOrderListsDirty( true ),
-m_overflowListDirty(true),
-m_isOverflowOnly( shouldBeOverflowOnly() ),
-m_markedForRepaint( false ),
-m_hasOverlaidWidgets( false ),
-m_marquee( 0 )
-{
-}
-
-RenderLayer::~RenderLayer()
-{
- // Child layers will be deleted by their corresponding render objects, so
- // our destructor doesn't have to do anything.
- delete m_hBar;
- delete m_vBar;
- delete m_scrollMediator;
- delete m_posZOrderList;
- delete m_negZOrderList;
- delete m_overflowList;
- delete m_marquee;
-}
-
-void RenderLayer::updateLayerPosition()
-{
-
- // The canvas is sized to the docWidth/Height over in RenderCanvas::layout, so we
- // don't need to ever update our layer position here.
- if (renderer()->isCanvas())
- return;
-
- int x = m_object->xPos();
- int y = m_object->yPos() - m_object->borderTopExtra();
-
- if (!m_object->isPositioned()) {
- // We must adjust our position by walking up the render tree looking for the
- // nearest enclosing object with a layer.
- RenderObject* curr = m_object->parent();
- while (curr && !curr->layer()) {
- x += curr->xPos();
- y += curr->yPos();
- curr = curr->parent();
- }
- if (curr)
- y += curr->borderTopExtra();
- }
-
- if (m_object->isRelPositioned())
- static_cast<RenderBox*>(m_object)->relativePositionOffset(x, y);
-
- // Subtract our parent's scroll offset.
- if (m_object->isPositioned() && enclosingPositionedAncestor()) {
- RenderLayer* positionedParent = enclosingPositionedAncestor();
-
- // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
- positionedParent->subtractScrollOffset(x, y);
- positionedParent->checkInlineRelOffset(m_object, x, y);
- }
- else if (parent())
- parent()->subtractScrollOffset(x, y);
-
- setPos(x,y);
-}
-
-TQRegion RenderLayer::paintedRegion(RenderLayer* rootLayer)
-{
- updateZOrderLists();
- TQRegion r;
- if (m_negZOrderList) {
- uint count = m_negZOrderList->count();
- for (uint i = 0; i < count; i++) {
- RenderLayer* child = m_negZOrderList->at(i);
- r += child->paintedRegion(rootLayer);
- }
- }
- const RenderStyle *s= renderer()->style();
- if (s->visibility() == VISIBLE) {
- int x = 0; int y = 0;
- convertToLayerCoords(rootLayer,x,y);
- TQRect cr(x,y,width(),height());
- if ( s->backgroundImage() || s->backgroundColor().isValid() || s->hasBorder() ||
- renderer()->scrollsOverflow() || renderer()->isReplaced() ) {
- r += cr;
- } else {
- r += renderer()->visibleFlowRegion(x, y);
- }
- }
-
- if (m_posZOrderList) {
- uint count = m_posZOrderList->count();
- for (uint i = 0; i < count; i++) {
- RenderLayer* child = m_posZOrderList->at(i);
- r += child->paintedRegion(rootLayer);
- }
- }
- return r;
-}
-
-void RenderLayer::repaint( Priority p, bool markForRepaint )
-{
- if (markForRepaint && m_markedForRepaint)
- return;
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->repaint( p, markForRepaint );
- TQRect layerBounds, damageRect, fgrect;
- calculateRects(renderer()->canvas()->layer(), renderer()->viewRect(), layerBounds, damageRect, fgrect);
- m_visibleRect = damageRect.intersect( layerBounds );
- if (m_visibleRect.isValid())
- renderer()->canvas()->repaintViewRectangle( m_visibleRect.x(), m_visibleRect.y(), m_visibleRect.width(), m_visibleRect.height(), (p > NormalPriority) );
- if (markForRepaint)
- m_markedForRepaint = true;
-}
-
-void RenderLayer::updateLayerPositions(RenderLayer* rootLayer, bool doFullRepaint, bool checkForRepaint)
-{
- if (doFullRepaint) {
- m_object->repaint();
- checkForRepaint = doFullRepaint = false;
- }
-
- updateLayerPosition(); // For relpositioned layers or non-positioned layers,
- // we need to keep in sync, since we may have shifted relative
- // to our parent layer.
-
- if (m_hBar || m_vBar) {
- // Need to position the scrollbars.
- int x = 0;
- int y = 0;
- convertToLayerCoords(rootLayer, x, y);
- TQRect layerBounds = TQRect(x,y,width(),height());
- positionScrollbars(layerBounds);
- }
-
-#ifdef APPLE_CHANGES
- // FIXME: Child object could override visibility.
- if (checkForRepaint && (m_object->style()->visibility() == VISIBLE))
- m_object->repaintAfterLayoutIfNeeded(m_repaintRect, m_fullRepaintRect);
-#else
- if (checkForRepaint && m_markedForRepaint) {
- TQRect layerBounds, damageRect, fgrect;
- calculateRects(rootLayer, renderer()->viewRect(), layerBounds, damageRect, fgrect);
- TQRect vr = damageRect.intersect( layerBounds );
- if (vr != m_visibleRect && vr.isValid()) {
- renderer()->canvas()->repaintViewRectangle( vr.x(), vr.y(), vr.width(), vr.height() );
- m_visibleRect = vr;
- }
- }
- m_markedForRepaint = false;
-#endif
-
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositions(rootLayer, doFullRepaint, checkForRepaint);
-
- // With all our children positioned, now update our marquee if we need to.
- if (m_marquee)
- m_marquee->updateMarqueePosition();
-}
-
-void RenderLayer::updateWidgetMasks(RenderLayer* rootLayer)
-{
- if (hasOverlaidWidgets() && !renderer()->canvas()->pagedMode()) {
- updateZOrderLists();
- uint count = m_posZOrderList ? m_posZOrderList->count() : 0;
- bool needUpdate = (count || !m_region.isNull());
- if (count) {
- TQScrollView* sv = m_object->document()->view();
- m_region = TQRect(0,0,sv->contentsWidth(),sv->contentsHeight());
-
- for (uint i = 0; i < count; i++) {
- RenderLayer* child = m_posZOrderList->at(i);
- if (child->zIndex() == 0 && child->renderer()->style()->position() == STATIC)
- continue; // we don't know the widget's exact stacking position within flow
- m_region -= child->paintedRegion(rootLayer);
- }
- } else {
- m_region = TQRegion();
- }
- if (needUpdate)
- renderer()->updateWidgetMasks();
- }
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateWidgetMasks(rootLayer);
-}
-
-short RenderLayer::width() const
-{
- int w = m_object->width();
- if (!m_object->hasOverflowClip())
- w = kMax(m_object->overflowWidth(), w);
- return w;
-}
-
-int RenderLayer::height() const
-{
- int h = m_object->height() + m_object->borderTopExtra() + m_object->borderBottomExtra();
- if (!m_object->hasOverflowClip())
- h = kMax(m_object->overflowHeight(), h);
- return h;
-}
-
-
-RenderLayer *RenderLayer::stackingContext() const
-{
- RenderLayer* curr = parent();
- for ( ; curr && !curr->m_object->isCanvas() &&
- curr->m_object->style()->hasAutoZIndex();
- curr = curr->parent());
- return curr;
-}
-
-RenderLayer* RenderLayer::enclosingPositionedAncestor() const
-{
- RenderLayer* curr = parent();
- for ( ; curr && !curr->m_object->isCanvas() &&
- !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
- curr = curr->parent());
-
- return curr;
-}
-
-#ifdef APPLE_CHANGES
-bool RenderLayer::isTransparent()
-{
- return m_object->style()->opacity() < 1.0f;
-}
-
-RenderLayer* RenderLayer::transparentAncestor()
-{
- RenderLayer* curr = parent();
- for ( ; curr && curr->m_object->style()->opacity() == 1.0f; curr = curr->parent());
- return curr;
-}
-#endif
-
-void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
-{
- return renderArena->allocate(sz);
-}
-
-void RenderLayer::operator delete(void* ptr, size_t sz)
-{
- assert(inRenderLayerDetach);
-
- // Stash size where detach can find it.
- *(size_t *)ptr = sz;
-}
-
-void RenderLayer::detach(RenderArena* renderArena)
-{
-#ifndef NDEBUG
- inRenderLayerDetach = true;
-#endif
- delete this;
-#ifndef NDEBUG
- inRenderLayerDetach = false;
-#endif
-
- // Recover the size left there for us by operator delete and free the memory.
- renderArena->free(*(size_t *)this, this);
-}
-
-void RenderLayer::addChild(RenderLayer *child, RenderLayer* beforeChild)
-{
- RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
- if (prevSibling) {
- child->setPreviousSibling(prevSibling);
- prevSibling->setNextSibling(child);
- }
- else
- setFirstChild(child);
-
- if (beforeChild) {
- beforeChild->setPreviousSibling(child);
- child->setNextSibling(beforeChild);
- }
- else
- setLastChild(child);
-
- child->setParent(this);
-
- if (child->isOverflowOnly())
- dirtyOverflowList();
- else {
- // Dirty the z-order list in which we are contained. The stackingContext() can be null in the
- // case where we're building up generated content layers. This is ok, since the lists will start
- // off dirty in that case anyway.
- RenderLayer* stackingContext = child->stackingContext();
- if (stackingContext)
- stackingContext->dirtyZOrderLists();
- }
-}
-
-RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
-{
- // remove the child
- if (oldChild->previousSibling())
- oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
- if (oldChild->nextSibling())
- oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
-
- if (m_first == oldChild)
- m_first = oldChild->nextSibling();
- if (m_last == oldChild)
- m_last = oldChild->previousSibling();
-
- if (oldChild->isOverflowOnly())
- dirtyOverflowList();
- else {
- // Dirty the z-order list in which we are contained. When called via the
- // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
- // from the main layer tree, so we need to null-check the |stackingContext| value.
- RenderLayer* stackingContext = oldChild->stackingContext();
- if (stackingContext)
- stackingContext->dirtyZOrderLists();
- }
-
- oldChild->setPreviousSibling(0);
- oldChild->setNextSibling(0);
- oldChild->setParent(0);
-
- return oldChild;
-}
-
-void RenderLayer::removeOnlyThisLayer()
-{
- if (!m_parent)
- return;
-
- // Remove us from the parent.
- RenderLayer* parent = m_parent;
- RenderLayer* nextSib = nextSibling();
- parent->removeChild(this);
-
- // Now walk our kids and reattach them to our parent.
- RenderLayer* current = m_first;
- while (current) {
- RenderLayer* next = current->nextSibling();
- removeChild(current);
- parent->addChild(current, nextSib);
- current = next;
- }
-
- detach(renderer()->renderArena());
-}
-
-void RenderLayer::insertOnlyThisLayer()
-{
- if (!m_parent && renderer()->parent()) {
- // We need to connect ourselves when our renderer() has a parent.
- // Find our enclosingLayer and add ourselves.
- RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
- if (parentLayer)
- parentLayer->addChild(this,
- renderer()->parent()->findNextLayer(parentLayer, renderer()));
- }
-
- // Remove all descendant layers from the hierarchy and add them to the new position.
- for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
- curr->moveLayers(m_parent, this);
-}
-
-void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
-{
- if (ancestorLayer == this)
- return;
-
- if (m_object->style()->position() == FIXED) {
- // Add in the offset of the view. We can obtain this by calling
- // absolutePosition() on the RenderCanvas.
- int xOff, yOff;
- m_object->absolutePosition(xOff, yOff, true);
- x += xOff;
- y += yOff;
- return;
- }
-
- RenderLayer* parentLayer;
- if (m_object->style()->position() == ABSOLUTE)
- parentLayer = enclosingPositionedAncestor();
- else
- parentLayer = parent();
-
- if (!parentLayer) return;
-
- parentLayer->convertToLayerCoords(ancestorLayer, x, y);
-
- x += xPos();
- y += yPos();
-}
-
-void RenderLayer::scrollOffset(int& x, int& y)
-{
- x += scrollXOffset();
- y += scrollYOffset();
-}
-
-void RenderLayer::subtractScrollOffset(int& x, int& y)
-{
- x -= scrollXOffset();
- y -= scrollYOffset();
-}
-
-void RenderLayer::checkInlineRelOffset(const RenderObject* o, int& x, int& y)
-{
- if(o->style()->position() != ABSOLUTE || !renderer()->isRelPositioned() || !renderer()->isInlineFlow())
- return;
-
- // Our renderer is an enclosing relpositioned inline, we need to add in the offset of the first line
- // box from the rest of the content, but only in the cases where we know our descendant is positioned
- // relative to the inline itself.
- assert( o->container() == m_object );
-
- RenderFlow* flow = static_cast<RenderFlow*>(m_object);
- int sx = 0, sy = 0;
- if (flow->firstLineBox()) {
- if (flow->style()->direction() == LTR)
- sx = flow->firstLineBox()->xPos();
- else
- sx = flow->lastLineBox()->xPos();
- sy = flow->firstLineBox()->yPos();
- } else {
- sx = flow->staticX(); // ###
- sy = flow->staticY();
- }
- bool isInlineType = o->style()->isOriginalDisplayInlineType();
-
- if (!o->hasStaticX())
- x += sx;
-
- // Despite the positioned child being a block display type inside an inline, we still keep
- // its x locked to our left. Arguably the correct behavior would be to go flush left to
- // the block that contains us, but that isn't what other browsers do.
- if (o->hasStaticX() && !isInlineType)
- // Avoid adding in the left border/padding of the containing block twice. Subtract it out.
- x += sx - (o->containingBlock()->borderLeft() + o->containingBlock()->paddingLeft());
-
- if (!o->hasStaticY())
- y += sy;
-}
-
-void RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
-{
- if (renderer()->style()->overflowX() != OMARQUEE || !renderer()->hasOverflowClip()) {
- if (x < 0) x = 0;
- if (y < 0) y = 0;
-
- // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
- // to be (for overflow:hidden blocks).
- // ### merge the scrollWidth()/scrollHeight() methods
- int maxX = m_scrollWidth - m_object->clientWidth();
- int maxY = m_scrollHeight - m_object->clientHeight();
-
- if (x > maxX) x = maxX;
- if (y > maxY) y = maxY;
- }
-
- // FIXME: Eventually, we will want to perform a blit. For now never
- // blit, since the check for blitting is going to be very
- // complicated (since it will involve testing whether our layer
- // is either occluded by another layer or clipped by an enclosing
- // layer or contains fixed backgrounds, etc.).
- m_scrollX = x;
- m_scrollY = y;
-
- // Update the positions of our child layers.
- RenderLayer* rootLayer = root();
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->updateLayerPositions(rootLayer);
-
- // Fire the scroll DOM event.
- m_object->element()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false);
-
- // Just schedule a full repaint of our object.
- if (repaint)
- m_object->repaint(RealtimePriority);
-
- if (updateScrollbars) {
- if (m_hBar)
- m_hBar->setValue(m_scrollX);
- if (m_vBar)
- m_vBar->setValue(m_scrollY);
- }
-}
-
-void RenderLayer::updateScrollPositionFromScrollbars()
-{
- bool needUpdate = false;
- int newX = m_scrollX;
- int newY = m_scrollY;
-
- if (m_hBar) {
- newX = m_hBar->value();
- if (newX != m_scrollX)
- needUpdate = true;
- }
-
- if (m_vBar) {
- newY = m_vBar->value();
- if (newY != m_scrollY)
- needUpdate = true;
- }
-
- if (needUpdate)
- scrollToOffset(newX, newY, false);
-}
-
-void
-RenderLayer::showScrollbar(Qt::Orientation o, bool show)
-{
- TQScrollBar *sb = (o == Qt::Horizontal) ? m_hBar : m_vBar;
-
- if (show && !sb) {
- TQScrollView* scrollView = m_object->document()->view();
- sb = new TQScrollBar(o, scrollView, "__khtml");
- scrollView->addChild(sb, 0, -50000);
- sb->setBackgroundMode(TQWidget::NoBackground);
- sb->show();
- if (!m_scrollMediator)
- m_scrollMediator = new RenderScrollMediator(this);
- m_scrollMediator->connect(sb, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(slotValueChanged()));
- }
- else if (!show && sb) {
- delete sb;
- sb = 0;
- }
-
- if (o == Qt::Horizontal)
- m_hBar = sb;
- else
- m_vBar = sb;
-}
-
-int RenderLayer::verticalScrollbarWidth()
-{
- if (!m_vBar)
- return 0;
-
-#ifdef APPLE_CHANGES
- return m_vBar->width();
-#else
- return m_vBar->style().pixelMetric(TQStyle::PM_ScrollBarExtent);
-#endif
-
-}
-
-int RenderLayer::horizontalScrollbarHeight()
-{
- if (!m_hBar)
- return 0;
-
-#ifdef APPLE_CHANGES
- return m_hBar->height();
-#else
- return m_hBar->style().pixelMetric(TQStyle::PM_ScrollBarExtent);
-#endif
-
-}
-
-void RenderLayer::positionScrollbars(const TQRect& absBounds)
-{
-#ifdef APPLE_CHANGES
- if (m_vBar) {
- scrollView->addChild(m_vBar, absBounds.x()+absBounds.width()-m_object->borderRight()-m_vBar->width(),
- absBounds.y()+m_object->borderTop());
- m_vBar->resize(m_vBar->width(), absBounds.height() -
- (m_object->borderTop()+m_object->borderBottom()) -
- (m_hBar ? m_hBar->height()-1 : 0));
- }
-
- if (m_hBar) {
- scrollView->addChild(m_hBar, absBounds.x()+m_object->borderLeft(),
- absBounds.y()+absBounds.height()-m_object->borderBottom()-m_hBar->height());
- m_hBar->resize(absBounds.width() - (m_object->borderLeft()+m_object->borderRight()) -
- (m_vBar ? m_vBar->width()-1 : 0), m_hBar->height());
- }
-#else
- int tx = absBounds.x();
- int ty = absBounds.y();
- int bl = m_object->borderLeft();
- int bt = m_object->borderTop();
- int w = width() - bl - m_object->borderRight();
- int h = height() - bt - m_object->borderBottom();
-
- if (w <= 0 || h <= 0 || (!m_vBar && !m_hBar))
- return;
-
- TQScrollView* scrollView = m_object->document()->view();
-
- tx += bl;
- ty += bt;
-
- TQScrollBar *b = m_hBar;
- if (!m_hBar)
- b = m_vBar;
- int sw = b->style().pixelMetric(TQStyle::PM_ScrollBarExtent);
-
- if (m_vBar) {
- TQRect vBarRect = TQRect(tx + w - sw + 1, ty, sw, h - (m_hBar ? sw : 0) + 1);
- m_vBar->resize(vBarRect.width(), vBarRect.height());
- scrollView->addChild(m_vBar, vBarRect.x(), vBarRect.y());
- }
-
- if (m_hBar) {
- TQRect hBarRect = TQRect(tx, ty + h - sw + 1, w - (m_vBar ? sw : 0) + 1, sw);
- m_hBar->resize(hBarRect.width(), hBarRect.height());
- scrollView->addChild(m_hBar, hBarRect.x(), hBarRect.y());
- }
-#endif
-}
-
-#define LINE_STEP 10
-#define PAGE_KEEP 40
-
-void RenderLayer::checkScrollbarsAfterLayout()
-{
- int rightPos = m_object->rightmostPosition(true);
- int bottomPos = m_object->lowestPosition(true);
-
-/* TODO
- m_scrollLeft = m_object->leftmostPosition(true);
- m_scrollTop = m_object->highestPosition(true);
-*/
-
- int clientWidth = m_object->clientWidth();
- int clientHeight = m_object->clientHeight();
- m_scrollWidth = clientWidth;
- m_scrollHeight = clientHeight;
-
- if (rightPos - m_object->borderLeft() > m_scrollWidth)
- m_scrollWidth = rightPos - m_object->borderLeft();
- if (bottomPos - m_object->borderTop() > m_scrollHeight)
- m_scrollHeight = bottomPos - m_object->borderTop();
-
- bool needHorizontalBar = rightPos > width();
- bool needVerticalBar = bottomPos > height();
-
- bool haveHorizontalBar = m_hBar && m_hBar->isEnabled();
- bool haveVerticalBar = m_vBar && m_vBar->isEnabled();
-
- bool hasOvf = m_object->hasOverflowClip();
-
- // overflow:scroll should just enable/disable.
- if (hasOvf && m_object->style()->overflowX() == OSCROLL)
- m_hBar->setEnabled(needHorizontalBar);
- if (hasOvf && m_object->style()->overflowY() == OSCROLL)
- m_vBar->setEnabled(needVerticalBar);
-
- // overflow:auto may need to lay out again if scrollbars got added/removed.
- bool scrollbarsChanged = (hasOvf && m_object->style()->overflowX() == OAUTO && haveHorizontalBar != needHorizontalBar)
- || (hasOvf && m_object->style()->overflowY() == OAUTO && haveVerticalBar != needVerticalBar);
- if (scrollbarsChanged) {
- if (m_object->style()->overflowX() == OAUTO) {
- showScrollbar(Qt::Horizontal, needHorizontalBar);
- if (m_hBar)
- m_hBar->setEnabled(true);
- }
- if (m_object->style()->overflowY() == OAUTO) {
- showScrollbar(Qt::Vertical, needVerticalBar);
- if (m_vBar)
- m_vBar->setEnabled(true);
- }
-
- m_object->setNeedsLayout(true);
- if (m_object->isRenderBlock())
- static_cast<RenderBlock*>(m_object)->layoutBlock(true);
- else
- m_object->layout();
- return;
- }
-
- // Set up the range (and page step/line step).
- if (m_hBar) {
- int pageStep = (clientWidth-PAGE_KEEP);
- if (pageStep < 0) pageStep = clientWidth;
- m_hBar->setSteps(LINE_STEP, pageStep);
-#ifdef APPLE_CHANGES
- m_hBar->setKnobProportion(clientWidth, m_scrollWidth);
-#else
- m_hBar->setRange(0, needHorizontalBar ? m_scrollWidth-clientWidth : 0);
-#endif
- }
- if (m_vBar) {
- int pageStep = (clientHeight-PAGE_KEEP);
- if (pageStep < 0) pageStep = clientHeight;
- m_vBar->setSteps(LINE_STEP, pageStep);
-#ifdef APPLE_CHANGES
- m_vBar->setKnobProportion(clientHeight, m_scrollHeight);
-#else
- m_vBar->setRange(0, needVerticalBar ? m_scrollHeight-clientHeight : 0);
-#endif
- }
-}
-
-void RenderLayer::paintScrollbars(RenderObject::PaintInfo& pI)
-{
-#ifdef APPLE_CHANGES
- if (m_hBar)
- m_hBar->paint(p, damageRect);
- if (m_vBar)
- m_vBar->paint(p, damageRect);
-#else
- if (!m_object->element())
- return;
-
- TQScrollView* scrollView = m_object->document()->view();
- if (m_hBar) {
- int x = m_hBar->x();
- int y = m_hBar->y();
- scrollView->viewportToContents(x, y, x, y);
- RenderWidget::paintWidget(pI, m_hBar, x, y);
- }
- if (m_vBar) {
- int x = m_vBar->x();
- int y = m_vBar->y();
- scrollView->viewportToContents(x, y, x, y);
- RenderWidget::paintWidget(pI, m_vBar, x, y);
- }
-#endif
-}
-
-void RenderLayer::paint(TQPainter *p, const TQRect& damageRect, bool selectionOnly)
-{
- paintLayer(this, p, damageRect, selectionOnly);
-}
-
-static void setClip(TQPainter* p, const TQRect& paintDirtyRect, const TQRect& clipRect)
-{
- if (paintDirtyRect == clipRect)
- return;
- p->save();
-
-#ifdef APPLE_CHANGES
- p->addClip(clipRect);
-#else
-
- TQRect clippedRect = p->xForm(clipRect);
- TQRegion creg(clippedRect);
- TQRegion old = p->clipRegion();
- if (!old.isNull())
- creg = old.intersect(creg);
- p->setClipRegion(creg);
-#endif
-
-}
-
-static void restoreClip(TQPainter* p, const TQRect& paintDirtyRect, const TQRect& clipRect)
-{
- if (paintDirtyRect == clipRect)
- return;
- p->restore();
-}
-
-void RenderLayer::paintLayer(RenderLayer* rootLayer, TQPainter *p,
- const TQRect& paintDirtyRect, bool selectionOnly)
-{
- // Calculate the clip rects we should use.
- TQRect layerBounds, damageRect, clipRectToApply;
- calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
- int x = layerBounds.x();
- int y = layerBounds.y();
-
- // Ensure our lists are up-to-date.
- updateZOrderLists();
- updateOverflowList();
-
-#ifdef APPLE_CHANGES
- // Set our transparency if we need to.
- if (isTransparent())
- p->beginTransparencyLayer(renderer()->style()->opacity());
-#endif
-
- // We want to paint our layer, but only if we intersect the damage rect.
- bool shouldPaint = intersectsDamageRect(layerBounds, damageRect);
- if (shouldPaint && !selectionOnly) {
- // Paint our background first, before painting any child layers.
- if (!damageRect.isEmpty()) {
- // Establish the clip used to paint our background.
- setClip(p, paintDirtyRect, damageRect);
-
- // Paint the background.
- RenderObject::PaintInfo paintInfo(p, damageRect, PaintActionElementBackground);
- renderer()->paint(paintInfo,
- x - renderer()->xPos(), y - renderer()->yPos() + renderer()->borderTopExtra());
-
- // Position our scrollbars.
- positionScrollbars(layerBounds);
-
- // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
- // z-index. We paint after we painted the background/border, so that the scrollbars will
- // sit above the background/border.
- paintScrollbars(paintInfo);
-
- // Restore the clip.
- restoreClip(p, paintDirtyRect, damageRect);
- }
- }
-
- // Now walk the sorted list of children with negative z-indices.
- if (m_negZOrderList) {
- uint count = m_negZOrderList->count();
- for (uint i = 0; i < count; i++) {
- RenderLayer* child = m_negZOrderList->at(i);
- child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
- }
- }
-
- // Now establish the appropriate clip and paint our child RenderObjects.
- if (shouldPaint && !clipRectToApply.isEmpty()) {
- // Set up the clip used when painting our children.
- setClip(p, paintDirtyRect, clipRectToApply);
-
- RenderObject::PaintInfo paintInfo(p, clipRectToApply, PaintActionSelection);
-
- int tx = x - renderer()->xPos();
- int ty = y - renderer()->yPos() + renderer()->borderTopExtra();
-
- if (selectionOnly)
- renderer()->paint(paintInfo, tx, ty);
- else {
- paintInfo.phase = PaintActionChildBackgrounds;
- renderer()->paint(paintInfo, tx, ty);
- paintInfo.phase = PaintActionFloat;
- renderer()->paint(paintInfo, tx, ty);
- paintInfo.phase = PaintActionForeground;
- renderer()->paint(paintInfo, tx, ty);
- RenderCanvas *rc = static_cast<RenderCanvas*>(renderer()->document()->renderer());
- if (rc->maximalOutlineSize()) {
- paintInfo.phase = PaintActionOutline;
- renderer()->paint(paintInfo, tx, ty);
- }
- if (rc->selectionStart() && rc->selectionEnd()) {
- paintInfo.phase = PaintActionSelection;
- renderer()->paint(paintInfo, tx, ty);
- }
- }
-
- // Now restore our clip.
- restoreClip(p, paintDirtyRect, clipRectToApply);
- }
-
- // Paint any child layers that have overflow.
- if (m_overflowList)
- for (TQValueList<RenderLayer*>::iterator it = m_overflowList->begin(); it != m_overflowList->end(); ++it)
- (*it)->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
-
- // Now walk the sorted list of children with positive z-indices.
- if (m_posZOrderList) {
- uint count = m_posZOrderList->count();
- for (uint i = 0; i < count; i++) {
- RenderLayer* child = m_posZOrderList->at(i);
- child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
- }
- }
-
-#ifdef BOX_DEBUG
- {
- int ax=0;
- int ay=0;
- renderer()->absolutePosition( ax, ay );
- p->setPen(TQPen(TQColor("yellow"), 1, Qt::DotLine));
- p->setBrush( Qt::NoBrush );
- p->drawRect(ax, ay, width(), height());
- }
-#endif
-
-#ifdef APPLE_CHANGES
- // End our transparency layer
- if (isTransparent())
- p->endTransparencyLayer();
-#endif
-}
-
-bool RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
-{
-#ifdef APPLE_CHANGES
- // Clear our our scrollbar variable
- RenderLayer::gScrollBar = 0;
-#endif
-
- int stx = m_x;
- int sty = m_y;
-
-#ifdef __GNUC__
-#warning HACK
-#endif
- if (renderer()->isCanvas()) {
- stx += static_cast<RenderCanvas*>(renderer())->view()->contentsX();
- sty += static_cast<RenderCanvas*>(renderer())->view()->contentsY();
- }
-
- TQRect damageRect(stx,sty, width(), height());
- RenderLayer* insideLayer = nodeAtPointForLayer(this, info, x, y, damageRect);
-
- // Now determine if the result is inside an anchor.
- DOM::NodeImpl* node = info.innerNode();
- while (node) {
- if (node->hasAnchor() && !info.URLElement())
- info.setURLElement(node);
- node = node->parentNode();
- }
-
- // Next set up the correct :hover/:active state along the new chain.
- updateHoverActiveState(info);
-
- // Now return whether we were inside this layer (this will always be true for the root
- // layer).
- return insideLayer;
-}
-
-RenderLayer* RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
- int xMousePos, int yMousePos, const TQRect& hitTestRect)
-{
- // Calculate the clip rects we should use.
- TQRect layerBounds, bgRect, fgRect;
- calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect);
-
- // Ensure our lists are up-to-date.
- updateZOrderLists();
- updateOverflowList();
-
- // This variable tracks which layer the mouse ends up being inside. The minute we find an insideLayer,
- // we are done and can return it.
- RenderLayer* insideLayer = 0;
-
- // Begin by walking our list of positive layers from highest z-index down to the lowest
- // z-index.
- if (m_posZOrderList) {
- uint count = m_posZOrderList->count();
- for (int i = count-1; i >= 0; i--) {
- RenderLayer* child = m_posZOrderList->at(i);
- insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
- if (insideLayer)
- return insideLayer;
- }
- }
-
- // Now check our overflow objects.
- if (m_overflowList) {
- TQValueList<RenderLayer*>::iterator it = m_overflowList->end();
- for (--it; it != m_overflowList->end(); --it) {
- insideLayer = (*it)->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
- if (insideLayer)
- return insideLayer;
- }
- }
-
- // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
- if (containsPoint(xMousePos, yMousePos, fgRect) &&
- renderer()->nodeAtPoint(info, xMousePos, yMousePos,
- layerBounds.x() - renderer()->xPos(),
- layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
- HitTestChildrenOnly)) {
- if (info.innerNode() != m_object->element())
- return this;
- }
-
- // Now check our negative z-index children.
- if (m_negZOrderList) {
- uint count = m_negZOrderList->count();
- for (int i = count-1; i >= 0; i--) {
- RenderLayer* child = m_negZOrderList->at(i);
- insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
- if (insideLayer)
- return insideLayer;
- }
- }
-
- // Next we want to see if the mouse pos is inside this layer but not any of its children.
- if (containsPoint(xMousePos, yMousePos, bgRect) &&
- renderer()->nodeAtPoint(info, xMousePos, yMousePos,
- layerBounds.x() - renderer()->xPos(),
- layerBounds.y() - renderer()->yPos() + m_object->borderTopExtra(),
- HitTestSelfOnly))
- return this;
-
- // No luck.
- return 0;
-}
-
-void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, TQRect& overflowClipRect,
- TQRect& posClipRect, TQRect& fixedClipRect)
-{
- if (parent())
- parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);
-
- switch (m_object->style()->position()) {
- // A fixed object is essentially the root of its containing block hierarchy, so when
- // we encounter such an object, we reset our clip rects to the fixedClipRect.
- case FIXED:
- posClipRect = fixedClipRect;
- overflowClipRect = fixedClipRect;
- break;
- case ABSOLUTE:
- overflowClipRect = posClipRect;
- break;
- case RELATIVE:
- posClipRect = overflowClipRect;
- break;
- default:
- break;
- }
-
- // Update the clip rects that will be passed to child layers.
- if (m_object->hasOverflowClip() || m_object->hasClip()) {
- // This layer establishes a clip of some kind.
- int x = 0;
- int y = 0;
- convertToLayerCoords(rootLayer, x, y);
-
- if (m_object->hasOverflowClip()) {
- TQRect newOverflowClip = m_object->getOverflowClipRect(x,y);
- overflowClipRect = newOverflowClip.intersect(overflowClipRect);
- if (m_object->isPositioned() || m_object->isRelPositioned())
- posClipRect = newOverflowClip.intersect(posClipRect);
- }
- if (m_object->hasClip()) {
- TQRect newPosClip = m_object->getClipRect(x,y);
- posClipRect = posClipRect.intersect(newPosClip);
- overflowClipRect = overflowClipRect.intersect(newPosClip);
- fixedClipRect = fixedClipRect.intersect(newPosClip);
- }
- }
-}
-
-void RenderLayer::calculateRects(const RenderLayer* rootLayer, const TQRect& paintDirtyRect, TQRect& layerBounds,
- TQRect& backgroundRect, TQRect& foregroundRect)
-{
- TQRect overflowClipRect = paintDirtyRect;
- TQRect posClipRect = paintDirtyRect;
- TQRect fixedClipRect = paintDirtyRect;
- if (parent())
- parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);
-
- int x = 0;
- int y = 0;
- convertToLayerCoords(rootLayer, x, y);
- layerBounds = TQRect(x,y,width(),height());
-
- backgroundRect = m_object->style()->position() == FIXED ? fixedClipRect :
- (m_object->isPositioned() ? posClipRect : overflowClipRect);
- foregroundRect = backgroundRect;
-
- // Update the clip rects that will be passed to child layers.
- if (m_object->hasOverflowClip() || m_object->hasClip()) {
- // This layer establishes a clip of some kind.
- if (m_object->hasOverflowClip())
- foregroundRect = foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
-
- if (m_object->hasClip()) {
- // Clip applies to *us* as well, so go ahead and update the damageRect.
- TQRect newPosClip = m_object->getClipRect(x,y);
- backgroundRect = backgroundRect.intersect(newPosClip);
- foregroundRect = foregroundRect.intersect(newPosClip);
- }
-
- // If we establish a clip at all, then go ahead and make sure our background
- // rect is intersected with our layer's bounds.
- backgroundRect = backgroundRect.intersect(layerBounds);
- }
-}
-
-bool RenderLayer::intersectsDamageRect(const TQRect& layerBounds, const TQRect& damageRect) const
-{
- return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
- (renderer()->hasOverhangingFloats() && !renderer()->hasOverflowClip()) ||
- (renderer()->isInline() && !renderer()->isReplaced()) ||
- layerBounds.intersects(damageRect));
-}
-
-bool RenderLayer::containsPoint(int x, int y, const TQRect& damageRect) const
-{
- return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
- renderer()->hasOverhangingFloats() ||
- (renderer()->isInline() && !renderer()->isReplaced()) ||
- damageRect.contains(x, y));
-}
-
-// This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
-// content (and perhaps XBL). That's why it uses the render tree and not the DOM tree.
-static RenderObject* hoverAncestor(RenderObject* obj)
-{
- return (!obj->isInline() && obj->continuation()) ? obj->continuation() : obj->parent();
-}
-
-static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
-{
- if (!obj1 || !obj2)
- return 0;
-
- for (RenderObject* currObj1 = obj1; currObj1; currObj1 = hoverAncestor(currObj1))
- for (RenderObject* currObj2 = obj2; currObj2; currObj2 = hoverAncestor(currObj2))
- if (currObj1 == currObj2)
- return currObj1;
-
- return 0;
-}
-
-
-void RenderLayer::updateHoverActiveState(RenderObject::NodeInfo& info)
-{
- // We don't update :hover/:active state when the info is marked as readonly.
- if (info.readonly())
- return;
-
- DOM::NodeImpl *e = m_object->element();
- DOM::DocumentImpl *doc = e ? e->getDocument() : 0;
- if (!doc) return;
-
- // Check to see if the hovered node has changed. If not, then we don't need to
- // do anything.
- DOM::NodeImpl* oldHoverNode = doc->hoverNode();
- DOM::NodeImpl* newHoverNode = info.innerNode();
-
- if (oldHoverNode == newHoverNode && (!oldHoverNode || oldHoverNode->active() == info.active()))
- return;
-
- // Update our current hover node.
- doc->setHoverNode(newHoverNode);
- if (info.active())
- doc->setActiveNode(newHoverNode);
- else
- doc->setActiveNode(0);
-
- // We have two different objects. Fetch their renderers.
- RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
- RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0;
-
- // Locate the common ancestor render object for the two renderers.
- RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
-
- // The old hover path only needs to be cleared up to (and not including) the common ancestor;
- for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = hoverAncestor(curr)) {
- curr->setMouseInside(false);
- if (curr->element()) {
- curr->element()->setActive(false);
- curr->element()->setHovered(false);
- }
- }
-
- // Now set the hover state for our new object up to the root.
- for (RenderObject* curr = newHoverObj; curr; curr = hoverAncestor(curr)) {
- curr->setMouseInside(true);
- if (curr->element()) {
- curr->element()->setActive(info.active());
- curr->element()->setHovered(true);
- }
- }
-}
-
-// Sort the buffer from lowest z-index to highest. The common scenario will have
-// most z-indices equal, so we optimize for that case (i.e., the list will be mostly
-// sorted already).
-static void sortByZOrder(TQPtrVector<RenderLayer>* buffer,
- TQPtrVector<RenderLayer>* mergeBuffer,
- uint start, uint end)
-{
- if (start >= end)
- return; // Sanity check.
-
- if (end - start <= 6) {
- // Apply a bubble sort for smaller lists.
- for (uint i = end-1; i > start; i--) {
- bool sorted = true;
- for (uint j = start; j < i; j++) {
- RenderLayer* elt = buffer->at(j);
- RenderLayer* elt2 = buffer->at(j+1);
- if (elt->zIndex() > elt2->zIndex()) {
- sorted = false;
- buffer->insert(j, elt2);
- buffer->insert(j+1, elt);
- }
- }
- if (sorted)
- return;
- }
- }
- else {
- // Peform a merge sort for larger lists.
- uint mid = (start+end)/2;
- sortByZOrder(buffer, mergeBuffer, start, mid);
- sortByZOrder(buffer, mergeBuffer, mid, end);
-
- RenderLayer* elt = buffer->at(mid-1);
- RenderLayer* elt2 = buffer->at(mid);
-
- // Handle the fast common case (of equal z-indices). The list may already
- // be completely sorted.
- if (elt->zIndex() <= elt2->zIndex())
- return;
-
- // We have to merge sort. Ensure our merge buffer is big enough to hold
- // all the items.
- mergeBuffer->resize(end - start);
- uint i1 = start;
- uint i2 = mid;
-
- elt = buffer->at(i1);
- elt2 = buffer->at(i2);
-
- while (i1 < mid || i2 < end) {
- if (i1 < mid && (i2 == end || elt->zIndex() <= elt2->zIndex())) {
- mergeBuffer->insert(mergeBuffer->count(), elt);
- i1++;
- if (i1 < mid)
- elt = buffer->at(i1);
- }
- else {
- mergeBuffer->insert(mergeBuffer->count(), elt2);
- i2++;
- if (i2 < end)
- elt2 = buffer->at(i2);
- }
- }
-
- for (uint i = start; i < end; i++)
- buffer->insert(i, mergeBuffer->at(i-start));
-
- mergeBuffer->clear();
- }
-}
-
-void RenderLayer::dirtyZOrderLists()
-{
- if (m_posZOrderList)
- m_posZOrderList->clear();
- if (m_negZOrderList)
- m_negZOrderList->clear();
- m_zOrderListsDirty = true;
-}
-
-void RenderLayer::dirtyOverflowList()
-{
- if (m_overflowList)
- m_overflowList->clear();
- m_overflowListDirty = true;
-}
-
-void RenderLayer::updateZOrderLists()
-{
- if (!isStackingContext() || !m_zOrderListsDirty)
- return;
-
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->collectLayers(m_posZOrderList, m_negZOrderList);
-
- // Sort the two lists.
- if (m_posZOrderList) {
- TQPtrVector<RenderLayer> mergeBuffer;
- sortByZOrder(m_posZOrderList, &mergeBuffer, 0, m_posZOrderList->count());
- }
- if (m_negZOrderList) {
- TQPtrVector<RenderLayer> mergeBuffer;
- sortByZOrder(m_negZOrderList, &mergeBuffer, 0, m_negZOrderList->count());
- }
-
- m_zOrderListsDirty = false;
-}
-
-void RenderLayer::updateOverflowList()
-{
- if (!m_overflowListDirty)
- return;
-
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isOverflowOnly()) {
- if (!m_overflowList)
- m_overflowList = new TQValueList<RenderLayer*>;
- m_overflowList->append(child);
- }
- }
-
- m_overflowListDirty = false;
-}
-
-void RenderLayer::collectLayers(TQPtrVector<RenderLayer>*& posBuffer, TQPtrVector<RenderLayer>*& negBuffer)
-{
- // FIXME: A child render object or layer could override visibility. Don't remove this
- // optimization though until RenderObject's nodeAtPoint is patched to understand what to do
- // when visibility is overridden by a child.
- if (renderer()->style()->visibility() != VISIBLE)
- return;
-
- // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
- if (!isOverflowOnly()) {
-
- // Determine which buffer the child should be in.
- TQPtrVector<RenderLayer>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
-
- // Create the buffer if it doesn't exist yet.
- if (!buffer)
- buffer = new TQPtrVector<RenderLayer>();
-
- // Resize by a power of 2 when our buffer fills up.
- if (buffer->count() == buffer->size())
- buffer->resize(2*(buffer->size()+1));
-
- // Append ourselves at the end of the appropriate buffer.
- buffer->insert(buffer->count(), this);
- }
-
- // Recur into our children to collect more layers, but only if we don't establish
- // a stacking context.
- if (!isStackingContext()) {
- for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
- child->collectLayers(posBuffer, negBuffer);
- }
-}
-
-#ifdef ENABLE_DUMP
-#ifndef KDE_USE_FINAL
-static TQTextStream &operator<<(TQTextStream &ts, const TQRect &r)
-{
- return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
-}
-#endif
-
-static void write(TQTextStream &ts, RenderObject& o, const TQString& indent )
-{
- o.dump(ts, indent);
-
- for (RenderObject *child = o.firstChild(); child; child = child->nextSibling()) {
- if (child->layer()) continue;
- write( ts, *child, indent + " " );
- }
-}
-
-static void write(TQTextStream &ts, const RenderLayer &l,
- const TQRect& layerBounds, const TQRect& backgroundClipRect, const TQRect& clipRect,
- int layerType = 0, const TQString& indent = TQString::null)
-
-{
- ts << indent << "layer";
-
- ts << " at (" << l.xPos() << "," << l.yPos() << ") size " << l.width() << "x" << l.height();
-
- if (layerBounds != layerBounds.intersect(backgroundClipRect)) {
- ts << " backgroundClip " << backgroundClipRect;
- }
- if (layerBounds != layerBounds.intersect(clipRect)) {
- ts << " clip " << clipRect;
- }
-
- if (layerType == -1)
- ts << " layerType: background only";
- else if (layerType == 1)
- ts << " layerType: foreground only";
-
- ts << "\n";
-
- if (layerType != -1)
- write( ts, *l.renderer(), indent + " " );
-
- ts << "\n";
-}
-
-static void writeLayers(TQTextStream &ts, const RenderLayer* rootLayer, RenderLayer* l,
- const TQRect& paintDirtyRect, const TQString& indent)
-{
- // Calculate the clip rects we should use.
- TQRect layerBounds, damageRect, clipRectToApply;
- l->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
-
- // Ensure our lists are up-to-date.
- l->updateZOrderLists();
- l->updateOverflowList();
-
- bool shouldPaint = l->intersectsDamageRect(layerBounds, damageRect);
- TQPtrVector<RenderLayer>* negList = l->negZOrderList();
- TQValueList<RenderLayer*>* ovfList = l->overflowList();
- if (shouldPaint && negList && negList->count() > 0)
- write(ts, *l, layerBounds, damageRect, clipRectToApply, -1, indent);
-
- if (negList) {
- for (unsigned i = 0; i != negList->count(); ++i)
- writeLayers(ts, rootLayer, negList->at(i), paintDirtyRect, indent );
- }
-
- if (shouldPaint)
- write(ts, *l, layerBounds, damageRect, clipRectToApply, negList && negList->count() > 0, indent);
-
- if (ovfList) {
- for (TQValueList<RenderLayer*>::iterator it = ovfList->begin(); it != ovfList->end(); ++it)
- writeLayers(ts, rootLayer, *it, paintDirtyRect, indent);
- }
-
- TQPtrVector<RenderLayer>* posList = l->posZOrderList();
- if (posList) {
- for (unsigned i = 0; i != posList->count(); ++i)
- writeLayers(ts, rootLayer, posList->at(i), paintDirtyRect, indent);
- }
-}
-
-
-void RenderLayer::dump(TQTextStream &ts, const TQString &ind)
-{
- assert( renderer()->isCanvas() );
-
- writeLayers(ts, this, this, TQRect(xPos(), yPos(), width(), height()), ind);
-}
-
-
-#endif
-
-bool RenderLayer::shouldBeOverflowOnly() const
-{
- return renderer()->style() && renderer()->hasOverflowClip() &&
- !renderer()->isPositioned() && !renderer()->isRelPositioned();
- /* && !isTransparent(); */
-}
-
-void RenderLayer::styleChanged()
-{
- bool isOverflowOnly = shouldBeOverflowOnly();
- if (isOverflowOnly != m_isOverflowOnly) {
- m_isOverflowOnly = isOverflowOnly;
- RenderLayer* p = parent();
- RenderLayer* sc = stackingContext();
- if (p)
- p->dirtyOverflowList();
- if (sc)
- sc->dirtyZOrderLists();
- }
-
- if (m_object->hasOverflowClip() &&
- m_object->style()->overflowX() == OMARQUEE && m_object->style()->marqueeBehavior() != MNONE) {
- if (!m_marquee)
- m_marquee = new Marquee(this);
- m_marquee->updateMarqueeStyle();
- }
- else if (m_marquee) {
- delete m_marquee;
- m_marquee = 0;
- }
-}
-
-void RenderLayer::suspendMarquees()
-{
- if (m_marquee)
- m_marquee->suspend();
-
- for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
- curr->suspendMarquees();
-}
-
-// --------------------------------------------------------------------------
-// Marquee implementation
-
-Marquee::Marquee(RenderLayer* l)
-:m_layer(l), m_currentLoop(0), m_totalLoops(0), m_timerId(0), m_start(0), m_end(0), m_speed(0), m_unfurlPos(0), m_reset(false),
- m_suspended(false), m_stopped(false), m_whiteSpace(NORMAL), m_direction(MAUTO)
-{
-}
-
-int Marquee::marqueeSpeed() const
-{
- int result = m_layer->renderer()->style()->marqueeSpeed();
- DOM::NodeImpl* elt = m_layer->renderer()->element();
- if (elt && elt->id() == ID_MARQUEE) {
- HTMLMarqueeElementImpl* marqueeElt = static_cast<HTMLMarqueeElementImpl*>(elt);
- result = kMax(result, marqueeElt->minimumDelay());
- }
- return result;
-}
-
-EMarqueeDirection Marquee::direction() const
-{
- // FIXME: Support the CSS3 "auto" value for determining the direction of the marquee.
- // For now just map MAUTO to MBACKWARD
- EMarqueeDirection result = m_layer->renderer()->style()->marqueeDirection();
- EDirection dir = m_layer->renderer()->style()->direction();
- if (result == MAUTO)
- result = MBACKWARD;
- if (result == MFORWARD)
- result = (dir == LTR) ? MRIGHT : MLEFT;
- if (result == MBACKWARD)
- result = (dir == LTR) ? MLEFT : MRIGHT;
-
- // Now we have the real direction. Next we check to see if the increment is negative.
- // If so, then we reverse the direction.
- Length increment = m_layer->renderer()->style()->marqueeIncrement();
- if (increment.value() < 0)
- result = static_cast<EMarqueeDirection>(-result);
-
- return result;
-}
-
-bool Marquee::isHorizontal() const
-{
- return direction() == MLEFT || direction() == MRIGHT;
-}
-
-bool Marquee::isUnfurlMarquee() const
-{
- EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
- return (behavior == MUNFURL);
-}
-
-int Marquee::computePosition(EMarqueeDirection dir, bool stopAtContentEdge)
-{
- RenderObject* o = m_layer->renderer();
- RenderStyle* s = o->style();
- if (isHorizontal()) {
- bool ltr = s->direction() == LTR;
- int clientWidth = o->clientWidth();
- int contentWidth = ltr ? o->rightmostPosition(true, false) : o->leftmostPosition(true, false);
- if (ltr)
- contentWidth += (o->paddingRight() - o->borderLeft());
- else {
- contentWidth = o->width() - contentWidth;
- contentWidth += (o->paddingLeft() - o->borderRight());
- }
- if (dir == MRIGHT) {
- if (stopAtContentEdge)
- return kMax(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
- else
- return ltr ? contentWidth : clientWidth;
- }
- else {
- if (stopAtContentEdge)
- return kMin(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
- else
- return ltr ? -clientWidth : -contentWidth;
- }
- }
- else {
- int contentHeight = m_layer->renderer()->lowestPosition(true, false) -
- m_layer->renderer()->borderTop() + m_layer->renderer()->paddingBottom();
- int clientHeight = m_layer->renderer()->clientHeight();
- if (dir == MUP) {
- if (stopAtContentEdge)
- return kMin(contentHeight - clientHeight, 0);
- else
- return -clientHeight;
- }
- else {
- if (stopAtContentEdge)
- return kMax(contentHeight - clientHeight, 0);
- else
- return contentHeight;
- }
- }
-}
-
-void Marquee::start()
-{
- if (m_timerId || m_layer->renderer()->style()->marqueeIncrement().value() == 0)
- return;
-
- if (!m_suspended && !m_stopped) {
- if (isUnfurlMarquee()) {
- bool forward = direction() == MDOWN || direction() == MRIGHT;
- bool isReversed = (forward && m_currentLoop % 2) || (!forward && !(m_currentLoop % 2));
- m_unfurlPos = isReversed ? m_end : m_start;
- m_layer->renderer()->setChildNeedsLayout(true);
- }
- else {
- if (isHorizontal())
- m_layer->scrollToOffset(m_start, 0, false, false);
- else
- m_layer->scrollToOffset(0, m_start, false, false);
- }
- }
- else
- m_suspended = false;
-
- m_stopped = false;
- m_timerId = startTimer(speed());
-}
-
-void Marquee::suspend()
-{
- if (m_timerId) {
- killTimer(m_timerId);
- m_timerId = 0;
- }
-
- m_suspended = true;
-}
-
-void Marquee::stop()
-{
- if (m_timerId) {
- killTimer(m_timerId);
- m_timerId = 0;
- }
-
- m_stopped = true;
-}
-
-void Marquee::updateMarqueePosition()
-{
- bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
- if (activate) {
- if (isUnfurlMarquee()) {
- if (m_unfurlPos < m_start) {
- m_unfurlPos = m_start;
- m_layer->renderer()->setChildNeedsLayout(true);
- }
- else if (m_unfurlPos > m_end) {
- m_unfurlPos = m_end;
- m_layer->renderer()->setChildNeedsLayout(true);
- }
- }
- else {
- EMarqueeBehavior behavior = m_layer->renderer()->style()->marqueeBehavior();
- m_start = computePosition(direction(), behavior == MALTERNATE);
- m_end = computePosition(reverseDirection(), behavior == MALTERNATE || behavior == MSLIDE);
- }
- if (!m_stopped) start();
- }
-}
-
-void Marquee::updateMarqueeStyle()
-{
- RenderStyle* s = m_layer->renderer()->style();
-
- if (m_direction != s->marqueeDirection() || (m_totalLoops != s->marqueeLoopCount() && m_currentLoop >= m_totalLoops))
- m_currentLoop = 0; // When direction changes or our loopCount is a smaller number than our current loop, reset our loop.
-
- m_totalLoops = s->marqueeLoopCount();
- m_direction = s->marqueeDirection();
- m_whiteSpace = s->whiteSpace();
-
- if (m_layer->renderer()->isHTMLMarquee()) {
- // Hack for WinIE. In WinIE, a value of 0 or lower for the loop count for SLIDE means to only do
- // one loop.
- if (m_totalLoops <= 0 && (s->marqueeBehavior() == MSLIDE || s->marqueeBehavior() == MUNFURL))
- m_totalLoops = 1;
-
- // Hack alert: Set the white-space value to nowrap for horizontal marquees with inline children, thus ensuring
- // all the text ends up on one line by default. Limit this hack to the <marquee> element to emulate
- // WinIE's behavior. Someone using CSS3 can use white-space: nowrap on their own to get this effect.
- // Second hack alert: Set the text-align back to auto. WinIE completely ignores text-align on the
- // marquee element.
- // FIXME: Bring these up with the CSS WG.
- if (isHorizontal() && m_layer->renderer()->childrenInline()) {
- s->setWhiteSpace(NOWRAP);
- s->setTextAlign(TAAUTO);
- }
- }
-
- if (speed() != marqueeSpeed()) {
- m_speed = marqueeSpeed();
- if (m_timerId) {
- killTimer(m_timerId);
- m_timerId = startTimer(speed());
- }
- }
-
- // Check the loop count to see if we should now stop.
- bool activate = (m_totalLoops <= 0 || m_currentLoop < m_totalLoops);
- if (activate && !m_timerId)
- m_layer->renderer()->setNeedsLayout(true);
- else if (!activate && m_timerId) {
- // Destroy the timer.
- killTimer(m_timerId);
- m_timerId = 0;
- }
-}
-
-void Marquee::timerEvent(TQTimerEvent* /*evt*/)
-{
- if (m_layer->renderer()->needsLayout())
- return;
-
- if (m_reset) {
- m_reset = false;
- if (isHorizontal())
- m_layer->scrollToXOffset(m_start);
- else
- m_layer->scrollToYOffset(m_start);
- return;
- }
-
- RenderStyle* s = m_layer->renderer()->style();
-
- int endPoint = m_end;
- int range = m_end - m_start;
- int newPos;
- if (range == 0)
- newPos = m_end;
- else {
- bool addIncrement = direction() == MUP || direction() == MLEFT;
- bool isReversed = s->marqueeBehavior() == MALTERNATE && m_currentLoop % 2;
- if (isUnfurlMarquee()) {
- isReversed = (!addIncrement && m_currentLoop % 2) || (addIncrement && !(m_currentLoop % 2));
- addIncrement = !isReversed;
- }
- if (isReversed) {
- // We're going in the reverse direction.
- endPoint = m_start;
- range = -range;
- if (!isUnfurlMarquee())
- addIncrement = !addIncrement;
- }
- bool positive = range > 0;
- int clientSize = isUnfurlMarquee() ? abs(range) :
- (isHorizontal() ? m_layer->renderer()->clientWidth() : m_layer->renderer()->clientHeight());
- int increment = kMax(1, abs(m_layer->renderer()->style()->marqueeIncrement().width(clientSize)));
- int currentPos = isUnfurlMarquee() ? m_unfurlPos :
- (isHorizontal() ? m_layer->scrollXOffset() : m_layer->scrollYOffset());
- newPos = currentPos + (addIncrement ? increment : -increment);
- if (positive)
- newPos = kMin(newPos, endPoint);
- else
- newPos = kMax(newPos, endPoint);
- }
-
- if (newPos == endPoint) {
- m_currentLoop++;
- if (m_totalLoops > 0 && m_currentLoop >= m_totalLoops) {
- killTimer(m_timerId);
- m_timerId = 0;
- }
- else if (s->marqueeBehavior() != MALTERNATE && s->marqueeBehavior() != MUNFURL)
- m_reset = true;
- }
-
- if (isUnfurlMarquee()) {
- m_unfurlPos = newPos;
- m_layer->renderer()->setChildNeedsLayout(true);
- }
- else {
- if (isHorizontal())
- m_layer->scrollToXOffset(newPos);
- else
- m_layer->scrollToYOffset(newPos);
- }
-}
-
-#include "render_layer.moc"
diff --git a/khtml/rendering/render_layer.h b/khtml/rendering/render_layer.h
deleted file mode 100644
index a8f1e5adc..000000000
--- a/khtml/rendering/render_layer.h
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- * Copyright (C) 2003 Apple Computer, Inc.
- *
- * Portions are Copyright (C) 1998 Netscape Communications Corporation.
- *
- * Other contributors:
- * Robert O'Callahan <roc+@cs.cmu.edu>
- * David Baron <dbaron@fas.harvard.edu>
- * Christian Biesinger <cbiesinger@web.de>
- * Randall Jesup <rjesup@wgate.com>
- * Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
- * Josh Soref <timeless@mac.com>
- * Boris Zbarsky <bzbarsky@mit.edu>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Alternatively, the contents of this file may be used under the terms
- * of either the Mozilla Public License Version 1.1, found at
- * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
- * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
- * (the "GPL"), in which case the provisions of the MPL or the GPL are
- * applicable instead of those above. If you wish to allow use of your
- * version of this file only under the terms of one of those two
- * licenses (the MPL or the GPL) and not to allow others to use your
- * version of this file under the LGPL, indicate your decision by
- * deletingthe provisions above and replace them with the notice and
- * other provisions required by the MPL or the GPL, as the case may be.
- * If you do not delete the provisions above, a recipient may use your
- * version of this file under any of the LGPL, the MPL or the GPL.
- */
-
-#ifndef render_layer_h
-#define render_layer_h
-
-#include <tqcolor.h>
-#include <tqrect.h>
-#include <assert.h>
-
-#include "render_object.h"
-
-class TQScrollBar;
-template <class T> class TQPtrVector;
-
-namespace khtml {
- class RenderStyle;
- class RenderTable;
- class CachedObject;
- class RenderCanvas;
- class RenderText;
- class RenderFrameSet;
- class RenderObject;
- class RenderScrollMediator;
-
-class RenderScrollMediator: public TQObject
-{
- Q_OBJECT
-public:
- RenderScrollMediator(RenderLayer* layer)
- :m_layer(layer) {}
-
-public slots:
- void slotValueChanged();
-
-private:
- RenderLayer* m_layer;
-};
-
-// This class handles the auto-scrolling of layers with overflow: marquee.
-class Marquee: public TQObject
-{
- Q_OBJECT
-
-public:
- Marquee(RenderLayer* l);
-
- void timerEvent(TQTimerEvent*);
-
- int speed() const { return m_speed; }
- int marqueeSpeed() const;
- EMarqueeDirection direction() const;
- EMarqueeDirection reverseDirection() const { return static_cast<EMarqueeDirection>(-direction()); }
- bool isHorizontal() const;
- bool isUnfurlMarquee() const;
- int unfurlPos() const { return m_unfurlPos; }
-
- EWhiteSpace whiteSpace() { return m_whiteSpace; }
-
- int computePosition(EMarqueeDirection dir, bool stopAtClientEdge);
-
- void setEnd(int end) { m_end = end; }
-
- void start();
- void suspend();
- void stop();
-
- void updateMarqueeStyle();
- void updateMarqueePosition();
-
-private:
- RenderLayer* m_layer;
- int m_currentLoop;
- int m_totalLoops;
- int m_timerId;
- int m_start;
- int m_end;
- int m_speed;
- int m_unfurlPos;
- bool m_reset:1;
- bool m_suspended:1;
- bool m_stopped:1;
- EWhiteSpace m_whiteSpace : 3;
- EMarqueeDirection m_direction : 4;
-};
-
-class RenderLayer
-{
-public:
-#ifdef APPLE_CHANGES
- static TQScrollBar* gScrollBar;
-#endif
-
- RenderLayer(RenderObject* object);
- ~RenderLayer();
-
- RenderObject* renderer() const { return m_object; }
- RenderLayer *parent() const { return m_parent; }
- RenderLayer *previousSibling() const { return m_previous; }
- RenderLayer *nextSibling() const { return m_next; }
-
- RenderLayer *firstChild() const { return m_first; }
- RenderLayer *lastChild() const { return m_last; }
-
- void addChild(RenderLayer *newChild, RenderLayer* beforeChild = 0);
- RenderLayer* removeChild(RenderLayer *oldChild);
-
- void removeOnlyThisLayer();
- void insertOnlyThisLayer();
-
- void styleChanged();
-
- Marquee* marquee() const { return m_marquee; }
- void suspendMarquees();
-
- bool isOverflowOnly() const { return m_isOverflowOnly; }
-
-#ifdef APPLE_CHANGES
- bool isTransparent();
- RenderLayer* transparentAncestor();
-#endif
-
- RenderLayer* root() {
- RenderLayer* curr = this;
- while (curr->parent()) curr = curr->parent();
- return curr;
- }
-
- int xPos() const { return m_x; }
- int yPos() const { return m_y; }
-
- short width() const;
- int height() const;
-
- short scrollWidth() const { return m_scrollWidth; }
- int scrollHeight() const { return m_scrollHeight; }
-
- void resize( int w, int h ) {
- m_scrollWidth = w; m_scrollHeight = h;
- }
-
- void setPos( int xPos, int yPos ) {
- m_x = xPos;
- m_y = yPos;
- }
-
- // Scrolling methods for layers that can scroll their overflow.
- void scrollOffset(int& x, int& y);
- void subtractScrollOffset(int& x, int& y);
- void checkInlineRelOffset(const RenderObject* o, int& x, int& y);
- short scrollXOffset() { return m_scrollX; }
- int scrollYOffset() { return m_scrollY; }
- void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true);
- void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY); }
- void scrollToYOffset(int y) { scrollToOffset(m_scrollX, y); }
- void showScrollbar(Qt::Orientation, bool);
- TQScrollBar* horizontalScrollbar() { return m_hBar; }
- TQScrollBar* verticalScrollbar() { return m_vBar; }
- int verticalScrollbarWidth();
- int horizontalScrollbarHeight();
- void positionScrollbars(const TQRect &damageRect);
- void paintScrollbars(RenderObject::PaintInfo& pI);
- void checkScrollbarsAfterLayout();
- void slotValueChanged(int);
- void repaint(Priority p=NormalPriority, bool markForRepaint = false);
- void updateScrollPositionFromScrollbars();
-
- void updateLayerPosition();
- void updateLayerPositions( RenderLayer* rootLayer, bool doFullRepaint = false, bool checkForRepaint = false);
-
- // Get the enclosing stacking context for this layer. A stacking context is a layer
- // that has a non-auto z-index.
- RenderLayer* stackingContext() const;
- bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isCanvas(); }
-
- void dirtyZOrderLists();
- void updateZOrderLists();
- TQPtrVector<RenderLayer>* posZOrderList() const { return m_posZOrderList; }
- TQPtrVector<RenderLayer>* negZOrderList() const { return m_negZOrderList; }
-
- void dirtyOverflowList();
- void updateOverflowList();
- TQValueList<RenderLayer*>* overflowList() const { return m_overflowList; }
-
- void setHasOverlaidWidgets(bool b=true) { m_hasOverlaidWidgets = b; }
- bool hasOverlaidWidgets() const { return m_hasOverlaidWidgets; }
- TQRegion getMask() const { return m_region; }
- TQRegion paintedRegion(RenderLayer* rootLayer);
- void updateWidgetMasks(RenderLayer* rootLayer);
-
- // Gets the nearest enclosing positioned ancestor layer (also includes
- // the <html> layer and the root layer).
- RenderLayer* enclosingPositionedAncestor() const;
-
- void convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const;
-
- bool hasAutoZIndex() const { return renderer()->style()->hasAutoZIndex(); }
- int zIndex() const { return renderer()->style()->zIndex(); }
-
- // The two main functions that use the layer system. The paint method
- // paints the layers that intersect the damage rect from back to
- // front. The nodeAtPoint method looks for mouse events by walking
- // layers that intersect the point from front to back.
- KDE_EXPORT void paint(TQPainter *p, const TQRect& damageRect, bool selectionOnly=false);
- bool nodeAtPoint(RenderObject::NodeInfo& info, int x, int y);
-
- // This method figures out our layerBounds in coordinates relative to
- // |rootLayer}. It also computes our background and foreground clip rects
- // for painting/event handling.
- void calculateRects(const RenderLayer* rootLayer, const TQRect& paintDirtyRect, TQRect& layerBounds,
- TQRect& backgroundRect, TQRect& foregroundRect);
- void calculateClipRects(const RenderLayer* rootLayer, TQRect& overflowClipRect,
- TQRect& posClipRect, TQRect& fixedClipRect);
-
- bool intersectsDamageRect(const TQRect& layerBounds, const TQRect& damageRect) const;
- bool containsPoint(int x, int y, const TQRect& damageRect) const;
-
- void updateHoverActiveState(RenderObject::NodeInfo& info);
-
- void detach(RenderArena* renderArena);
-
-#ifdef ENABLE_DUMP
- KDE_EXPORT void dump(TQTextStream &stream, const TQString &ind = TQString::null);
-#endif
-
- // Overloaded new operator. Derived classes must override operator new
- // in order to allocate out of the RenderArena.
- void* operator new(size_t sz, RenderArena* renderArena) throw();
-
- // Overridden to prevent the normal delete from being called.
- void operator delete(void* ptr, size_t sz);
-
-private:
- // The normal operator new is disallowed on all render objects.
- void* operator new(size_t sz) throw();
-
-private:
- void setNextSibling(RenderLayer* next) { m_next = next; }
- void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
- void setParent(RenderLayer* parent) { m_parent = parent; }
- void setFirstChild(RenderLayer* first) { m_first = first; }
- void setLastChild(RenderLayer* last) { m_last = last; }
-
- void collectLayers(TQPtrVector<RenderLayer>*&, TQPtrVector<RenderLayer>*&);
-
- KDE_EXPORT void paintLayer(RenderLayer* rootLayer, TQPainter *p, const TQRect& paintDirtyRect, bool selectionOnly=false);
- RenderLayer* nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
- int x, int y, const TQRect& hitTestRect);
- bool shouldBeOverflowOnly() const;
-
-protected:
- RenderObject* m_object;
-
- RenderLayer* m_parent;
- RenderLayer* m_previous;
- RenderLayer* m_next;
-
- RenderLayer* m_first;
- RenderLayer* m_last;
-
- // Our (x,y) coordinates are in our parent layer's coordinate space.
- short m_x;
- int m_y;
-
- // Our scroll offsets if the view is scrolled.
- short m_scrollX;
- int m_scrollY;
-
- // The width/height of our scrolled area.
- short m_scrollWidth;
- int m_scrollHeight;
-
- // For layers with overflow, we have a pair of scrollbars.
- TQScrollBar* m_hBar;
- TQScrollBar* m_vBar;
- RenderScrollMediator* m_scrollMediator;
-
- // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the
- // descendant layers within the stacking context that have z-indices of 0 or greater
- // (auto will count as 0). m_negZOrderList holds descendants within our stacking context with negative
- // z-indices.
- TQPtrVector<RenderLayer>* m_posZOrderList;
- TQPtrVector<RenderLayer>* m_negZOrderList;
-
- // This list contains our overflow child layers.
- TQValueList<RenderLayer*>* m_overflowList;
-
- bool m_zOrderListsDirty: 1;
- bool m_overflowListDirty: 1;
- bool m_isOverflowOnly: 1;
- bool m_markedForRepaint: 1;
- bool m_hasOverlaidWidgets: 1;
-
- TQRect m_visibleRect;
-
- TQRegion m_region; // used by overlaid (non z-order aware) widgets
-
- Marquee* m_marquee; // Used by layers with overflow:marquee
-};
-
-} // namespace
-#endif
diff --git a/khtml/rendering/render_line.cpp b/khtml/rendering/render_line.cpp
deleted file mode 100644
index 2bcbe366e..000000000
--- a/khtml/rendering/render_line.cpp
+++ /dev/null
@@ -1,996 +0,0 @@
-/**
-* This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2003-2006 Apple Computer, Inc.
- * (C) 2006 Germain Garand (germain@ebooksfrance.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-// -------------------------------------------------------------------------
-
-#include <kdebug.h>
-#include <assert.h>
-#include <tqpainter.h>
-#include <kglobal.h>
-
-#include "rendering/render_flow.h"
-#include "rendering/render_text.h"
-#include "rendering/render_table.h"
-#include "rendering/render_inline.h"
-#include "rendering/render_block.h"
-#include "rendering/render_arena.h"
-#include "rendering/render_line.h"
-#include "xml/dom_nodeimpl.h"
-#include "xml/dom_docimpl.h"
-#include "html/html_formimpl.h"
-#include "misc/htmltags.h"
-#include "khtmlview.h"
-
-using namespace DOM;
-using namespace khtml;
-
-#ifndef NDEBUG
-static bool inInlineBoxDetach;
-#endif
-
-class khtml::EllipsisBox : public InlineBox
-{
-public:
- EllipsisBox(RenderObject* obj, const DOM::DOMString& ellipsisStr, InlineFlowBox* p,
- int w, int y, int h, int b, bool firstLine, InlineBox* markupBox)
- :InlineBox(obj), m_str(ellipsisStr) {
- m_parent = p;
- m_width = w;
- m_y = y;
- m_height = h;
- m_baseline = b;
- m_firstLine = firstLine;
- m_constructed = true;
- m_markupBox = markupBox;
- }
-
- void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
- bool nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty);
-
-private:
- DOM::DOMString m_str;
- InlineBox* m_markupBox;
-};
-
-void InlineBox::detach(RenderArena* renderArena)
-{
- if (m_parent)
- m_parent->removeFromLine(this);
-#ifndef NDEBUG
- inInlineBoxDetach = true;
-#endif
- delete this;
-#ifndef NDEBUG
- inInlineBoxDetach = false;
-#endif
-
- // Recover the size left there for us by operator delete and free the memory.
- renderArena->free(*(size_t *)this, this);
-}
-
-void* InlineBox::operator new(size_t sz, RenderArena* renderArena) throw()
-{
- return renderArena->allocate(sz);
-}
-
-void InlineBox::operator delete(void* ptr, size_t sz)
-{
- assert(inInlineBoxDetach);
-
- // Stash size where detach can find it.
- *(size_t *)ptr = sz;
-}
-
-static bool needsOutlinePhaseRepaint(RenderObject* o, RenderObject::PaintInfo& i, int tx, int ty) {
- if (o->style()->outlineWidth() <= 0)
- return false;
- TQRect r(tx+o->xPos(),ty+o->yPos(),o->width(),o->height());
- if (r.intersects(i.r))
- return false;
- r.addCoords(-o->style()->outlineSize(),
- -o->style()->outlineSize(),
- o->style()->outlineSize(),
- o->style()->outlineSize());
- if (!r.intersects(i.r))
- return false;
- return true;
-}
-
-void InlineBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
-{
- if ( i.phase == PaintActionOutline && !needsOutlinePhaseRepaint(object(), i, tx, ty) )
- return;
-
- // Paint all phases of replaced elements atomically, as though the replaced element established its
- // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
- // specification.)
- bool paintSelectionOnly = i.phase == PaintActionSelection;
- RenderObject::PaintInfo info(i.p, i.r, paintSelectionOnly ? i.phase : PaintActionElementBackground);
- object()->paint(info, tx, ty);
- if (!paintSelectionOnly) {
- info.phase = PaintActionChildBackgrounds;
- object()->paint(info, tx, ty);
- info.phase = PaintActionFloat;
- object()->paint(info, tx, ty);
- info.phase = PaintActionForeground;
- object()->paint(info, tx, ty);
- info.phase = PaintActionOutline;
- object()->paint(info, tx, ty);
- }
-}
-
-bool InlineBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
-{
- // Hit test all phases of replaced elements atomically, as though the replaced element established its
- // own stacking context. (See Appendix E.2, section 6.4 on inline block/table elements in the CSS2.1
- // specification.)
- bool inside = false;
- return object()->nodeAtPoint(i, x, y, tx, ty, HitTestAll, inside); // ### port hitTest
-}
-
-RootInlineBox* InlineBox::root()
-{
- if (m_parent)
- return m_parent->root();
- return static_cast<RootInlineBox*>(this);
-}
-
-InlineFlowBox::~InlineFlowBox()
-{
- /* If we're destroyed, set the children free, and break their links */
- while (m_firstChild)
- removeFromLine(m_firstChild);
-}
-
-void InlineFlowBox::removeFromLine(InlineBox *child)
-{
- if (child == m_firstChild) {
- m_firstChild = child->nextOnLine();
- }
- if (child == m_lastChild) {
- m_lastChild = child->prevOnLine();
- }
- if (child->nextOnLine()) {
- child->nextOnLine()->m_prev = child->prevOnLine();
- }
- if (child->prevOnLine()) {
- child->prevOnLine()->m_next = child->nextOnLine();
- }
-
- child->setParent(0);
-}
-
-bool InlineBox::canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth)
-{
- // Non-replaced elements can always accommodate an ellipsis.
- if (!m_object || !m_object->isReplaced())
- return true;
-
- TQRect boxRect(m_x, 0, m_width, 10);
- TQRect ellipsisRect(ltr ? blockEdge - ellipsisWidth : blockEdge, 0, ellipsisWidth, 10);
- return !(boxRect.intersects(ellipsisRect));
-}
-
-int InlineBox::placeEllipsisBox(bool /*ltr*/, int /*blockEdge*/, int /*ellipsisWidth*/, bool&)
-{
- // Use -1 to mean "we didn't set the position."
- return -1;
-}
-
-int InlineFlowBox::marginLeft() const
-{
- if (!includeLeftEdge())
- return 0;
-
- RenderStyle* cstyle = object()->style();
- Length margin = cstyle->marginLeft();
- if (!margin.isVariable())
- return (margin.isFixed() ? margin.value() : object()->marginLeft());
- return 0;
-}
-
-int InlineFlowBox::marginRight() const
-{
- if (!includeRightEdge())
- return 0;
-
- RenderStyle* cstyle = object()->style();
- Length margin = cstyle->marginRight();
- if (!margin.isVariable())
- return (margin.isFixed() ? margin.value() : object()->marginRight());
- return 0;
-}
-
-int InlineFlowBox::marginBorderPaddingLeft() const
-{
- return marginLeft() + borderLeft() + paddingLeft();
-}
-
-int InlineFlowBox::marginBorderPaddingRight() const
-{
- return marginRight() + borderRight() + paddingRight();
-}
-
-int InlineFlowBox::getFlowSpacingWidth() const
-{
- int totWidth = marginBorderPaddingLeft() + marginBorderPaddingRight();
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->isInlineFlowBox())
- totWidth += static_cast<InlineFlowBox*>(curr)->getFlowSpacingWidth();
- }
- return totWidth;
-}
-
-bool InlineFlowBox::nextOnLineExists()
-{
- if (!parent())
- return false;
-
- if (nextOnLine())
- return true;
-
- return parent()->nextOnLineExists();
-}
-
-bool InlineFlowBox::prevOnLineExists()
-{
- if (!parent())
- return false;
-
- if (prevOnLine())
- return true;
-
- return parent()->prevOnLineExists();
-}
-
-bool InlineFlowBox::onEndChain(RenderObject* endObject)
-{
- if (!endObject)
- return false;
-
- if (endObject == object())
- return true;
-
- RenderObject* curr = endObject;
- RenderObject* parent = curr->parent();
- while (parent && !parent->isRenderBlock()) {
- if (parent->lastChild() != curr || parent == object())
- return false;
-
- curr = parent;
- parent = curr->parent();
- }
-
- return true;
-}
-
-void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject)
-{
- // All boxes start off open. They will not apply any margins/border/padding on
- // any side.
- bool includeLeftEdge = false;
- bool includeRightEdge = false;
-
- RenderFlow* flow = static_cast<RenderFlow*>(object());
-
- if (!flow->firstChild())
- includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines.
- else if (parent()) { // The root inline box never has borders/margins/padding.
- bool ltr = flow->style()->direction() == LTR;
-
- // Check to see if all initial lines are unconstructed. If so, then
- // we know the inline began on this line.
- if (!flow->firstLineBox()->isConstructed()) {
- if (ltr && flow->firstLineBox() == this)
- includeLeftEdge = true;
- else if (!ltr && flow->lastLineBox() == this)
- includeRightEdge = true;
- }
-
- // In order to determine if the inline ends on this line, we check three things:
- // (1) If we are the last line and we don't have a continuation(), then we can
- // close up.
- // (2) If the last line box for the flow has an object following it on the line (ltr,
- // reverse for rtl), then the inline has closed.
- // (3) The line may end on the inline. If we are the last child (climbing up
- // the end object's chain), then we just closed as well.
- if (!flow->lastLineBox()->isConstructed()) {
- if (ltr) {
- if (!nextLineBox() &&
- ((lastLine && !object()->continuation()) || nextOnLineExists()
- || onEndChain(endObject)))
- includeRightEdge = true;
- }
- else {
- if ((!prevLineBox() || !prevLineBox()->isConstructed()) &&
- ((lastLine && !object()->continuation()) ||
- prevOnLineExists() || onEndChain(endObject)))
- includeLeftEdge = true;
- }
-
- }
- }
-
- setEdges(includeLeftEdge, includeRightEdge);
-
- // Recur into our children.
- for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
- if (currChild->isInlineFlowBox()) {
- InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);
- currFlow->determineSpacingForFlowBoxes(lastLine, endObject);
- }
- }
-}
-
-int InlineFlowBox::placeBoxesHorizontally(int x)
-{
- // Set our x position.
- setXPos(x);
-
- int startX = x;
- x += borderLeft() + paddingLeft();
-
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isText()) {
- InlineTextBox* text = static_cast<InlineTextBox*>(curr);
- text->setXPos(x);
- x += curr->width();
- }
- else {
- if (curr->object()->isPositioned()) {
- if (curr->object()->parent()->style()->direction() == LTR)
- curr->setXPos(x);
- else {
- // Our offset that we cache needs to be from the edge of the right border box and
- // not the left border box. We have to subtract |x| from the width of the block
- // (which can be obtained by walking up to the root line box).
- InlineBox* root = this;
- while (!root->isRootInlineBox())
- root = root->parent();
- curr->setXPos(root->object()->width()-x);
- }
- continue; // The positioned object has no effect on the width.
- }
- if (curr->object()->isInlineFlow()) {
- InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
- x += flow->marginLeft();
- x = flow->placeBoxesHorizontally(x);
- x += flow->marginRight();
- }
- else {
- x += curr->object()->marginLeft();
- curr->setXPos(x);
- x += curr->width() + curr->object()->marginRight();
- }
- }
- }
-
- x += borderRight() + paddingRight();
- setWidth(x-startX);
- return x;
-}
-
-void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
-{
- int maxPositionTop = 0;
- int maxPositionBottom = 0;
- int maxAscent = 0;
- int maxDescent = 0;
-
- // Figure out if we're in strict mode.
- RenderObject* curr = object();
- while (curr && !curr->element())
- curr = curr->container();
- bool strictMode = (curr && curr->element()->getDocument()->inStrictMode());
-
- computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
-
- if (maxAscent + maxDescent < kMax(maxPositionTop, maxPositionBottom))
- adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
-
- int maxHeight = maxAscent + maxDescent;
- int topPosition = heightOfBlock;
- int bottomPosition = heightOfBlock;
- placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition);
-
- setOverflowPositions(topPosition, bottomPosition);
-
- // Shrink boxes with no text children in quirks and almost strict mode.
- if (!strictMode)
- shrinkBoxesWithNoTextChildren(topPosition, bottomPosition);
-
- heightOfBlock += maxHeight;
-}
-
-void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
- int maxPositionTop, int maxPositionBottom)
-{
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- // The computed lineheight needs to be extended for the
- // positioned elements
- // see khtmltests/rendering/html_align.html
-
- if (curr->object()->isPositioned())
- continue; // Positioned placeholders don't affect calculations.
- if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) {
- if (curr->yPos() == PositionTop) {
- if (maxAscent + maxDescent < curr->height())
- maxDescent = curr->height() - maxAscent;
- }
- else {
- if (maxAscent + maxDescent < curr->height())
- maxAscent = curr->height() - maxDescent;
- }
-
- if ( maxAscent + maxDescent >= kMax( maxPositionTop, maxPositionBottom ) )
- break;
- }
-
- if (curr->isInlineFlowBox())
- static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
- }
-}
-
-void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
- int& maxAscent, int& maxDescent, bool strictMode)
-{
- if (isRootInlineBox()) {
- // Examine our root box.
- setHeight(object()->lineHeight(m_firstLine));
- bool isTableCell = object()->isTableCell();
- if (isTableCell) {
- RenderTableCell* tableCell = static_cast<RenderTableCell*>(object());
- setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine));
- }
- else
- setBaseline(object()->baselinePosition(m_firstLine));
- if (hasTextChildren() || strictMode) {
- int ascent = baseline();
- int descent = height() - ascent;
- if (maxAscent < ascent)
- maxAscent = ascent;
- if (maxDescent < descent)
- maxDescent = descent;
- }
- }
-
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isPositioned())
- continue; // Positioned placeholders don't affect calculations.
-
- curr->setHeight(curr->object()->lineHeight(m_firstLine));
- curr->setBaseline(curr->object()->baselinePosition(m_firstLine));
- curr->setYPos(curr->object()->verticalPositionHint(m_firstLine));
- if (curr->yPos() == PositionTop) {
- if (maxPositionTop < curr->height())
- maxPositionTop = curr->height();
- }
- else if (curr->yPos() == PositionBottom) {
- if (maxPositionBottom < curr->height())
- maxPositionBottom = curr->height();
- }
- else if (curr->hasTextChildren() || strictMode) {
- int ascent = curr->baseline() - curr->yPos();
- int descent = curr->height() - ascent;
- if (maxAscent < ascent)
- maxAscent = ascent;
- if (maxDescent < descent)
- maxDescent = descent;
- }
-
- if (curr->isInlineFlowBox())
- static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
- }
-}
-
-void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
- int& topPosition, int& bottomPosition)
-{
- if (isRootInlineBox()) {
- setYPos(y + maxAscent - baseline());// Place our root box.
- // CSS2: 10.8.1 - line-height on the block level element specifies the *minimum*
- // height of the generated line box
- if (hasTextChildren() && maxHeight < object()->lineHeight(m_firstLine))
- maxHeight = object()->lineHeight(m_firstLine);
- }
-
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isPositioned())
- continue; // Positioned placeholders don't affect calculations.
-
- // Adjust boxes to use their real box y/height and not the logical height (as dictated by
- // line-height).
- if (curr->isInlineFlowBox())
- static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode,
- topPosition, bottomPosition);
-
- bool childAffectsTopBottomPos = true;
-
- if (curr->yPos() == PositionTop)
- curr->setYPos(y);
- else if (curr->yPos() == PositionBottom)
- curr->setYPos(y + maxHeight - curr->height());
- else {
- if (!strictMode && !curr->hasTextDescendant())
- childAffectsTopBottomPos = false;
- curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline());
- }
- int newY = curr->yPos();
- int newHeight = curr->height();
- int newBaseline = curr->baseline();
- int overflowTop = 0;
- int overflowBottom = 0;
- if (curr->isInlineTextBox() || curr->isInlineFlowBox()) {
- const TQFontMetrics &fm = curr->object()->fontMetrics( m_firstLine );
-#ifdef APPLE_CHANGES
- newBaseline = fm.ascent();
- newY += curr->baseline() - newBaseline;
- newHeight = newBaseline+fm.descent();
-#else
- // only adjust if the leading delta is superior to the font's natural leading
- if ( kAbs(fm.ascent() - curr->baseline()) > fm.leading()/2 ) {
- int ascent = fm.ascent()+fm.leading()/2;
- newBaseline = ascent;
- newY += curr->baseline() - newBaseline;
- newHeight = fm.lineSpacing();
- }
-#endif
- for (ShadowData* shadow = curr->object()->style()->textShadow(); shadow; shadow = shadow->next) {
- overflowTop = kMin(overflowTop, shadow->y - shadow->blur);
- overflowBottom = kMax(overflowBottom, shadow->y + shadow->blur);
- }
- if (curr->isInlineFlowBox()) {
- newHeight += curr->object()->borderTop() + curr->object()->paddingTop() +
- curr->object()->borderBottom() + curr->object()->paddingBottom();
- newY -= curr->object()->borderTop() + curr->object()->paddingTop();
- newBaseline += curr->object()->borderTop() + curr->object()->paddingTop();
- }
- } else {
- newY += curr->object()->marginTop();
- newHeight = curr->height() - (curr->object()->marginTop() + curr->object()->marginBottom());
- overflowTop = curr->object()->overflowTop();
- overflowBottom = curr->object()->overflowHeight() - newHeight;
- }
- curr->setYPos(newY);
- curr->setHeight(newHeight);
- curr->setBaseline(newBaseline);
-
- if (childAffectsTopBottomPos) {
- topPosition = kMin(topPosition, newY + overflowTop);
- bottomPosition = kMax(bottomPosition, newY + newHeight + overflowBottom);
- }
- }
-
- if (isRootInlineBox()) {
- const TQFontMetrics &fm = object()->fontMetrics( m_firstLine );
-#ifdef APPLE_CHANGES
- setHeight(fm.ascent()+fm.descent());
- setYPos(yPos() + baseline() - fm.ascent());
- setBaseline(fm.ascent());
-#else
- if ( kAbs(fm.ascent() - baseline()) > fm.leading()/2 ) {
- int ascent = fm.ascent()+fm.leading()/2;
- setHeight(fm.lineSpacing());
- setYPos(yPos() + baseline() - ascent);
- setBaseline(ascent);
- }
-#endif
- if (hasTextDescendant() || strictMode) {
- if (yPos() < topPosition)
- topPosition = yPos();
- if (yPos() + height() > bottomPosition)
- bottomPosition = yPos() + height();
- }
- }
-}
-
-void InlineFlowBox::shrinkBoxesWithNoTextChildren(int topPos, int bottomPos)
-{
- // First shrink our kids.
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (curr->object()->isPositioned())
- continue; // Positioned placeholders don't affect calculations.
-
- if (curr->isInlineFlowBox())
- static_cast<InlineFlowBox*>(curr)->shrinkBoxesWithNoTextChildren(topPos, bottomPos);
- }
-
- // See if we have text children. If not, then we need to shrink ourselves to fit on the line.
- if (!hasTextDescendant()) {
- if (yPos() < topPos)
- setYPos(topPos);
- if (yPos() + height() > bottomPos)
- setHeight(bottomPos - yPos());
- if (baseline() > height())
- setBaseline(height());
- }
-}
-
-bool InlineFlowBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
-{
- // Check children first.
- for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
- if (!curr->object()->layer() && curr->nodeAtPoint(i, x, y, tx, ty)) {
- object()->setInnerNode(i);
- return true;
- }
- }
-
- // Now check ourselves.
- TQRect rect(tx + m_x, ty + m_y, m_width, m_height);
- if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) {
- object()->setInnerNode(i);
- return true;
- }
-
- return false;
-}
-
-
-void InlineFlowBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
-{
- bool intersectsDamageRect = true;
- int xPos = tx + m_x - object()->maximalOutlineSize(i.phase);
- int w = width() + 2 * object()->maximalOutlineSize(i.phase);
- if ((xPos >= i.r.x() + i.r.width()) || (xPos + w <= i.r.x()))
- intersectsDamageRect = false;
-
- if (intersectsDamageRect) {
- if (i.phase == PaintActionOutline) {
- // Add ourselves to the paint info struct's list of inlines that need to paint their
- // outlines.
- if (object()->style()->visibility() == VISIBLE && object()->style()->outlineWidth() > 0 &&
- !object()->isInlineContinuation() && !isRootInlineBox()) {
- if (!i.outlineObjects)
- i.outlineObjects = new TQValueList<RenderFlow*>;
- i.outlineObjects->append(static_cast<RenderFlow*>(object()));
- }
- }
- else {
- // 1. Paint our background and border.
- paintBackgroundAndBorder(i, tx, ty);
-
- // 2. Paint our underline and overline.
- paintDecorations(i, tx, ty, false);
- }
- }
-
- // 3. Paint our children.
- for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
- if (!curr->object()->layer())
- curr->paint(i, tx, ty);
- }
-
- // 4. Paint our strike-through
- if (intersectsDamageRect && i.phase != PaintActionOutline)
- paintDecorations(i, tx, ty, true);
-}
-
-
-void InlineFlowBox::paintBackgrounds(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
- int my, int mh, int _tx, int _ty, int w, int h)
-{
- if (!bgLayer)
- return;
- paintBackgrounds(p, c, bgLayer->next(), my, mh, _tx, _ty, w, h);
- paintBackground(p, c, bgLayer, my, mh, _tx, _ty, w, h);
-}
-
-void InlineFlowBox::paintBackground(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
- int my, int mh, int _tx, int _ty, int w, int h)
-{
- CachedImage* bg = bgLayer->backgroundImage();
- bool hasBackgroundImage = bg && (bg->pixmap_size() == bg->valid_rect().size()) &&
- !bg->isTransparent() && !bg->isErrorImage();
- if (!hasBackgroundImage || (!prevLineBox() && !nextLineBox()) || !parent())
- object()->paintBackgroundExtended(p, c, bgLayer, my, mh, _tx, _ty, w, h, borderLeft(), borderRight(), paddingLeft(), paddingRight());
- else {
- // We have a background image that spans multiple lines.
- // We need to adjust _tx and _ty by the width of all previous lines.
- // Think of background painting on inlines as though you had one long line, a single continuous
- // strip. Even though that strip has been broken up across multiple lines, you still paint it
- // as though you had one single line. This means each line has to pick up the background where
- // the previous line left off.
- // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
- // but it isn't even clear how this should work at all.
- int xOffsetOnLine = 0;
- for (InlineRunBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
- xOffsetOnLine += curr->width();
- int startX = _tx - xOffsetOnLine;
- int totalWidth = xOffsetOnLine;
- for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox())
- totalWidth += curr->width();
- p->save();
- p->setClipRect(TQRect(_tx, _ty, width(), height()), TQPainter::CoordPainter);
- object()->paintBackgroundExtended(p, c, bgLayer, my, mh, startX, _ty,
- totalWidth, h, borderLeft(), borderRight(), paddingLeft(), paddingRight());
- p->restore();
- }
-}
-
-void InlineFlowBox::paintBackgroundAndBorder(RenderObject::PaintInfo& pI, int _tx, int _ty)
-{
- if (object()->style()->visibility() != VISIBLE || pI.phase != PaintActionForeground)
- return;
-
- // Move x/y to our coordinates.
- _tx += m_x;
- _ty += m_y;
-
- int w = width();
- int h = height();
-
- int my = kMax(_ty, pI.r.y());
- int mh;
- if (_ty<pI.r.y())
- mh= kMax(0,h-(pI.r.y()-_ty));
- else
- mh = kMin(pI.r.height(),h);
-
- // You can use p::first-line to specify a background. If so, the root line boxes for
- // a line may actually have to paint a background.
- RenderStyle* styleToUse = object()->style(m_firstLine);
- if ((!parent() && m_firstLine && styleToUse != object()->style()) ||
- (parent() && object()->shouldPaintBackgroundOrBorder())) {
- TQColor c = styleToUse->backgroundColor();
- paintBackgrounds(pI.p, c, styleToUse->backgroundLayers(), my, mh, _tx, _ty, w, h);
-
- // :first-line cannot be used to put borders on a line. Always paint borders with our
- // non-first-line style.
- if (parent() && object()->style()->hasBorder())
- object()->paintBorder(pI.p, _tx, _ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge());
- }
-}
-
-static bool shouldDrawDecoration(RenderObject* obj)
-{
- bool shouldDraw = false;
- for (RenderObject* curr = obj->firstChild();
- curr; curr = curr->nextSibling()) {
- if (curr->isInlineFlow()) {
- shouldDraw = true;
- break;
- }
- else if (curr->isText() && !curr->isBR() && (curr->style()->preserveWS() ||
- !curr->element() || !curr->element()->containsOnlyWhitespace())) {
- shouldDraw = true;
- break;
- }
- }
- return shouldDraw;
-}
-
-void InlineFlowBox::paintDecorations(RenderObject::PaintInfo& pI, int _tx, int _ty, bool paintedChildren)
-{
- // Now paint our text decorations. We only do this if we aren't in quirks mode (i.e., in
- // almost-strict mode or strict mode).
- if (object()->style()->htmlHacks() || object()->style()->visibility() != VISIBLE)
- return;
-
- _tx += m_x;
- _ty += m_y;
- RenderStyle* styleToUse = object()->style(m_firstLine);
- int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect();
- if (deco != TDNONE &&
- ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) &&
- shouldDrawDecoration(object())) {
- // We must have child boxes and have decorations defined.
- _tx += borderLeft() + paddingLeft();
- int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight());
- if ( !w )
- return;
- const TQFontMetrics &fm = object()->fontMetrics( m_firstLine );
- // thick lines on small fonts look ugly
- int thickness = fm.height() > 20 ? fm.lineWidth() : 1;
- TQColor underline, overline, linethrough;
- underline = overline = linethrough = styleToUse->color();
- if (!parent())
- object()->getTextDecorationColors(deco, underline, overline, linethrough);
-
- if (styleToUse->font() != pI.p->font())
- pI.p->setFont(styleToUse->font());
-
- if (deco & UNDERLINE && !paintedChildren) {
- int underlineOffset = ( fm.height() + m_baseline ) / 2;
- if (underlineOffset <= m_baseline) underlineOffset = m_baseline+1;
-
- pI.p->fillRect(_tx, _ty + underlineOffset, w, thickness, underline );
- }
- if (deco & OVERLINE && !paintedChildren) {
- pI.p->fillRect(_tx, _ty, w, thickness, overline );
- }
- if (deco & LINE_THROUGH && paintedChildren) {
- pI.p->fillRect(_tx, _ty + 2*m_baseline/3, w, thickness, linethrough );
- }
- }
-}
-
-bool InlineFlowBox::canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth)
-{
- for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
- if (!box->canAccommodateEllipsisBox(ltr, blockEdge, ellipsisWidth))
- return false;
- }
- return true;
-}
-
-int InlineFlowBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
-{
- int result = -1;
- for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
- int currResult = box->placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
- if (currResult != -1 && result == -1)
- result = currResult;
- }
- return result;
-}
-
-void InlineFlowBox::clearTruncation()
-{
- for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
- box->clearTruncation();
-}
-
-void EllipsisBox::paint(RenderObject::PaintInfo& i, int _tx, int _ty)
-{
- TQPainter* p = i.p;
- RenderStyle* _style = m_firstLine ? m_object->style(true) : m_object->style();
- if (_style->font() != p->font())
- p->setFont(_style->font());
-
- const Font* font = &_style->htmlFont();
- TQColor textColor = _style->color();
- if (textColor != p->pen().color())
- p->setPen(textColor);
- /*
- bool setShadow = false;
- if (_style->textShadow()) {
- p->setShadow(_style->textShadow()->x, _style->textShadow()->y,
- _style->textShadow()->blur, _style->textShadow()->color);
- setShadow = true;
- }*/
-
- const DOMString& str = m_str.string();
- font->drawText(p, m_x + _tx,
- m_y + _ty + m_baseline,
- (str.implementation())->s,
- str.length(), 0, str.length(),
- 0,
- TQPainter::LTR, _style->visuallyOrdered());
-
- /*
- if (setShadow)
- p->clearShadow();
- */
-
- if (m_markupBox) {
- // Paint the markup box
- _tx += m_x + m_width - m_markupBox->xPos();
- _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
- m_markupBox->object()->paint(i, _tx, _ty);
- }
-}
-
-bool EllipsisBox::nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty)
-{
- // Hit test the markup box.
- if (m_markupBox) {
- _tx += m_x + m_width - m_markupBox->xPos();
- _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline());
- if (m_markupBox->nodeAtPoint(info, _x, _y, _tx, _ty)) {
- object()->setInnerNode(info);
- return true;
- }
- }
-
- TQRect rect(_tx + m_x, _ty + m_y, m_width, m_height);
- if (object()->style()->visibility() == VISIBLE && rect.contains(_x, _y)) {
- object()->setInnerNode(info);
- return true;
- }
- return false;
-}
-
-void RootInlineBox::detach(RenderArena* arena)
-{
- detachEllipsisBox(arena);
- InlineFlowBox::detach(arena);
-}
-
-void RootInlineBox::detachEllipsisBox(RenderArena* arena)
-{
- if (m_ellipsisBox) {
- m_ellipsisBox->detach(arena);
- m_ellipsisBox = 0;
- }
-}
-
-void RootInlineBox::clearTruncation()
-{
- if (m_ellipsisBox) {
- detachEllipsisBox(m_object->renderArena());
- InlineFlowBox::clearTruncation();
- }
-}
-
-bool RootInlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth)
-{
- // First sanity-check the unoverflowed width of the whole line to see if there is sufficient room.
- int delta = ltr ? lineBoxEdge - blockEdge : blockEdge - lineBoxEdge;
- if (width() - delta < ellipsisWidth)
- return false;
-
- // Next iterate over all the line boxes on the line. If we find a replaced element that intersects
- // then we refuse to accommodate the ellipsis. Otherwise we're ok.
- return InlineFlowBox::canAccommodateEllipsisBox(ltr, blockEdge, ellipsisWidth);
-}
-
-void RootInlineBox::placeEllipsis(const DOMString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox)
-{
- // Create an ellipsis box.
- m_ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this,
- ellipsisWidth - (markupBox ? markupBox->width() : 0),
- yPos(), height(), baseline(), !prevRootBox(),
- markupBox);
-
- if (ltr && (xPos() + width() + ellipsisWidth) <= blockEdge) {
- m_ellipsisBox->m_x = xPos() + width();
- return;
- }
-
- // Now attempt to find the nearest glyph horizontally and place just to the right (or left in RTL)
- // of that glyph. Mark all of the objects that intersect the ellipsis box as not painting (as being
- // truncated).
- bool foundBox = false;
- m_ellipsisBox->m_x = placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
-}
-
-int RootInlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
-{
- int result = InlineFlowBox::placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);
- if (result == -1)
- result = ltr ? blockEdge - ellipsisWidth : blockEdge;
- return result;
-}
-
-void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const
-{
- if (m_ellipsisBox)
- m_ellipsisBox->paint(i, _tx, _ty);
-}
-
-void RootInlineBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
-{
- InlineFlowBox::paint(i, tx, ty);
- paintEllipsisBox(i, tx, ty);
-}
-
-bool RootInlineBox::nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty)
-{
- if (m_ellipsisBox && object()->style()->visibility() == VISIBLE) {
- if (m_ellipsisBox->nodeAtPoint(i, x, y, tx, ty)) {
- object()->setInnerNode(i);
- return true;
- }
- }
- return InlineFlowBox::nodeAtPoint(i, x, y, tx, ty);
-}
-
diff --git a/khtml/rendering/render_line.h b/khtml/rendering/render_line.h
deleted file mode 100644
index d42f2acb8..000000000
--- a/khtml/rendering/render_line.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * This file is part of the line box implementation for KDE.
- *
- * Copyright (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_LINE_H
-#define RENDER_LINE_H
-
-namespace khtml {
-
-class EllipsisBox;
-class InlineFlowBox;
-class RootInlineBox;
-
-// InlineBox represents a rectangle that occurs on a line. It corresponds to
-// some RenderObject (i.e., it represents a portion of that RenderObject).
-class InlineBox
-{
-public:
- InlineBox(RenderObject* obj)
- :m_object(obj), m_x(0), m_width(0), m_y(0), m_height(0), m_baseline(0),
- m_firstLine(false), m_constructed(false)
- {
- m_next = 0;
- m_prev = 0;
- m_parent = 0;
- }
-
- virtual ~InlineBox() {}
-
- void detach(RenderArena* renderArena);
-
- virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
- virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
-
- // Overloaded new operator.
- void* operator new(size_t sz, RenderArena* renderArena) throw();
-
- // Overridden to prevent the normal delete from being called.
- void operator delete(void* ptr, size_t sz);
-
-private:
- // The normal operator new is disallowed.
- void* operator new(size_t sz) throw();
-
-public:
- virtual bool isInlineBox() const { return false; }
- virtual bool isInlineFlowBox() const { return false; }
- virtual bool isContainer() const { return false; }
- virtual bool isInlineTextBox() const { return false; }
- virtual bool isRootInlineBox() const { return false; }
-
- bool isConstructed() const { return m_constructed; }
- virtual void setConstructed() {
- m_constructed = true;
- if (m_next)
- m_next->setConstructed();
- }
-
- void setFirstLineStyleBit(bool f) { m_firstLine = f; }
-
- InlineBox* nextOnLine() { return m_next; }
- InlineBox* prevOnLine() { return m_prev; }
- RenderObject* object() const { return m_object; }
-
- InlineFlowBox* parent() { return m_parent; }
- void setParent(InlineFlowBox* par) { m_parent = par; }
-
- RootInlineBox* root();
-
- void setWidth(short w) { m_width = w; }
- short width() const { return m_width; }
-
- void setXPos(short x) { m_x = x; }
- short xPos() const { return m_x; }
-
- void setYPos(int y) { m_y = y; }
- int yPos() const { return m_y; }
-
- void setHeight(int h) { m_height = h; }
- int height() const { return m_height; }
-
- void setBaseline(int b) { m_baseline = b; }
- int baseline() const { return m_baseline; }
-
- virtual bool hasTextChildren() const { return true; }
- virtual bool hasTextDescendant() const { return true; }
-
- virtual int topOverflow() const { return yPos(); }
- virtual int bottomOverflow() const { return yPos()+height(); }
-
- virtual long minOffset() const { return 0; }
- virtual long maxOffset() const { return 0; }
-
- virtual void clearTruncation() {};
-
- virtual bool canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth);
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
-
-public: // FIXME: Would like to make this protected, but methods are accessing these
- // members over in the part.
- RenderObject* m_object;
-
- short m_x;
- short m_width;
- int m_y;
- int m_height;
- int m_baseline;
-
- bool m_firstLine : 1;
- bool m_constructed : 1;
-
- InlineBox* m_next; // The next element on the same line as us.
- InlineBox* m_prev; // The previous element on the same line as us.
-
- InlineFlowBox* m_parent; // The box that contains us.
-};
-
-class InlineRunBox : public InlineBox
-{
-public:
- InlineRunBox(RenderObject* obj)
- :InlineBox(obj)
- {
- m_prevLine = 0;
- m_nextLine = 0;
- }
-
- InlineRunBox* prevLineBox() { return m_prevLine; }
- InlineRunBox* nextLineBox() { return m_nextLine; }
- void setNextLineBox(InlineRunBox* n) { m_nextLine = n; }
- void setPreviousLineBox(InlineRunBox* p) { m_prevLine = p; }
-
- virtual void paintBackgroundAndBorder(RenderObject::PaintInfo&, int /*_tx*/, int /*_ty*/) {}
- virtual void paintDecorations(RenderObject::PaintInfo&, int /*_tx*/, int /*_ty*/, bool /*paintedChildren*/ = false) {}
-
-protected:
- InlineRunBox* m_prevLine; // The previous box that also uses our RenderObject
- InlineRunBox* m_nextLine; // The next box that also uses our RenderObject
-};
-
-class InlineFlowBox : public InlineRunBox
-{
-public:
- InlineFlowBox(RenderObject* obj)
- :InlineRunBox(obj)
- {
- m_firstChild = 0;
- m_lastChild = 0;
- m_includeLeftEdge = m_includeRightEdge = false;
- m_hasTextChildren = false;
- m_hasTextDescendant = false;
- m_afterPageBreak = false;
- }
-
- ~InlineFlowBox();
-
- virtual bool isInlineFlowBox() const { return true; }
-
- InlineFlowBox* prevFlowBox() const { return static_cast<InlineFlowBox*>(m_prevLine); }
- InlineFlowBox* nextFlowBox() const { return static_cast<InlineFlowBox*>(m_nextLine); }
-
- InlineBox* firstChild() const { return m_firstChild; }
- InlineBox* lastChild() const { return m_lastChild; }
-
- virtual void setConstructed() {
- InlineBox::setConstructed();
- if (m_firstChild)
- m_firstChild->setConstructed();
- }
- void addToLine(InlineBox* child) {
- if (!m_firstChild)
- m_firstChild = m_lastChild = child;
- else {
- m_lastChild->m_next = child;
- child->m_prev = m_lastChild;
- m_lastChild = child;
- }
- child->setFirstLineStyleBit(m_firstLine);
- child->setParent(this);
- if (!m_hasTextChildren && child->isInlineTextBox()) {
- m_hasTextDescendant = m_hasTextChildren = true;
- for (InlineFlowBox* p = m_parent; p && !p->hasTextDescendant(); p = p->parent())
- p->m_hasTextDescendant = true;
- }
- }
-
- virtual void clearTruncation();
-
- void removeFromLine(InlineBox* child);
- virtual void paintBackgroundAndBorder(RenderObject::PaintInfo&, int _tx, int _ty);
- void paintBackgrounds(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
- int my, int mh, int _tx, int _ty, int w, int h);
- void paintBackground(TQPainter* p, const TQColor& c, const BackgroundLayer* bgLayer,
- int my, int mh, int _tx, int _ty, int w, int h);
- virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
- virtual void paintDecorations(RenderObject::PaintInfo&, int _tx, int _ty, bool paintedChildren = false);
- virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
-
- int marginBorderPaddingLeft() const;
- int marginBorderPaddingRight() const;
- int marginLeft() const;
- int marginRight( )const;
- int borderLeft() const { if (includeLeftEdge()) return object()->borderLeft(); return 0; }
- int borderRight() const { if (includeRightEdge()) return object()->borderRight(); return 0; }
- int paddingLeft() const { if (includeLeftEdge()) return object()->paddingLeft(); return 0; }
- int paddingRight() const { if (includeRightEdge()) return object()->paddingRight(); return 0; }
-
- bool includeLeftEdge() const { return m_includeLeftEdge; }
- bool includeRightEdge() const { return m_includeRightEdge; }
- void setEdges(bool includeLeft, bool includeRight) {
- m_includeLeftEdge = includeLeft;
- m_includeRightEdge = includeRight;
- }
- virtual bool hasTextChildren() const { return m_hasTextChildren; }
- bool hasTextDescendant() const { return m_hasTextDescendant; }
-
- // Helper functions used during line construction and placement.
- void determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject);
- int getFlowSpacingWidth() const;
- bool nextOnLineExists();
- bool prevOnLineExists();
- bool onEndChain(RenderObject* endObject);
- int placeBoxesHorizontally(int x);
- void verticallyAlignBoxes(int& heightOfBlock);
- void computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
- int& maxAscent, int& maxDescent, bool strictMode);
- void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
- int maxPositionTop, int maxPositionBottom);
- void placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
- int& topPosition, int& bottomPosition);
- void shrinkBoxesWithNoTextChildren(int topPosition, int bottomPosition);
-
- virtual void setOverflowPositions(int /*top*/, int /*bottom*/) {}
-
- void setAfterPageBreak(bool b = true) { m_afterPageBreak = b; }
- bool afterPageBreak() const { return m_afterPageBreak; }
-
- virtual bool canAccommodateEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth);
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
-
-protected:
- InlineBox* m_firstChild;
- InlineBox* m_lastChild;
- bool m_includeLeftEdge : 1;
- bool m_includeRightEdge : 1;
- bool m_hasTextChildren : 1;
- bool m_hasTextDescendant : 1;
- bool m_afterPageBreak : 1;
-};
-
-class RootInlineBox : public InlineFlowBox
-{
-public:
- RootInlineBox(RenderObject* obj) : InlineFlowBox(obj), m_ellipsisBox(0)
- {
- m_topOverflow = m_bottomOverflow = 0;
- }
-
- virtual void detach(RenderArena* renderArena);
- void detachEllipsisBox(RenderArena* renderArena);
-
- RootInlineBox* nextRootBox() { return static_cast<RootInlineBox*>(m_nextLine); }
- RootInlineBox* prevRootBox() { return static_cast<RootInlineBox*>(m_prevLine); }
-
- virtual bool isRootInlineBox() const { return true; }
- virtual int topOverflow() const { return m_topOverflow; }
- virtual int bottomOverflow() const { return m_bottomOverflow; }
- virtual void setOverflowPositions(int top, int bottom) { m_topOverflow = top; m_bottomOverflow = bottom; }
-
- bool canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth);
- void placeEllipsis(const DOM::DOMString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox = 0);
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool&);
-
- EllipsisBox* ellipsisBox() const { return m_ellipsisBox; }
- void paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const;
- bool hitTestEllipsisBox(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty);
-
- virtual void clearTruncation();
-
- virtual void paint(RenderObject::PaintInfo& i, int _tx, int _ty);
- virtual bool nodeAtPoint(RenderObject::NodeInfo& i, int x, int y, int tx, int ty);
-
-protected:
- int m_topOverflow;
- int m_bottomOverflow;
-
- // An inline text box that represents our text truncation string.
- EllipsisBox* m_ellipsisBox;
-};
-
-} //namespace
-
-#endif
diff --git a/khtml/rendering/render_list.cpp b/khtml/rendering/render_list.cpp
deleted file mode 100644
index 769b79670..000000000
--- a/khtml/rendering/render_list.cpp
+++ /dev/null
@@ -1,586 +0,0 @@
-/**
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2002 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "rendering/render_list.h"
-#include "rendering/render_canvas.h"
-#include "rendering/enumerate.h"
-#include "rendering/counter_tree.h"
-#include "html/html_listimpl.h"
-#include "misc/helper.h"
-#include "misc/htmltags.h"
-#include "misc/loader.h"
-#include "xml/dom_docimpl.h"
-
-#include <kdebug.h>
-#include <kglobal.h>
-#include <tqvaluelist.h>
-
-//#define BOX_DEBUG
-
-using namespace khtml;
-using namespace Enumerate;
-
-const int cMarkerPadding = 7;
-
-// -------------------------------------------------------------------------
-
-RenderListItem::RenderListItem(DOM::NodeImpl* node)
- : RenderBlock(node)
-{
- // init RenderObject attributes
- setInline(false); // our object is not Inline
-
- predefVal = -1;
- m_marker = 0;
- m_counter = 0;
- m_insideList = false;
- m_deleteMarker = false;
-}
-
-void RenderListItem::setStyle(RenderStyle *_style)
-{
- RenderBlock::setStyle(_style);
-
- RenderStyle *newStyle = new RenderStyle();
- newStyle->ref();
-
- newStyle->inheritFrom(style());
-
- if(!m_marker && style()->listStyleType() != LNONE) {
- m_marker = new (renderArena()) RenderListMarker(element());
- m_marker->setIsAnonymous( true );
- m_marker->setStyle(newStyle);
- m_marker->setListItem( this );
- m_deleteMarker = true;
- } else if ( m_marker && style()->listStyleType() == LNONE) {
- m_marker->detach();
- m_marker = 0;
- }
- else if ( m_marker ) {
- m_marker->setStyle(newStyle);
- }
-
- newStyle->deref();
-}
-
-void RenderListItem::detach()
-{
- if ( m_marker && m_deleteMarker )
- m_marker->detach();
- RenderBlock::detach();
-}
-
-static RenderObject* getParentOfFirstLineBox(RenderObject* curr, RenderObject* marker)
-{
- RenderObject* firstChild = curr->firstChild();
- if (!firstChild)
- return 0;
-
- for (RenderObject* currChild = firstChild;
- currChild; currChild = currChild->nextSibling()) {
- if (currChild == marker)
- continue;
-
- if (currChild->isInline())
- return curr;
-
- if (currChild->isFloating() || currChild->isPositioned())
- continue;
-
- if (currChild->isTable() || !currChild->isRenderBlock())
- break;
-
- if (currChild->style()->htmlHacks() && currChild->element() &&
- (currChild->element()->id() == ID_UL || currChild->element()->id() == ID_OL))
- break;
-
- RenderObject* lineBox = getParentOfFirstLineBox(currChild, marker);
- if (lineBox)
- return lineBox;
- }
-
- return 0;
-}
-
-
-void RenderListItem::updateMarkerLocation()
-{
- // Sanity check the location of our marker.
- if (m_marker) {
- RenderObject* markerPar = m_marker->parent();
- RenderObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker);
- if (!lineBoxParent) {
- // If the marker is currently contained inside an anonymous box,
- // then we are the only item in that anonymous box (since no line box
- // parent was found). It's ok to just leave the marker where it is
- // in this case.
- if (markerPar && markerPar->isAnonymousBlock())
- lineBoxParent = markerPar;
- else
- lineBoxParent = this;
- }
- if (markerPar != lineBoxParent)
- {
- if (markerPar)
- markerPar->removeChild(m_marker);
- if (!lineBoxParent)
- lineBoxParent = this;
- lineBoxParent->addChild(m_marker, lineBoxParent->firstChild());
- m_deleteMarker = false;
- if (!m_marker->minMaxKnown())
- m_marker->calcMinMaxWidth();
- recalcMinMaxWidths();
- }
- }
-}
-
-void RenderListItem::calcMinMaxWidth()
-{
- // Make sure our marker is in the correct location.
- updateMarkerLocation();
- if (!minMaxKnown())
- RenderBlock::calcMinMaxWidth();
-}
-/*
-short RenderListItem::marginLeft() const
-{
- if (m_insideList)
- return RenderBlock::marginLeft();
- else
- return kMax(m_marker->markerWidth(), RenderBlock::marginLeft());
-}
-
-short RenderListItem::marginRight() const
-{
- return RenderBlock::marginRight();
-}*/
-
-void RenderListItem::layout( )
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
-
- updateMarkerLocation();
- RenderBlock::layout();
-}
-
-// -----------------------------------------------------------
-
-RenderListMarker::RenderListMarker(DOM::NodeImpl* node)
- : RenderBox(node), m_listImage(0), m_markerWidth(0)
-{
- // init RenderObject attributes
- setInline(true); // our object is Inline
- setReplaced(true); // pretend to be replaced
- // val = -1;
- // m_listImage = 0;
-}
-
-RenderListMarker::~RenderListMarker()
-{
- if(m_listImage)
- m_listImage->deref(this);
- if (m_listItem)
- m_listItem->resetListMarker();
-}
-
-void RenderListMarker::setStyle(RenderStyle *s)
-{
- if ( s && style() && s->listStylePosition() != style()->listStylePosition() )
- setNeedsLayoutAndMinMaxRecalc();
-
- RenderBox::setStyle(s);
-
- if ( m_listImage != style()->listStyleImage() ) {
- if(m_listImage) m_listImage->deref(this);
- m_listImage = style()->listStyleImage();
- if(m_listImage) m_listImage->ref(this);
- }
-}
-
-
-void RenderListMarker::paint(PaintInfo& paintInfo, int _tx, int _ty)
-{
- if (paintInfo.phase != PaintActionForeground)
- return;
-
- if (style()->visibility() != VISIBLE) return;
-
- _tx += m_x;
- _ty += m_y;
-
- if((_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top()))
- return;
-
- if(shouldPaintBackgroundOrBorder())
- paintBoxDecorations(paintInfo, _tx, _ty);
-
- TQPainter* p = paintInfo.p;
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << nodeName().string() << "(ListMarker)::paintObject(" << _tx << ", " << _ty << ")" << endl;
-#endif
- p->setFont(style()->font());
- const TQFontMetrics fm = p->fontMetrics();
-
-
- // The marker needs to adjust its tx, for the case where it's an outside marker.
- RenderObject* listItem = 0;
- int leftLineOffset = 0;
- int rightLineOffset = 0;
- if (!listPositionInside()) {
- listItem = this;
- int yOffset = 0;
- int xOffset = 0;
- while (listItem && listItem != m_listItem) {
- yOffset += listItem->yPos();
- xOffset += listItem->xPos();
- listItem = listItem->parent();
- }
-
- // Now that we have our xoffset within the listbox, we need to adjust ourselves by the delta
- // between our current xoffset and our desired position (which is just outside the border box
- // of the list item).
- if (style()->direction() == LTR) {
- leftLineOffset = m_listItem->leftRelOffset(yOffset, m_listItem->leftOffset(yOffset));
- _tx -= (xOffset - leftLineOffset) + m_listItem->paddingLeft() + m_listItem->borderLeft();
- }
- else {
- rightLineOffset = m_listItem->rightRelOffset(yOffset, m_listItem->rightOffset(yOffset));
- _tx += (rightLineOffset-xOffset) + m_listItem->paddingRight() + m_listItem->borderRight();
- }
- }
-
- int offset = fm.ascent()*2/3;
- bool haveImage = m_listImage && !m_listImage->isErrorImage();
- if (haveImage)
- offset = m_listImage->pixmap().width();
-
- int xoff = 0;
- int yoff = fm.ascent() - offset;
-
- int bulletWidth = offset/2;
- if (offset%2)
- bulletWidth++;
- if (!listPositionInside()) {
- if (listItem && listItem->style()->direction() == LTR)
- xoff = -cMarkerPadding - offset;
- else
- xoff = cMarkerPadding + (haveImage ? 0 : (offset - bulletWidth));
- }
- else if (style()->direction() == RTL)
- xoff += haveImage ? cMarkerPadding : (m_width - bulletWidth);
-
- if ( m_listImage && !m_listImage->isErrorImage()) {
- p->drawPixmap( TQPoint( _tx + xoff, _ty ), m_listImage->pixmap());
- return;
- }
-
-#ifdef BOX_DEBUG
- p->setPen( Qt::red );
- p->drawRect( _tx + xoff, _ty + yoff, offset, offset );
-#endif
-
- const TQColor color( style()->color() );
- p->setPen( color );
-
- switch(style()->listStyleType()) {
- case LDISC:
- p->setBrush( color );
- p->drawEllipse( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
- return;
- case LCIRCLE:
- p->setBrush( Qt::NoBrush );
- p->drawEllipse( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
- return;
- case LSQUARE:
- p->setBrush( color );
- p->drawRect( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
- return;
- case LBOX:
- p->setBrush( Qt::NoBrush );
- p->drawRect( _tx + xoff, _ty + (3 * yoff)/2, (offset>>1)+1, (offset>>1)+1 );
- return;
- case LDIAMOND: {
- static TQPointArray diamond(4);
- int x = _tx + xoff;
- int y = _ty + (3 * yoff)/2 - 1;
- int s = (offset>>2)+1;
- diamond[0] = TQPoint(x+s, y);
- diamond[1] = TQPoint(x+2*s, y+s);
- diamond[2] = TQPoint(x+s, y+2*s);
- diamond[3] = TQPoint(x, y+s);
- p->setBrush( color );
- p->drawConvexPolygon( diamond, 0, 4 );
- return;
- }
- case LNONE:
- return;
- default:
- if (!m_item.isEmpty()) {
- if(listPositionInside()) {
- if( style()->direction() == LTR) {
- p->drawText(_tx, _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, m_item);
- p->drawText(_tx + fm.width(m_item), _ty, 0, 0, Qt::AlignLeft|TQt::DontClip,
- TQString::fromLatin1(". "));
- }
- else {
- const TQString& punct(TQString::fromLatin1(" ."));
- p->drawText(_tx, _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, punct);
- p->drawText(_tx + fm.width(punct), _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, m_item);
- }
- } else {
- if (style()->direction() == LTR) {
- const TQString& punct(TQString::fromLatin1(". "));
- p->drawText(_tx-offset/2, _ty, 0, 0, Qt::AlignRight|TQt::DontClip, punct);
- p->drawText(_tx-offset/2-fm.width(punct), _ty, 0, 0, Qt::AlignRight|TQt::DontClip, m_item);
- }
- else {
- const TQString& punct(TQString::fromLatin1(" ."));
- p->drawText(_tx+offset/2, _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, punct);
- p->drawText(_tx+offset/2+fm.width(punct), _ty, 0, 0, Qt::AlignLeft|TQt::DontClip, m_item);
- }
- }
- }
- }
-}
-
-void RenderListMarker::layout()
-{
- KHTMLAssert( needsLayout() );
-
- if ( !minMaxKnown() )
- calcMinMaxWidth();
-
- setNeedsLayout(false);
-}
-
-void RenderListMarker::setPixmap( const TQPixmap &p, const TQRect& r, CachedImage *o)
-{
- if(o != m_listImage) {
- RenderBox::setPixmap(p, r, o);
- return;
- }
-
- if(m_width != m_listImage->pixmap_size().width() || m_height != m_listImage->pixmap_size().height())
- setNeedsLayoutAndMinMaxRecalc();
- else
- repaintRectangle(0, 0, m_width, m_height);
-}
-
-void RenderListMarker::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- m_markerWidth = m_width = 0;
-
- if(m_listImage && !m_listImage->isErrorImage()) {
- m_markerWidth = m_listImage->pixmap().width() + cMarkerPadding;
- if (listPositionInside())
- m_width = m_markerWidth;
- m_height = m_listImage->pixmap().height();
- m_minWidth = m_maxWidth = m_width;
- setMinMaxKnown();
- return;
- }
-
- const TQFontMetrics &fm = style()->fontMetrics();
- m_height = fm.ascent();
-
- // Skip uncounted elements
- switch(style()->listStyleType()) {
- // Glyphs:
- case LDISC:
- case LCIRCLE:
- case LSQUARE:
- case LBOX:
- case LDIAMOND:
- m_markerWidth = fm.ascent();
- goto end;
- default:
- break;
- }
-
- { // variable scope
- CounterNode *counter = m_listItem->m_counter;
- if (!counter) {
- counter = m_listItem->getCounter("list-item", true);
- counter->setRenderer(this);
- m_listItem->m_counter = counter;
- }
-
-
- assert(counter);
- int value = counter->count();
- if (counter->isReset()) value = counter->value();
- int total = value;
- if (counter->parent()) total = counter->parent()->total();
-
- switch(style()->listStyleType())
- {
-// Numeric:
- case LDECIMAL:
- m_item.setNum ( value );
- break;
- case DECIMAL_LEADING_ZERO: {
- int decimals = 2;
- int t = total/100;
- while (t>0) {
- t = t/10;
- decimals++;
- }
- decimals = kMax(decimals, 2);
- TQString num = TQString::number(value);
- m_item.fill('0',decimals-num.length());
- m_item.append(num);
- break;
- }
- case ARABIC_INDIC:
- m_item = toArabicIndic( value );
- break;
- case LAO:
- m_item = toLao( value );
- break;
- case PERSIAN:
- case URDU:
- m_item = toPersianUrdu( value );
- break;
- case THAI:
- m_item = toThai( value );
- break;
- case TIBETAN:
- m_item = toTibetan( value );
- break;
-// Algoritmic:
- case LOWER_ROMAN:
- m_item = toRoman( value, false );
- break;
- case UPPER_ROMAN:
- m_item = toRoman( value, true );
- break;
- case HEBREW:
- m_item = toHebrew( value );
- break;
- case ARMENIAN:
- m_item = toArmenian( value );
- break;
- case GEORGIAN:
- m_item = toGeorgian( value );
- break;
-// Alphabetic:
- case LOWER_ALPHA:
- case LOWER_LATIN:
- m_item = toLowerLatin( value );
- break;
- case UPPER_ALPHA:
- case UPPER_LATIN:
- m_item = toUpperLatin( value );
- break;
- case LOWER_GREEK:
- m_item = toLowerGreek( value );
- break;
- case UPPER_GREEK:
- m_item = toUpperGreek( value );
- break;
- case HIRAGANA:
- m_item = toHiragana( value );
- break;
- case HIRAGANA_IROHA:
- m_item = toHiraganaIroha( value );
- break;
- case KATAKANA:
- m_item = toKatakana( value );
- break;
- case KATAKANA_IROHA:
- m_item = toKatakanaIroha( value );
- break;
-// Ideographic:
- case JAPANESE_FORMAL:
- m_item = toJapaneseFormal( value );
- break;
- case JAPANESE_INFORMAL:
- m_item = toJapaneseInformal( value );
- break;
- case SIMP_CHINESE_FORMAL:
- m_item = toSimpChineseFormal( value );
- break;
- case SIMP_CHINESE_INFORMAL:
- m_item = toSimpChineseInformal( value );
- break;
- case TRAD_CHINESE_FORMAL:
- m_item = toTradChineseFormal( value );
- break;
- case CJK_IDEOGRAPHIC:
- // CSS 3 List says treat as trad-chinese-informal
- case TRAD_CHINESE_INFORMAL:
- m_item = toTradChineseInformal( value );
- break;
-// special:
- case LNONE:
- break;
- default:
- KHTMLAssert(false);
- }
- m_markerWidth = fm.width(m_item) + fm.width(TQString::fromLatin1(". "));
- }
-
-end:
- if(listPositionInside())
- m_width = m_markerWidth;
-
- m_minWidth = m_width;
- m_maxWidth = m_width;
-
- setMinMaxKnown();
-}
-
-short RenderListMarker::lineHeight(bool /*b*/) const
-{
- return height();
-}
-
-short RenderListMarker::baselinePosition(bool /*b*/) const
-{
- return height();
-}
-
-void RenderListMarker::calcWidth()
-{
- RenderBox::calcWidth();
-}
-
-/*
-int CounterListItem::recount() const
-{
- static_cast<RenderListItem*>(m_renderer)->m_marker->setNeedsLayoutAndMinMaxRecalc();
-}
-
-void CounterListItem::setSelfDirty()
-{
-
-}*/
-
-
-#undef BOX_DEBUG
diff --git a/khtml/rendering/render_list.h b/khtml/rendering/render_list.h
deleted file mode 100644
index b70132671..000000000
--- a/khtml/rendering/render_list.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_LIST_H
-#define RENDER_LIST_H
-
-#include "rendering/render_block.h"
-
-// ### list-style-position, list-style-image is still missing
-
-namespace DOM
-{
- class DocumentImpl;
-}
-
-namespace khtml
-{
-
-class RenderListItem;
-class RenderListMarker;
-class CounterNode;
-
-// -----------------------------------------------------------------------------
-
-class RenderListItem : public RenderBlock
-{
- friend class RenderListMarker;
-// friend class CounterListItem;
-
-public:
- RenderListItem(DOM::NodeImpl*);
-
- virtual const char *renderName() const { return "RenderListItem"; }
-
- virtual void setStyle(RenderStyle *style);
-
- virtual bool isListItem() const { return true; }
-
- void setValue( long v ) { predefVal = v; }
-
- virtual void layout( );
- virtual void detach( );
- virtual void calcMinMaxWidth();
- //virtual short marginLeft() const;
- //virtual short marginRight() const;
-
- void setInsideList(bool b ) { m_insideList = b; }
-
-protected:
-
- void updateMarkerLocation();
- void resetListMarker() { m_marker = 0; }
-
- RenderListMarker *m_marker;
- CounterNode *m_counter;
- signed long predefVal : 30;
- bool m_insideList : 1;
- bool m_deleteMarker: 1;
-};
-
-// -----------------------------------------------------------------------------
-
-class RenderListMarker : public RenderBox
-{
-public:
- RenderListMarker(DOM::NodeImpl* node);
- ~RenderListMarker();
-
- virtual void setStyle(RenderStyle *style);
-
- virtual const char *renderName() const { return "RenderListMarker"; }
- // so the marker gets to layout itself. Only needed for
- // list-style-position: inside
-
- virtual void paint(PaintInfo& i, int xoff, int yoff);
- virtual void layout( );
- virtual void calcMinMaxWidth();
-
- virtual short lineHeight( bool firstLine ) const;
- virtual short baselinePosition( bool firstLine ) const;
-
- virtual void setPixmap( const TQPixmap &, const TQRect&, CachedImage *);
-
- virtual void calcWidth();
-
- virtual bool isListMarker() const { return true; }
-
- virtual short markerWidth() const { return m_markerWidth; }
-
- RenderListItem* listItem() const { return m_listItem; }
- void setListItem(RenderListItem* listItem) { m_listItem = listItem; }
-
- bool listPositionInside() const
- { return !m_listItem->m_insideList || style()->listStylePosition() == INSIDE; }
-
-protected:
- friend class RenderListItem;
-
- TQString m_item;
- CachedImage *m_listImage;
- short m_markerWidth;
- RenderListItem* m_listItem;
-};
-
-// Implementation of list-item counter
-// ### should replace most list-item specific code in renderObject::getCounter
-/*
-class CounterListItem : public CounterNode
-{
-public:
- int count() const;
-
- virtual void recount( bool first = false );
- virtual void setSelfDirty();
-
-}; */
-
-} //namespace
-
-#endif
diff --git a/khtml/rendering/render_object.cpp b/khtml/rendering/render_object.cpp
deleted file mode 100644
index f03039759..000000000
--- a/khtml/rendering/render_object.cpp
+++ /dev/null
@@ -1,2330 +0,0 @@
-/**
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2002-2006 Apple Computer, Inc.
- * (C) 2006 Germain Garand <germain@ebooksfrance.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "rendering/render_object.h"
-#include "rendering/render_table.h"
-#include "rendering/render_list.h"
-#include "rendering/render_canvas.h"
-#include "rendering/render_block.h"
-#include "rendering/render_arena.h"
-#include "rendering/render_layer.h"
-#include "rendering/render_line.h"
-#include "rendering/render_inline.h"
-#include "rendering/render_text.h"
-#include "rendering/render_replaced.h"
-#include "rendering/render_generated.h"
-#include "rendering/counter_tree.h"
-
-#include "xml/dom_elementimpl.h"
-#include "xml/dom_docimpl.h"
-#include "dom/dom_doc.h"
-#include "misc/htmlhashes.h"
-#include "misc/loader.h"
-
-#include <kdebug.h>
-#include <kglobal.h>
-#include <tqpainter.h>
-#include "khtmlview.h"
-#include <khtml_part.h>
-
-#include <assert.h>
-using namespace DOM;
-using namespace khtml;
-
-#define RED_LUMINOSITY 30
-#define GREEN_LUMINOSITY 59
-#define BLUE_LUMINOSITY 11
-#define INTENSITY_FACTOR 25
-#define LIGHT_FACTOR 0
-#define LUMINOSITY_FACTOR 75
-
-#define MAX_COLOR 255
-#define COLOR_DARK_THRESHOLD 51
-#define COLOR_LIGHT_THRESHOLD 204
-
-#define COLOR_LITE_BS_FACTOR 45
-#define COLOR_LITE_TS_FACTOR 70
-
-#define COLOR_DARK_BS_FACTOR 30
-#define COLOR_DARK_TS_FACTOR 50
-
-#define LIGHT_GRAY tqRgb(192, 192, 192)
-#define DARK_GRAY tqRgb(96, 96, 96)
-
-#ifndef NDEBUG
-static void *baseOfRenderObjectBeingDeleted;
-#endif
-
-//#define MASK_DEBUG
-
-void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
-{
- return renderArena->allocate(sz);
-}
-
-void RenderObject::operator delete(void* ptr, size_t sz)
-{
- assert(baseOfRenderObjectBeingDeleted == ptr);
-
- // Stash size where detach can find it.
- *(size_t *)ptr = sz;
-}
-
-RenderObject *RenderObject::createObject(DOM::NodeImpl* node, RenderStyle* style)
-{
- RenderObject *o = 0;
- khtml::RenderArena* arena = node->getDocument()->renderArena();
- switch(style->display())
- {
- case NONE:
- break;
- case INLINE:
- o = new (arena) RenderInline(node);
- break;
- case BLOCK:
- o = new (arena) RenderBlock(node);
- break;
- case INLINE_BLOCK:
- o = new (arena) RenderBlock(node);
- break;
- case LIST_ITEM:
- o = new (arena) RenderListItem(node);
- break;
- case RUN_IN:
- case COMPACT:
- o = new (arena) RenderBlock(node);
- break;
- case TABLE:
- case INLINE_TABLE:
- style->setFlowAroundFloats(true);
- o = new (arena) RenderTable(node);
- break;
- case TABLE_ROW_GROUP:
- case TABLE_HEADER_GROUP:
- case TABLE_FOOTER_GROUP:
- o = new (arena) RenderTableSection(node);
- break;
- case TABLE_ROW:
- o = new (arena) RenderTableRow(node);
- break;
- case TABLE_COLUMN_GROUP:
- case TABLE_COLUMN:
- o = new (arena) RenderTableCol(node);
- break;
- case TABLE_CELL:
- o = new (arena) RenderTableCell(node);
- break;
- case TABLE_CAPTION:
- o = new (arena) RenderBlock(node);
- break;
- }
- return o;
-}
-
-
-RenderObject::RenderObject(DOM::NodeImpl* node)
- : CachedObjectClient(),
- m_style( 0 ),
- m_node( node ),
- m_parent( 0 ),
- m_previous( 0 ),
- m_next( 0 ),
- m_verticalPosition( PositionUndefined ),
- m_needsLayout( false ),
- m_normalChildNeedsLayout( false ),
- m_markedForRepaint( false ),
- m_posChildNeedsLayout( false ),
- m_minMaxKnown( false ),
- m_floating( false ),
-
- m_positioned( false ),
- m_overhangingContents( false ),
- m_relPositioned( false ),
- m_paintBackground( false ),
-
- m_isAnonymous( node->isDocumentNode() ),
- m_recalcMinMax( false ),
- m_isText( false ),
- m_inline( true ),
- m_attached( false ),
-
- m_replaced( false ),
- m_mouseInside( false ),
- m_hasFirstLine( false ),
- m_isSelectionBorder( false ),
- m_isRoot( false ),
- m_afterPageBreak( false ),
- m_needsPageClear( false ),
- m_containsPageBreak( false ),
- m_hasOverflowClip( false ),
- m_doNotDelete( false )
-{
- assert( node );
- if (node->getDocument()->documentElement() == node) setIsRoot(true);
-}
-
-RenderObject::~RenderObject()
-{
- const BackgroundLayer* bgLayer = m_style->backgroundLayers();
- while (bgLayer) {
- if(bgLayer->backgroundImage())
- bgLayer->backgroundImage()->deref(this);
- bgLayer = bgLayer->next();
- }
-
- if (m_style)
- m_style->deref();
-}
-
-
-
-RenderObject* RenderObject::objectBelow() const
-{
- RenderObject* obj = firstChild();
- if ( !obj ) {
- obj = nextSibling();
- if ( !obj )
- {
- obj = parent();
- while (obj && !obj->nextSibling())
- obj = obj->parent();
- if (obj)
- obj = obj->nextSibling();
- }
- }
- return obj;
-}
-
-RenderObject* RenderObject::objectAbove() const
-{
- RenderObject* obj = previousSibling();
- if ( !obj )
- return parent();
-
- RenderObject* last = obj->lastChild();
- while ( last )
- {
- obj = last;
- last = last->lastChild();
- }
- return obj;
-}
-/*
-bool RenderObject::isRoot() const
-{
- return !isAnonymous() &&
- element()->getDocument()->documentElement() == element();
-}*/
-
-bool RenderObject::isHR() const
-{
- return element() && element()->id() == ID_HR;
-}
-
-bool RenderObject::isWordBreak() const
-{
- return element() && element()->id() == ID_WBR;
-}
-
-bool RenderObject::isHTMLMarquee() const
-{
- return element() && element()->renderer() == this && element()->id() == ID_MARQUEE;
-}
-
-void RenderObject::addChild(RenderObject* , RenderObject *)
-{
- KHTMLAssert(0);
-}
-
-RenderObject* RenderObject::removeChildNode(RenderObject* )
-{
- KHTMLAssert(0);
- return 0;
-}
-
-void RenderObject::removeChild(RenderObject *o )
-{
- setNeedsLayout(true);
- removeChildNode( o );
-}
-
-void RenderObject::appendChildNode(RenderObject*)
-{
- KHTMLAssert(0);
-}
-
-void RenderObject::insertChildNode(RenderObject*, RenderObject*)
-{
- KHTMLAssert(0);
-}
-
-RenderObject *RenderObject::nextRenderer() const
-{
- if (firstChild())
- return firstChild();
- else if (nextSibling())
- return nextSibling();
- else {
- const RenderObject *r = this;
- while (r && !r->nextSibling())
- r = r->parent();
- if (r)
- return r->nextSibling();
- }
- return 0;
-}
-
-RenderObject *RenderObject::previousRenderer() const
-{
- if (previousSibling()) {
- RenderObject *r = previousSibling();
- while (r->lastChild())
- r = r->lastChild();
- return r;
- }
- else if (parent()) {
- return parent();
- }
- else {
- return 0;
- }
-}
-
-static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject,
- RenderLayer*& beforeChild)
-{
- if (obj->layer()) {
- if (!beforeChild && newObject) {
- // We need to figure out the layer that follows newObject. We only do
- // this the first time we find a child layer, and then we update the
- // pointer values for newObject and beforeChild used by everyone else.
- beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
- newObject = 0;
- }
- parentLayer->addChild(obj->layer(), beforeChild);
- return;
- }
-
- for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
- addLayers(curr, parentLayer, newObject, beforeChild);
-}
-
-void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
-{
- if (!parentLayer)
- return;
-
- RenderObject* object = newObject;
- RenderLayer* beforeChild = 0;
- ::addLayers(this, parentLayer, object, beforeChild);
-}
-
-void RenderObject::removeLayers(RenderLayer* parentLayer)
-{
- if (!parentLayer)
- return;
-
- if (layer()) {
- parentLayer->removeChild(layer());
- return;
- }
-
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
- curr->removeLayers(parentLayer);
-}
-
-void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
-{
- if (!newParent)
- return;
-
- if (layer()) {
- if (oldParent)
- oldParent->removeChild(layer());
- newParent->addChild(layer());
- return;
- }
-
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
- curr->moveLayers(oldParent, newParent);
-}
-
-RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
- bool checkParent)
-{
- // Error check the parent layer passed in. If it's null, we can't find anything.
- if (!parentLayer)
- return 0;
-
- // Step 1: If our layer is a child of the desired parent, then return our layer.
- RenderLayer* ourLayer = layer();
- if (ourLayer && ourLayer->parent() == parentLayer)
- return ourLayer;
-
- // Step 2: If we don't have a layer, or our layer is the desired parent, then descend
- // into our siblings trying to find the next layer whose parent is the desired parent.
- if (!ourLayer || ourLayer == parentLayer) {
- for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
- curr; curr = curr->nextSibling()) {
- RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
- if (nextLayer)
- return nextLayer;
- }
- }
-
- // Step 3: If our layer is the desired parent layer, then we're finished. We didn't
- // find anything.
- if (parentLayer == ourLayer)
- return 0;
-
- // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
- // follow us to see if we can locate a layer.
- if (checkParent && parent())
- return parent()->findNextLayer(parentLayer, this, true);
-
- return 0;
-}
-
-RenderLayer* RenderObject::enclosingLayer() const
-{
- const RenderObject* curr = this;
- while (curr) {
- RenderLayer *layer = curr->layer();
- if (layer)
- return layer;
- curr = curr->parent();
- }
- return 0;
-}
-
-RenderLayer* RenderObject::enclosingStackingContext() const
-{
- RenderLayer* l = enclosingLayer();
- while (l && !l->isStackingContext())
- l = l->parent();
- return l;
-}
-
-int RenderObject::offsetLeft() const
-{
- if ( isPositioned() )
- return xPos();
-
- if ( isBody() && style()->htmlHacks() )
- return 0;
-
- int x = xPos();
- if (isRelPositioned()) {
- int y = 0;
- static_cast<const RenderBox*>(this)->relativePositionOffset(x, y);
- }
-
- RenderObject* offsetPar = offsetParent();
- for( RenderObject* curr = parent();
- curr && curr != offsetPar;
- curr = curr->parent() )
- x += curr->xPos();
-
- if ( offsetPar && offsetPar->isBody() && style()->htmlHacks() )
- x += offsetPar->xPos();
-
- return x;
-}
-
-int RenderObject::offsetTop() const
-{
- if ( isPositioned() )
- return yPos();
-
- if ( isBody() && style()->htmlHacks() )
- return 0;
-
- int y = yPos();
- if (isRelPositioned()) {
- int x = 0;
- static_cast<const RenderBox*>(this)->relativePositionOffset(x, y);
- }
- RenderObject* offsetPar = offsetParent();
- for( RenderObject* curr = parent();
- curr && curr != offsetPar;
- curr = curr->parent() )
- y += curr->yPos();
-
- if ( offsetPar && offsetPar->isBody() && style()->htmlHacks() )
- y += offsetPar->yPos();
-
- return y;
-}
-
-RenderObject* RenderObject::offsetParent() const
-{
- if (isBody())
- return 0;
-
- // can't really use containing blocks here (#113280)
- bool skipTables = isPositioned() || isRelPositioned();
- bool strict = !style()->htmlHacks();
- RenderObject* curr = parent();
- while (curr && (!curr->element() ||
- (!curr->isPositioned() && !curr->isRelPositioned() &&
- !(strict && skipTables ? curr->isRoot() : curr->isBody())))) {
- if (!skipTables && curr->element() && (curr->isTableCell() || curr->isTable()))
- break;
- curr = curr->parent();
- }
- return curr;
-}
-
-// IE extensions.
-// clientWidth and clientHeight represent the interior of an object
-short RenderObject::clientWidth() const
-{
- return width() - borderLeft() - borderRight() -
- (layer() ? layer()->verticalScrollbarWidth() : 0);
-}
-
-int RenderObject::clientHeight() const
-{
- return height() - borderTop() - borderBottom() -
- (layer() ? layer()->horizontalScrollbarHeight() : 0);
-}
-
-// scrollWidth/scrollHeight is the size including the overflow area
-short RenderObject::scrollWidth() const
-{
- return (hasOverflowClip() && layer()) ? layer()->scrollWidth() : overflowWidth() - overflowLeft();
-}
-
-int RenderObject::scrollHeight() const
-{
- return (hasOverflowClip() && layer()) ? layer()->scrollHeight() : overflowHeight() - overflowTop();
-}
-
-bool RenderObject::hasStaticX() const
-{
- return (style()->left().isVariable() && style()->right().isVariable());
-}
-
-bool RenderObject::hasStaticY() const
-{
- return (style()->top().isVariable() && style()->bottom().isVariable());
-}
-
-void RenderObject::setPixmap(const TQPixmap&, const TQRect& /*r*/, CachedImage* image)
-{
- //repaint bg when it finished loading
- if(image && parent() && style() && style()->backgroundLayers()->containsImage(image)) {
- isBody() ? canvas()->repaint() : repaint();
- }
-}
-
-void RenderObject::setNeedsLayout(bool b, bool markParents)
-{
- bool alreadyNeededLayout = m_needsLayout;
- m_needsLayout = b;
- if (b) {
- if (!alreadyNeededLayout && markParents && m_parent) {
- dirtyFormattingContext( false );
- markContainingBlocksForLayout();
- }
- }
- else {
- m_posChildNeedsLayout = false;
- m_normalChildNeedsLayout = false;
- }
-}
-
-void RenderObject::setChildNeedsLayout(bool b, bool markParents)
-{
- bool alreadyNeededLayout = m_normalChildNeedsLayout;
- m_normalChildNeedsLayout = b;
- if (b) {
- if (!alreadyNeededLayout && markParents)
- markContainingBlocksForLayout();
- }
- else {
- m_posChildNeedsLayout = false;
- m_normalChildNeedsLayout = false;
- }
-}
-
-void RenderObject::markContainingBlocksForLayout()
-{
- RenderObject *o = container();
- RenderObject *last = this;
-
- while (o) {
- if (!last->isText() && (last->style()->position() == FIXED || last->style()->position() == ABSOLUTE)) {
- if (o->m_posChildNeedsLayout)
- return;
- o->m_posChildNeedsLayout = true;
- }
- else {
- if (o->m_normalChildNeedsLayout)
- return;
- o->m_normalChildNeedsLayout = true;
- }
-
- last = o;
- o = o->container();
- }
-
- last->scheduleRelayout();
-}
-
-RenderBlock *RenderObject::containingBlock() const
-{
- if(isTableCell())
- return static_cast<RenderBlock*>( parent()->parent()->parent() );
- if (isCanvas())
- return const_cast<RenderBlock*>( static_cast<const RenderBlock*>(this) );
-
- RenderObject *o = parent();
- if(m_style->position() == FIXED) {
- while ( o && !o->isCanvas() )
- o = o->parent();
- }
- else if(m_style->position() == ABSOLUTE) {
- while (o &&
- ( o->style()->position() == STATIC || ( o->isInline() && !o->isReplaced() ) ) && !o->isCanvas()) {
- // for relpos inlines, return the nearest block - it will host the positioned objects list
- if (o->isInline() && !o->isReplaced() && o->style()->position() == RELATIVE)
- return o->containingBlock();
- o = o->parent();
- }
- } else {
- while(o && ( ( o->isInline() && !o->isReplaced() ) || o->isTableRow() || o->isTableSection() ||
- o->isTableCol() || o->isFrameSet() ) )
- o = o->parent();
- }
- // this is just to make sure we return a valid element.
- // the case below should never happen...
- if(!o || !o->isRenderBlock()) {
- if(!isCanvas()) {
-#ifndef NDEBUG
- kdDebug( 6040 ) << this << ": " << renderName() << "(RenderObject): No containingBlock!" << endl;
- kdDebug( 6040 ) << kdBacktrace() << endl;
- const RenderObject* p = this;
- while (p->parent()) p = p->parent();
- p->printTree();
-#endif
- }
- return 0L;
- }
-
- return static_cast<RenderBlock*>( o );
-}
-
-short RenderObject::containingBlockWidth() const
-{
- // ###
- return containingBlock()->contentWidth();
-}
-
-int RenderObject::containingBlockHeight() const
-{
- // ###
- return containingBlock()->contentHeight();
-}
-
-bool RenderObject::sizesToMaxWidth() const
-{
- // Marquees in WinIE are like a mixture of blocks and inline-blocks. They size as though they're blocks,
- // but they allow text to sit on the same line as the marquee.
- if (isFloating() || isCompact() ||
- (isInlineBlockOrInlineTable() && !isHTMLMarquee()) ||
- (element() && (element()->id() == ID_BUTTON || element()->id() == ID_LEGEND)))
- return true;
-
- // Children of a horizontal marquee do not fill the container by default.
- // FIXME: Need to deal with MAUTO value properly. It could be vertical.
- if (parent()->style()->overflowX() == OMARQUEE) {
- EMarqueeDirection dir = parent()->style()->marqueeDirection();
- if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
- return true;
- }
-
-#ifdef APPLE_CHANGES // ### what the heck is a flexbox?
- // Flexible horizontal boxes lay out children at their maxwidths. Also vertical boxes
- // that don't stretch their kids lay out their children at their maxwidths.
- if (parent()->isFlexibleBox() &&
- (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
- return true;
-#endif
-
- return false;
-}
-
-// from Mozilla's nsCSSColorUtils.cpp
-static int brightness(int red, int green, int blue)
-{
-
- int intensity = (red + green + blue) / 3;
-
- int luminosity =
- ((RED_LUMINOSITY * red) / 100) +
- ((GREEN_LUMINOSITY * green) / 100) +
- ((BLUE_LUMINOSITY * blue) / 100);
-
- return ((intensity * INTENSITY_FACTOR) +
- (luminosity * LUMINOSITY_FACTOR)) / 100;
-}
-
-static void calc3DColor(TQColor &color, bool darken)
-{
- int rb = color.red();
- int gb = color.green();
- int bb = color.blue();
-
- int brightness_ = brightness(rb,gb,bb);
-
- int f0, f1;
- if (brightness_ < COLOR_DARK_THRESHOLD) {
- f0 = COLOR_DARK_BS_FACTOR;
- f1 = COLOR_DARK_TS_FACTOR;
- } else if (brightness_ > COLOR_LIGHT_THRESHOLD) {
- f0 = COLOR_LITE_BS_FACTOR;
- f1 = COLOR_LITE_TS_FACTOR;
- } else {
- f0 = COLOR_DARK_BS_FACTOR +
- (brightness_ *
- (COLOR_LITE_BS_FACTOR - COLOR_DARK_BS_FACTOR) / MAX_COLOR);
- f1 = COLOR_DARK_TS_FACTOR +
- (brightness_ *
- (COLOR_LITE_TS_FACTOR - COLOR_DARK_TS_FACTOR) / MAX_COLOR);
- }
-
- if (darken) {
- int r = rb - (f0 * rb / 100);
- int g = gb - (f0 * gb / 100);
- int b = bb - (f0 * bb / 100);
- if ((r == rb) && (g == gb) && (b == bb))
- color = (color == Qt::black) ? DARK_GRAY : Qt::black;
- else
- color.setRgb(r, g, b);
- } else {
- int r = kMin(rb + (f1 * (MAX_COLOR - rb) / 100), 255);
- int g = kMin(gb + (f1 * (MAX_COLOR - gb) / 100), 255);
- int b = kMin(bb + (f1 * (MAX_COLOR - bb) / 100), 255);
- if ((r == rb) && (g == gb) && (b == bb))
- color = (color == Qt::white) ? LIGHT_GRAY : Qt::white;
- else
- color.setRgb(r, g, b);
- }
-}
-
-void RenderObject::drawBorder(TQPainter *p, int x1, int y1, int x2, int y2,
- BorderSide s, TQColor c, const TQColor& textcolor, EBorderStyle style,
- int adjbw1, int adjbw2, bool invalidisInvert)
-{
- int width = (s==BSTop||s==BSBottom?y2-y1:x2-x1);
-
- if(style == DOUBLE && width < 3)
- style = SOLID;
-
- if(!c.isValid()) {
- if(invalidisInvert)
- {
- p->setRasterOp(TQt::XorROP);
- c = Qt::white;
- }
- else {
- if(style == INSET || style == OUTSET || style == RIDGE || style ==
- GROOVE)
- c = Qt::white;
- else
- c = textcolor;
- }
- }
-
- switch(style)
- {
- case BNATIVE:
- case BNONE:
- case BHIDDEN:
- // should not happen
- if(invalidisInvert && p->rasterOp() == TQt::XorROP)
- p->setRasterOp(TQt::CopyROP);
-
- return;
- case DOTTED:
- if ( width == 1 ) {
- // workaround Qt brokenness
- p->setPen(TQPen(c, width, Qt::SolidLine));
- switch(s) {
- case BSBottom:
- case BSTop:
- for ( ; x1 < x2; x1 += 2 )
- p->drawPoint( x1, y1 );
- break;
- case BSRight:
- case BSLeft:
- for ( ; y1 < y2; y1 += 2 )
- p->drawPoint( x1, y1 );
- }
- break;
- }
-
- p->setPen(TQPen(c, width, Qt::DotLine));
- /* nobreak; */
- case DASHED:
- if(style == DASHED)
- p->setPen(TQPen(c, width == 1 ? 0 : width, width == 1 ? Qt::DotLine : Qt::DashLine));
-
- if (width > 0)
- switch(s) {
- case BSBottom:
- case BSTop:
- p->drawLine(x1, (y1+y2)/2, x2, (y1+y2)/2);
- break;
- case BSRight:
- case BSLeft:
- p->drawLine((x1+x2)/2, y1, (x1+x2)/2, y2);
- break;
- }
-
- break;
- case DOUBLE:
- {
- int third = (width+1)/3;
-
- if (adjbw1 == 0 && adjbw2 == 0)
- {
- p->setPen(Qt::NoPen);
- p->setBrush(c);
- switch(s)
- {
- case BSTop:
- case BSBottom:
- p->drawRect(x1, y1 , x2-x1, third);
- p->drawRect(x1, y2-third, x2-x1, third);
- break;
- case BSLeft:
- p->drawRect(x1 , y1+1, third, y2-y1-1);
- p->drawRect(x2-third, y1+1, third, y2-y1-1);
- break;
- case BSRight:
- p->drawRect(x1 , y1+1, third, y2-y1-1);
- p->drawRect(x2-third, y1+1, third, y2-y1-1);
- break;
- }
- }
- else
- {
- int adjbw1bigthird;
- if (adjbw1>0) adjbw1bigthird = adjbw1+1;
- else adjbw1bigthird = adjbw1 - 1;
- adjbw1bigthird /= 3;
-
- int adjbw2bigthird;
- if (adjbw2>0) adjbw2bigthird = adjbw2 + 1;
- else adjbw2bigthird = adjbw2 - 1;
- adjbw2bigthird /= 3;
-
- switch(s)
- {
- case BSTop:
- drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y1 , x2-kMax((-adjbw2*2+1)/3,0), y1 + third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y2 - third, x2-kMax(( adjbw2*2+1)/3,0), y2 , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- break;
- case BSLeft:
- drawBorder(p, x1 , y1+kMax((-adjbw1*2+1)/3,0), x1+third, y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(p, x2 - third, y1+kMax(( adjbw1*2+1)/3,0), x2 , y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- break;
- case BSBottom:
- drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y1 , x2-kMax(( adjbw2*2+1)/3,0), y1+third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y2-third, x2-kMax((-adjbw2*2+1)/3,0), y2 , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- break;
- case BSRight:
- drawBorder(p, x1 , y1+kMax(( adjbw1*2+1)/3,0), x1+third, y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- drawBorder(p, x2-third, y1+kMax((-adjbw1*2+1)/3,0), x2 , y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
- break;
- default:
- break;
- }
- }
- break;
- }
- case RIDGE:
- case GROOVE:
- {
- EBorderStyle s1;
- EBorderStyle s2;
- if (style==GROOVE)
- {
- s1 = INSET;
- s2 = OUTSET;
- }
- else
- {
- s1 = OUTSET;
- s2 = INSET;
- }
-
- int adjbw1bighalf;
- int adjbw2bighalf;
- if (adjbw1>0) adjbw1bighalf=adjbw1+1;
- else adjbw1bighalf=adjbw1-1;
- adjbw1bighalf/=2;
-
- if (adjbw2>0) adjbw2bighalf=adjbw2+1;
- else adjbw2bighalf=adjbw2-1;
- adjbw2bighalf/=2;
-
- switch (s)
- {
- case BSTop:
- drawBorder(p, x1+kMax(-adjbw1 ,0)/2, y1 , x2-kMax(-adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
- drawBorder(p, x1+kMax( adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax( adjbw2+1,0)/2, y2 , s, c, textcolor, s2, adjbw1/2, adjbw2/2);
- break;
- case BSLeft:
- drawBorder(p, x1 , y1+kMax(-adjbw1 ,0)/2, (x1+x2+1)/2, y2-kMax(-adjbw2,0)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
- drawBorder(p, (x1+x2+1)/2, y1+kMax( adjbw1+1,0)/2, x2 , y2-kMax( adjbw2+1,0)/2, s, c, textcolor, s2, adjbw1/2, adjbw2/2);
- break;
- case BSBottom:
- drawBorder(p, x1+kMax( adjbw1 ,0)/2, y1 , x2-kMax( adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
- drawBorder(p, x1+kMax(-adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax(-adjbw2+1,0)/2, y2 , s, c, textcolor, s1, adjbw1/2, adjbw2/2);
- break;
- case BSRight:
- drawBorder(p, x1 , y1+kMax( adjbw1 ,0)/2, (x1+x2+1)/2, y2-kMax( adjbw2,0)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
- drawBorder(p, (x1+x2+1)/2, y1+kMax(-adjbw1+1,0)/2, x2 , y2-kMax(-adjbw2+1,0)/2, s, c, textcolor, s1, adjbw1/2, adjbw2/2);
- break;
- }
- break;
- }
- case INSET:
- case OUTSET:
- calc3DColor(c, (style == OUTSET && (s == BSBottom || s == BSRight)) ||
- (style == INSET && ( s == BSTop || s == BSLeft ) ) );
- /* nobreak; */
- case SOLID:
- p->setPen(Qt::NoPen);
- p->setBrush(c);
- Q_ASSERT(x2>=x1);
- Q_ASSERT(y2>=y1);
- if (adjbw1==0 && adjbw2 == 0) {
- p->drawRect(x1,y1,x2-x1,y2-y1);
- return;
- }
- TQPointArray quad(4);
- switch(s) {
- case BSTop:
- quad.setPoints(4,
- x1+kMax(-adjbw1,0), y1,
- x1+kMax( adjbw1,0), y2,
- x2-kMax( adjbw2,0), y2,
- x2-kMax(-adjbw2,0), y1);
- break;
- case BSBottom:
- quad.setPoints(4,
- x1+kMax( adjbw1,0), y1,
- x1+kMax(-adjbw1,0), y2,
- x2-kMax(-adjbw2,0), y2,
- x2-kMax( adjbw2,0), y1);
- break;
- case BSLeft:
- quad.setPoints(4,
- x1, y1+kMax(-adjbw1,0),
- x1, y2-kMax(-adjbw2,0),
- x2, y2-kMax( adjbw2,0),
- x2, y1+kMax( adjbw1,0));
- break;
- case BSRight:
- quad.setPoints(4,
- x1, y1+kMax( adjbw1,0),
- x1, y2-kMax( adjbw2,0),
- x2, y2-kMax(-adjbw2,0),
- x2, y1+kMax(-adjbw1,0));
- break;
- }
- p->drawConvexPolygon(quad);
- break;
- }
-
- if(invalidisInvert && p->rasterOp() == TQt::XorROP)
- p->setRasterOp(TQt::CopyROP);
-}
-
-void RenderObject::paintBorder(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin, bool end)
-{
- const TQColor& tc = style->borderTopColor();
- const TQColor& bc = style->borderBottomColor();
- const TQColor& lc = style->borderLeftColor();
- const TQColor& rc = style->borderRightColor();
-
- bool tt = style->borderTopIsTransparent();
- bool bt = style->borderBottomIsTransparent();
- bool rt = style->borderRightIsTransparent();
- bool lt = style->borderLeftIsTransparent();
-
- EBorderStyle ts = style->borderTopStyle();
- EBorderStyle bs = style->borderBottomStyle();
- EBorderStyle ls = style->borderLeftStyle();
- EBorderStyle rs = style->borderRightStyle();
-
- bool render_t = ts > BHIDDEN && !tt;
- bool render_l = ls > BHIDDEN && begin && !lt;
- bool render_r = rs > BHIDDEN && end && !rt;
- bool render_b = bs > BHIDDEN && !bt;
-
- if(render_t) {
- bool ignore_left =
- (tc == lc) && (tt == lt) &&
- (ts >= OUTSET) &&
- (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET);
-
- bool ignore_right =
- (tc == rc) && (tt == rt) &&
- (ts >= OUTSET) &&
- (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET);
-
- drawBorder(p, _tx, _ty, _tx + w, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
- ignore_left?0:style->borderLeftWidth(),
- ignore_right?0:style->borderRightWidth());
- }
-
- if(render_b) {
- bool ignore_left =
- (bc == lc) && (bt == lt) &&
- (bs >= OUTSET) &&
- (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET);
-
- bool ignore_right =
- (bc == rc) && (bt == rt) &&
- (bs >= OUTSET) &&
- (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET);
-
- drawBorder(p, _tx, _ty + h - style->borderBottomWidth(), _tx + w, _ty + h, BSBottom, bc, style->color(), bs,
- ignore_left?0:style->borderLeftWidth(),
- ignore_right?0:style->borderRightWidth());
- }
-
- if(render_l)
- {
- bool ignore_top =
- (tc == lc) && (tt == lt) &&
- (ls >= OUTSET) &&
- (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
-
- bool ignore_bottom =
- (bc == lc) && (bt == lt) &&
- (ls >= OUTSET) &&
- (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
-
- drawBorder(p, _tx, _ty, _tx + style->borderLeftWidth(), _ty + h, BSLeft, lc, style->color(), ls,
- ignore_top?0:style->borderTopWidth(),
- ignore_bottom?0:style->borderBottomWidth());
- }
-
- if(render_r)
- {
- bool ignore_top =
- (tc == rc) && (tt == rt) &&
- (rs >= DOTTED || rs == INSET) &&
- (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET);
-
- bool ignore_bottom =
- (bc == rc) && (bt == rt) &&
- (rs >= DOTTED || rs == INSET) &&
- (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET);
-
- drawBorder(p, _tx + w - style->borderRightWidth(), _ty, _tx + w, _ty + h, BSRight, rc, style->color(), rs,
- ignore_top?0:style->borderTopWidth(),
- ignore_bottom?0:style->borderBottomWidth());
- }
-}
-
-void RenderObject::paintOutline(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style)
-{
- int ow = style->outlineWidth();
- if(!ow) return;
-
- const TQColor& oc = style->outlineColor();
- EBorderStyle os = style->outlineStyle();
- int offset = style->outlineOffset();
-
-#ifdef APPLE_CHANGES
- if (style->outlineStyleIsAuto()) {
- p->initFocusRing(ow, offset, oc);
- addFocusRingRects(p, _tx, _ty);
- p->drawFocusRing();
- p->clearFocusRing();
- return;
- }
-#endif
-
- _tx -= offset;
- _ty -= offset;
- w += 2*offset;
- h += 2*offset;
-
- drawBorder(p, _tx-ow, _ty-ow, _tx, _ty+h+ow, BSLeft,
- TQColor(oc), style->color(),
- os, ow, ow, true);
-
- drawBorder(p, _tx-ow, _ty-ow, _tx+w+ow, _ty, BSTop,
- TQColor(oc), style->color(),
- os, ow, ow, true);
-
- drawBorder(p, _tx+w, _ty-ow, _tx+w+ow, _ty+h+ow, BSRight,
- TQColor(oc), style->color(),
- os, ow, ow, true);
-
- drawBorder(p, _tx-ow, _ty+h, _tx+w+ow, _ty+h+ow, BSBottom,
- TQColor(oc), style->color(),
- os, ow, ow, true);
-
-}
-
-void RenderObject::paint( PaintInfo&, int /*tx*/, int /*ty*/)
-{
-}
-
-void RenderObject::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
-{
- if(parent()) parent()->repaintRectangle(x, y, w, h, p, f);
-}
-
-#ifdef ENABLE_DUMP
-
-TQString RenderObject::information() const
-{
- TQString str;
- int x; int y;
- absolutePosition(x,y);
- x += inlineXPos();
- y += inlineYPos();
- TQTextStream ts( &str, IO_WriteOnly );
- ts << renderName()
- << "(" << (style() ? style()->refCount() : 0) << ")"
- << ": " << (void*)this << " ";
- ts << "{" << x << " " << y << "} ";
- if (isInline()) ts << "il ";
- if (childrenInline()) ts << "ci ";
- if (isFloating()) ts << "fl ";
- if (isAnonymous()) ts << "an ";
- if (isRelPositioned()) ts << "rp ";
- if (isPositioned()) ts << "ps ";
- if (isReplaced()) ts << "rp ";
- if (overhangingContents()) ts << "oc ";
- if (needsLayout()) ts << "nl ";
- if (minMaxKnown()) ts << "mmk ";
- if (m_recalcMinMax) ts << "rmm ";
- if (mouseInside()) ts << "mi ";
- if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
- if (style() && style()->hasAutoZIndex()) ts << "zI: auto ";
- if (element()) {
- if (element()->active()) ts << "act ";
- if (element()->hasAnchor()) ts << "anchor ";
- if (element()->focused()) ts << "focus ";
- ts << " <" << getTagName(element()->id()) << ">";
-
- } else if (isPseudoAnonymous() && style() && style()->styleType() != RenderStyle::NOPSEUDO) {
- ts << " <" << getTagName(node()->id());
- TQString pseudo;
- switch (style()->styleType()) {
- case RenderStyle::FIRST_LETTER:
- pseudo = ":first-letter"; break;
- case RenderStyle::BEFORE:
- pseudo = ":before"; break;
- case RenderStyle::AFTER:
- pseudo = ":after"; break;
- default:
- pseudo = ":pseudo-element";
- }
- ts << pseudo;
- ts << ">";
- }
- ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"
- << " [" << minWidth() << "-" << maxWidth() << "]"
- << " { mT: " << marginTop() << " qT: " << isTopMarginQuirk()
- << " mB: " << marginBottom() << " qB: " << isBottomMarginQuirk()
- << "}"
- << (isTableCell() ?
- ( TQString::fromLatin1(" [r=") +
- TQString::number( static_cast<const RenderTableCell *>(this)->row() ) +
- TQString::fromLatin1(" c=") +
- TQString::number( static_cast<const RenderTableCell *>(this)->col() ) +
- TQString::fromLatin1(" rs=") +
- TQString::number( static_cast<const RenderTableCell *>(this)->rowSpan() ) +
- TQString::fromLatin1(" cs=") +
- TQString::number( static_cast<const RenderTableCell *>(this)->colSpan() ) +
- TQString::fromLatin1("]") ) : TQString::null );
- if ( layer() )
- ts << " layer=" << layer();
- if ( continuation() )
- ts << " continuation=" << continuation();
- if (isText())
- ts << " \"" << TQConstString(static_cast<const RenderText *>(this)->text(), kMin(static_cast<const RenderText *>(this)->length(), 10u)).string() << "\"";
- return str;
-}
-
-void RenderObject::printTree(int indent) const
-{
- TQString ind;
- ind.fill(' ', indent);
-
- kdDebug() << ind << information() << endl;
-
- RenderObject *child = firstChild();
- while( child != 0 )
- {
- child->printTree(indent+2);
- child = child->nextSibling();
- }
-}
-
-static TQTextStream &operator<<(TQTextStream &ts, const TQRect &r)
-{
- return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
-}
-
-//A bit like getTagName, but handles XML, too.
-static TQString lookupTagName(NodeImpl* node) {
- return node->getDocument()->getName(NodeImpl::ElementId, node->id()).string();
-}
-
-void RenderObject::dump(TQTextStream &ts, const TQString &ind) const
-{
- if ( !layer() )
- ts << endl;
-
- ts << ind << renderName();
-
- if (style() && style()->zIndex()) {
- ts << " zI: " << style()->zIndex();
- }
-
- if (element()) {
- TQString tagName(lookupTagName(element()));
- if (!tagName.isEmpty()) {
- ts << " {" << tagName << "}";
- }
- } else if (isPseudoAnonymous() && style() && style()->styleType() != RenderStyle::NOPSEUDO) {
- TQString pseudo;
- TQString tagName(lookupTagName(node()));
- switch (style()->styleType()) {
- case RenderStyle::FIRST_LETTER:
- pseudo = ":first-letter"; break;
- case RenderStyle::BEFORE:
- pseudo = ":before"; break;
- case RenderStyle::AFTER:
- pseudo = ":after"; break;
- default:
- pseudo = ":pseudo-element";
- }
- ts << " {" << tagName << pseudo << "}";
- }
-
- TQRect r(xPos(), yPos(), width(), height());
- ts << " " << r;
-
- if ( parent() )
- ts << style()->createDiff( *parent()->style() );
-
- if (isAnonymous()) { ts << " anonymousBox"; }
- if (isFloating()) { ts << " floating"; }
- if (isPositioned()) { ts << " positioned"; }
- if (isRelPositioned()) { ts << " relPositioned"; }
- if (isText()) { ts << " text"; }
- if (isInline()) { ts << " inline"; }
- if (isReplaced()) { ts << " replaced"; }
- if (shouldPaintBackgroundOrBorder()) { ts << " paintBackground"; }
- if (needsLayout()) { ts << " needsLayout"; }
- if (minMaxKnown()) { ts << " minMaxKnown"; }
- if (overhangingContents()) { ts << " overhangingContents"; }
- if (hasFirstLine()) { ts << " hasFirstLine"; }
- if (afterPageBreak()) { ts << " afterPageBreak"; }
-}
-#endif
-
-void RenderObject::selectionStartEnd(int& spos, int& epos)
-{
- if (parent())
- parent()->selectionStartEnd(spos, epos);
-}
-
-void RenderObject::setStyle(RenderStyle *style)
-{
- if (m_style == style)
- return;
-
- RenderStyle::Diff d = m_style ? m_style->diff( style ) : RenderStyle::Layout;
- //tqDebug("m_style: %p new style, diff=%d", m_style, d);
-
- Priority pri = NormalPriority;
- if (m_style) {
- pri = HighPriority;
- if ( d >= RenderStyle::Visible && !isText() && m_parent &&
- ( d == RenderStyle::Position ||
- m_style->outlineWidth() > style->outlineWidth() ||
- (!m_style->hidesOverflow() && style->hidesOverflow()) ||
- ( m_style->hasClip() && !(m_style->clip() == style->clip()) ) ) ) {
- // schedule a repaint with the old style
- if (layer() && !isInlineFlow())
- layer()->repaint(pri);
- else
- repaint(pri);
- }
-
- if ( ( isFloating() && m_style->floating() != style->floating() ) ||
- ( isPositioned() && m_style->position() != style->position() &&
- style->position() != ABSOLUTE && style->position() != FIXED ) )
- removeFromObjectLists();
-
- if ( layer() ) {
- if ( ( m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
- m_style->zIndex() != style->zIndex() ||
- m_style->visibility() != style->visibility() ) ) {
- layer()->stackingContext()->dirtyZOrderLists();
- layer()->dirtyZOrderLists();
- }
- }
-
- // reset style flags
- m_floating = false;
- m_positioned = false;
- m_relPositioned = false;
- m_paintBackground = false;
- m_hasOverflowClip = false;
- }
-
- // only honour z-index for non-static objects
- // ### and objects with opacity
- if ( style->position() == STATIC ) {
- if ( isRoot() )
- style->setZIndex( 0 );
- else
- style->setHasAutoZIndex();
- }
-
- RenderStyle *oldStyle = m_style;
- m_style = style;
-
- updateBackgroundImages(oldStyle);
-
- m_style->ref();
-
- if (oldStyle)
- oldStyle->deref();
-
- setShouldPaintBackgroundOrBorder(m_style->hasBorder() || m_style->hasBackground());
-
- m_hasFirstLine = (style->getPseudoStyle(RenderStyle::FIRST_LINE) != 0);
- if (m_parent) {
- if (d == RenderStyle::Position && !attemptDirectLayerTranslation())
- d = RenderStyle::Layout;
-
- if ( d > RenderStyle::Position) {
- // we must perform a full layout
- if (!isText() && d == RenderStyle::CbLayout) {
- dirtyFormattingContext( true );
- }
- setNeedsLayoutAndMinMaxRecalc();
- } else if (!isText() && d >= RenderStyle::Visible) {
- // a repaint is enough
- if (layer()) {
- if (canvas() && canvas()->needsWidgetMasks()) {
- // update our widget masks
- RenderLayer *p, *d = 0;
- for (p=layer()->parent();p;p=p->parent())
- if (p->hasOverlaidWidgets()) d=p;
- if (d) // deepest
- d->updateWidgetMasks( canvas()->layer() );
- }
- }
- if (layer() && !isInlineFlow())
- layer()->repaint(pri);
- else
- repaint(pri);
- }
- }
-}
-
-bool RenderObject::attemptDirectLayerTranslation()
-{
- // When the difference between two successive styles is only 'Position'
- // we may attempt to save a layout by directly updating the object position.
-
- KHTMLAssert( m_style->position() != STATIC );
- if (!layer())
- return false;
- setInline(m_style->isDisplayInlineType());
- setPositioned(m_style->position() != RELATIVE);
- setRelPositioned(m_style->position() == RELATIVE);
- int oldXPos = xPos();
- int oldYPos = yPos();
- int oldWidth = width();
- int oldHeight = height();
- calcWidth();
- calcHeight();
- if (oldWidth != width() || oldHeight != height()) {
- // implicit size change or overconstrained dimensions:
- // we'll need a layout.
- setWidth(oldWidth);
- setHeight(oldHeight);
- // kdDebug() << "Layer translation failed for " << information() << endl;
- return false;
- }
- layer()->updateLayerPosition();
- if (m_style->position() != FIXED) {
- bool needsDocSizeUpdate = true;
- RenderObject *cb = container();
- while (cb) {
- if (cb->hasOverflowClip() && cb->layer()) {
- cb->layer()->checkScrollbarsAfterLayout();
- needsDocSizeUpdate = false;
- break;
- }
- cb = cb->container();
- }
- if (needsDocSizeUpdate && canvas()) {
- bool posXOffset = (xPos()-oldXPos >= 0);
- bool posYOffset = (yPos()-oldYPos >= 0);
- canvas()->updateDocSizeAfterLayerTranslation(this, posXOffset, posYOffset);
- }
- }
- // success
- return true;
-}
-
-void RenderObject::dirtyFormattingContext( bool checkContainer )
-{
- if (m_markedForRepaint && !checkContainer)
- return;
- m_markedForRepaint = true;
- if (layer() && (style()->position() == FIXED || style()->position() == ABSOLUTE))
- return;
- if (m_parent && (checkContainer || style()->width().isVariable() || style()->height().isVariable() ||
- !(isFloating() || flowAroundFloats() || isTableCell())))
- m_parent->dirtyFormattingContext(false);
-}
-
-void RenderObject::repaintDuringLayout()
-{
- if (canvas()->needsFullRepaint() || isText())
- return;
- if (layer() && !isInlineFlow()) {
- layer()->repaint( NormalPriority, true );
- } else {
- repaint();
- canvas()->deferredRepaint( this );
- }
-}
-
-void RenderObject::setOverhangingContents(bool p)
-{
- if (m_overhangingContents == p)
- return;
-
- RenderBlock *cb = containingBlock();
- if (p)
- {
- m_overhangingContents = true;
- KHTMLAssert( cb != this || isCanvas());
- if (cb && cb != this)
- cb->setOverhangingContents();
- }
- else
- {
- RenderObject *n;
- bool c=false;
-
- for( n = firstChild(); n != 0; n = n->nextSibling() )
- {
- if (n->isPositioned() || n->overhangingContents())
- c=true;
- }
-
- if (c)
- return;
- else
- {
- m_overhangingContents = false;
- KHTMLAssert( cb != this );
- if (cb && cb != this)
- cb->setOverhangingContents(false);
- }
- }
-}
-
-void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
-{
- // FIXME: This will be slow when a large number of images is used. Fix by using a dict.
- const BackgroundLayer* oldLayers = oldStyle ? oldStyle->backgroundLayers() : 0;
- const BackgroundLayer* newLayers = m_style ? m_style->backgroundLayers() : 0;
- for (const BackgroundLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
- if (currOld->backgroundImage() && (!newLayers || !newLayers->containsImage(currOld->backgroundImage())))
- currOld->backgroundImage()->deref(this);
- }
- for (const BackgroundLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
- if (currNew->backgroundImage() && (!oldLayers || !oldLayers->containsImage(currNew->backgroundImage())))
- currNew->backgroundImage()->ref(this);
- }
-}
-
-TQRect RenderObject::viewRect() const
-{
- return containingBlock()->viewRect();
-}
-
-bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f) const
-{
- RenderObject* p = parent();
- if (p) {
- p->absolutePosition(xPos, yPos, f);
- if ( p->hasOverflowClip() )
- p->layer()->subtractScrollOffset( xPos, yPos );
- return true;
- }
- else
- {
- xPos = yPos = 0;
- return false;
- }
-}
-
-void RenderObject::caretPos(int /*offset*/, int /*flags*/, int &_x, int &_y, int &width, int &height)
-{
- _x = _y = height = -1;
- width = 1; // the caret has a default width of one pixel. If you want
- // to check for validity, only test the x-coordinate for >= 0.
-}
-
-int RenderObject::paddingTop() const
-{
- int w = 0;
- Length padding = m_style->paddingTop();
- if (padding.isPercent())
- w = containingBlock()->contentWidth();
- w = padding.minWidth(w);
- if ( isTableCell() && padding.isVariable() )
- w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
- return w;
-}
-
-int RenderObject::paddingBottom() const
-{
- int w = 0;
- Length padding = style()->paddingBottom();
- if (padding.isPercent())
- w = containingBlock()->contentWidth();
- w = padding.minWidth(w);
- if ( isTableCell() && padding.isVariable() )
- w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
- return w;
-}
-
-int RenderObject::paddingLeft() const
-{
- int w = 0;
- Length padding = style()->paddingLeft();
- if (padding.isPercent())
- w = containingBlock()->contentWidth();
- w = padding.minWidth(w);
- if ( isTableCell() && padding.isVariable() )
- w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
- return w;
-}
-
-int RenderObject::paddingRight() const
-{
- int w = 0;
- Length padding = style()->paddingRight();
- if (padding.isPercent())
- w = containingBlock()->contentWidth();
- w = padding.minWidth(w);
- if ( isTableCell() && padding.isVariable() )
- w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
- return w;
-}
-
-RenderObject *RenderObject::container() const
-{
- // This method is extremely similar to containingBlock(), but with a few notable
- // exceptions.
- // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
- // the object is not part of the primary document subtree yet.
- // (2) For normal flow elements, it just returns the parent.
- // (3) For absolute positioned elements, it will return a relative positioned inline.
- // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
- // the layout of the positioned object. This does mean that calcAbsoluteHorizontal and
- // calcAbsoluteVertical have to use container().
- EPosition pos = m_style->position();
- RenderObject *o = 0;
- if( pos == FIXED ) {
- // container() can be called on an object that is not in the
- // tree yet. We don't call canvas() since it will assert if it
- // can't get back to the canvas. Instead we just walk as high up
- // as we can. If we're in the tree, we'll get the root. If we
- // aren't we'll get the root of our little subtree (most likely
- // we'll just return 0).
- o = parent();
- while ( o && o->parent() ) o = o->parent();
- }
- else if ( pos == ABSOLUTE ) {
- // Same goes here. We technically just want our containing block, but
- // we may not have one if we're part of an uninstalled subtree. We'll
- // climb as high as we can though.
- o = parent();
- while (o && o->style()->position() == STATIC && !o->isCanvas())
- o = o->parent();
- }
- else
- o = parent();
- return o;
-}
-
-DOM::DocumentImpl* RenderObject::document() const
-{
- return m_node->getDocument();
-}
-
-void RenderObject::remove()
-{
- if ( parent() )
- //have parent, take care of the tree integrity
- parent()->removeChild(this);
-}
-
-void RenderObject::removeFromObjectLists()
-{
- // in destruction mode, don't care.
- if ( !document()->renderer() ) return;
-
- if (isFloating()) {
- RenderBlock* outermostBlock = containingBlock();
- for (RenderBlock* p = outermostBlock; p && !p->isCanvas() && p->containsFloat(this);) {
- outermostBlock = p;
- if (p->isFloatingOrPositioned())
- break;
- p = p->containingBlock();
- }
-
- if (outermostBlock)
- outermostBlock->markAllDescendantsWithFloatsForLayout(this);
- }
-
- if (isPositioned()) {
- RenderObject *p;
- for (p = parent(); p; p = p->parent()) {
- if (p->isRenderBlock())
- static_cast<RenderBlock*>(p)->removePositionedObject(this);
- }
- }
-}
-
-RenderArena* RenderObject::renderArena() const
-{
- return m_node->getDocument()->renderArena();
-}
-
-void RenderObject::detach()
-{
- detachCounters();
-
- deleteInlineBoxes();
- remove();
-
- // make sure our DOM-node don't think we exist
- if ( node() && node()->renderer() == this)
- node()->setRenderer(0);
-
- // by default no refcounting
- arenaDelete(renderArena(), this);
-}
-
-void RenderObject::arenaDelete(RenderArena *arena, void *base)
-{
-#ifndef NDEBUG
- void *savedBase = baseOfRenderObjectBeingDeleted;
- baseOfRenderObjectBeingDeleted = base;
-#endif
- delete this;
-#ifndef NDEBUG
- baseOfRenderObjectBeingDeleted = savedBase;
-#endif
-
- // Recover the size left there for us by operator delete and free the memory.
- arena->free(*(size_t *)base, base);
-}
-
-void RenderObject::arenaDelete(RenderArena *arena)
-{
- // static_cast unfortunately doesn't work, since we multiple inherit
- // in eg. RenderWidget.
- arenaDelete(arena, dynamic_cast<void *>(this));
-}
-
-FindSelectionResult RenderObject::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state )
-{
-#if 0
- NodeInfo info(true, false);
- if ( nodeAtPoint( info, _x, _y, _tx, _ty ) && info.innerNode() )
- {
- RenderObject* r = info.innerNode()->renderer();
- if ( r ) {
- if ( r == this ) {
- node = info.innerNode();
- offset = 0; // we have no text...
- return SelectionPointInside;
- }
- else
- return r->checkSelectionPoint( _x, _y, _tx, _ty, node, offset, state );
- }
- }
- //kdDebug(6030) << "nodeAtPoint Failed. Fallback - hmm, SelectionPointAfter" << endl;
- node = 0;
- offset = 0;
- return SelectionPointAfter;
-#endif
- int off = offset;
- DOM::NodeImpl* nod = node;
-
- for (RenderObject *child = firstChild(); child; child=child->nextSibling()) {
- // ignore empty text boxes, they produce totally bogus information
- // for caret navigation (LS)
- if (child->isText() && !static_cast<RenderText *>(child)->inlineTextBoxCount())
- continue;
-
-// kdDebug(6040) << "iterating " << (child ? child->renderName() : "") << "@" << child << (child->isText() ? " contains: \"" + TQConstString(static_cast<RenderText *>(child)->text(), kMin(static_cast<RenderText *>(child)->length(), 10u)).string() + "\"" : TQString::null) << endl;
-// kdDebug(6040) << "---------- checkSelectionPoint recursive -----------" << endl;
- khtml::FindSelectionResult pos = child->checkSelectionPoint(_x, _y, _tx+xPos(), _ty+yPos(), nod, off, state);
-// kdDebug(6040) << "-------- end checkSelectionPoint recursive ---------" << endl;
-// kdDebug(6030) << this << " child->findSelectionNode returned result=" << pos << " nod=" << nod << " off=" << off << endl;
- switch(pos) {
- case SelectionPointBeforeInLine:
- case SelectionPointInside:
- //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " returning SelectionPointInside offset=" << offset << endl;
- node = nod;
- offset = off;
- return SelectionPointInside;
- case SelectionPointBefore:
- //x,y is before this element -> stop here
- if ( state.m_lastNode ) {
- node = state.m_lastNode;
- offset = state.m_lastOffset;
- //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " before this child "
- // << node << "-> returning SelectionPointInside, offset=" << offset << endl;
- return SelectionPointInside;
- } else {
- node = nod;
- offset = off;
- //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " before us -> returning SelectionPointBefore " << node << "/" << offset << endl;
- return SelectionPointBefore;
- }
- break;
- case SelectionPointAfter:
- if (state.m_afterInLine) break;
- // fall through
- case SelectionPointAfterInLine:
- if (pos == SelectionPointAfterInLine) state.m_afterInLine = true;
- //kdDebug(6030) << "RenderObject::checkSelectionPoint: selection after: " << nod << " offset: " << off << " afterInLine: " << state.m_afterInLine << endl;
- state.m_lastNode = nod;
- state.m_lastOffset = off;
- // No "return" here, obviously. We must keep looking into the children.
- break;
- }
- }
- // If we are after the last child, return lastNode/lastOffset
- // But lastNode can be 0L if there is no child, for instance.
- if ( state.m_lastNode )
- {
- node = state.m_lastNode;
- offset = state.m_lastOffset;
- }
- //kdDebug(6030) << "fallback - SelectionPointAfter node=" << node << " offset=" << offset << endl;
- return SelectionPointAfter;
-}
-
-bool RenderObject::mouseInside() const
-{
- if (!m_mouseInside && continuation())
- return continuation()->mouseInside();
- return m_mouseInside;
-}
-
-bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
-{
- int tx = _tx + xPos();
- int ty = _ty + yPos();
-
- inside |= ( style()->visibility() != HIDDEN &&
- (_y >= ty) && (_y < ty + height()) && (_x >= tx) && (_x < tx + width())) || isRoot() || isBody();
- bool inOverflowRect = inside;
- if ( !inOverflowRect ) {
- int ol = overflowLeft();
- int ot = overflowTop();
- TQRect overflowRect( tx+ol, ty+ot, overflowWidth()-ol, overflowHeight()-ot );
- inOverflowRect = overflowRect.contains( _x, _y );
- }
-
- // ### table should have its own, more performant method
- if (hitTestAction != HitTestSelfOnly &&
- (( !isRenderBlock() ||
- !static_cast<RenderBlock*>( this )->isPointInScrollbar( _x, _y, _tx, _ty )) &&
- (overhangingContents() || inOverflowRect || isInline() || isRoot() || isCanvas() ||
- isTableRow() || isTableSection() || inside || mouseInside() ))) {
- if ( hitTestAction == HitTestChildrenOnly )
- inside = false;
- if ( hasOverflowClip() && layer() )
- layer()->subtractScrollOffset(tx, ty);
- for (RenderObject* child = lastChild(); child; child = child->previousSibling())
- if (!child->layer() && child->nodeAtPoint(info, _x, _y, tx, ty, HitTestAll))
- inside = true;
- }
-
- if (inside)
- setInnerNode(info);
-
- return inside;
-}
-
-
-void RenderObject::setInnerNode(NodeInfo& info)
-{
- if (!info.innerNode() && !isInline() && continuation()) {
- // We are in the margins of block elements that are part of a continuation. In
- // this case we're actually still inside the enclosing inline element that was
- // split. Go ahead and set our inner node accordingly.
- info.setInnerNode(continuation()->element());
- if (!info.innerNonSharedNode())
- info.setInnerNonSharedNode(continuation()->element());
- }
-
- if (!info.innerNode() && element())
- info.setInnerNode(element());
-
- if(!info.innerNonSharedNode() && element())
- info.setInnerNonSharedNode(element());
-}
-
-
-short RenderObject::verticalPositionHint( bool firstLine ) const
-{
- short vpos = m_verticalPosition;
- if ( m_verticalPosition == PositionUndefined || firstLine ) {
- vpos = getVerticalPosition( firstLine );
- if ( !firstLine )
- const_cast<RenderObject *>(this)->m_verticalPosition = vpos;
- }
- return vpos;
-
-}
-
-short RenderObject::getVerticalPosition( bool firstLine, RenderObject* ref ) const
-{
- // vertical align for table cells has a different meaning
- int vpos = 0;
- if ( !isTableCell() && isInline() ) {
- EVerticalAlign va = style()->verticalAlign();
- if ( va == TOP ) {
- vpos = PositionTop;
- } else if ( va == BOTTOM ) {
- vpos = PositionBottom;
- } else {
- if (!ref) ref = parent();
- bool checkParent = ref->isInline() && !ref->isReplacedBlock() &&
- !( ref->style()->verticalAlign() == TOP || ref->style()->verticalAlign() == BOTTOM );
- vpos = checkParent ? ref->verticalPositionHint( firstLine ) : 0;
- // don't allow elements nested inside text-top to have a different valignment.
- if ( va == BASELINE )
- return vpos;
- else if ( va == LENGTH )
- return vpos - style()->verticalAlignLength().width( lineHeight( firstLine ) );
-
- const TQFont &f = ref->font( firstLine );
- int fontsize = f.pixelSize();
-
- if ( va == SUB )
- vpos += fontsize/5 + 1;
- else if ( va == SUPER )
- vpos -= fontsize/3 + 1;
- else if ( va == TEXT_TOP ) {
- vpos += baselinePosition( firstLine ) - (TQFontMetrics(f).ascent() + TQFontMetrics(f).leading()/2);
- } else if ( va == MIDDLE ) {
- TQRect b = TQFontMetrics(f).boundingRect('x');
- vpos += -b.height()/2 - lineHeight( firstLine )/2 + baselinePosition( firstLine );
- } else if ( va == TEXT_BOTTOM ) {
- vpos += TQFontMetrics(f).descent() + TQFontMetrics(f).leading()/2;
- if ( !isReplaced() )
- vpos -= fontMetrics(firstLine).descent();
- } else if ( va == BASELINE_MIDDLE )
- vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
- }
- }
- return vpos;
-}
-
-short RenderObject::lineHeight( bool firstLine ) const
-{
- // Inline blocks are replaced elements. Otherwise, just pass off to
- // the base class. If we're being queried as though we're the root line
- // box, then the fact that we're an inline-block is irrelevant, and we behave
- // just like a block.
-
- if (isReplaced() && (!isInlineBlockOrInlineTable() || !needsLayout()))
- return height()+marginTop()+marginBottom();
-
- Length lh;
- if( firstLine && hasFirstLine() ) {
- RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
- if ( pseudoStyle )
- lh = pseudoStyle->lineHeight();
- }
- else
- lh = style()->lineHeight();
-
- // its "unset", choose nice default
- if ( lh.value() < 0 )
- return style()->fontMetrics().lineSpacing();
-
- if ( lh.isPercent() )
- return lh.minWidth( style()->font().pixelSize() );
-
- // its fixed
- return lh.value();
-}
-
-short RenderObject::baselinePosition( bool firstLine ) const
-{
- // Inline blocks are replaced elements. Otherwise, just pass off to
- // the base class. If we're being queried as though we're the root line
- // box, then the fact that we're an inline-block is irrelevant, and we behave
- // just like a block.
-
- if (isReplaced() && (!isInlineBlockOrInlineTable() || !needsLayout()))
- return height()+marginTop()+marginBottom();
-
- const TQFontMetrics &fm = fontMetrics( firstLine );
- return fm.ascent() + ( lineHeight( firstLine) - fm.height() ) / 2;
-}
-
-void RenderObject::invalidateVerticalPositions()
-{
- m_verticalPosition = PositionUndefined;
- RenderObject *child = firstChild();
- while( child ) {
- child->invalidateVerticalPositions();
- child = child->nextSibling();
- }
-}
-
-void RenderObject::recalcMinMaxWidths()
-{
- KHTMLAssert( m_recalcMinMax );
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
-#endif
-
- RenderObject *child = firstChild();
- int cmin=0;
- int cmax=0;
-
- while( child ) {
- bool test = false;
- if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
- cmin = child->minWidth();
- cmax = child->maxWidth();
- test = true;
- }
- if ( child->m_recalcMinMax )
- child->recalcMinMaxWidths();
- if ( !child->m_minMaxKnown )
- child->calcMinMaxWidth();
- if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) )
- m_minMaxKnown = false;
- child = child->nextSibling();
- }
-
- // we need to recalculate, if the contains inline children, as the change could have
- // happened somewhere deep inside the child tree
- if ( ( !isInline() || isReplacedBlock() ) && childrenInline() )
- m_minMaxKnown = false;
-
- if ( !m_minMaxKnown )
- calcMinMaxWidth();
- m_recalcMinMax = false;
-}
-
-void RenderObject::scheduleRelayout(RenderObject *clippedObj)
-{
- if (!isCanvas()) return;
- KHTMLView *view = static_cast<RenderCanvas *>(this)->view();
- if ( view )
- view->scheduleRelayout(clippedObj);
-}
-
-
-void RenderObject::removeLeftoverAnonymousBoxes()
-{
-}
-
-InlineBox* RenderObject::createInlineBox(bool /*makePlaceHolderBox*/, bool /*isRootLineBox*/)
-{
- KHTMLAssert(false);
- return 0;
-}
-
-void RenderObject::getTextDecorationColors(int decorations, TQColor& underline, TQColor& overline,
- TQColor& linethrough, bool quirksMode)
-{
- RenderObject* curr = this;
- do {
- RenderStyle *st = curr->style();
- int currDecs = st->textDecoration();
- if (currDecs) {
- if (currDecs & UNDERLINE) {
- decorations &= ~UNDERLINE;
- underline = st->color();
- }
- if (currDecs & OVERLINE) {
- decorations &= ~OVERLINE;
- overline = st->color();
- }
- if (currDecs & LINE_THROUGH) {
- decorations &= ~LINE_THROUGH;
- linethrough = st->color();
- }
- }
- curr = curr->parent();
- if (curr && curr->isRenderBlock() && curr->continuation())
- curr = curr->continuation();
- } while (curr && decorations && (!quirksMode || !curr->element() ||
- (curr->element()->id() != ID_A && curr->element()->id() != ID_FONT)));
-
- // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
- if (decorations && curr) {
- RenderStyle *st = curr->style();
- if (decorations & UNDERLINE)
- underline = st->color();
- if (decorations & OVERLINE)
- overline = st->color();
- if (decorations & LINE_THROUGH)
- linethrough = st->color();
- }
-}
-
-int RenderObject::maximalOutlineSize(PaintAction p) const
-{
- if (p != PaintActionOutline)
- return 0;
- return static_cast<RenderCanvas*>(document()->renderer())->maximalOutlineSize();
-}
-
-void RenderObject::collectBorders(TQValueList<CollapsedBorderValue>& borderStyles)
-{
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
- curr->collectBorders(borderStyles);
-}
-
-bool RenderObject::flowAroundFloats() const
-{
- return isReplaced() || hasOverflowClip() || style()->flowAroundFloats();
-}
-
-bool RenderObject::usesLineWidth() const
-{
- // 1. All auto-width objects that avoid floats should always use lineWidth
- // 2. For objects with a specified width, we match WinIE's behavior:
- // (a) tables use contentWidth
- // (b) <hr>s use lineWidth
- // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode.
- return (flowAroundFloats() && (style()->width().isVariable() || isHR() || (style()->htmlHacks() && !isTable())));
-}
-
-bool RenderObject::hasCounter(const TQString& counter) const
-{
- if (style() && (!isText() || isCounter())) {
- if (lookupCounter(counter)) return true;
- if (style()->hasCounterReset(counter)) {
- return true;
- }
- else if (style()->hasCounterIncrement(counter)) {
- return true;
- }
- }
- if (counter == "list-item") {
- if (isListItem()) return true;
- if (element() && (
- element()->id() == ID_OL ||
- element()->id() == ID_UL ||
- element()->id() == ID_MENU ||
- element()->id() == ID_DIR))
- return true;
- } else
- if (counter == "-khtml-quotes" && isQuote()) {
- return (static_cast<const RenderQuote*>(this)->quoteCount() != 0);
- }
- return false;
-}
-
-CounterNode* RenderObject::getCounter(const TQString& counter, bool view, bool counters)
-{
-// kdDebug( 6040 ) << renderName() << " getCounter(" << counter << ")" << endl;
-
- if (!style()) return 0;
-
- if (isText() && !isCounter()) return 0;
-
- CounterNode *i = lookupCounter(counter);
- if (i) return i;
- int val = 0;
-
- if (style()->hasCounterReset(counter) || isRoot()) {
- i = new CounterReset(this);
- val = style()->counterReset(counter);
- if (style()->hasCounterIncrement(counter)) {
- val += style()->counterIncrement(counter);
- }
-// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
- }
- else
- if (style()->hasCounterIncrement(counter)) {
- i = new CounterNode(this);
- val = style()->counterIncrement(counter);
-// kdDebug( 6040 ) << renderName() << " counter-increment: " << counter << " " << val << endl;
- }
- else if (counter == "list-item") {
- if (isListItem()) {
- if (element() && element()->id() == ID_LI) {
- DOMString v = static_cast<ElementImpl*>(element())->getAttribute(ATTR_VALUE);
- if ( !v.isEmpty() ) {
- i = new CounterReset(this);
- val = v.toInt();
-// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
- }
- }
- if (!i) {
- i = new CounterNode(this);
- val = 1;
-// kdDebug( 6040 ) << renderName() << " counter-increment: " << counter << " " << val << endl;
- }
- }
- else
- if (element() && element()->id() == ID_OL) {
- i = new CounterReset(this);
- DOMString v = static_cast<ElementImpl*>(element())->getAttribute(ATTR_START);
- if ( !v.isEmpty() )
- val = v.toInt()-1;
- else
- val = 0;
-// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
- }
- else
- if (element() &&
- (element()->id() == ID_UL ||
- element()->id() == ID_MENU||
- element()->id() == ID_DIR))
- {
- i = new CounterReset(this);
- val = 0;
-// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl;
- }
- }
- else if (counter == "-khtml-quotes" && isQuote()) {
- i = new CounterNode(this);
- val = static_cast<RenderQuote*>(this)->quoteCount();
- }
-
- if (!i) {
- i = new CounterNode(this);
- val = 0;
-// kdDebug( 6040 ) << renderName() << " counter-increment: " << counter << " " << val << endl;
- }
- i->setValue(val);
- if (view) i->setIsVisual();
- if (counters) i->setHasCounters();
-
- insertCounter(counter, i);
-
- if (!isRoot()) {
- CounterNode *last=0, *current=0;
- RenderObject *n = previousSibling();
- while(n) {
- if (n->hasCounter(counter)) {
- current = n->getCounter(counter);
- break;
- }
- else
- n = n->previousSibling();
- }
- last = current;
-
- CounterNode *sibling = current;
- // counter-reset on same render-level is our counter-parent
- if (last) {
- // Found render-sibling, now search for later counter-siblings among its render-children
- n = n->lastChild();
- while (n) {
- if (n->hasCounter(counter)) {
- current = n->getCounter(counter);
- if (last->parent() == current->parent() || sibling == current->parent()) {
- last = current;
- // If the current counter is not the last, search deeper
- if (current->nextSibling()) {
- n = n->lastChild();
- continue;
- }
- else
- break;
- }
- }
- n = n->previousSibling();
- }
- if (sibling->isReset())
- {
- if (last != sibling)
- sibling->insertAfter(i, last);
- else
- sibling->insertAfter(i, 0);
- }
- else if (last->parent())
- last->parent()->insertAfter(i, last);
- }
- else if (parent()) {
- // Nothing found among siblings, let our parent search
- last = parent()->getCounter(counter, false);
- if (last->isReset())
- last->insertAfter(i, 0);
- else if (last->parent())
- last->parent()->insertAfter(i, last);
- }
- }
-
- return i;
-}
-
-CounterNode* RenderObject::lookupCounter(const TQString& counter) const
-{
- TQDict<khtml::CounterNode>* counters = document()->counters(this);
- if (counters)
- return counters->find(counter);
- else
- return 0;
-}
-
-void RenderObject::detachCounters()
-{
- TQDict<khtml::CounterNode>* counters = document()->counters(this);
- if (!counters) return;
-
- TQDictIterator<khtml::CounterNode> i(*counters);
-
- while (i.current()) {
- (*i)->remove();
- delete (*i);
- ++i;
- }
- document()->removeCounters(this);
-}
-
-void RenderObject::insertCounter(const TQString& counter, CounterNode* val)
-{
- TQDict<khtml::CounterNode>* counters = document()->counters(this);
-
- if (!counters) {
- counters = new TQDict<khtml::CounterNode>(11);
- document()->setCounters(this, counters);
- }
-
- counters->insert(counter, val);
-}
-
-void RenderObject::updateWidgetMasks() {
- for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
- if ( curr->isWidget() && static_cast<RenderWidget*>(curr)->needsMask() ) {
- TQWidget* w = static_cast<RenderWidget*>(curr)->widget();
- if (!w)
- return;
- RenderLayer* l = curr->enclosingStackingContext();
- TQRegion r = l ? l->getMask() : TQRegion();
- int x,y;
- if (!r.isNull() && curr->absolutePosition(x,y)) {
- int pbx = curr->borderLeft()+curr->paddingLeft();
- int pby = curr->borderTop()+curr->paddingTop();
- x+= pbx;
- y+= pby;
- r = r.intersect(TQRect(x,y,
- curr->width()-pbx-curr->borderRight()-curr->paddingRight(),
- curr->height()-pby-curr->borderBottom()-curr->paddingBottom()));
-#ifdef MASK_DEBUG
- TQMemArray<TQRect> ar = r.rects();
- kdDebug(6040) << "|| Setting widget mask for " << curr->information() << endl;
- for (int i = 0; i < ar.size() ; ++i) {
- kdDebug(6040) << " " << ar[i] << endl;
- }
-#endif
- r.translate(-x,-y);
- w->setMask(r);
- } else {
- w->clearMask();
- }
- }
- else if (!curr->layer() || !curr->layer()->isStackingContext())
- curr->updateWidgetMasks();
-
- }
-}
-
-TQRegion RenderObject::visibleFlowRegion(int x, int y) const
-{
- TQRegion r;
- for (RenderObject* ro=firstChild();ro;ro=ro->nextSibling()) {
- if( !ro->layer() && !ro->isInlineFlow() && ro->style()->visibility() == VISIBLE) {
- const RenderStyle *s = ro->style();
- if (ro->isRelPositioned())
- static_cast<const RenderBox*>(ro)->relativePositionOffset(x,y);
- if ( s->backgroundImage() || s->backgroundColor().isValid() || s->hasBorder() )
- r += TQRect(x + ro->effectiveXPos(),y + ro->effectiveYPos(), ro->effectiveWidth(), ro->effectiveHeight());
- else
- r += ro->visibleFlowRegion(x+ro->xPos(), y+ro->yPos());
- }
- }
- return r;
-}
-
-#undef RED_LUMINOSITY
-#undef GREEN_LUMINOSITY
-#undef BLUE_LUMINOSITY
-#undef INTENSITY_FACTOR
-#undef LIGHT_FACTOR
-#undef LUMINOSITY_FACTOR
-
-#undef MAX_COLOR
-#undef COLOR_DARK_THRESHOLD
-#undef COLOR_LIGHT_THRESHOLD
-
-#undef COLOR_LITE_BS_FACTOR
-#undef COLOR_LITE_TS_FACTOR
-
-#undef COLOR_DARK_BS_FACTOR
-#undef COLOR_DARK_TS_FACTOR
-
-#undef LIGHT_GRAY
-#undef DARK_GRAY
-
diff --git a/khtml/rendering/render_object.h b/khtml/rendering/render_object.h
deleted file mode 100644
index e15dabbbc..000000000
--- a/khtml/rendering/render_object.h
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * This file is part of the html renderer for KDE.
- *
- * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2002-2003 Apple Computer, Inc.
- * (C) 2004 Allan Sandfeld Jensen
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef render_object_h
-#define render_object_h
-
-#include <tqcolor.h>
-#include <tqrect.h>
-#include <assert.h>
-#include <tqvaluelist.h>
-
-#include <kdebug.h>
-#include <kglobal.h>
-
-#include "xml/dom_docimpl.h"
-#include "misc/khtmllayout.h"
-#include "misc/loader_client.h"
-#include "misc/helper.h"
-#include "rendering/render_style.h"
-
-class TQPainter;
-class TQTextStream;
-class CSSStyle;
-class KHTMLView;
-
-#ifndef NDEBUG
-#define KHTMLAssert( x ) if( !(x) ) { \
- const RenderObject *o = this; while( o->parent() ) o = o->parent(); \
- o->printTree(); \
- tqDebug(" this object = %p, %s", (void*) this, kdBacktrace().latin1() ); \
- assert( x ); \
-}
-#else
-#define KHTMLAssert( x )
-#endif
-
-/*
- * The painting of a layer occurs in three distinct phases. Each phase involves
- * a recursive descent into the layer's render objects. The first phase is the background phase.
- * The backgrounds and borders of all blocks are painted. Inlines are not painted at all.
- * Floats must paint above block backgrounds but entirely below inline content that can overlap them.
- * In the foreground phase, all inlines are fully painted. Inline replaced elements will get all
- * three phases invoked on them during this phase.
- */
-
-typedef enum {
- PaintActionElementBackground = 0,
- PaintActionChildBackground,
- PaintActionChildBackgrounds,
- PaintActionFloat,
- PaintActionForeground,
- PaintActionOutline,
- PaintActionSelection,
- PaintActionCollapsedTableBorders
-} PaintAction;
-
-typedef enum {
- HitTestAll = 0,
- HitTestSelfOnly = 1,
- HitTestChildrenOnly = 2
-} HitTestAction;
-
-typedef enum {
- PageBreakNormal = 0, // all rules apply
- PageBreakHarder = 1, // page-break-inside: avoid is ignored
- PageBreakForced = 2 // page-break-after/before: avoid, orphans and widows ignored
-} PageBreakLevel;
-
-typedef enum {
- LowPriority = 0,
- NormalPriority = 1,
- HighPriority = 2,
- RealtimePriority = 3
-} Priority;
-
-inline PageBreakLevel operator| (PageBreakLevel a, PageBreakLevel b) {
- if (a == PageBreakForced || b == PageBreakForced)
- return PageBreakForced;
- if (a == PageBreakHarder || b == PageBreakHarder)
- return PageBreakHarder;
- return PageBreakNormal;
-}
-
-namespace DOM {
- class HTMLAreaElementImpl;
- class DOMString;
- class NodeImpl;
- class DocumentImpl;
- class ElementImpl;
- class EventImpl;
-}
-
-namespace khtml {
- class RenderFlow;
- class RenderStyle;
- class RenderTable;
- class CachedObject;
- class RenderObject;
- class RenderCanvas;
- class RenderText;
- class RenderFrameSet;
- class RenderArena;
- class RenderLayer;
- class RenderBlock;
- class InlineBox;
- class InlineFlowBox;
- class CounterNode;
-
-/**
- * Base Class for all rendering tree objects.
- */
-class RenderObject : public CachedObjectClient
-{
- RenderObject(const RenderObject&);
- RenderObject& operator=(const RenderObject&);
-public:
-
- RenderObject(DOM::NodeImpl* node);
- virtual ~RenderObject();
-
- RenderObject *parent() const { return m_parent; }
-
- RenderObject *previousSibling() const { return m_previous; }
- RenderObject *nextSibling() const { return m_next; }
-
- virtual RenderObject *firstChild() const { return 0; }
- virtual RenderObject *lastChild() const { return 0; }
-
- RenderObject *nextRenderer() const;
- RenderObject *previousRenderer() const;
-
- virtual bool childAllowed() const { return false; }
- virtual int borderTopExtra() const { return 0; }
- virtual int borderBottomExtra() const { return 0; }
-
- virtual RenderLayer* layer() const { return 0; }
- RenderLayer* enclosingLayer() const;
- RenderLayer* enclosingStackingContext() const;
- void addLayers(RenderLayer* parentLayer, RenderObject* newObject);
- void removeLayers(RenderLayer* parentLayer);
- void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
- RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
- bool checkParent=true);
- virtual void positionChildLayers() { }
- virtual bool requiresLayer() const {
- return isRoot()/* ### */ || isPositioned() || isRelPositioned() || hasOverflowClip();
- }
-
- // ### rename to overflowClipRect and clipRect
- virtual TQRect getOverflowClipRect(int /*tx*/, int /*ty*/)
- { return TQRect(0,0,0,0); }
- virtual TQRect getClipRect(int /*tx*/, int /*ty*/) { return TQRect(0,0,0,0); }
- bool hasClip() const { return isPositioned() && style()->hasClip(); }
- bool hasOverflowClip() const { return m_hasOverflowClip; }
-
- bool scrollsOverflow() const { return scrollsOverflowX() || scrollsOverflowY(); }
- bool scrollsOverflowX() const { return hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO); }
- bool scrollsOverflowY() const { return hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO); }
-
- virtual int getBaselineOfFirstLineBox() { return -1; } // Tables and blocks implement this.
- virtual InlineFlowBox* getFirstLineBox() { return 0; } // Tables and blocks implement this.
-
- // Whether or not a positioned element requires normal flow x/y to be computed
- // to determine its position.
- bool hasStaticX() const;
- bool hasStaticY() const;
-
- // Linear tree traversal
- RenderObject *objectBelow() const;
- RenderObject *objectAbove() const;
-
- // Returns if an object has counter-increment or counter-reset
- bool hasCounter(const TQString& counter) const;
- // Calculates the value of the counter
- CounterNode* getCounter(const TQString& counter, bool view = false, bool counters = false);
- // Detaches all counterNodes
- void detachCounters();
-
-
-protected:
- // Helper functions for counter-cache
- void insertCounter(const TQString& counter, CounterNode* value);
- CounterNode* lookupCounter(const TQString& counter) const;
-
-public:
- //////////////////////////////////////////
- // RenderObject tree manipulation
- virtual void addChild(RenderObject *newChild, RenderObject *beforeChild = 0);
- void removeChild(RenderObject *oldChild);
-
- // raw tree manipulation
- virtual RenderObject* removeChildNode(RenderObject* child);
- virtual void appendChildNode(RenderObject* child);
- virtual void insertChildNode(RenderObject* child, RenderObject* before);
- //////////////////////////////////////////
-
- //////////////////////////////////////////
- // Helper functions. Dangerous to use!
- void setPreviousSibling(RenderObject *previous) { m_previous = previous; }
- void setNextSibling(RenderObject *next) { m_next = next; }
- void setParent(RenderObject *parent) { m_parent = parent; }
- //////////////////////////////////////////
-
-public:
- virtual const char *renderName() const { return "RenderObject"; }
-#ifdef ENABLE_DUMP
- TQString information() const;
- virtual void printTree(int indent=0) const;
- virtual void dump(TQTextStream &stream, const TQString &ind = TQString::null) const;
-#endif
-
- static RenderObject *createObject(DOM::NodeImpl* node, RenderStyle* style);
-
- // Overloaded new operator. Derived classes must override operator new
- // in order to allocate out of the RenderArena.
- void* operator new(size_t sz, RenderArena* renderArena) throw();
-
- // Overridden to prevent the normal delete from being called.
- void operator delete(void* ptr, size_t sz);
-
-private:
- // The normal operator new is disallowed on all render objects.
- void* operator new(size_t sz);
-
-public:
- RenderArena* renderArena() const;
- virtual RenderFlow* continuation() const { return 0; }
- virtual bool isInlineContinuation() const { return false; }
-
-
- bool isRoot() const { return m_isRoot && !m_isAnonymous; }
- void setIsRoot(bool b) { m_isRoot = b; }
- bool isHR() const;
- // some helper functions...
- virtual bool isRenderBlock() const { return false; }
- virtual bool isRenderInline() const { return false; }
- virtual bool isInlineFlow() const { return false; }
- virtual bool isBlockFlow() const { return false; }
- virtual bool isInlineBlockOrInlineTable() const { return false; }
- virtual bool childrenInline() const { return false; }
- virtual bool isBox() const { return false; }
- virtual bool isRenderReplaced() const { return false; }
-
- virtual bool isGlyph() const { return false; }
- virtual bool isCounter() const { return false; }
- virtual bool isQuote() const { return false; }
- virtual bool isListItem() const { return false; }
- virtual bool isListMarker() const { return false; }
- virtual bool isCanvas() const { return false; }
- virtual bool isBR() const { return false; }
- virtual bool isTableCell() const { return false; }
- virtual bool isTableRow() const { return false; }
- virtual bool isTableSection() const { return false; }
- virtual bool isTableCol() const { return false; }
- virtual bool isTable() const { return false; }
- virtual bool isWidget() const { return false; }
- virtual bool isBody() const { return false; }
- virtual bool isFormElement() const { return false; }
- virtual bool isFrameSet() const { return false; }
- virtual bool isApplet() const { return false; }
-
- bool isHTMLMarquee() const;
- bool isWordBreak() const;
-
- bool isAnonymous() const { return m_isAnonymous; }
- void setIsAnonymous(bool b) { m_isAnonymous = b; }
- bool isAnonymousBlock() const { return isAnonymous() && style()->display() == BLOCK && node()->isDocumentNode(); }
- bool isPseudoAnonymous() const { return isAnonymous() && !node()->isDocumentNode(); }
-
- bool isFloating() const { return m_floating; }
- bool isPositioned() const { return m_positioned; }
- bool isRelPositioned() const { return m_relPositioned; }
- bool isText() const { return m_isText; }
- bool isInline() const { return m_inline; }
- bool isCompact() const { return style()->display() == COMPACT; } // compact
- bool isRunIn() const { return style()->display() == RUN_IN; } // run-in object
- bool mouseInside() const;
- bool isReplaced() const { return m_replaced; }
- bool isReplacedBlock() const { return isInline() && isReplaced() && isRenderBlock(); }
- bool shouldPaintBackgroundOrBorder() const { return m_paintBackground; }
- bool needsLayout() const { return m_needsLayout || m_normalChildNeedsLayout || m_posChildNeedsLayout; }
- bool markedForRepaint() const { return m_markedForRepaint; }
- void setMarkedForRepaint(bool m) { m_markedForRepaint = m; }
- bool selfNeedsLayout() const { return m_needsLayout; }
- bool posChildNeedsLayout() const { return m_posChildNeedsLayout; }
- bool normalChildNeedsLayout() const { return m_normalChildNeedsLayout; }
- bool minMaxKnown() const{ return m_minMaxKnown; }
- bool overhangingContents() const { return m_overhangingContents; }
- bool hasFirstLine() const { return m_hasFirstLine; }
- bool isSelectionBorder() const { return m_isSelectionBorder; }
- bool recalcMinMax() const { return m_recalcMinMax; }
-
- RenderCanvas* canvas() const;
- // don't even think about making this method virtual!
- DOM::DocumentImpl* document() const;
- DOM::NodeImpl* element() const { return isAnonymous() ? 0L : m_node; }
- DOM::NodeImpl* node() const { return m_node; }
-
- /**
- * returns the object containing this one. can be different from parent for
- * positioned elements
- */
- RenderObject *container() const;
-
- void setOverhangingContents(bool p=true);
- void markContainingBlocksForLayout();
- void dirtyFormattingContext( bool checkContainer );
- void repaintDuringLayout();
- void setNeedsLayout(bool b, bool markParents = true);
- void setChildNeedsLayout(bool b, bool markParents = true);
- void setMinMaxKnown(bool b=true) {
- m_minMaxKnown = b;
- if ( !b ) {
- RenderObject *o = this;
- RenderObject *root = this;
- while( o ) { // ### && !o->m_recalcMinMax ) {
- o->m_recalcMinMax = true;
- root = o;
- o = o->m_parent;
- }
- }
- }
- void setNeedsLayoutAndMinMaxRecalc() {
- setMinMaxKnown(false);
- setNeedsLayout(true);
- }
- void setPositioned(bool b=true) { m_positioned = b; }
- void setRelPositioned(bool b=true) { m_relPositioned = b; }
- void setFloating(bool b=true) { m_floating = b; }
- void setInline(bool b=true) { m_inline = b; }
- void setMouseInside(bool b=true) { m_mouseInside = b; }
- void setShouldPaintBackgroundOrBorder(bool b=true) { m_paintBackground = b; }
- void setRenderText() { m_isText = true; }
- void setReplaced(bool b=true) { m_replaced = b; }
- void setHasOverflowClip(bool b = true) { m_hasOverflowClip = b; }
- void setIsSelectionBorder(bool b=true) { m_isSelectionBorder = b; }
-
- void scheduleRelayout(RenderObject *clippedObj = 0);
-
- void updateBackgroundImages(RenderStyle* oldStyle);
-
- virtual InlineBox* createInlineBox(bool makePlaceHolderBox, bool isRootLineBox);
-
- virtual short lineHeight( bool firstLine ) const;
- virtual short verticalPositionHint( bool firstLine ) const;
- virtual short baselinePosition( bool firstLine ) const;
- short getVerticalPosition( bool firstLine, RenderObject* ref=0 ) const;
-
- /*
- * Print the object and its children, clipped by (x|y|w|h).
- * (tx|ty) is the calculated position of the parent
- */
- struct PaintInfo {
- PaintInfo(TQPainter* _p, const TQRect& _r, PaintAction _phase)
- : p(_p), r(_r), phase(_phase), outlineObjects(0) {}
- ~PaintInfo() { delete outlineObjects; }
- TQPainter* p;
- TQRect r;
- PaintAction phase;
- TQValueList<RenderFlow *>* outlineObjects; // used to list which outlines should be painted by a block with inline children
- };
- virtual void paint( PaintInfo& i, int tx, int ty);
-
- void paintBorder(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin=true, bool end=true);
- void paintOutline(TQPainter *p, int _tx, int _ty, int w, int h, const RenderStyle* style);
-
- virtual void paintBoxDecorations(PaintInfo&, int /*_tx*/, int /*_ty*/) {}
-
- virtual void paintBackgroundExtended(TQPainter* /*p*/, const TQColor& /*c*/, const BackgroundLayer */*bgLayer*/,
- int /*clipy*/, int /*cliph*/, int /*_tx*/, int /*_ty*/,
- int /*w*/, int /*height*/, int /*bleft*/, int /*bright*/, int /*pleft*/, int /*pright*/ ) {}
-
-
- /*
- * This function calculates the minimum & maximum width that the object
- * can be set to.
- *
- * when the Element calls setMinMaxKnown(true), calcMinMaxWidth() will
- * be no longer called.
- *
- * when a element has a fixed size, m_minWidth and m_maxWidth should be
- * set to the same value. This has the special meaning that m_width,
- * contains the actual value.
- *
- * assumes calcMinMaxWidth has already been called for all children.
- */
- virtual void calcMinMaxWidth() { }
-
- /*
- * Does the min max width recalculations after changes.
- */
- void recalcMinMaxWidths();
-
- /*
- * Calculates the actual width of the object (only for non inline
- * objects)
- */
- virtual void calcWidth() {}
-
- /*
- * Calculates the actual width of the object (only for non inline
- * objects)
- */
- virtual void calcHeight() {}
-
- /*
- * This function should cause the Element to calculate its
- * width and height and the layout of its content
- *
- * when the Element calls setNeedsLayout(false), layout() is no
- * longer called during relayouts, as long as there is no
- * style sheet change. When that occurs, m_needsLayout will be
- * set to true and the Element receives layout() calls
- * again.
- */
- virtual void layout() = 0;
-
- /* This function performs a layout only if one is needed. */
- void layoutIfNeeded() { if (needsLayout()) layout(); }
-
- // used for element state updates that can not be fixed with a
- // repaint and do not need a relayout
- virtual void updateFromElement() {}
-
- // Called immediately after render-object is inserted
- virtual void attach() { m_attached = true; }
- bool attached() { return m_attached; }
- // The corresponding closing element has been parsed. ### remove me
- virtual void close() { }
-
- virtual int availableHeight() const { return 0; }
-
- // Whether or not the element shrinks to its max width (rather than filling the width
- // of a containing block). HTML4 buttons, legends, and floating/compact elements do this.
- bool sizesToMaxWidth() const;
-
- /*
- * NeesPageClear indicates the object crossed a page-break but could not break itself and now
- * needs to be moved clear by its parent.
- */
- void setNeedsPageClear(bool b = true) { m_needsPageClear = b; }
- virtual bool needsPageClear() const { return m_needsPageClear; }
-
- /*
- * ContainsPageBreak indicates the object contains a clean page-break.
- * ### should be removed and replaced with (crossesPageBreak && !needsPageClear)
- */
- void setContainsPageBreak(bool b = true) { m_containsPageBreak = b; }
- virtual bool containsPageBreak() const { return m_containsPageBreak; }
-
- virtual int pageTopAfter(int y) const { if (parent()) return parent()->pageTopAfter(y); else return 0; }
-
- virtual int crossesPageBreak(int top, int bottom) const
- { if (parent()) return parent()->crossesPageBreak(top, bottom); else return 0; }
-
- // Checks if a page-break before child is possible at the given page-break level
- // false means the child should attempt the break self.
- virtual bool canClear(RenderObject */*child*/, PageBreakLevel level)
- { if (parent()) return parent()->canClear(this, level); else return false; }
-
- void setAfterPageBreak(bool b = true) { m_afterPageBreak = b; };
- void setBeforePageBreak(bool b = true) { m_beforePageBreak = b; };
- virtual bool afterPageBreak() const { return m_afterPageBreak; }
- virtual bool beforePageBreak() const { return m_beforePageBreak; }
-
- // does a query on the rendertree and finds the innernode
- // and overURL for the given position
- // if readonly == false, it will recalc hover styles accordingly
- class NodeInfo
- {
- friend class RenderImage;
- friend class RenderFlow;
- friend class RenderInline;
- friend class RenderText;
- friend class RenderWidget;
- friend class RenderObject;
- friend class RenderFrameSet;
- friend class RenderLayer;
- friend class DOM::HTMLAreaElementImpl;
- public:
- NodeInfo(bool readonly, bool active)
- : m_innerNode(0), m_innerNonSharedNode(0), m_innerURLElement(0), m_readonly(readonly), m_active(active)
- { }
-
- DOM::NodeImpl* innerNode() const { return m_innerNode; }
- DOM::NodeImpl* innerNonSharedNode() const { return m_innerNonSharedNode; }
- DOM::NodeImpl* URLElement() const { return m_innerURLElement; }
- bool readonly() const { return m_readonly; }
- bool active() const { return m_active; }
-
- private:
- void setInnerNode(DOM::NodeImpl* n) { m_innerNode = n; }
- void setInnerNonSharedNode(DOM::NodeImpl* n) { m_innerNonSharedNode = n; }
- void setURLElement(DOM::NodeImpl* n) { m_innerURLElement = n; }
-
- DOM::NodeImpl* m_innerNode;
- DOM::NodeImpl* m_innerNonSharedNode;
- DOM::NodeImpl* m_innerURLElement;
- bool m_readonly;
- bool m_active;
- };
-
- /** contains stateful information for a checkSelectionPoint call
- */
- struct SelPointState {
- /** last node that was before the current position */
- DOM::NodeImpl *m_lastNode;
- /** offset of last node */
- long m_lastOffset;
- /** true when the last node had the result SelectionAfterInLine */
- bool m_afterInLine;
-
- SelPointState() : m_lastNode(0), m_lastOffset(0), m_afterInLine(false)
- {}
- };
-
- virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
- DOM::NodeImpl*&, int & offset,
- SelPointState & );
- virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction, bool inside = false);
- void setInnerNode(NodeInfo& info);
-
- // set the style of the object.
- virtual void setStyle(RenderStyle *style);
-
- // returns the containing block level element for this element.
- RenderBlock *containingBlock() const;
-
- // return just the width of the containing block
- virtual short containingBlockWidth() const;
- // return just the height of the containing block
- virtual int containingBlockHeight() const;
-
- // size of the content area (box size minus padding/border)
- virtual short contentWidth() const { return 0; }
- virtual int contentHeight() const { return 0; }
-
- // intrinsic extend of replaced elements. undefined otherwise
- virtual short intrinsicWidth() const { return 0; }
- virtual int intrinsicHeight() const { return 0; }
-
- // relative to parent node
- virtual void setPos( int /*xPos*/, int /*yPos*/ ) { }
- virtual void setWidth( int /*width*/ ) { }
- virtual void setHeight( int /*height*/ ) { }
-
- virtual int xPos() const { return 0; }
- virtual int yPos() const { return 0; }
-
- /** the position of the object from where it begins drawing, including
- * its negative overflow
- */
- int effectiveXPos() const { return xPos() + (hasOverflowClip() ? 0 : overflowLeft()); }
-
- /** the position of the object from where it begins drawing, including
- * its negative overflow
- */
- int effectiveYPos() const { return yPos() + (hasOverflowClip() ? -borderTopExtra() : kMin(overflowTop(), -borderTopExtra())); }
-
- /** Leftmost coordinate of this inline element relative to containing
- * block. Always zero for non-inline elements.
- */
- virtual int inlineXPos() const { return 0; }
- /** Topmost coordinate of this inline element relative to containing
- * block. Always zero for non-inline elements.
- */
- virtual int inlineYPos() const { return 0; }
-
- // calculate client position of box
- virtual bool absolutePosition(int &/*xPos*/, int &/*yPos*/, bool fixed = false) const;
-
- // width and height are without margins but include paddings and borders
- virtual short width() const { return 0; }
- virtual int height() const { return 0; }
-
- // The height of a block when you include overflow spillage out of
- // the bottom of the block (e.g., a <div style="height:25px"> that
- // has a 100px tall image inside it would have an overflow height
- // of borderTop() + paddingTop() + 100px.
- virtual int overflowHeight() const { return height(); }
- virtual int overflowWidth() const { return width(); }
- // how much goes over the left hand side (0 or a negative number)
- virtual int overflowTop() const { return 0; }
- virtual int overflowLeft() const { return 0; }
-
- /**
- * Returns the height that is effectively considered when contemplating the
- * object as a whole -- usually the overflow height, or the height if clipped.
- */
- int effectiveHeight() const { return hasOverflowClip() ? height() + borderTopExtra() + borderBottomExtra() :
- kMax(overflowHeight() - overflowTop(), height() + borderTopExtra() + borderBottomExtra()); }
- /**
- * Returns the width that is effectively considered when contemplating the
- * object as a whole -- usually the overflow width, or the width if clipped.
- */
- int effectiveWidth() const { return hasOverflowClip() ? width() : overflowWidth() - overflowLeft(); }
-
- // IE extensions, heavily used in ECMA
- virtual short offsetWidth() const { return width(); }
- virtual int offsetHeight() const { return height() + borderTopExtra() + borderBottomExtra(); }
- virtual int offsetLeft() const;
- virtual int offsetTop() const;
- virtual RenderObject* offsetParent() const;
- short clientWidth() const;
- int clientHeight() const;
- short scrollWidth() const;
- int scrollHeight() const;
-
- virtual bool isSelfCollapsingBlock() const { return false; }
- short collapsedMarginTop() const { return maxTopMargin(true)-maxTopMargin(false); }
- short collapsedMarginBottom() const { return maxBottomMargin(true)-maxBottomMargin(false); }
-
- virtual bool isTopMarginQuirk() const { return false; }
- virtual bool isBottomMarginQuirk() const { return false; }
- virtual short maxTopMargin(bool positive) const
- { return positive ? kMax( int( marginTop() ), 0 ) : - kMin( int( marginTop() ), 0 ); }
- virtual short maxBottomMargin(bool positive) const
- { return positive ? kMax( int( marginBottom() ), 0 ) : - kMin( int( marginBottom() ), 0 ); }
-
- virtual short marginTop() const { return 0; }
- virtual short marginBottom() const { return 0; }
- virtual short marginLeft() const { return 0; }
- virtual short marginRight() const { return 0; }
-
- virtual int paddingTop() const;
- virtual int paddingBottom() const;
- virtual int paddingLeft() const;
- virtual int paddingRight() const;
-
- virtual int borderTop() const { return style()->borderTopWidth(); }
- virtual int borderBottom() const { return style()->borderBottomWidth(); }
- virtual int borderLeft() const { return style()->borderLeftWidth(); }
- virtual int borderRight() const { return style()->borderRightWidth(); }
-
- virtual short minWidth() const { return 0; }
- virtual int maxWidth() const { return 0; }
-
- RenderStyle* style() const { return m_style; }
- RenderStyle* style( bool firstLine ) const {
- RenderStyle *s = m_style;
- if( firstLine && hasFirstLine() ) {
- RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
- if ( pseudoStyle )
- s = pseudoStyle;
- }
- return s;
- }
-
- void getTextDecorationColors(int decorations, TQColor& underline, TQColor& overline,
- TQColor& linethrough, bool quirksMode=false);
-
- enum BorderSide {
- BSTop, BSBottom, BSLeft, BSRight
- };
- void drawBorder(TQPainter *p, int x1, int y1, int x2, int y2, BorderSide s,
- TQColor c, const TQColor& textcolor, EBorderStyle style,
- int adjbw1, int adjbw2, bool invalidisInvert = false);
-
- // Used by collapsed border tables.
- virtual void collectBorders(TQValueList<CollapsedBorderValue>& borderStyles);
-
- // force a complete repaint
- virtual void repaint(Priority p = NormalPriority) { if(m_parent) m_parent->repaint(p); }
- virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
-
- virtual unsigned int length() const { return 1; }
-
- virtual bool isHidden() const { return isFloating() || isPositioned(); }
-
- // Special objects are objects that are neither really inline nor blocklevel
- bool isFloatingOrPositioned() const { return (isFloating() || isPositioned()); };
- virtual bool hasOverhangingFloats() const { return false; }
- virtual bool hasFloats() const { return false; }
- virtual bool containsFloat(RenderObject* /*o*/) const { return false; }
- virtual void markAllDescendantsWithFloatsForLayout(RenderObject* /*floatToRemove*/ = 0) {}
-
- bool flowAroundFloats() const;
- bool usesLineWidth() const;
-
- // positioning of inline children (bidi)
- virtual void position(InlineBox*, int, int, bool) {}
-// virtual void position(int, int, int, int, int, bool, bool, int) {}
-
- // Applied as a "slop" to dirty rect checks during the outline painting phase's dirty-rect checks.
- int maximalOutlineSize(PaintAction p) const;
-
- enum SelectionState {
- SelectionNone,
- SelectionStart,
- SelectionInside,
- SelectionEnd,
- SelectionBoth
- };
-
- virtual SelectionState selectionState() const { return SelectionNone;}
- virtual void setSelectionState(SelectionState) {}
-
- /**
- * Flags which influence the appearence and position
- * @param CFOverride input overrides existing character, caret should be
- * cover the whole character
- * @param CFOutside coordinates are to be interpreted outside of the
- * render object
- * @param CFOutsideEnd coordinates are to be interpreted at the outside
- * end of the render object (only valid if CFOutside is also set)
- */
- enum CaretFlags { CFOverride = 0x01, CFOutside = 0x02, CFOutsideEnd = 0x04 };
-
- /**
- * Returns the content coordinates of the caret within this render object.
- * @param offset zero-based offset determining position within the render object.
- * @param flags combination of enum CaretFlags
- * @param _x returns the left coordinate
- * @param _y returns the top coordinate
- * @param width returns the caret's width
- * @param height returns the caret's height
- */
- virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
-
- // returns the lowest position of the lowest object in that particular object.
- // This 'height' is relative to the topleft of the margin box of the object.
- // Implemented in RenderFlow.
- virtual int lowestPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
- virtual int rightmostPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
- virtual int leftmostPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
- virtual int highestPosition(bool /*includeOverflowInterior*/=true, bool /*includeSelf*/=true) const { return 0; }
-
- // recursively invalidate current layout
- // unused: void invalidateLayout();
-
- virtual void calcVerticalMargins() {}
- void removeFromObjectLists();
-
- virtual void deleteInlineBoxes(RenderArena* arena=0) {(void)arena;}
- virtual void detach( );
-
- void setDoNotDelete(bool b) { m_doNotDelete = b; }
- bool doNotDelete() const { return m_doNotDelete; }
-
- const TQFont &font(bool firstLine) const {
- return style( firstLine )->font();
- }
-
- const TQFontMetrics &fontMetrics(bool firstLine) const {
- return style( firstLine )->fontMetrics();
- }
-
- /** returns the lowest possible value the caret offset may have to
- * still point to a valid position.
- *
- * Returns 0 by default.
- */
- virtual long minOffset() const { return 0; }
- /** returns the highest possible value the caret offset may have to
- * still point to a valid position.
- *
- * Returns 0 by default, as generic elements are considered to have no
- * width.
- */
- virtual long maxOffset() const { return 0; }
-
- virtual void setPixmap(const TQPixmap &, const TQRect&, CachedImage *);
-
- TQRegion visibleFlowRegion(int x, int y) const;
-
-protected:
- virtual void selectionStartEnd(int& spos, int& epos);
-
- virtual TQRect viewRect() const;
- void remove();
- void invalidateVerticalPositions();
- bool attemptDirectLayerTranslation();
- void updateWidgetMasks();
-
- virtual void removeLeftoverAnonymousBoxes();
-
- void arenaDelete(RenderArena *arena);
-
-private:
- RenderStyle* m_style;
- DOM::NodeImpl* m_node;
- RenderObject *m_parent;
- RenderObject *m_previous;
- RenderObject *m_next;
-
- short m_verticalPosition;
-
- bool m_needsLayout : 1;
- bool m_normalChildNeedsLayout : 1;
- bool m_markedForRepaint : 1;
- bool m_posChildNeedsLayout : 1;
-
- bool m_minMaxKnown : 1;
- bool m_floating : 1;
-
- bool m_positioned : 1;
- bool m_overhangingContents : 1;
- bool m_relPositioned : 1;
- bool m_paintBackground : 1; // if the box has something to paint in the
- // background painting phase (background, border, etc)
-
- bool m_isAnonymous : 1;
- bool m_recalcMinMax : 1;
- bool m_isText : 1;
- bool m_inline : 1;
- bool m_attached : 1;
-
- bool m_replaced : 1;
- bool m_mouseInside : 1;
- bool m_hasFirstLine : 1;
- bool m_isSelectionBorder : 1;
-
- bool m_isRoot : 1;
-
- bool m_beforePageBreak : 1;
- bool m_afterPageBreak : 1;
-
- bool m_needsPageClear : 1;
- bool m_containsPageBreak : 1;
-
- bool m_hasOverflowClip : 1;
-
- bool m_doNotDelete : 1; // This object should not be auto-deleted
-
- // ### we have 16 + 26 bits.
-
-
- void arenaDelete(RenderArena *arena, void *objectBase);
-
- friend class RenderLayer;
- friend class RenderListItem;
- friend class RenderContainer;
- friend class RenderCanvas;
-};
-
-
-enum VerticalPositionHint {
- PositionTop = -0x4000,
- PositionBottom = 0x4000,
- PositionUndefined = 0x3fff
-};
-
-} //namespace
-#endif
diff --git a/khtml/rendering/render_replaced.cpp b/khtml/rendering/render_replaced.cpp
deleted file mode 100644
index 319f842e7..000000000
--- a/khtml/rendering/render_replaced.cpp
+++ /dev/null
@@ -1,940 +0,0 @@
-/**
- * This file is part of the HTML widget for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003 Apple Computer, Inc.
- * Copyright (C) 2004 Germain Garand (germain@ebooksfrance.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include "render_replaced.h"
-#include "render_layer.h"
-#include "render_canvas.h"
-#include "render_line.h"
-
-#include "render_arena.h"
-
-#include <assert.h>
-#include <tqwidget.h>
-#include <tqpainter.h>
-#include <tqevent.h>
-#include <tqapplication.h>
-#include <tqlineedit.h>
-#include <kglobalsettings.h>
-#include <tqobjectlist.h>
-#include <tqvaluevector.h>
-
-#include "khtml_ext.h"
-#include "khtmlview.h"
-#include "xml/dom2_eventsimpl.h"
-#include "khtml_part.h"
-#include "xml/dom_docimpl.h"
-#include <kdebug.h>
-
-bool khtml::allowWidgetPaintEvents = false;
-
-using namespace khtml;
-using namespace DOM;
-
-
-RenderReplaced::RenderReplaced(DOM::NodeImpl* node)
- : RenderBox(node)
-{
- // init RenderObject attributes
- setReplaced(true);
-
- m_intrinsicWidth = 300;
- m_intrinsicHeight = 150;
-}
-
-void RenderReplaced::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown());
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "RenderReplaced::calcMinMaxWidth() known=" << minMaxKnown() << endl;
-#endif
-
- m_width = calcReplacedWidth();
- m_width = calcBoxWidth( m_width );
-
- if ( style()->width().isPercent() || style()->height().isPercent() ||
- style()->maxWidth().isPercent() || style()->maxHeight().isPercent() ||
- style()->minWidth().isPercent() || style()->minHeight().isPercent() ) {
- m_minWidth = 0;
- m_maxWidth = m_width;
- }
- else
- m_minWidth = m_maxWidth = m_width;
-
- setMinMaxKnown();
-}
-
-void RenderReplaced::position(InlineBox* box, int /*from*/, int /*len*/, bool /*reverse*/)
-{
- setPos( box->xPos(), box->yPos() );
-}
-
-// -----------------------------------------------------------------------------
-
-RenderWidget::RenderWidget(DOM::NodeImpl* node)
- : RenderReplaced(node)
-{
- m_widget = 0;
- // a widget doesn't support being anonymous
- assert(!isAnonymous());
- m_view = node->getDocument()->view();
- m_arena.reset(renderArena());
- m_resizePending = false;
- m_discardResizes = false;
- m_isKHTMLWidget = false;
- m_needsMask = false;
-
- // this is no real reference counting, its just there
- // to make sure that we're not deleted while we're recursed
- // in an eventFilter of the widget
- ref();
-}
-
-void RenderWidget::detach()
-{
- remove();
- deleteInlineBoxes();
-
- if ( m_widget ) {
- if ( m_view ) {
- m_view->setWidgetVisible(this, false);
- m_view->removeChild( m_widget );
- }
-
- m_widget->removeEventFilter( this );
- m_widget->setMouseTracking( false );
- }
-
- deref();
-}
-
-RenderWidget::~RenderWidget()
-{
- KHTMLAssert( refCount() <= 0 );
-
- if(m_widget) {
- m_widget->hide();
- m_widget->deleteLater();
- }
-}
-
-class TQWidgetResizeEvent : public TQEvent
-{
-public:
- enum { Type = TQEvent::User + 0xbee };
- TQWidgetResizeEvent( int _w, int _h ) :
- TQEvent( ( TQEvent::Type ) Type ), w( _w ), h( _h ) {}
- int w;
- int h;
-};
-
-void RenderWidget::resizeWidget( int w, int h )
-{
- // ugly hack to limit the maximum size of the widget ( as X11 has problems if
- // its bigger )
- h = kMin( h, 3072 );
- w = kMin( w, 2000 );
-
- if (m_widget->width() != w || m_widget->height() != h) {
- m_resizePending = isKHTMLWidget();
- ref();
- element()->ref();
- TQApplication::postEvent( this, new TQWidgetResizeEvent( w, h ) );
- element()->deref();
- deref();
- }
-}
-
-void RenderWidget::cancelPendingResize()
-{
- if (!m_widget)
- return;
- m_discardResizes = true;
- TQApplication::sendPostedEvents(this, TQWidgetResizeEvent::Type);
- m_discardResizes = false;
-}
-
-bool RenderWidget::event( TQEvent *e )
-{
- if ( m_widget && (e->type() == (TQEvent::Type)TQWidgetResizeEvent::Type) ) {
- m_resizePending = false;
- if (m_discardResizes)
- return true;
- TQWidgetResizeEvent *re = static_cast<TQWidgetResizeEvent *>(e);
- m_widget->resize( re->w, re->h );
- repaint();
- }
- // eat all events - except if this is a frame (in which case KHTMLView handles it all)
- if ( ::tqqt_cast<KHTMLView *>( m_widget ) )
- return TQObject::event( e );
- return true;
-}
-
-void RenderWidget::flushWidgetResizes() //static
-{
- TQApplication::sendPostedEvents( 0, TQWidgetResizeEvent::Type );
-}
-
-void RenderWidget::setQWidget(TQWidget *widget)
-{
- if (widget != m_widget)
- {
- if (m_widget) {
- m_widget->removeEventFilter(this);
- disconnect( m_widget, TQT_SIGNAL( destroyed()), this, TQT_SLOT( slotWidgetDestructed()));
- m_widget->hide();
- m_widget->deleteLater(); //Might happen due to event on the widget, so be careful
- m_widget = 0;
- }
- m_widget = widget;
- if (m_widget) {
- connect( m_widget, TQT_SIGNAL( destroyed()), this, TQT_SLOT( slotWidgetDestructed()));
- m_widget->installEventFilter(this);
-
- if ( (m_isKHTMLWidget = !strcmp(m_widget->name(), "__khtml")) && !::tqqt_cast<TQFrame*>(m_widget))
- m_widget->setBackgroundMode( TQWidget::NoBackground );
-
- if (m_widget->focusPolicy() > TQ_StrongFocus)
- m_widget->setFocusPolicy(TQ_StrongFocus);
- // if we've already received a layout, apply the calculated space to the
- // widget immediately, but we have to have really been full constructed (with a non-null
- // style pointer).
- if (!needsLayout() && style()) {
- resizeWidget( m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
- m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom() );
- }
- else
- setPos(xPos(), -500000);
- }
- m_view->setWidgetVisible(this, false);
- m_view->addChild( m_widget, 0, -500000);
- if ( m_widget ) m_widget->hide();
- m_resizePending = false;
- }
-}
-
-void RenderWidget::layout( )
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
- if ( m_widget ) {
- resizeWidget( m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
- m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom() );
- if (!isKHTMLWidget() && !isFrame() && !m_needsMask) {
- m_needsMask = true;
- RenderLayer* rl = enclosingStackingContext();
- RenderLayer* el = enclosingLayer();
- while (rl && el && el != rl) {
- if (el->renderer()->style()->position() != STATIC) {
- m_needsMask = false;
- break;
- }
- el = el->parent();
- }
- if (m_needsMask) {
- if (rl) rl->setHasOverlaidWidgets();
- canvas()->setNeedsWidgetMasks();
- }
- }
- }
-
- setNeedsLayout(false);
-}
-
-void RenderWidget::updateFromElement()
-{
- if (m_widget) {
- // Color:
- TQColor color = style()->color();
- TQColor backgroundColor = style()->backgroundColor();
-
- if ( color.isValid() || backgroundColor.isValid() ) {
- TQPalette pal(TQApplication::palette(m_widget));
-
- int contrast_ = TDEGlobalSettings::contrast();
- int highlightVal = 100 + (2*contrast_+4)*16/10;
- int lowlightVal = 100 + (2*contrast_+4)*10;
-
- if (backgroundColor.isValid()) {
- if (!isKHTMLWidget())
- widget()->setEraseColor(backgroundColor );
- for ( int i = 0; i < TQPalette::NColorGroups; ++i ) {
- pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Background, backgroundColor );
- pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Light, backgroundColor.light(highlightVal) );
- pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Dark, backgroundColor.dark(lowlightVal) );
- pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Mid, backgroundColor.dark(120) );
- pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Midlight, backgroundColor.light(110) );
- pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Button, backgroundColor );
- pal.setColor( (TQPalette::ColorGroup)i, TQColorGroup::Base, backgroundColor );
- }
- }
- if ( color.isValid() ) {
- struct ColorSet {
- TQPalette::ColorGroup cg;
- TQColorGroup::ColorRole cr;
- };
- const struct ColorSet toSet [] = {
- { TQPalette::Active, TQColorGroup::Foreground },
- { TQPalette::Active, TQColorGroup::ButtonText },
- { TQPalette::Active, TQColorGroup::Text },
- { TQPalette::Inactive, TQColorGroup::Foreground },
- { TQPalette::Inactive, TQColorGroup::ButtonText },
- { TQPalette::Inactive, TQColorGroup::Text },
- { TQPalette::Disabled,TQColorGroup::ButtonText },
- { TQPalette::NColorGroups, TQColorGroup::NColorRoles },
- };
- const ColorSet *set = toSet;
- while( set->cg != TQPalette::NColorGroups ) {
- pal.setColor( set->cg, set->cr, color );
- ++set;
- }
-
- TQColor disfg = color;
- int h, s, v;
- disfg.hsv( &h, &s, &v );
- if (v > 128)
- // dark bg, light fg - need a darker disabled fg
- disfg = disfg.dark(lowlightVal);
- else if (disfg != Qt::black)
- // light bg, dark fg - need a lighter disabled fg - but only if !black
- disfg = disfg.light(highlightVal);
- else
- // black fg - use darkgray disabled fg
- disfg = Qt::darkGray;
- pal.setColor(TQPalette::Disabled,TQColorGroup::Foreground,disfg);
- }
-
- m_widget->setPalette(pal);
- }
- else
- m_widget->unsetPalette();
- // Border:
- TQFrame* frame = ::tqqt_cast<TQFrame*>(m_widget);
- if (frame) {
- if (shouldPaintBackgroundOrBorder())
- {
- frame->setFrameShape(TQFrame::NoFrame);
- }
- }
-
- }
-
- RenderReplaced::updateFromElement();
-}
-
-void RenderWidget::slotWidgetDestructed()
-{
- if (m_view)
- m_view->setWidgetVisible(this, false);
- m_widget = 0;
-}
-
-void RenderWidget::setStyle(RenderStyle *_style)
-{
- RenderReplaced::setStyle(_style);
- if(m_widget)
- {
- m_widget->setFont(style()->font());
- if (style()->visibility() != VISIBLE) {
- if (m_view)
- m_view->setWidgetVisible(this, false);
- m_widget->hide();
- }
- }
-
- // Don't paint borders if the border-style is native
- // or borders are not supported on this widget
- if (!canHaveBorder() ||
- (style()->borderLeftStyle() == BNATIVE &&
- style()->borderRightStyle() == BNATIVE &&
- style()->borderTopStyle() == BNATIVE &&
- style()->borderBottomStyle() == BNATIVE))
- {
- setShouldPaintBackgroundOrBorder(false);
- }
-}
-
-void RenderWidget::paint(PaintInfo& paintInfo, int _tx, int _ty)
-{
- _tx += m_x;
- _ty += m_y;
-
- if (shouldPaintBackgroundOrBorder() &&
- (paintInfo.phase == PaintActionChildBackground || paintInfo.phase == PaintActionChildBackgrounds))
- paintBoxDecorations(paintInfo, _tx, _ty);
-
- if (!m_widget || !m_view || paintInfo.phase != PaintActionForeground)
- return;
-
- // not visible or not even once layouted
- if (style()->visibility() != VISIBLE || m_y <= -500000 || m_resizePending )
- return;
-
- if ( (_ty > paintInfo.r.bottom()) || (_ty + m_height <= paintInfo.r.top()) ||
- (_tx + m_width <= paintInfo.r.left()) || (_tx > paintInfo.r.right()) )
- return;
-
- int xPos = _tx+borderLeft()+paddingLeft();
- int yPos = _ty+borderTop()+paddingTop();
-
- bool khtmlw = isKHTMLWidget();
- int childw = m_widget->width();
- int childh = m_widget->height();
- if ( (childw == 2000 || childh == 3072) && m_widget->inherits( "KHTMLView" ) ) {
- KHTMLView *vw = static_cast<KHTMLView *>(m_widget);
- int cy = m_view->contentsY();
- int ch = m_view->visibleHeight();
-
-
- int childx = m_view->childX( m_widget );
- int childy = m_view->childY( m_widget );
-
- int xNew = xPos;
- int yNew = childy;
-
- // tqDebug("cy=%d, ch=%d, childy=%d, childh=%d", cy, ch, childy, childh );
- if ( childh == 3072 ) {
- if ( cy + ch > childy + childh ) {
- yNew = cy + ( ch - childh )/2;
- } else if ( cy < childy ) {
- yNew = cy + ( ch - childh )/2;
- }
-// tqDebug("calculated yNew=%d", yNew);
- }
- yNew = kMin( yNew, yPos + m_height - childh );
- yNew = kMax( yNew, yPos );
- if ( yNew != childy || xNew != childx ) {
- if ( vw->contentsHeight() < yNew - yPos + childh )
- vw->resizeContents( vw->contentsWidth(), yNew - yPos + childh );
- vw->setContentsPos( xNew - xPos, yNew - yPos );
- }
- xPos = xNew;
- yPos = yNew;
- }
- m_view->setWidgetVisible(this, true);
- m_view->addChild(m_widget, xPos, yPos );
- m_widget->show();
- if (khtmlw)
- paintWidget(paintInfo, m_widget, xPos, yPos);
-}
-
-#include <tqinternal_p.h>
-
-// The PaintBuffer class provides a shared buffer for widget painting.
-//
-// It will grow to encompass the biggest widget encountered, in order to avoid
-// constantly resizing.
-// When it grows over maxPixelBuffering, it periodically checks if such a size
-// is still needed. If not, it shrinks down to the biggest size < maxPixelBuffering
-// that was requested during the overflow lapse.
-
-class PaintBuffer: public TQObject
-{
-public:
- static const int maxPixelBuffering = 320*200;
- static const int leaseTime = 20*1000;
-
- static TQPixmap *grab( TQSize s = TQSize() ) {
- if (!m_inst)
- m_inst = new PaintBuffer;
- return m_inst->getBuf( s );
- }
- static void release() { m_inst->m_grabbed = false; }
-protected:
- PaintBuffer(): m_overflow(false), m_grabbed(false),
- m_timer(0), m_resetWidth(0), m_resetHeight(0) {};
- void timerEvent(TQTimerEvent* e) {
- assert( m_timer == e->timerId() );
- if (m_grabbed)
- return;
- m_buf.resize(m_resetWidth, m_resetHeight);
- m_resetWidth = m_resetHeight = 0;
- killTimer( m_timer );
- m_timer = 0;
- }
-
- TQPixmap *getBuf( TQSize s ) {
- assert( !m_grabbed );
- if (s.isEmpty())
- return 0;
-
- m_grabbed = true;
- bool cur_overflow = false;
-
- int nw = kMax(m_buf.width(), s.width());
- int nh = kMax(m_buf.height(), s.height());
-
- if (!m_overflow && (nw*nh > maxPixelBuffering))
- cur_overflow = true;
-
- if (nw != m_buf.width() || nh != m_buf.height())
- m_buf.resize(nw, nh);
-
- if (cur_overflow) {
- m_overflow = true;
- m_timer = startTimer( leaseTime );
- } else if (m_overflow) {
- if( s.width()*s.height() > maxPixelBuffering ) {
- killTimer( m_timer );
- m_timer = startTimer( leaseTime );
- } else {
- if (s.width() > m_resetWidth)
- m_resetWidth = s.width();
- if (s.height() > m_resetHeight)
- m_resetHeight = s.height();
- }
- }
- return &m_buf;
- }
-private:
- static PaintBuffer* m_inst;
- TQPixmap m_buf;
- bool m_overflow;
- bool m_grabbed;
- int m_timer;
- int m_resetWidth;
- int m_resetHeight;
-};
-
-PaintBuffer *PaintBuffer::m_inst = 0;
-
-static void copyWidget(const TQRect& r, TQPainter *p, TQWidget *widget, int tx, int ty)
-{
- if (r.isNull() || r.isEmpty() )
- return;
- TQRegion blit(r);
- TQValueVector<TQWidget*> cw;
- TQValueVector<TQRect> cr;
-
- if (!widget->childrenListObject().isEmpty()) {
- // build region
- TQObjectList childWidgets = widget->childrenListObject();
- TQObjectListIterator it(childWidgets);
- for (; it.current(); ++it) {
- TQWidget* const w = ::tqqt_cast<TQWidget *>(it.current());
- if ( w && !w->isTopLevel() && !w->isHidden()) {
- TQRect r2 = w->geometry();
- blit -= r2;
- r2 = r2.intersect( r );
- r2.moveBy(-w->x(), -w->y());
- cr.append(r2);
- cw.append(w);
- }
- }
- }
- TQMemArray<TQRect> br = blit.rects();
-
- const int cnt = br.size();
- const bool external = p->device()->isExtDev();
- TQPixmap* const pm = PaintBuffer::grab( widget->size() );
- if (!pm)
- {
- kdWarning(6040) << "Rendering widget [ " << widget->className() << " ] failed due to invalid size." << endl;
- return;
- }
-
- // fill background
- if ( external ) {
- // even hackier!
- TQPainter pt( pm );
- const TQColor c = widget->colorGroup().base();
- for (int i = 0; i < cnt; ++i)
- pt.fillRect( br[i], c );
- } else {
- TQRect dr;
- for (int i = 0; i < cnt; ++i ) {
- dr = br[i];
- dr.moveBy( tx, ty );
- dr = p->xForm( dr );
- bitBlt(pm, br[i].topLeft(), p->device(), dr);
- }
- }
-
- // send paint event
- TQPainter::redirect(widget, pm);
- TQPaintEvent e( r, false );
- TQApplication::sendEvent( widget, &e );
- TQPainter::redirect(widget, 0);
-
- // transfer result
- if ( external )
- for ( int i = 0; i < cnt; ++i )
- p->drawPixmap(TQPoint(tx+br[i].x(), ty+br[i].y()), *pm, br[i]);
- else
- for ( int i = 0; i < cnt; ++i )
- bitBlt(p->device(), p->xForm( TQPoint(tx, ty) + br[i].topLeft() ), pm, br[i]);
-
- // cleanup and recurse
- PaintBuffer::release();
- TQValueVector<TQWidget*>::iterator cwit = cw.begin();
- TQValueVector<TQWidget*>::iterator cwitEnd = cw.end();
- TQValueVector<TQRect>::const_iterator crit = cr.begin();
- for (; cwit != cwitEnd; ++cwit, ++crit)
- copyWidget(*crit, p, *cwit, tx+(*cwit)->x(), ty+(*cwit)->y());
-}
-
-void RenderWidget::paintWidget(PaintInfo& pI, TQWidget *widget, int tx, int ty)
-{
- TQPainter* const p = pI.p;
- allowWidgetPaintEvents = true;
-
- const bool dsbld = TQSharedDoubleBuffer::isDisabled();
- TQSharedDoubleBuffer::setDisabled(true);
- TQRect rr = pI.r;
- rr.moveBy(-tx, -ty);
- const TQRect r = widget->rect().intersect( rr );
- copyWidget(r, p, widget, tx, ty);
- TQSharedDoubleBuffer::setDisabled(dsbld);
-
- allowWidgetPaintEvents = false;
-}
-
-bool RenderWidget::eventFilter(TQObject* /*o*/, TQEvent* e)
-{
- // no special event processing if this is a frame (in which case KHTMLView handles it all)
- if ( ::tqqt_cast<KHTMLView *>( m_widget ) )
- return false;
- if ( !element() ) return true;
-
-
- static bool directToWidget = false;
- if (directToWidget) {
- //We're trying to get the event to the widget
- //promptly. So get out of here..
- return false;
- }
-
- ref();
- element()->ref();
-
- bool filtered = false;
-
- //kdDebug() << "RenderWidget::eventFilter type=" << e->type() << endl;
- switch(e->type()) {
- case TQEvent::FocusOut:
- // First, forward it to the widget, so that Qt gets a precise
- // state of the focus before pesky JS can try changing it..
- directToWidget = true;
- TQApplication::sendEvent(m_widget, e);
- directToWidget = false;
- filtered = true; //We already delivered it!
-
- // Don't count popup as a valid reason for losing the focus
- // (example: opening the options of a select combobox shouldn't emit onblur)
- if ( TQT_TQFOCUSEVENT(e)->reason() != TQFocusEvent::Popup )
- handleFocusOut();
- break;
- case TQEvent::FocusIn:
- //As above, forward to the widget first...
- directToWidget = true;
- TQApplication::sendEvent(m_widget, e);
- directToWidget = false;
- filtered = true; //We already delivered it!
-
- //kdDebug(6000) << "RenderWidget::eventFilter captures FocusIn" << endl;
- element()->getDocument()->setFocusNode(element());
-// if ( isEditable() ) {
-// KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>( element()->view->part()->browserExtension() );
-// if ( ext ) ext->editableWidgetFocused( m_widget );
-// }
- break;
- case TQEvent::KeyPress:
- case TQEvent::KeyRelease:
- // TODO this seems wrong - Qt events are not correctly translated to DOM ones,
- // like in KHTMLView::dispatchKeyEvent()
- if (element()->dispatchKeyEvent(TQT_TQKEYEVENT(e),false))
- filtered = true;
- break;
-
- case TQEvent::Wheel:
- if (widget()->parentWidget() == view()->viewport()) {
- // don't allow the widget to react to wheel event unless its
- // currently focused. this avoids accidentally changing a select box
- // or something while wheeling a webpage.
- if (tqApp->focusWidget() != widget() &&
- widget()->focusPolicy() <= TQ_StrongFocus) {
- TQT_TQWHEELEVENT(e)->ignore();
- TQApplication::sendEvent(view(), e);
- filtered = true;
- }
- }
- break;
- default:
- break;
- };
-
- element()->deref();
-
- // stop processing if the widget gets deleted, but continue in all other cases
- if (hasOneRef())
- filtered = true;
- deref();
-
- return filtered;
-}
-
-void RenderWidget::EventPropagator::sendEvent(TQEvent *e) {
- switch(e->type()) {
- case TQEvent::MouseButtonPress:
- mousePressEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::MouseButtonRelease:
- mouseReleaseEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::MouseButtonDblClick:
- mouseDoubleClickEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::MouseMove:
- mouseMoveEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::KeyPress:
- keyPressEvent(TQT_TQKEYEVENT(e));
- break;
- case TQEvent::KeyRelease:
- keyReleaseEvent(TQT_TQKEYEVENT(e));
- break;
- default:
- break;
- }
-}
-
-void RenderWidget::ScrollViewEventPropagator::sendEvent(TQEvent *e) {
- switch(e->type()) {
- case TQEvent::MouseButtonPress:
- viewportMousePressEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::MouseButtonRelease:
- viewportMouseReleaseEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::MouseButtonDblClick:
- viewportMouseDoubleClickEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::MouseMove:
- viewportMouseMoveEvent(TQT_TQMOUSEEVENT(e));
- break;
- case TQEvent::KeyPress:
- keyPressEvent(TQT_TQKEYEVENT(e));
- break;
- case TQEvent::KeyRelease:
- keyReleaseEvent(TQT_TQKEYEVENT(e));
- break;
- default:
- break;
- }
-}
-
-bool RenderWidget::handleEvent(const DOM::EventImpl& ev)
-{
- bool ret = false;
- switch(ev.id()) {
- case EventImpl::MOUSEDOWN_EVENT:
- case EventImpl::MOUSEUP_EVENT:
- case EventImpl::MOUSEMOVE_EVENT: {
- if (!ev.isMouseEvent()) break;
- const MouseEventImpl &me = static_cast<const MouseEventImpl &>(ev);
- TQMouseEvent* const qme = me.qEvent();
-
- int absx = 0;
- int absy = 0;
-
- absolutePosition(absx, absy);
- TQPoint p(me.clientX() - absx + m_view->contentsX(),
- me.clientY() - absy + m_view->contentsY());
- TQMouseEvent::Type type;
- int button = 0;
- int state = 0;
-
- if (qme) {
- button = qme->button();
- state = qme->state();
- type = qme->type();
- } else {
- switch(me.id()) {
- case EventImpl::MOUSEDOWN_EVENT:
- type = TQMouseEvent::MouseButtonPress;
- break;
- case EventImpl::MOUSEUP_EVENT:
- type = TQMouseEvent::MouseButtonRelease;
- break;
- case EventImpl::MOUSEMOVE_EVENT:
- default:
- type = TQMouseEvent::MouseMove;
- break;
- }
- switch (me.button()) {
- case 0:
- button = Qt::LeftButton;
- break;
- case 1:
- button = Qt::MidButton;
- break;
- case 2:
- button = Qt::RightButton;
- break;
- default:
- break;
- }
- if (me.ctrlKey())
- state |= ControlButton;
- if (me.altKey())
- state |= AltButton;
- if (me.shiftKey())
- state |= ShiftButton;
- if (me.metaKey())
- state |= MetaButton;
- }
-
-// kdDebug(6000) << "sending event to widget "
-// << " pos=" << p << " type=" << type
-// << " button=" << button << " state=" << state << endl;
- TQMouseEvent e(type, p, button, state);
- TQScrollView * sc = ::tqqt_cast<TQScrollView*>(m_widget);
- if (sc && !::tqqt_cast<TQListBox*>(m_widget))
- static_cast<ScrollViewEventPropagator *>(sc)->sendEvent(TQT_TQEVENT(&e));
- else
- static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(&e));
- ret = e.isAccepted();
- break;
- }
- case EventImpl::KEYDOWN_EVENT:
- // do nothing; see the mapping table below
- break;
- case EventImpl::KEYUP_EVENT: {
- if (!ev.isKeyRelatedEvent()) break;
-
- const KeyEventBaseImpl& domKeyEv = static_cast<const KeyEventBaseImpl &>(ev);
- if (domKeyEv.isSynthetic() && !acceptsSyntheticEvents()) break;
-
- TQKeyEvent* const ke = domKeyEv.qKeyEvent();
- static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(ke));
- ret = ke->isAccepted();
- break;
- }
- case EventImpl::KEYPRESS_EVENT: {
- if (!ev.isKeyRelatedEvent()) break;
-
- const KeyEventBaseImpl& domKeyEv = static_cast<const KeyEventBaseImpl &>(ev);
- if (domKeyEv.isSynthetic() && !acceptsSyntheticEvents()) break;
-
- // See KHTMLView::dispatchKeyEvent: autorepeat is just keypress in the DOM
- // but it's keyrelease+keypress in Qt. So here we do the inverse mapping as
- // the one done in KHTMLView: generate two events for one DOM auto-repeat keypress.
- // Similarly, DOM keypress events with non-autorepeat Qt event do nothing here,
- // because the matching Qt keypress event was already sent from DOM keydown event.
-
- // Reverse drawing as the one in KHTMLView:
- // DOM: Down Press | Press | Up
- // Qt: (nothing) Press | Release(autorepeat) + Press(autorepeat) | Release
- //
- // Qt::KeyPress is sent for DOM keypress and not DOM keydown to allow
- // sites to block a key with onkeypress, #99749
-
- TQKeyEvent* const ke = domKeyEv.qKeyEvent();
- if (ke->isAutoRepeat()) {
- TQKeyEvent releaseEv( TQEvent::KeyRelease, ke->key(), ke->ascii(), ke->state(),
- ke->text(), ke->isAutoRepeat(), ke->count() );
- static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(&releaseEv));
- }
- static_cast<EventPropagator *>(m_widget)->sendEvent(TQT_TQEVENT(ke));
- ret = ke->isAccepted();
- break;
- }
- case EventImpl::MOUSEOUT_EVENT: {
- TQEvent moe( TQEvent::Leave );
- TQApplication::sendEvent(m_widget, &moe);
- break;
- }
- case EventImpl::MOUSEOVER_EVENT: {
- TQEvent moe( TQEvent::Enter );
- TQApplication::sendEvent(m_widget, &moe);
- view()->part()->resetHoverText();
- break;
- }
- default:
- break;
- }
- return ret;
-}
-
-void RenderWidget::deref()
-{
- if (_ref) _ref--;
-// tqDebug( "deref(%p): width get count is %d", this, _ref);
- if (!_ref) {
- khtml::SharedPtr<RenderArena> guard(m_arena); //Since delete on us gets called -first-,
- //before the arena free
- arenaDelete(m_arena.get());
- }
-}
-
-FindSelectionResult RenderReplaced::checkSelectionPoint(int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int &offset, SelPointState &)
-{
-#if 0
- kdDebug(6040) << "RenderReplaced::checkSelectionPoint(_x="<<_x<<",_y="<<_y<<",_tx="<<_tx<<",_ty="<<_ty<<")" << endl
- << "xPos: " << xPos() << " yPos: " << yPos() << " width: " << width() << " height: " << height() << endl
- << "_ty + yPos: " << (_ty + yPos()) << " + height: " << (_ty + yPos() + height()) << "; _tx + xPos: " << (_tx + xPos()) << " + width: " << (_tx + xPos() + width()) << endl;
-#endif
- node = element();
- offset = 0;
-
- if ( _y < _ty + yPos() )
- return SelectionPointBefore; // above -> before
-
- if ( _y > _ty + yPos() + height() ) {
- // below -> after
- // Set the offset to the max
- offset = 1;
- return SelectionPointAfter;
- }
- if ( _x > _tx + xPos() + width() ) {
- // to the right
- // ### how to regard bidi in replaced elements? (LS)
- offset = 1;
- return SelectionPointAfterInLine;
- }
-
- // The Y matches, check if we're on the left
- if ( _x < _tx + xPos() ) {
- // ### how to regard bidi in replaced elements? (LS)
- return SelectionPointBeforeInLine;
- }
-
- offset = _x > _tx + xPos() + width()/2;
- return SelectionPointInside;
-}
-
-#ifdef ENABLE_DUMP
-void RenderWidget::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderReplaced::dump(stream,ind);
- if ( widget() )
- stream << " color=" << widget()->foregroundColor().name()
- << " bg=" << widget()->backgroundColor().name();
- else
- stream << " null widget";
-}
-#endif
-
-#include "render_replaced.moc"
-
diff --git a/khtml/rendering/render_replaced.h b/khtml/rendering/render_replaced.h
deleted file mode 100644
index 8432f170e..000000000
--- a/khtml/rendering/render_replaced.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * This file is part of the HTML widget for KDE.
- *
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef render_replaced_h
-#define render_replaced_h
-
-#include "rendering/render_block.h"
-#include <tqobject.h>
-#include <tqscrollview.h>
-
-class KHTMLView;
-class TQWidget;
-
-namespace DOM
-{
- class MouseEventImpl;
-}
-
-namespace khtml {
-
-class RenderReplaced : public RenderBox
-{
-public:
- RenderReplaced(DOM::NodeImpl* node);
-
- virtual const char *renderName() const { return "RenderReplaced"; }
- virtual bool isRenderReplaced() const { return true; }
-
- virtual bool childAllowed() const { return false; }
-
- virtual void calcMinMaxWidth();
-
- virtual short intrinsicWidth() const { return m_intrinsicWidth; }
- virtual int intrinsicHeight() const { return m_intrinsicHeight; }
-
- void setIntrinsicWidth(int w) { m_intrinsicWidth = w; }
- void setIntrinsicHeight(int h) { m_intrinsicHeight = h; }
-
- virtual void position(InlineBox*, int, int, bool);
-
- // Return before, after (offset set to max), or inside the replaced element,
- // at @p offset
- virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
- DOM::NodeImpl*& node, int & offset,
- SelPointState & );
-
- /** returns the lowest possible value the caret offset may have to
- * still point to a valid position.
- *
- * Returns 0.
- */
- virtual long minOffset() const { return 0; }
- /** returns the highest possible value the caret offset may have to
- * still point to a valid position.
- *
- * Returns 0.
- */
- virtual long maxOffset() const { return 0; }
-
-protected:
- short m_intrinsicWidth;
- short m_intrinsicHeight;
-};
-
-
-class RenderWidget : public TQObject, public RenderReplaced, public khtml::Shared<RenderWidget>
-{
- Q_OBJECT
-public:
- RenderWidget(DOM::NodeImpl* node);
- virtual ~RenderWidget();
-
- virtual void setStyle(RenderStyle *style);
- virtual void paint( PaintInfo& i, int tx, int ty );
- virtual bool isWidget() const { return true; };
-
- virtual bool isFrame() const { return false; }
-
- virtual void detach( );
- virtual void layout( );
-
- virtual void updateFromElement();
-
- TQWidget *widget() const { return m_widget; }
- KHTMLView* view() const { return m_view; }
-
- void deref();
-
- void cancelPendingResize();
- bool needsMask() const { return m_needsMask; }
-
- static void paintWidget(PaintInfo& pI, TQWidget *widget, int tx, int ty);
- virtual bool handleEvent(const DOM::EventImpl& ev);
-
-#ifdef ENABLE_DUMP
- virtual void dump(TQTextStream &stream, const TQString &ind) const;
-#endif
-
- // for ECMA to flush all pending resizes
- KDE_EXPORT static void flushWidgetResizes();
-
-public slots:
- void slotWidgetDestructed();
- bool isKHTMLWidget() const { return m_isKHTMLWidget; }
-
-protected:
- virtual bool canHaveBorder() const { return false; }
-
- virtual bool acceptsSyntheticEvents() const { return true; }
-
- virtual void handleFocusOut() {}
- bool event( TQEvent *e );
-
- bool eventFilter(TQObject* /*o*/, TQEvent* e);
- void setQWidget(TQWidget *widget);
- void resizeWidget( int w, int h );
-
- TQWidget *m_widget;
- KHTMLView* m_view;
-
- //Because we mess with normal detach due to ref/deref,
- //we need to keep track of the arena ourselves
- //so it doesn't get yanked from us, etc.
- SharedPtr<RenderArena> m_arena;
-
- bool m_resizePending;
- bool m_discardResizes;
- bool m_isKHTMLWidget;
- bool m_needsMask;
-
-public:
- virtual int borderTop() const { return canHaveBorder() ? RenderReplaced::borderTop() : 0; }
- virtual int borderBottom() const { return canHaveBorder() ? RenderReplaced::borderBottom() : 0; }
- virtual int borderLeft() const { return canHaveBorder() ? RenderReplaced::borderLeft() : 0; }
- virtual int borderRight() const { return canHaveBorder() ? RenderReplaced::borderRight() : 0; }
-
- class EventPropagator : public TQWidget {
- public:
- void sendEvent(TQEvent *e);
- };
- class ScrollViewEventPropagator : public TQScrollView {
- public:
- void sendEvent(TQEvent *e);
- };
-};
-
-extern bool allowWidgetPaintEvents;
-
-}
-
-#endif
diff --git a/khtml/rendering/render_style.cpp b/khtml/rendering/render_style.cpp
deleted file mode 100644
index a71dd4116..000000000
--- a/khtml/rendering/render_style.cpp
+++ /dev/null
@@ -1,1301 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2002-2005 Apple Computer, Inc.
- * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "xml/dom_stringimpl.h"
-#include "css/cssstyleselector.h"
-#include "css/css_valueimpl.h"
-#include "render_style.h"
-
-#include "kdebug.h"
-
-using namespace khtml;
-using namespace DOM;
-
-/* CSS says Fixed for the default padding value, but we treat variable as 0 padding anyways, and like
- * this is works fine for table paddings aswell
- */
-StyleSurroundData::StyleSurroundData()
- : margin( Fixed ), padding( Variable )
-{
-}
-
-StyleSurroundData::StyleSurroundData(const StyleSurroundData& o )
- : Shared<StyleSurroundData>(),
- offset( o.offset ), margin( o.margin ), padding( o.padding ),
- border( o.border )
-{
-}
-
-bool StyleSurroundData::operator==(const StyleSurroundData& o) const
-{
- return offset==o.offset && margin==o.margin &&
- padding==o.padding && border==o.border;
-}
-
-StyleBoxData::StyleBoxData()
- : z_index( 0 ), z_auto( true )
-{
- min_width = min_height = RenderStyle::initialMinSize();
- max_width = max_height = RenderStyle::initialMaxSize();
- box_sizing = RenderStyle::initialBoxSizing();
-}
-
-StyleBoxData::StyleBoxData(const StyleBoxData& o )
- : Shared<StyleBoxData>(),
- width( o.width ), height( o.height ),
- min_width( o.min_width ), max_width( o.max_width ),
- min_height ( o.min_height ), max_height( o.max_height ),
- box_sizing( o.box_sizing),
- z_index( o.z_index ), z_auto( o.z_auto )
-{
-}
-
-bool StyleBoxData::operator==(const StyleBoxData& o) const
-{
- return
- width == o.width &&
- height == o.height &&
- min_width == o.min_width &&
- max_width == o.max_width &&
- min_height == o.min_height &&
- max_height == o.max_height &&
- box_sizing == o.box_sizing &&
- z_index == o.z_index &&
- z_auto == o.z_auto;
-}
-
-StyleVisualData::StyleVisualData()
- : textDecoration(RenderStyle::initialTextDecoration()),
- palette( TQApplication::palette() )
-{
-}
-
-StyleVisualData::~StyleVisualData() {
-}
-
-StyleVisualData::StyleVisualData(const StyleVisualData& o )
- : Shared<StyleVisualData>(),
- clip( o.clip ), textDecoration(o.textDecoration),
- palette( o.palette )
-{
-}
-
-BackgroundLayer::BackgroundLayer()
-:m_image(RenderStyle::initialBackgroundImage()),
- m_bgAttachment(RenderStyle::initialBackgroundAttachment()),
- m_bgClip(RenderStyle::initialBackgroundClip()),
- m_bgOrigin(RenderStyle::initialBackgroundOrigin()),
- m_bgRepeat(RenderStyle::initialBackgroundRepeat()),
- m_backgroundSize(RenderStyle::initialBackgroundSize()),
- m_next(0)
-{
- m_imageSet = m_attachmentSet = m_clipSet = m_originSet =
- m_repeatSet = m_xPosSet = m_yPosSet = m_backgroundSizeSet = false;
-}
-
-BackgroundLayer::BackgroundLayer(const BackgroundLayer& o)
-{
- m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
- m_image = o.m_image;
- m_xPosition = o.m_xPosition;
- m_yPosition = o.m_yPosition;
- m_bgAttachment = o.m_bgAttachment;
- m_bgClip = o.m_bgClip;
- m_bgOrigin = o.m_bgOrigin;
- m_bgRepeat = o.m_bgRepeat;
- m_backgroundSize = o.m_backgroundSize;
- m_imageSet = o.m_imageSet;
- m_attachmentSet = o.m_attachmentSet;
- m_clipSet = o.m_clipSet;
- m_originSet = o.m_originSet;
- m_repeatSet = o.m_repeatSet;
- m_xPosSet = o.m_xPosSet;
- m_yPosSet = o.m_yPosSet;
- m_backgroundSizeSet = o.m_backgroundSizeSet;
-}
-
-BackgroundLayer::~BackgroundLayer()
-{
- delete m_next;
-}
-
-BackgroundLayer& BackgroundLayer::operator=(const BackgroundLayer& o) {
- if (m_next != o.m_next) {
- delete m_next;
- m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
- }
-
- m_image = o.m_image;
- m_xPosition = o.m_xPosition;
- m_yPosition = o.m_yPosition;
- m_bgAttachment = o.m_bgAttachment;
- m_bgClip = o.m_bgClip;
- m_bgOrigin = o.m_bgOrigin;
- m_bgRepeat = o.m_bgRepeat;
- m_backgroundSize = o.m_backgroundSize;
-
- m_imageSet = o.m_imageSet;
- m_attachmentSet = o.m_attachmentSet;
- m_originSet = o.m_originSet;
- m_repeatSet = o.m_repeatSet;
- m_xPosSet = o.m_xPosSet;
- m_yPosSet = o.m_yPosSet;
- m_backgroundSizeSet = o.m_backgroundSizeSet;
-
- return *this;
-}
-
-bool BackgroundLayer::operator==(const BackgroundLayer& o) const {
- return m_image == o.m_image && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition &&
- m_bgAttachment == o.m_bgAttachment && m_bgClip == o.m_bgClip && m_bgOrigin == o.m_bgOrigin && m_bgRepeat == o.m_bgRepeat &&
- m_backgroundSize.width == o.m_backgroundSize.width && m_backgroundSize.height == o.m_backgroundSize.height &&
- m_imageSet == o.m_imageSet && m_attachmentSet == o.m_attachmentSet && m_repeatSet == o.m_repeatSet &&
- m_xPosSet == o.m_xPosSet && m_yPosSet == o.m_yPosSet && m_backgroundSizeSet == o.m_backgroundSizeSet &&
- ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
-}
-
-void BackgroundLayer::fillUnsetProperties()
-{
- BackgroundLayer* curr;
- for (curr = this; curr && curr->isBackgroundImageSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_image = pattern->m_image;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
- for (curr = this; curr && curr->isBackgroundXPositionSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_xPosition = pattern->m_xPosition;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
- for (curr = this; curr && curr->isBackgroundYPositionSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_yPosition = pattern->m_yPosition;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
- for (curr = this; curr && curr->isBackgroundAttachmentSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_bgAttachment = pattern->m_bgAttachment;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
- for (curr = this; curr && curr->isBackgroundClipSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_bgClip = pattern->m_bgClip;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
- for (curr = this; curr && curr->isBackgroundOriginSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_bgOrigin = pattern->m_bgOrigin;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
- for (curr = this; curr && curr->isBackgroundRepeatSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_bgRepeat = pattern->m_bgRepeat;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-
- for (curr = this; curr && curr->isBackgroundSizeSet(); curr = curr->next());
- if (curr && curr != this) {
- // We need to fill in the remaining values with the pattern specified.
- for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
- curr->m_backgroundSize = pattern->m_backgroundSize;
- pattern = pattern->next();
- if (pattern == curr || !pattern)
- pattern = this;
- }
- }
-}
-
-void BackgroundLayer::cullEmptyLayers()
-{
- BackgroundLayer *next;
- for (BackgroundLayer *p = this; p; p = next) {
- next = p->m_next;
- if (next && !next->isBackgroundImageSet() &&
- !next->isBackgroundXPositionSet() && !next->isBackgroundYPositionSet() &&
- !next->isBackgroundAttachmentSet() && !next->isBackgroundClipSet() &&
- !next->isBackgroundOriginSet() && !next->isBackgroundRepeatSet() &&
- !next->isBackgroundSizeSet()) {
- delete next;
- p->m_next = 0;
- break;
- }
- }
-}
-
-StyleBackgroundData::StyleBackgroundData()
-{}
-
-StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o)
- : Shared<StyleBackgroundData>(), m_background(o.m_background), m_outline(o.m_outline)
-{}
-
-bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
-{
- return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
-}
-
-StyleGeneratedData::StyleGeneratedData() : Shared<StyleGeneratedData>(), content(0), counter_reset(0), counter_increment(0) {}
-
-StyleGeneratedData::~StyleGeneratedData()
-{
- if (counter_reset) counter_reset->deref();
- if (counter_increment) counter_increment->deref();
- delete content;
-}
-
-StyleGeneratedData::StyleGeneratedData(const StyleGeneratedData& o)
- : Shared<StyleGeneratedData>(), content(0),
- counter_reset(o.counter_reset), counter_increment(o.counter_increment)
-{
- if (o.content) content = new ContentData(*o.content);
- if (counter_reset) counter_reset->ref();
- if (counter_increment) counter_increment->ref();
-}
-
-bool StyleGeneratedData::contentDataEquivalent(const StyleGeneratedData* otherStyle) const
-{
- ContentData* c1 = content;
- ContentData* c2 = otherStyle->content;
-
- while (c1 && c2) {
- if (c1->_contentType != c2->_contentType)
- return false;
- if (c1->_contentType == CONTENT_TEXT) {
- DOM::DOMString c1Str(c1->_content.text);
- DOM::DOMString c2Str(c2->_content.text);
- if (c1Str != c2Str)
- return false;
- }
- else if (c1->_contentType == CONTENT_OBJECT) {
- if (c1->_content.object != c2->_content.object)
- return false;
- }
- else if (c1->_contentType == CONTENT_COUNTER) {
- if (c1->_content.counter != c2->_content.counter)
- return false;
- }
- else if (c1->_contentType == CONTENT_QUOTE) {
- if (c1->_content.quote != c2->_content.quote)
- return false;
- }
-
- c1 = c1->_nextContent;
- c2 = c2->_nextContent;
- }
-
- return !c1 && !c2;
-}
-
-static bool compareCounterActList(const CSSValueListImpl* ca, const CSSValueListImpl* cb) {
- // weeee....
- CSSValueListImpl* a = const_cast<CSSValueListImpl*>(ca);
- CSSValueListImpl* b = const_cast<CSSValueListImpl*>(cb);
-
- if (!a && !b) return true;
- if (!a || !b) return false;
- if (a->length() != b->length()) return false;
- for(uint i=0; i< a->length(); i++) {
- CSSValueImpl *ai = a->item(i);
- CSSValueImpl *bi = b->item(i);
- assert(ai && ai->cssValueType() == CSSValue::CSS_CUSTOM);
- assert(bi && bi->cssValueType() == CSSValue::CSS_CUSTOM);
- CounterActImpl* caa = static_cast<CounterActImpl*>(ai);
- CounterActImpl* cab = static_cast<CounterActImpl*>(bi);
- if (caa->value() != cab->value()) return false;
- if (caa->counter() != cab->counter()) return false;
- }
- return true;
-}
-
-bool StyleGeneratedData::counterDataEquivalent(const StyleGeneratedData* otherStyle) const
-{
- return compareCounterActList(counter_reset, otherStyle->counter_reset) &&
- compareCounterActList(counter_increment, otherStyle->counter_increment);
-}
-
-bool StyleGeneratedData::operator==(const StyleGeneratedData& o) const
-{
- return contentDataEquivalent(&o) && counterDataEquivalent(&o);
-}
-
-StyleMarqueeData::StyleMarqueeData()
-{
- increment = RenderStyle::initialMarqueeIncrement();
- speed = RenderStyle::initialMarqueeSpeed();
- direction = RenderStyle::initialMarqueeDirection();
- behavior = RenderStyle::initialMarqueeBehavior();
- loops = RenderStyle::initialMarqueeLoopCount();
-}
-
-StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData& o)
-:Shared<StyleMarqueeData>(), increment(o.increment), speed(o.speed), loops(o.loops),
- behavior(o.behavior), direction(o.direction)
-{}
-
-bool StyleMarqueeData::operator==(const StyleMarqueeData& o) const
-{
- return (increment == o.increment && speed == o.speed && direction == o.direction &&
- behavior == o.behavior && loops == o.loops);
-}
-
-StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
-:Shared<StyleCSS3NonInheritedData>()
-, opacity(RenderStyle::initialOpacity())
-{
-}
-
-StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o)
-:Shared<StyleCSS3NonInheritedData>(),
- opacity(o.opacity),
-#ifdef APPLE_CHANGES
- flexibleBox(o.flexibleBox),
-#endif
- marquee(o.marquee)
-{
-}
-
-bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData& o) const
-{
- return
- opacity == o.opacity &&
-#ifdef APPLE_CHANGES
- flexibleBox == o.flexibleBox &&
-#endif
- marquee == o.marquee;
-}
-
-StyleCSS3InheritedData::StyleCSS3InheritedData()
-:Shared<StyleCSS3InheritedData>(), textShadow(0), wordWrap(RenderStyle::initialWordWrap())
-#ifdef APPLE_CHANGES
-, userModify(READ_ONLY), textSizeAdjust(RenderStyle::initialTextSizeAdjust())
-#endif
-{
-
-}
-
-StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData& o)
-:Shared<StyleCSS3InheritedData>()
-{
- textShadow = o.textShadow ? new ShadowData(*o.textShadow) : 0;
- wordWrap = o.wordWrap;
-#ifdef APPLE_CHANGES
- userModify = o.userModify;
- textSizeAdjust = o.textSizeAdjust;
-#endif
-}
-
-StyleCSS3InheritedData::~StyleCSS3InheritedData()
-{
- delete textShadow;
-}
-
-bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData& o) const
-{
- return shadowDataEquivalent(o) && (wordWrap == o.wordWrap)
-#ifdef APPLE_CHANGES
- && (userModify == o.userModify) && (textSizeAdjust == o.textSizeAdjust)
-#endif
- ;
-}
-
-bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData& o) const
-{
- if (!textShadow && o.textShadow || textShadow && !o.textShadow)
- return false;
- if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
- return false;
- return true;
-}
-
-StyleInheritedData::StyleInheritedData()
- : indent( RenderStyle::initialTextIndent() ), line_height( RenderStyle::initialLineHeight() ),
- style_image( RenderStyle::initialListStyleImage() ),
- font(), color( RenderStyle::initialColor() ),
- border_hspacing( RenderStyle::initialBorderHorizontalSpacing() ),
- border_vspacing( RenderStyle::initialBorderVerticalSpacing() ),
- widows( RenderStyle::initialWidows() ), orphans( RenderStyle::initialOrphans() ),
- quotes(0)
-{
-}
-
-StyleInheritedData::~StyleInheritedData()
-{
- if (quotes) quotes->deref();
-}
-
-StyleInheritedData::StyleInheritedData(const StyleInheritedData& o )
- : Shared<StyleInheritedData>(),
- indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ),
- font( o.font ), color( o.color ),
- border_hspacing( o.border_hspacing ),
- border_vspacing( o.border_vspacing ),
- widows(o.widows), orphans(o.orphans)
-{
- quotes = o.quotes;
- if (quotes) quotes->ref();
-}
-
-bool StyleInheritedData::operator==(const StyleInheritedData& o) const
-{
- return
- indent == o.indent &&
- line_height == o.line_height &&
- border_hspacing == o.border_hspacing &&
- border_vspacing == o.border_vspacing &&
- style_image == o.style_image &&
- font == o.font &&
- color == o.color &&
- border_hspacing == o.border_hspacing &&
- border_vspacing == o.border_vspacing &&
- quotes == o.quotes &&
- widows == o.widows &&
- orphans == o.orphans ;
-
- // doesn't work because structs are not packed
- //return memcmp(this, &o, sizeof(*this))==0;
-}
-
-RenderStyle::RenderStyle()
-{
-// counter++;
- if (!_default)
- _default = new RenderStyle(true);
-
- box = _default->box;
- visual = _default->visual;
- background = _default->background;
- surround = _default->surround;
- generated = _default->generated;
- css3NonInheritedData = _default->css3NonInheritedData;
- css3InheritedData = _default->css3InheritedData;
-
- inherited = _default->inherited;
-
- setBitDefaults();
-
- pseudoStyle = 0;
-}
-
-RenderStyle::RenderStyle(bool)
-{
- setBitDefaults();
-
- box.init();
- visual.init();
- background.init();
- surround.init();
- generated.init();
- css3NonInheritedData.init();
-#ifdef APPLE_CHANGES // ### yet to be merged
- css3NonInheritedData.access()->flexibleBox.init();
-#endif
- css3NonInheritedData.access()->marquee.init();
- css3InheritedData.init();
- inherited.init();
-
- pseudoStyle = 0;
-}
-
-RenderStyle::RenderStyle(const RenderStyle& o)
- : Shared<RenderStyle>(),
- inherited_flags( o.inherited_flags ), noninherited_flags( o.noninherited_flags ),
- box( o.box ), visual( o.visual ), background( o.background ), surround( o.surround ), generated(o.generated),
- css3NonInheritedData( o.css3NonInheritedData ), css3InheritedData( o.css3InheritedData ),
- inherited( o.inherited ), pseudoStyle( 0 )
-{}
-
-void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
-{
- css3InheritedData = inheritParent->css3InheritedData;
- inherited = inheritParent->inherited;
- inherited_flags = inheritParent->inherited_flags;
-
- // Simulate ":after,:before { white-space: pre-line }"
- if (styleType() == AFTER || styleType() == BEFORE)
- setWhiteSpace(PRE_LINE);
-}
-
-RenderStyle::~RenderStyle()
-{
- RenderStyle *ps = pseudoStyle;
- RenderStyle *prev = 0;
-
- while (ps) {
- prev = ps;
- ps = ps->pseudoStyle;
- // to prevent a double deletion.
- // this works only because the styles below aren't really shared
- // Dirk said we need another construct as soon as these are shared
- prev->pseudoStyle = 0;
- prev->deref();
- }
-}
-
-bool RenderStyle::operator==(const RenderStyle& o) const
-{
-// compare everything except the pseudoStyle pointer
- return (inherited_flags == o.inherited_flags &&
- noninherited_flags == o.noninherited_flags &&
- box == o.box &&
- visual == o.visual &&
- background == o.background &&
- surround == o.surround &&
- generated == o.generated &&
- css3NonInheritedData == o.css3NonInheritedData &&
- css3InheritedData == o.css3InheritedData &&
- inherited == o.inherited);
-}
-
-enum EPseudoBit { NO_BIT = 0x0,
- FIRST_LINE_BIT = 0x1, FIRST_LETTER_BIT = 0x2, SELECTION_BIT = 0x4,
- BEFORE_BIT = 0x8, AFTER_BIT = 0x10, MARKER_BIT = 0x20,
- REPLACED_BIT = 0x40
- };
-
-static int pseudoBit(RenderStyle::PseudoId pseudo)
-{
- switch (pseudo) {
- case RenderStyle::BEFORE:
- return BEFORE_BIT;
- case RenderStyle::AFTER:
- return AFTER_BIT;
- case RenderStyle::MARKER:
- return MARKER_BIT;
- case RenderStyle::REPLACED:
- return REPLACED_BIT;
- case RenderStyle::FIRST_LINE:
- return FIRST_LINE_BIT;
- case RenderStyle::FIRST_LETTER:
- return FIRST_LETTER_BIT;
- case RenderStyle::SELECTION:
- return SELECTION_BIT;
- default:
- return NO_BIT;
- }
-}
-
-bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
-{
- return (pseudoBit(pseudo) & noninherited_flags.f._pseudoBits) != 0;
-}
-
-void RenderStyle::setHasPseudoStyle(PseudoId pseudo, bool b)
-{
- if (b)
- noninherited_flags.f._pseudoBits |= pseudoBit(pseudo);
- else
- noninherited_flags.f._pseudoBits &= ~(pseudoBit(pseudo));
-}
-
-RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid) const
-{
- if (!hasPseudoStyle(pid)) return 0;
-
- RenderStyle *ps = 0;
- if (noninherited_flags.f._styleType==NOPSEUDO)
- for (ps = pseudoStyle; ps; ps = ps->pseudoStyle)
- if (ps->noninherited_flags.f._styleType==pid)
- break;
- return ps;
-}
-
-RenderStyle* RenderStyle::addPseudoStyle(PseudoId pid)
-{
- if (hasPseudoStyle(pid)) return getPseudoStyle(pid);
-
- RenderStyle *ps = 0;
-
- switch (pid) {
- case FIRST_LETTER: // pseudo-elements (FIRST_LINE has a special handling)
- case SELECTION:
- case BEFORE:
- case AFTER:
- ps = new RenderStyle();
- break;
- default:
- ps = new RenderStyle(*this); // use the real copy constructor to get an identical copy
- }
- ps->ref();
- ps->noninherited_flags.f._styleType = pid;
- ps->pseudoStyle = pseudoStyle;
-
- pseudoStyle = ps;
-
- setHasPseudoStyle(pid, true);
-
- return ps;
-}
-
-void RenderStyle::removePseudoStyle(PseudoId pid)
-{
- RenderStyle *ps = pseudoStyle;
- RenderStyle *prev = this;
-
- while (ps) {
- if (ps->noninherited_flags.f._styleType==pid) {
- prev->pseudoStyle = ps->pseudoStyle;
- ps->deref();
- return;
- }
- prev = ps;
- ps = ps->pseudoStyle;
- }
-
- setHasPseudoStyle(pid, false);
-}
-
-
-bool RenderStyle::inheritedNotEqual( RenderStyle *other ) const
-{
- return
- (
- inherited_flags != other->inherited_flags ||
- inherited != other->inherited ||
- css3InheritedData != other->css3InheritedData
- );
-}
-
-/*
- compares two styles. The result gives an idea of the action that
- needs to be taken when replacing the old style with a new one.
-
- CbLayout: The containing block of the object needs a relayout.
- Layout: the RenderObject needs a relayout after the style change
- Visible: The change is visible, but no relayout is needed
- NonVisible: The object does need neither repaint nor relayout after
- the change.
-
- ### TODO:
- A lot can be optimised here based on the display type, lots of
- optimisations are unimplemented, and currently result in the
- worst case result causing a relayout of the containing block.
-*/
-RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
-{
- // we anyway assume they are the same
-// EDisplay _display : 5;
-
- // NonVisible:
-// ECursor _cursor_style : 4;
-// EUserInput _user_input : 2; as long as :enabled is not impl'd
-
-// ### this needs work to know more exactly if we need a relayout
-// or just a repaint
-
-// non-inherited attributes
-// DataRef<StyleBoxData> box;
-// DataRef<StyleVisualData> visual;
-// DataRef<StyleSurroundData> surround;
-
-// inherited attributes
-// DataRef<StyleInheritedData> inherited;
-
- if ( *box.get() != *other->box.get() ||
- *visual.get() != *other->visual.get() ||
- (*surround.get() != *other->surround.get()
- && (other->position() == STATIC || other->position() != position())) ||
- !(inherited->indent == other->inherited->indent) ||
- !(inherited->line_height == other->inherited->line_height) ||
- !(inherited->style_image == other->inherited->style_image) ||
- !(inherited->font == other->inherited->font) ||
- !(inherited->border_hspacing == other->inherited->border_hspacing) ||
- !(inherited->border_vspacing == other->inherited->border_vspacing) ||
- !(inherited_flags.f._visuallyOrdered == other->inherited_flags.f._visuallyOrdered) ||
- !(inherited_flags.f._htmlHacks == other->inherited_flags.f._htmlHacks) ||
- !(noninherited_flags.f._textOverflow == other->noninherited_flags.f._textOverflow) )
- return CbLayout;
-
- // changes causing Layout changes:
-
-// only for tables:
-// _border_collapse
-// EEmptyCell _empty_cells : 2 ;
-// ECaptionSide _caption_side : 2;
-// ETableLayout _table_layout : 1;
-// EPosition _position : 2;
-// EFloat _floating : 2;
- if ( ((int)noninherited_flags.f._display) >= TABLE ) {
- if ( !(inherited_flags.f._empty_cells == other->inherited_flags.f._empty_cells) ||
- !(inherited_flags.f._caption_side == other->inherited_flags.f._caption_side) ||
- !(inherited_flags.f._border_collapse == other->inherited_flags.f._border_collapse) ||
- !(noninherited_flags.f._table_layout == other->noninherited_flags.f._table_layout) ||
- !(noninherited_flags.f._position == other->noninherited_flags.f._position) ||
- !(noninherited_flags.f._floating == other->noninherited_flags.f._floating) ||
- !(noninherited_flags.f._flowAroundFloats == other->noninherited_flags.f._flowAroundFloats) ||
- !(noninherited_flags.f._unicodeBidi == other->noninherited_flags.f._unicodeBidi) )
- return CbLayout;
- }
-
-// only for lists:
-// EListStyleType _list_style_type : 5 ;
-// EListStylePosition _list_style_position :1;
- if (noninherited_flags.f._display == LIST_ITEM ) {
- if ( !(inherited_flags.f._list_style_type == other->inherited_flags.f._list_style_type) ||
- !(inherited_flags.f._list_style_position == other->inherited_flags.f._list_style_position) )
- return Layout;
- }
-
-// ### These could be better optimised
-// ETextAlign _text_align : 3;
-// ETextTransform _text_transform : 4;
-// EDirection _direction : 1;
-// EWhiteSpace _white_space : 2;
-// EClear _clear : 2;
- if ( !(inherited_flags.f._text_align == other->inherited_flags.f._text_align) ||
- !(inherited_flags.f._text_transform == other->inherited_flags.f._text_transform) ||
- !(inherited_flags.f._direction == other->inherited_flags.f._direction) ||
- !(inherited_flags.f._white_space == other->inherited_flags.f._white_space) ||
- !(noninherited_flags.f._clear == other->noninherited_flags.f._clear)
- )
- return Layout;
-
- // Overflow returns a layout hint.
- if (noninherited_flags.f._overflowX != other->noninherited_flags.f._overflowX ||
- noninherited_flags.f._overflowY != other->noninherited_flags.f._overflowY)
- return Layout;
-
-// only for inline:
-// EVerticalAlign _vertical_align : 4;
-
- if ( !(noninherited_flags.f._display == INLINE) &&
- !(noninherited_flags.f._vertical_align == other->noninherited_flags.f._vertical_align) )
- return Layout;
-
- if (*surround.get() != *other->surround.get()) {
- assert( other->position() != STATIC ); // this style is positioned or relatively positioned
- if ( surround->hasSamePBMData(*other->surround.get()) && // padding/border/margin are identical
- (other->position() == RELATIVE ||
- !(other->left().isVariable() && other->right().isVariable()) && // X isn't static
- !(other->top().isVariable() && other->bottom().isVariable()) )) // neither is Y
- // therefore only the offset is different
- return Position;
- return Layout;
- }
-
- // Visible:
-// EVisibility _visibility : 2;
-// int _text_decorations : 4;
-// DataRef<StyleBackgroundData> background;
- if (inherited->color != other->inherited->color ||
- !(inherited_flags.f._visibility == other->inherited_flags.f._visibility) ||
- !(inherited_flags.f._text_decorations == other->inherited_flags.f._text_decorations) ||
- !(noninherited_flags.f._hasClip == other->noninherited_flags.f._hasClip) ||
- visual->textDecoration != other->visual->textDecoration ||
- *background.get() != *other->background.get() ||
- css3NonInheritedData->opacity != other->css3NonInheritedData->opacity ||
- !css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get())
- )
- return Visible;
-
- RenderStyle::Diff ch = Equal;
- // Check for visible pseudo-changes:
- if (hasPseudoStyle(FIRST_LINE) != other->hasPseudoStyle(FIRST_LINE))
- ch = Visible;
- else
- if (hasPseudoStyle(FIRST_LINE) && other->hasPseudoStyle(FIRST_LINE))
- ch = getPseudoStyle(FIRST_LINE)->diff(other->getPseudoStyle(FIRST_LINE));
-
- if (ch != Equal) return ch;
-
- // Check for visible pseudo-changes:
- if (hasPseudoStyle(SELECTION) != other->hasPseudoStyle(SELECTION))
- ch = Visible;
- else
- if (hasPseudoStyle(SELECTION) && other->hasPseudoStyle(SELECTION))
- ch = getPseudoStyle(SELECTION)->diff(other->getPseudoStyle(SELECTION));
-
- return ch;
-}
-
-
-RenderStyle* RenderStyle::_default = 0;
-
-void RenderStyle::cleanup()
-{
- delete _default;
- _default = 0;
-}
-
-void RenderStyle::setPaletteColor(TQPalette::ColorGroup g, TQColorGroup::ColorRole r, const TQColor& c)
-{
- visual.access()->palette.setColor(g,r,c);
-}
-
-void RenderStyle::adjustBackgroundLayers()
-{
- if (backgroundLayers()->next()) {
- // First we cull out layers that have no properties set.
- accessBackgroundLayers()->cullEmptyLayers();
-
- // Next we repeat patterns into layers that don't have some properties set.
- accessBackgroundLayers()->fillUnsetProperties();
- }
-}
-
-void RenderStyle::setClip( Length top, Length right, Length bottom, Length left )
-{
- StyleVisualData *data = visual.access();
- data->clip.top = top;
- data->clip.right = right;
- data->clip.bottom = bottom;
- data->clip.left = left;
-}
-
-void RenderStyle::setQuotes(DOM::QuotesValueImpl* q)
-{
- DOM::QuotesValueImpl *t = inherited->quotes;
- inherited.access()->quotes = q;
- if (q) q->ref();
- if (t) t->deref();
-}
-
-TQString RenderStyle::openQuote(int level) const
-{
- if (inherited->quotes)
- return inherited->quotes->openQuote(level);
- else
- return "\""; // 0 is default quotes
-}
-
-TQString RenderStyle::closeQuote(int level) const
-{
- if (inherited->quotes)
- return inherited->quotes->closeQuote(level);
- else
- return "\""; // 0 is default quotes
-}
-
-void RenderStyle::addContent(CachedObject* o)
-{
- if (!o)
- return; // The object is null. Nothing to do. Just bail.
-
- StyleGeneratedData *t_generated = generated.access();
-
- ContentData* lastContent = t_generated->content;
- while (lastContent && lastContent->_nextContent)
- lastContent = lastContent->_nextContent;
-
- ContentData* newContentData = new ContentData;
-
- if (lastContent)
- lastContent->_nextContent = newContentData;
- else
- t_generated->content = newContentData;
-
- // o->ref();
- newContentData->_content.object = o;
- newContentData->_contentType = CONTENT_OBJECT;
-}
-
-void RenderStyle::addContent(DOM::DOMStringImpl* s)
-{
- if (!s)
- return; // The string is null. Nothing to do. Just bail.
-
- StyleGeneratedData *t_generated = generated.access();
-
- ContentData* lastContent = t_generated->content;
- while (lastContent && lastContent->_nextContent)
- lastContent = lastContent->_nextContent;
-
- if (lastContent) {
- if (lastContent->_contentType == CONTENT_TEXT) {
- // We can augment the existing string and share this ContentData node.
- DOMStringImpl* oldStr = lastContent->_content.text;
- DOMStringImpl* newStr = oldStr->copy();
- newStr->ref();
- oldStr->deref();
- newStr->append(s);
- lastContent->_content.text = newStr;
- return;
- }
- }
-
- ContentData* newContentData = new ContentData;
-
- if (lastContent)
- lastContent->_nextContent = newContentData;
- else
- t_generated->content = newContentData;
-
- newContentData->_content.text = s;
- newContentData->_content.text->ref();
- newContentData->_contentType = CONTENT_TEXT;
-
-}
-
-void RenderStyle::addContent(DOM::CounterImpl* c)
-{
- if (!c)
- return;
-
- StyleGeneratedData *t_generated = generated.access();
-
- ContentData* lastContent = t_generated->content;
- while (lastContent && lastContent->_nextContent)
- lastContent = lastContent->_nextContent;
-
- ContentData* newContentData = new ContentData;
-
- if (lastContent)
- lastContent->_nextContent = newContentData;
- else
- t_generated->content = newContentData;
-
- c->ref();
- newContentData->_content.counter = c;
- newContentData->_contentType = CONTENT_COUNTER;
-}
-
-void RenderStyle::addContent(EQuoteContent q)
-{
- if (q == NO_QUOTE)
- return;
-
- StyleGeneratedData *t_generated = generated.access();
-
- ContentData* lastContent = t_generated->content;
- while (lastContent && lastContent->_nextContent)
- lastContent = lastContent->_nextContent;
-
- ContentData* newContentData = new ContentData;
-
- if (lastContent)
- lastContent->_nextContent = newContentData;
- else
- t_generated->content = newContentData;
-
- newContentData->_content.quote = q;
- newContentData->_contentType = CONTENT_QUOTE;
-}
-
-// content: normal is the same as having no content at all
-void RenderStyle::setContentNormal() {
- if (generated->content != 0) {
- delete generated->content;
- generated.access()->content = 0;
- }
-}
-
-// content: none, add an empty content node
-void RenderStyle::setContentNone() {
- setContentNormal();
- generated.access()->content = new ContentData;
-}
-
-void RenderStyle::setContentData(ContentData *data) {
- if (data != generated->content) {
- if (data)
- generated.access()->content = new ContentData(*data);
- else
- generated.access()->content = 0;
- }
-}
-
-ContentData::ContentData(const ContentData& o) : _contentType(o._contentType)
-{
- switch (_contentType) {
- case CONTENT_OBJECT:
- _content.object = o._content.object;
- break;
- case CONTENT_TEXT:
- _content.text = o._content.text;
- _content.text->ref();
- break;
- case CONTENT_COUNTER:
- _content.counter = o._content.counter;
- _content.counter->ref();
- break;
- case CONTENT_QUOTE:
- _content.quote = o._content.quote;
- break;
- case CONTENT_NONE:
- default:
- break;
- }
-
- _nextContent = o._nextContent ? new ContentData(*o._nextContent) : 0;
-}
-
-ContentData::~ContentData()
-{
- clearContent();
-}
-
-void ContentData::clearContent()
-{
- delete _nextContent;
- _nextContent = 0;
-
- switch (_contentType)
- {
- case CONTENT_OBJECT:
- _content.object = 0;
- break;
- case CONTENT_TEXT:
- _content.text->deref();
- _content.text = 0;
- break;
- case CONTENT_COUNTER:
- _content.counter->deref();
- _content.counter = 0;
- break;
- case CONTENT_QUOTE:
- _content.quote = NO_QUOTE;
- break;
- default:
- ;
- }
-}
-
-void RenderStyle::setTextShadow(ShadowData* val, bool add)
-{
- StyleCSS3InheritedData* css3Data = css3InheritedData.access();
- if (!add) {
- delete css3Data->textShadow;
- css3Data->textShadow = val;
- return;
- }
-
- ShadowData* last = css3Data->textShadow;
- while (last->next) last = last->next;
- last->next = val;
-}
-
-ShadowData::ShadowData(const ShadowData& o)
-:x(o.x), y(o.y), blur(o.blur), color(o.color)
-{
- next = o.next ? new ShadowData(*o.next) : 0;
-}
-
-bool ShadowData::operator==(const ShadowData& o) const
-{
- if ((next && !o.next) || (!next && o.next) ||
- (next && o.next && *next != *o.next))
- return false;
-
- return x == o.x && y == o.y && blur == o.blur && color == o.color;
-}
-
-static bool hasCounter(const DOM::DOMString& c, CSSValueListImpl *l)
-{
- int len = l->length();
- for(int i=0; i<len; i++) {
- CounterActImpl* ca = static_cast<CounterActImpl*>(l->item(i));
- Q_ASSERT(ca != 0);
- if (ca->m_counter == c) return true;
- }
- return false;
-}
-
-bool RenderStyle::hasCounterReset(const DOM::DOMString& c) const
-{
- if (generated->counter_reset)
- return hasCounter(c, generated->counter_reset);
- else
- return false;
-}
-
-bool RenderStyle::hasCounterIncrement(const DOM::DOMString& c) const
-{
- if (generated->counter_increment)
- return hasCounter(c, generated->counter_increment);
- else
- return false;
-}
-
-static short readCounter(const DOM::DOMString& c, CSSValueListImpl *l)
-{
- int len = l->length();
- for(int i=0; i<len; i++) {
- CounterActImpl* ca = static_cast<CounterActImpl*>(l->item(i));
- Q_ASSERT(ca != 0);
- if (ca->m_counter == c) return ca->m_value;
- }
- return 0;
-}
-
-short RenderStyle::counterReset(const DOM::DOMString& c) const
-{
- if (generated->counter_reset)
- return readCounter(c, generated->counter_reset);
- else
- return 0;
-}
-
-short RenderStyle::counterIncrement(const DOM::DOMString& c) const
-{
- if (generated->counter_increment)
- return readCounter(c, generated->counter_increment);
- else
- return 0;
-}
-
-void RenderStyle::setCounterReset(CSSValueListImpl *l)
-{
- CSSValueListImpl *t = generated->counter_reset;
- generated.access()->counter_reset = l;
- if (l) l->ref();
- if (t) t->deref();
-}
-
-void RenderStyle::setCounterIncrement(CSSValueListImpl *l)
-{
- CSSValueListImpl *t = generated->counter_increment;
- generated.access()->counter_increment = l;
- if (l) l->ref();
- if (t) t->deref();
-}
-
-#ifdef ENABLE_DUMP
-
-static TQString describeFont( const TQFont &f)
-{
- TQString res = "'" + f.family() + "' ";
-
- if ( f.pointSize() > 0)
- res += TQString::number( f.pointSize() ) + "pt";
- else
- res += TQString::number( f.pixelSize() ) + "px";
-
- if ( f.bold() )
- res += " bold";
- if ( f.italic() )
- res += " italic";
- if ( f.underline() )
- res += " underline";
- if ( f.overline() )
- res += " overline";
- if ( f.strikeOut() )
- res += " strikeout";
- return res;
-}
-
-TQString RenderStyle::createDiff( const RenderStyle &parent ) const
-{
- TQString res;
- if ( color().isValid() && parent.color() != color() )
- res += " [color=" + color().name() + "]";
- if ( backgroundColor().isValid() && parent.backgroundColor() != backgroundColor() )
- res += " [bgcolor=" + backgroundColor().name() + "]";
- if ( parent.font() != font() )
- res += " [font=" + describeFont( font() ) + "]";
-
- return res;
-}
-#endif
-
-RenderPageStyle::RenderPageStyle() : next(0), m_pageType(ANY_PAGE)
-{
-}
-
-RenderPageStyle::~RenderPageStyle()
-{
- delete next;
-}
-
-RenderPageStyle* RenderPageStyle::getPageStyle(PageType type)
-{
- RenderPageStyle *ps = 0;
- for (ps = this; ps; ps = ps->next)
- if (ps->m_pageType==type)
- break;
- return ps;
-}
-
-RenderPageStyle* RenderPageStyle::addPageStyle(PageType type)
-{
- RenderPageStyle *ps = getPageStyle(type);
-
- if (!ps)
- {
- ps = new RenderPageStyle(*this); // use the real copy constructor to get an identical copy
- ps->m_pageType = type;
-
- ps->next = next;
- next = ps;
- }
-
- return ps;
-}
-
-void RenderPageStyle::removePageStyle(PageType type)
-{
- RenderPageStyle *ps = next;
- RenderPageStyle *prev = this;
-
- while (ps) {
- if (ps->m_pageType==type) {
- prev->next = ps->next;
- delete ps;
- return;
- }
- prev = ps;
- ps = ps->next;
- }
-}
diff --git a/khtml/rendering/render_style.h b/khtml/rendering/render_style.h
deleted file mode 100644
index 80d052980..000000000
--- a/khtml/rendering/render_style.h
+++ /dev/null
@@ -1,1524 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
- * (C) 2000 Antti Koivisto (koivisto@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003-2005 Apple Computer, Inc.
- * (C) 2004-2006 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDERSTYLE_H
-#define RENDERSTYLE_H
-
-/*
- * WARNING:
- * --------
- *
- * The order of the values in the enums have to agree with the order specified
- * in cssvalues.in, otherwise some optimizations in the parser will fail,
- * and produce invaliud results.
- */
-
-#include <tqcolor.h>
-#include <tqfont.h>
-#include <tqfontmetrics.h>
-#include <tqptrlist.h>
-#include <tqpalette.h>
-#include <tqapplication.h>
-
-#include "dom/dom_misc.h"
-#include "dom/dom_string.h"
-#include "misc/khtmllayout.h"
-#include "misc/shared.h"
-#include "rendering/font.h"
-
-#include <assert.h>
-
-#define SET_VAR(group,variable,value) \
- if (!(group->variable == value)) \
- group.access()->variable = value;
-
-#ifndef ENABLE_DUMP
-#ifndef NDEBUG
-#define ENABLE_DUMP 1
-#endif
-#endif
-
-namespace DOM {
- class DOMStringImpl;
- class ShadowValueImpl;
- class QuotesValueImpl;
- class CounterImpl;
- class CSSValueListImpl;
- class CounterActImpl;
-}
-
-namespace khtml {
-
- class CachedImage;
- class CachedObject;
-
-template <class DATA>
-class DataRef
-{
-public:
-
- DataRef()
- {
- data=0;
- }
- DataRef( const DataRef<DATA> &d )
- {
- data = d.data;
- data->ref();
- }
-
- ~DataRef()
- {
- if(data) data->deref();
- }
-
- const DATA* operator->() const
- {
- return data;
- }
-
- const DATA* get() const
- {
- return data;
- }
-
-
- DATA* access()
- {
- if (!data->hasOneRef())
- {
- data->deref();
- data = new DATA(*data);
- data->ref();
- }
- return data;
- }
-
- void init()
- {
- data = new DATA;
- data->ref();
- }
-
- DataRef<DATA>& operator=(const DataRef<DATA>& d)
- {
- if (data==d.data)
- return *this;
- if (data)
- data->deref();
- data = d.data;
-
- data->ref();
-
- return *this;
- }
-
- bool operator == ( const DataRef<DATA> &o ) const {
- return (*data == *(o.data) );
- }
- bool operator != ( const DataRef<DATA> &o ) const {
- return (*data != *(o.data) );
- }
-
-private:
- DATA* data;
-};
-
-
-//------------------------------------------------
-
-//------------------------------------------------
-// Box model attributes. Not inherited.
-
-struct LengthBox
-{
- LengthBox()
- {
- }
- LengthBox( LengthType t )
- : left( t ), right ( t ), top( t ), bottom( t ) {}
-
- Length left;
- Length right;
- Length top;
- Length bottom;
- Length& operator=(Length& len)
- {
- left=len;
- right=len;
- top=len;
- bottom=len;
- return len;
- }
-
- bool operator==(const LengthBox& o) const
- {
- return left==o.left && right==o.right && top==o.top && bottom==o.bottom;
- }
-
-
- bool nonZero() const { return left.value() || right.value() || top.value() || bottom.value(); }
-};
-
-
-
-enum EPosition {
- STATIC, RELATIVE, ABSOLUTE, FIXED
-};
-
-enum EFloat {
- FNONE = 0, FLEFT = 0x01, FRIGHT = 0x02, FLEFT_ALIGN = 0x05, FRIGHT_ALIGN = 0x06
-};
-
-enum EWordWrap {
- WWNORMAL = 0, WWBREAKWORD = 0x01
-};
-
-//------------------------------------------------
-// Border attributes. Not inherited.
-
-
-// These have been defined in the order of their precedence for border-collapsing. Do
-// not change this order!
-enum EBorderStyle {
- BNATIVE, BNONE, BHIDDEN, INSET, GROOVE, RIDGE, OUTSET, DOTTED, DASHED, SOLID, DOUBLE
-};
-
-class BorderValue
-{
-public:
- BorderValue() : width( 3 ), style( BNONE ) {}
-
- TQColor color;
- unsigned short width : 12;
- EBorderStyle style : 6;
-
- bool nonZero(bool checkStyle = true) const {
- return width != 0 && !(checkStyle && style == BNONE);
- }
-
- bool isTransparent() const {
- return color.isValid() && tqAlpha(color.rgb()) == 0;
- }
-
- bool operator==(const BorderValue& o) const
- {
- return width==o.width && style==o.style && color==o.color;
- }
-
- bool operator!=(const BorderValue& o) const
- {
- return !(*this == o);
- }
-};
-
-class OutlineValue : public BorderValue
-{
- public:
- OutlineValue()
- {
- _offset = 0;
- _auto = false;
- }
-
- bool operator==(const OutlineValue& o) const
- {
- return width==o.width && style==o.style && color==o.color && _offset == o._offset && _auto == o._auto;
- }
-
- bool operator!=(const OutlineValue& o) const
- {
- return !(*this == o);
- }
-
- int _offset;
- bool _auto;
-};
-
-enum EBorderPrecedence { BOFF, BTABLE, BCOLGROUP, BCOL, BROWGROUP, BROW, BCELL };
-
-struct CollapsedBorderValue
-{
- CollapsedBorderValue() :border(0), precedence(BOFF) {}
- CollapsedBorderValue(const BorderValue* b, EBorderPrecedence p) :border(b), precedence(p) {}
-
- int width() const { return border && border->nonZero() ? border->width : 0; }
- EBorderStyle style() const { return border ? border->style : BHIDDEN; }
- bool exists() const { return border; }
- TQColor color() const { return border ? border->color : TQColor(); }
- bool isTransparent() const { return border ? border->isTransparent() : true; }
-
- bool operator==(const CollapsedBorderValue& o) const
- {
- if (!border) return !o.border;
- if (!o.border) return false;
- return *border == *o.border && precedence == o.precedence;
- }
-
- const BorderValue* border;
- EBorderPrecedence precedence;
-};
-
-class BorderData : public Shared<BorderData>
-{
-public:
- BorderValue left;
- BorderValue right;
- BorderValue top;
- BorderValue bottom;
-
- bool hasBorder() const
- {
- return left.nonZero() || right.nonZero() || top.nonZero() || bottom.nonZero();
- }
-
- unsigned short borderLeftWidth() const {
- if (left.style == BNONE || left.style == BHIDDEN || left.style == BNATIVE)
- return 0;
- return left.width;
- }
-
- unsigned short borderRightWidth() const {
- if (right.style == BNONE || right.style == BHIDDEN || right.style == BNATIVE)
- return 0;
- return right.width;
- }
-
- unsigned short borderTopWidth() const {
- if (top.style == BNONE || top.style == BHIDDEN || top.style == BNATIVE)
- return 0;
- return top.width;
- }
-
- unsigned short borderBottomWidth() const {
- if (bottom.style == BNONE || bottom.style == BHIDDEN || bottom.style == BNATIVE)
- return 0;
- return bottom.width;
- }
-
- bool operator==(const BorderData& o) const
- {
- return left==o.left && right==o.right && top==o.top && bottom==o.bottom;
- }
-
-};
-
-class StyleSurroundData : public Shared<StyleSurroundData>
-{
-public:
- StyleSurroundData();
-
- StyleSurroundData(const StyleSurroundData& o );
- bool operator==(const StyleSurroundData& o) const;
- bool operator!=(const StyleSurroundData& o) const {
- return !(*this == o);
- }
- bool hasSamePBMData(const StyleSurroundData& o) const {
- return (margin == o.margin) && (padding == o.padding) && (border == o.border);
- }
-
- LengthBox offset;
- LengthBox margin;
- LengthBox padding;
- BorderData border;
-};
-
-
-//------------------------------------------------
-// Box attributes. Not inherited.
-
-enum EBoxSizing {
- BORDER_BOX, CONTENT_BOX
-};
-
-class StyleBoxData : public Shared<StyleBoxData>
-{
-public:
- StyleBoxData();
-
- StyleBoxData(const StyleBoxData& o );
-
-
- // copy and assignment
-// StyleBoxData(const StyleBoxData &other);
-// const StyleBoxData &operator = (const StyleBoxData &other);
-
- bool operator==(const StyleBoxData& o) const;
- bool operator!=(const StyleBoxData& o) const {
- return !(*this == o);
- }
-
- Length width;
- Length height;
-
- Length min_width;
- Length max_width;
-
- Length min_height;
- Length max_height;
-
- Length vertical_align;
-
- EBoxSizing box_sizing;
-
- signed int z_index :31;
- bool z_auto : 1;
-};
-
-//------------------------------------------------
-// Random visual rendering model attributes. Not inherited.
-
-enum EOverflow {
- OVISIBLE, OHIDDEN, OSCROLL, OAUTO, OMARQUEE
-};
-
-enum EVerticalAlign {
- BASELINE, MIDDLE, SUB, SUPER, TEXT_TOP,
- TEXT_BOTTOM, TOP, BOTTOM, BASELINE_MIDDLE, LENGTH
-};
-
-enum EClear{
- CNONE = 0, CLEFT = 1, CRIGHT = 2, CBOTH = 3
-};
-
-enum ETableLayout {
- TAUTO, TFIXED
-};
-
-enum EUnicodeBidi {
- UBNormal, Embed, Override
-};
-
-class StyleVisualData : public Shared<StyleVisualData>
-{
-public:
- StyleVisualData();
-
- ~StyleVisualData();
-
- StyleVisualData(const StyleVisualData& o );
-
- bool operator==( const StyleVisualData &o ) const {
- return ( clip == o.clip &&
- palette == o.palette );
- }
- bool operator!=( const StyleVisualData &o ) const {
- return !(*this == o);
- }
-
- LengthBox clip;
- unsigned textDecoration : 4; // Text decorations defined *only* by this element.
-
- TQPalette palette; //widget styling with IE attributes
-
-};
-
-//------------------------------------------------
-enum EBackgroundBox {
- BGBORDER, BGPADDING, BGCONTENT
-};
-
-enum EBackgroundRepeat {
- REPEAT, REPEAT_X, REPEAT_Y, NO_REPEAT
-};
-
-struct LengthSize {
- Length width;
- Length height;
-};
-
-struct BackgroundLayer {
-public:
- BackgroundLayer();
- ~BackgroundLayer();
-
- CachedImage* backgroundImage() const { return m_image; }
- Length backgroundXPosition() const { return m_xPosition; }
- Length backgroundYPosition() const { return m_yPosition; }
- bool backgroundAttachment() const { return m_bgAttachment; }
- EBackgroundBox backgroundClip() const { return m_bgClip; }
- EBackgroundBox backgroundOrigin() const { return m_bgOrigin; }
- EBackgroundRepeat backgroundRepeat() const { return m_bgRepeat; }
- LengthSize backgroundSize() const { return m_backgroundSize; }
-
- BackgroundLayer* next() const { return m_next; }
- BackgroundLayer* next() { return m_next; }
-
- bool isBackgroundImageSet() const { return m_imageSet; }
- bool isBackgroundXPositionSet() const { return m_xPosSet; }
- bool isBackgroundYPositionSet() const { return m_yPosSet; }
- bool isBackgroundAttachmentSet() const { return m_attachmentSet; }
- bool isBackgroundClipSet() const { return m_clipSet; }
- bool isBackgroundOriginSet() const { return m_originSet; }
- bool isBackgroundRepeatSet() const { return m_repeatSet; }
- bool isBackgroundSizeSet() const { return m_backgroundSizeSet; }
-
- void setBackgroundImage(CachedImage* i) { m_image = i; m_imageSet = true; }
- void setBackgroundXPosition(const Length& l) { m_xPosition = l; m_xPosSet = true; }
- void setBackgroundYPosition(const Length& l) { m_yPosition = l; m_yPosSet = true; }
- void setBackgroundAttachment(bool b) { m_bgAttachment = b; m_attachmentSet = true; }
- void setBackgroundClip(EBackgroundBox b) { m_bgClip = b; m_clipSet = true; }
- void setBackgroundOrigin(EBackgroundBox b) { m_bgOrigin = b; m_originSet = true; }
- void setBackgroundRepeat(EBackgroundRepeat r) { m_bgRepeat = r; m_repeatSet = true; }
- void setBackgroundSize(const LengthSize& b) { m_backgroundSize = b; m_backgroundSizeSet = true; }
-
- void clearBackgroundImage() { m_imageSet = false; }
- void clearBackgroundXPosition() { m_xPosSet = false; }
- void clearBackgroundYPosition() { m_yPosSet = false; }
- void clearBackgroundAttachment() { m_attachmentSet = false; }
- void clearBackgroundClip() { m_clipSet = false; }
- void clearBackgroundOrigin() { m_originSet = false; }
- void clearBackgroundRepeat() { m_repeatSet = false; }
- void clearBackgroundSize() { m_backgroundSizeSet = false; }
-
- void setNext(BackgroundLayer* n) { if (m_next != n) { delete m_next; m_next = n; } }
-
- BackgroundLayer& operator=(const BackgroundLayer& o);
- BackgroundLayer(const BackgroundLayer& o);
-
- bool operator==(const BackgroundLayer& o) const;
- bool operator!=(const BackgroundLayer& o) const {
- return !(*this == o);
- }
-
- bool containsImage(CachedImage* c) const { if (c == m_image) return true; if (m_next) return m_next->containsImage(c); return false; }
-
- bool hasImage() const {
- if (m_image)
- return true;
- return m_next ? m_next->hasImage() : false;
- }
- bool hasFixedImage() const {
- if (m_image && !m_bgAttachment)
- return true;
- return m_next ? m_next->hasFixedImage() : false;
- }
-
- void fillUnsetProperties();
- void cullEmptyLayers();
-
- CachedImage* m_image;
-
- Length m_xPosition;
- Length m_yPosition;
-
- bool m_bgAttachment : 1;
- EBackgroundBox m_bgClip : 2;
- EBackgroundBox m_bgOrigin : 2;
- EBackgroundRepeat m_bgRepeat : 2;
-
- LengthSize m_backgroundSize;
-
- bool m_imageSet : 1;
- bool m_attachmentSet : 1;
- bool m_clipSet : 1;
- bool m_originSet : 1;
- bool m_repeatSet : 1;
- bool m_xPosSet : 1;
- bool m_yPosSet : 1;
- bool m_backgroundSizeSet : 1;
-
- BackgroundLayer* m_next;
-};
-
-class StyleBackgroundData : public Shared<StyleBackgroundData>
-{
-public:
- StyleBackgroundData();
- ~StyleBackgroundData() {}
- StyleBackgroundData(const StyleBackgroundData& o );
-
- bool operator==(const StyleBackgroundData& o) const;
- bool operator!=(const StyleBackgroundData &o) const {
- return !(*this == o);
- }
-
- BackgroundLayer m_background;
- TQColor m_color;
- OutlineValue m_outline;
-};
-
-enum EQuoteContent {
- NO_QUOTE = 0, OPEN_QUOTE, CLOSE_QUOTE, NO_OPEN_QUOTE, NO_CLOSE_QUOTE
-};
-
-enum ContentType {
- CONTENT_NONE = 0, CONTENT_NORMAL, CONTENT_OBJECT,
- CONTENT_TEXT, CONTENT_COUNTER, CONTENT_QUOTE
-};
-
-struct ContentData {
- ContentData() : _contentType( CONTENT_NONE ), _nextContent(0) {}
- ContentData(const ContentData& o);
- ~ContentData();
- void clearContent();
-
- DOM::DOMStringImpl* contentText()
- { if (_contentType == CONTENT_TEXT) return _content.text; return 0; }
- CachedObject* contentObject()
- { if (_contentType == CONTENT_OBJECT) return _content.object; return 0; }
- DOM::CounterImpl* contentCounter()
- { if (_contentType == CONTENT_COUNTER) return _content.counter; return 0; }
- EQuoteContent contentQuote()
- { if (_contentType == CONTENT_QUOTE) return _content.quote; return NO_QUOTE; }
-
- ContentType _contentType;
-
- union {
- CachedObject* object;
- DOM::DOMStringImpl* text;
- DOM::CounterImpl* counter;
- EQuoteContent quote;
- } _content ;
-
- ContentData* _nextContent;
-};
-
-class StyleGeneratedData : public Shared<StyleGeneratedData>
-{
-public:
- StyleGeneratedData();
- ~StyleGeneratedData();
- StyleGeneratedData(const StyleGeneratedData& o );
-
- bool operator==(const StyleGeneratedData& o) const;
- bool operator!=(const StyleGeneratedData &o) const {
- return !(*this == o);
- }
-
- bool contentDataEquivalent(const StyleGeneratedData* otherStyle) const;
- bool counterDataEquivalent(const StyleGeneratedData* otherStyle) const;
-
- ContentData *content;
- DOM::CSSValueListImpl *counter_reset;
- DOM::CSSValueListImpl *counter_increment;
-};
-
-//------------------------------------------------
-// CSS3 Marquee Properties
-
-enum EMarqueeBehavior { MNONE, MSCROLL, MSLIDE, MALTERNATE, MUNFURL };
-enum EMarqueeDirection { MAUTO = 0, MLEFT = 1, MRIGHT = -1, MUP = 2, MDOWN = -2, MFORWARD = 3, MBACKWARD = -3 };
-
-class StyleMarqueeData : public Shared<StyleMarqueeData>
-{
-public:
- StyleMarqueeData();
- StyleMarqueeData(const StyleMarqueeData& o);
-
- bool operator==(const StyleMarqueeData& o) const;
- bool operator!=(const StyleMarqueeData& o) const {
- return !(*this == o);
- }
-
- Length increment;
- int speed;
-
- int loops; // -1 means infinite.
-
- EMarqueeBehavior behavior : 3;
- EMarqueeDirection direction : 3;
-};
-
-// This struct holds information about shadows for the text-shadow and box-shadow properties.
-struct ShadowData {
- ShadowData(int _x, int _y, int _blur, const TQColor& _color)
- :x(_x), y(_y), blur(_blur), color(_color), next(0) {}
- ShadowData(const ShadowData& o);
-
- ~ShadowData() { delete next; }
-
- bool operator==(const ShadowData& o) const;
- bool operator!=(const ShadowData &o) const {
- return !(*this == o);
- }
-
- int x;
- int y;
- int blur;
- TQColor color;
- ShadowData* next;
-};
-
-// This struct is for rarely used non-inherited CSS3 properties. By grouping them together,
-// we save space, and only allocate this object when someone actually uses
-// a non-inherited CSS3 property.
-class StyleCSS3NonInheritedData : public Shared<StyleCSS3NonInheritedData>
-{
-public:
- StyleCSS3NonInheritedData();
- ~StyleCSS3NonInheritedData() {}
- StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o);
-
- bool operator==(const StyleCSS3NonInheritedData& o) const;
- bool operator!=(const StyleCSS3NonInheritedData &o) const {
- return !(*this == o);
- }
-
- float opacity; // Whether or not we're transparent.
-#ifdef APPLE_CHANGES // ### we don't have those (yet)
- DataRef<StyleFlexibleBoxData> flexibleBox; // Flexible box properties
-#endif
- DataRef<StyleMarqueeData> marquee; // Marquee properties
-};
-
-// This struct is for rarely used inherited CSS3 properties. By grouping them together,
-// we save space, and only allocate this object when someone actually uses
-// an inherited CSS3 property.
-class StyleCSS3InheritedData : public Shared<StyleCSS3InheritedData>
-{
- public:
- StyleCSS3InheritedData();
- ~StyleCSS3InheritedData();
- StyleCSS3InheritedData(const StyleCSS3InheritedData& o);
-
- bool operator==(const StyleCSS3InheritedData& o) const;
- bool operator!=(const StyleCSS3InheritedData &o) const {
- return !(*this == o);
- }
- bool shadowDataEquivalent(const StyleCSS3InheritedData& o) const;
-
- ShadowData* textShadow; // Our text shadow information for shadowed text drawing.
-#ifdef APPLE_CHANGES
- EUserModify userModify : 2; // Flag used for editing state
- bool textSizeAdjust : 1; // An Apple extension. Not really CSS3 but not worth making a new struct over.
-#endif
- EWordWrap wordWrap : 1;
- private:
- StyleCSS3InheritedData &operator=(const StyleCSS3InheritedData &);
-};
-
-//------------------------------------------------
-// Inherited attributes.
-//
-// the inherited-decoration and inherited-shadow attributes
-// are inherited from the
-// first parent which is block level
-//
-
-enum EWhiteSpace {
- NORMAL, PRE, NOWRAP, PRE_WRAP, PRE_LINE, KHTML_NOWRAP
-};
-
-enum ETextAlign {
- TAAUTO, LEFT, RIGHT, CENTER, JUSTIFY, KHTML_LEFT, KHTML_RIGHT, KHTML_CENTER
-};
-
-enum ETextTransform {
- CAPITALIZE, UPPERCASE, LOWERCASE, TTNONE
-};
-
-enum EDirection {
- LTR, RTL
-};
-
-enum ETextDecoration {
- TDNONE = 0x0 , UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH= 0x4, BLINK = 0x8
-};
-
-enum EPageBreak {
- PBAUTO, PBALWAYS, PBAVOID,
- /* reserved for later use: */
- PBLEFT, PBRIGHT
-};
-
-class StyleInheritedData : public Shared<StyleInheritedData>
-{
- StyleInheritedData& operator=(const StyleInheritedData&);
-public:
- StyleInheritedData();
- ~StyleInheritedData();
- StyleInheritedData(const StyleInheritedData& o );
-
- bool operator==(const StyleInheritedData& o) const;
- bool operator != ( const StyleInheritedData &o ) const {
- return !(*this == o);
- }
-
- Length indent;
- // could be packed in a short but doesn't
- // make a difference currently because of padding
- Length line_height;
-
- CachedImage *style_image;
-
- khtml::Font font;
- TQColor color;
-
- short border_hspacing;
- short border_vspacing;
-
- // Paged media properties.
- short widows;
- short orphans;
-
- DOM::QuotesValueImpl* quotes;
-};
-
-
-enum EEmptyCell {
- SHOW, HIDE
-};
-
-enum ECaptionSide {
- CAPTOP, CAPBOTTOM, CAPLEFT, CAPRIGHT
-};
-
-
-enum EListStyleType {
- // Symbols:
- LDISC, LCIRCLE, LSQUARE, LBOX, LDIAMOND,
- // Numeric:
- LDECIMAL, DECIMAL_LEADING_ZERO, ARABIC_INDIC, LAO, PERSIAN, URDU, THAI, TIBETAN,
- // Algorithmic:
- LOWER_ROMAN, UPPER_ROMAN, HEBREW, ARMENIAN, GEORGIAN,
- // Ideographic:
- CJK_IDEOGRAPHIC, JAPANESE_FORMAL, JAPANESE_INFORMAL,
- SIMP_CHINESE_FORMAL, SIMP_CHINESE_INFORMAL, TRAD_CHINESE_FORMAL, TRAD_CHINESE_INFORMAL,
- // Alphabetic:
- LOWER_GREEK, UPPER_GREEK, LOWER_ALPHA, LOWER_LATIN, UPPER_ALPHA, UPPER_LATIN,
- HIRAGANA, KATAKANA, HIRAGANA_IROHA, KATAKANA_IROHA,
- // Special:
- LNONE
-};
-
-inline bool isListStyleCounted(EListStyleType type)
-{
- switch(type) {
- case LDISC: case LCIRCLE: case LSQUARE: case LBOX: case LDIAMOND:
- case LNONE:
- return false;
- default:
- return true;
- }
-}
-
-enum EListStylePosition { OUTSIDE, INSIDE };
-
-enum EVisibility { VISIBLE, HIDDEN, COLLAPSE };
-
-enum ECursor {
- CURSOR_AUTO, CURSOR_CROSS, CURSOR_DEFAULT, CURSOR_POINTER, CURSOR_PROGRESS, CURSOR_MOVE,
- CURSOR_E_RESIZE, CURSOR_NE_RESIZE, CURSOR_NW_RESIZE, CURSOR_N_RESIZE, CURSOR_SE_RESIZE, CURSOR_SW_RESIZE,
- CURSOR_S_RESIZE, CURSOR_W_RESIZE, CURSOR_TEXT, CURSOR_WAIT, CURSOR_HELP
-};
-
-enum EUserInput {
- UI_ENABLED, UI_DISABLED, UI_NONE
-};
-
-//------------------------------------------------
-
-enum EDisplay {
- INLINE, BLOCK, LIST_ITEM, RUN_IN,
- COMPACT, INLINE_BLOCK, TABLE, INLINE_TABLE,
- TABLE_ROW_GROUP, TABLE_HEADER_GROUP, TABLE_FOOTER_GROUP, TABLE_ROW,
- TABLE_COLUMN_GROUP, TABLE_COLUMN, TABLE_CELL,
- TABLE_CAPTION, NONE
-};
-
-class RenderStyle : public Shared<RenderStyle>
-{
- friend class CSSStyleSelector;
-public:
- KDE_EXPORT static void cleanup();
-
- // pseudo elements
- enum PseudoId {
- NOPSEUDO, FIRST_LINE, FIRST_LETTER, SELECTION,
- BEFORE, AFTER, REPLACED, MARKER
- };
-
-protected:
-
-// !START SYNC!: Keep this in sync with the copy constructor in render_style.cpp
-
- // inherit
- struct InheritedFlags {
- // 64 bit inherited, update unused when adding to the struct, or the operator will break.
- bool operator==( const InheritedFlags &other ) const
- { return _iflags ==other._iflags; }
- bool operator!=( const InheritedFlags &other ) const
- { return _iflags != other._iflags; }
-
- union {
- struct {
- EEmptyCell _empty_cells : 1 ;
- ECaptionSide _caption_side : 2;
- EListStyleType _list_style_type : 6;
- EListStylePosition _list_style_position :1;
-
- EVisibility _visibility : 2;
- ETextAlign _text_align : 4;
- ETextTransform _text_transform : 2;
- unsigned _text_decorations : 4;
- ECursor _cursor_style : 5;
-
- EDirection _direction : 1;
- bool _border_collapse : 1 ;
- EWhiteSpace _white_space : 3;
- // non CSS2 inherited
- bool _visuallyOrdered : 1;
- bool _htmlHacks :1;
- EUserInput _user_input : 2;
-
- bool _page_break_inside : 1; // AUTO/AVOID
-
- unsigned int unused : 27;
- } f;
- TQ_UINT64 _iflags;
- };
- } inherited_flags;
-
-// don't inherit
- struct NonInheritedFlags {
- // 64 bit non-inherited, update unused when adding to the struct, or the operator will break.
- bool operator==( const NonInheritedFlags &other ) const
- { return _niflags == other._niflags; }
- bool operator!=( const NonInheritedFlags &other ) const
- { return _niflags != other._niflags; }
-
- union {
- struct {
- EDisplay _display : 5;
- EDisplay _originalDisplay: 5;
- EOverflow _overflowX : 4 ;
- EOverflow _overflowY : 4 ;
- EVerticalAlign _vertical_align : 4;
- EClear _clear : 2;
- EPosition _position : 2;
- EFloat _floating : 3;
- ETableLayout _table_layout : 1;
- bool _flowAroundFloats :1;
-
- EPageBreak _page_break_before : 3;
- EPageBreak _page_break_after : 3;
-
- PseudoId _styleType : 4;
- bool _hasClip : 1;
- unsigned _pseudoBits : 8;
- EUnicodeBidi _unicodeBidi : 2;
-
- // non CSS2 non-inherited
- bool _textOverflow : 1; // Whether or not lines that spill out should be truncated with "..."
-
- unsigned int unused : 11;
- } f;
- TQ_UINT64 _niflags;
- };
- } noninherited_flags;
-
-// non-inherited attributes
- DataRef<StyleBoxData> box;
- DataRef<StyleVisualData> visual;
- DataRef<StyleBackgroundData> background;
- DataRef<StyleSurroundData> surround;
- DataRef<StyleGeneratedData> generated;
- DataRef<StyleCSS3NonInheritedData> css3NonInheritedData;
-
-// inherited attributes
- DataRef<StyleCSS3InheritedData> css3InheritedData;
- DataRef<StyleInheritedData> inherited;
-
-// list of associated pseudo styles
- RenderStyle* pseudoStyle;
-
-// !END SYNC!
-
-// static default style
- static RenderStyle* _default;
-
-private:
- RenderStyle(const RenderStyle*) {}
-
-protected:
- void setBitDefaults()
- {
- inherited_flags.f._empty_cells = initialEmptyCells();
- inherited_flags.f._caption_side = initialCaptionSide();
- inherited_flags.f._list_style_type = initialListStyleType();
- inherited_flags.f._list_style_position = initialListStylePosition();
- inherited_flags.f._visibility = initialVisibility();
- inherited_flags.f._text_align = initialTextAlign();
- inherited_flags.f._text_transform = initialTextTransform();
- inherited_flags.f._text_decorations = initialTextDecoration();
- inherited_flags.f._cursor_style = initialCursor();
- inherited_flags.f._direction = initialDirection();
- inherited_flags.f._border_collapse = initialBorderCollapse();
- inherited_flags.f._white_space = initialWhiteSpace();
- inherited_flags.f._visuallyOrdered = false;
- inherited_flags.f._htmlHacks=false;
- inherited_flags.f._user_input = UI_NONE;
- inherited_flags.f._page_break_inside = true;
- inherited_flags.f.unused = 0;
-
- noninherited_flags._niflags = 0L; // for safety: without this, the equality method sometimes
- // makes use of uninitialised bits according to valgrind
-
- noninherited_flags.f._display = noninherited_flags.f._originalDisplay = initialDisplay();
- noninherited_flags.f._overflowX = initialOverflowX();
- noninherited_flags.f._overflowY = initialOverflowY();
- noninherited_flags.f._vertical_align = initialVerticalAlign();
- noninherited_flags.f._clear = initialClear();
- noninherited_flags.f._position = initialPosition();
- noninherited_flags.f._floating = initialFloating();
- noninherited_flags.f._table_layout = initialTableLayout();
- noninherited_flags.f._flowAroundFloats= initialFlowAroundFloats();
- noninherited_flags.f._page_break_before = initialPageBreak();
- noninherited_flags.f._page_break_after = initialPageBreak();
- noninherited_flags.f._styleType = NOPSEUDO;
- noninherited_flags.f._hasClip = false;
- noninherited_flags.f._pseudoBits = 0;
- noninherited_flags.f._unicodeBidi = initialUnicodeBidi();
- noninherited_flags.f._textOverflow = initialTextOverflow();
- noninherited_flags.f.unused = 0;
- }
-
-public:
-
- RenderStyle();
- // used to create the default style.
- RenderStyle(bool);
- RenderStyle(const RenderStyle&);
-
- ~RenderStyle();
-
- void inheritFrom(const RenderStyle* inheritParent);
-
- PseudoId styleType() const { return noninherited_flags.f._styleType; }
- void setStyleType(PseudoId pi) { noninherited_flags.f._styleType = pi; }
- bool isGenerated() const {
- if (styleType() == AFTER || styleType() == BEFORE || styleType() == MARKER || styleType() == REPLACED)
- return true;
- else
- return false;
- }
-
- bool hasPseudoStyle(PseudoId pi) const;
- void setHasPseudoStyle(PseudoId pi, bool b=true);
- RenderStyle* getPseudoStyle(PseudoId pi) const;
- RenderStyle* addPseudoStyle(PseudoId pi);
- void removePseudoStyle(PseudoId pi);
-
- bool operator==(const RenderStyle& other) const;
- bool isFloating() const { return !(noninherited_flags.f._floating == FNONE); }
- bool hasMargin() const { return surround->margin.nonZero(); }
- bool hasBorder() const { return surround->border.hasBorder(); }
- bool hasOffset() const { return surround->offset.nonZero(); }
-
- bool hasBackground() const {
- if (backgroundColor().isValid() && tqAlpha(backgroundColor().rgb()) > 0)
- return true;
- else
- return background->m_background.hasImage();
- }
- bool hasFixedBackgroundImage() const { return background->m_background.hasFixedImage(); }
-
- bool visuallyOrdered() const { return inherited_flags.f._visuallyOrdered; }
- void setVisuallyOrdered(bool b) { inherited_flags.f._visuallyOrdered = b; }
-
-// attribute getter methods
-
- EDisplay display() const { return noninherited_flags.f._display; }
- EDisplay originalDisplay() const { return noninherited_flags.f._originalDisplay; }
-
- Length left() const { return surround->offset.left; }
- Length right() const { return surround->offset.right; }
- Length top() const { return surround->offset.top; }
- Length bottom() const { return surround->offset.bottom; }
-
- EPosition position() const { return noninherited_flags.f._position; }
- EFloat floating() const { return noninherited_flags.f._floating; }
-
- Length width() const { return box->width; }
- Length height() const { return box->height; }
- Length minWidth() const { return box->min_width; }
- Length maxWidth() const { return box->max_width; }
- Length minHeight() const { return box->min_height; }
- Length maxHeight() const { return box->max_height; }
-
- const BorderData& border() const { return surround->border; }
- const BorderValue& borderLeft() const { return surround->border.left; }
- const BorderValue& borderRight() const { return surround->border.right; }
- const BorderValue& borderTop() const { return surround->border.top; }
- const BorderValue& borderBottom() const { return surround->border.bottom; }
-
- unsigned short borderLeftWidth() const { return surround->border.borderLeftWidth(); }
- EBorderStyle borderLeftStyle() const { return surround->border.left.style; }
- const TQColor& borderLeftColor() const { return surround->border.left.color; }
- bool borderLeftIsTransparent() const { return surround->border.left.isTransparent(); }
- unsigned short borderRightWidth() const { return surround->border.borderRightWidth(); }
- EBorderStyle borderRightStyle() const { return surround->border.right.style; }
- const TQColor& borderRightColor() const { return surround->border.right.color; }
- bool borderRightIsTransparent() const { return surround->border.right.isTransparent(); }
- unsigned short borderTopWidth() const { return surround->border.borderTopWidth(); }
- EBorderStyle borderTopStyle() const { return surround->border.top.style; }
- const TQColor& borderTopColor() const { return surround->border.top.color; }
- bool borderTopIsTransparent() const { return surround->border.top.isTransparent(); }
- unsigned short borderBottomWidth() const { return surround->border.borderBottomWidth(); }
- EBorderStyle borderBottomStyle() const { return surround->border.bottom.style; }
- const TQColor& borderBottomColor() const { return surround->border.bottom.color; }
- bool borderBottomIsTransparent() const { return surround->border.bottom.isTransparent(); }
-
- unsigned short outlineSize() const { return outlineWidth() + outlineOffset(); }
- unsigned short outlineWidth() const
- { if(background->m_outline.style == BNONE || background->m_outline.style == BHIDDEN) return 0;
- else return background->m_outline.width; }
- EBorderStyle outlineStyle() const { return background->m_outline.style; }
- bool outlineStyleIsAuto() const { return background->m_outline._auto; }
- const TQColor & outlineColor() const { return background->m_outline.color; }
-
- EOverflow overflowX() const { return noninherited_flags.f._overflowX; }
- EOverflow overflowY() const { return noninherited_flags.f._overflowY; }
- bool hidesOverflow() const {
- // either both overflow are visible or none are
- return overflowX() != OVISIBLE;
- }
-
- EVisibility visibility() const { return inherited_flags.f._visibility; }
- EVerticalAlign verticalAlign() const { return noninherited_flags.f._vertical_align; }
- Length verticalAlignLength() const { return box->vertical_align; }
-
- Length clipLeft() const { return visual->clip.left; }
- Length clipRight() const { return visual->clip.right; }
- Length clipTop() const { return visual->clip.top; }
- Length clipBottom() const { return visual->clip.bottom; }
- LengthBox clip() const { return visual->clip; }
- bool hasClip() const { return noninherited_flags.f._hasClip; }
-
- EUnicodeBidi unicodeBidi() const { return noninherited_flags.f._unicodeBidi; }
-
- EClear clear() const { return noninherited_flags.f._clear; }
- ETableLayout tableLayout() const { return noninherited_flags.f._table_layout; }
-
- const TQFont & font() const { return inherited->font.f; }
- // use with care. call font->update() after modifications
- const Font &htmlFont() { return inherited->font; }
- const TQFontMetrics & fontMetrics() const { return inherited->font.fm; }
-
- const TQColor & color() const { return inherited->color; }
- Length textIndent() const { return inherited->indent; }
- ETextAlign textAlign() const { return inherited_flags.f._text_align; }
- ETextTransform textTransform() const { return inherited_flags.f._text_transform; }
- int textDecorationsInEffect() const { return inherited_flags.f._text_decorations; }
- int textDecoration() const { return visual->textDecoration; }
- int wordSpacing() const { return inherited->font.wordSpacing; }
- int letterSpacing() const { return inherited->font.letterSpacing; }
-
- EDirection direction() const { return inherited_flags.f._direction; }
- Length lineHeight() const { return inherited->line_height; }
-
- EWhiteSpace whiteSpace() const { return inherited_flags.f._white_space; }
- bool autoWrap() const {
- if (whiteSpace() == NORMAL || whiteSpace() == PRE_WRAP || whiteSpace() == PRE_LINE)
- return true;
- // nowrap | pre
- return false;
- }
- bool preserveLF() const {
- if (whiteSpace() == PRE || whiteSpace() == PRE_WRAP || whiteSpace() == PRE_LINE)
- return true;
- // normal | nowrap
- return false;
- }
- bool preserveWS() const {
- if (whiteSpace() == PRE || whiteSpace() == PRE_WRAP)
- return true;
- // normal | nowrap | pre-line
- return false;
- }
-
- const TQColor & backgroundColor() const { return background->m_color; }
- CachedImage *backgroundImage() const { return background->m_background.m_image; }
- EBackgroundRepeat backgroundRepeat() const { return background->m_background.m_bgRepeat; }
- bool backgroundAttachment() const { return background->m_background.m_bgAttachment; }
- Length backgroundXPosition() const { return background->m_background.m_xPosition; }
- Length backgroundYPosition() const { return background->m_background.m_yPosition; }
- BackgroundLayer* accessBackgroundLayers() { return &(background.access()->m_background); }
- const BackgroundLayer* backgroundLayers() const { return &(background->m_background); }
-
- // returns true for collapsing borders, false for separate borders
- bool borderCollapse() const { return inherited_flags.f._border_collapse; }
- short borderHorizontalSpacing() const { return inherited->border_hspacing; }
- short borderVerticalSpacing() const { return inherited->border_vspacing; }
- EEmptyCell emptyCells() const { return inherited_flags.f._empty_cells; }
- ECaptionSide captionSide() const { return inherited_flags.f._caption_side; }
-
- EListStyleType listStyleType() const { return inherited_flags.f._list_style_type; }
- CachedImage *listStyleImage() const { return inherited->style_image; }
- EListStylePosition listStylePosition() const { return inherited_flags.f._list_style_position; }
-
- Length marginTop() const { return surround->margin.top; }
- Length marginBottom() const { return surround->margin.bottom; }
- Length marginLeft() const { return surround->margin.left; }
- Length marginRight() const { return surround->margin.right; }
-
- Length paddingTop() const { return surround->padding.top; }
- Length paddingBottom() const { return surround->padding.bottom; }
- Length paddingLeft() const { return surround->padding.left; }
- Length paddingRight() const { return surround->padding.right; }
-
- ECursor cursor() const { return inherited_flags.f._cursor_style; }
-
- short widows() const { return inherited->widows; }
- short orphans() const { return inherited->orphans; }
- bool pageBreakInside() const { return inherited_flags.f._page_break_inside; }
- EPageBreak pageBreakBefore() const { return noninherited_flags.f._page_break_before; }
- EPageBreak pageBreakAfter() const { return noninherited_flags.f._page_break_after; }
-
- DOM::QuotesValueImpl* quotes() const { return inherited->quotes; }
- TQString openQuote(int level) const;
- TQString closeQuote(int level) const;
-
- // CSS3 Getter Methods
- EBoxSizing boxSizing() const { return box->box_sizing; }
- int outlineOffset() const {
- if (background->m_outline.style == BNONE || background->m_outline.style == BHIDDEN) return 0;
- return background->m_outline._offset;
- }
- ShadowData* textShadow() const { return css3InheritedData->textShadow; }
- EWordWrap wordWrap() const { return css3InheritedData->wordWrap; }
- float opacity() { return css3NonInheritedData->opacity; }
- EUserInput userInput() const { return inherited_flags.f._user_input; }
-
- Length marqueeIncrement() { return css3NonInheritedData->marquee->increment; }
- int marqueeSpeed() { return css3NonInheritedData->marquee->speed; }
- int marqueeLoopCount() { return css3NonInheritedData->marquee->loops; }
- EMarqueeBehavior marqueeBehavior() { return css3NonInheritedData->marquee->behavior; }
- EMarqueeDirection marqueeDirection() { return css3NonInheritedData->marquee->direction; }
- bool textOverflow() const { return noninherited_flags.f._textOverflow; }
- // End CSS3 Getters
-
-// attribute setter methods
-
- void setDisplay(EDisplay v) { noninherited_flags.f._display = v; }
- void setOriginalDisplay(EDisplay v) { noninherited_flags.f._originalDisplay = v; }
- void setPosition(EPosition v) { noninherited_flags.f._position = v; }
- void setFloating(EFloat v) { noninherited_flags.f._floating = v; }
-
- void setLeft(Length v) { SET_VAR(surround,offset.left,v) }
- void setRight(Length v) { SET_VAR(surround,offset.right,v) }
- void setTop(Length v) { SET_VAR(surround,offset.top,v) }
- void setBottom(Length v){ SET_VAR(surround,offset.bottom,v) }
-
- void setWidth(Length v) { SET_VAR(box,width,v) }
- void setHeight(Length v) { SET_VAR(box,height,v) }
-
- void setMinWidth(Length v) { SET_VAR(box,min_width,v) }
- void setMaxWidth(Length v) { SET_VAR(box,max_width,v) }
- void setMinHeight(Length v) { SET_VAR(box,min_height,v) }
- void setMaxHeight(Length v) { SET_VAR(box,max_height,v) }
-
- void resetBorderTop() { SET_VAR(surround, border.top, BorderValue()) }
- void resetBorderRight() { SET_VAR(surround, border.right, BorderValue()) }
- void resetBorderBottom() { SET_VAR(surround, border.bottom, BorderValue()) }
- void resetBorderLeft() { SET_VAR(surround, border.left, BorderValue()) }
- void resetOutline() { SET_VAR(background, m_outline, OutlineValue()) }
-
- void setBackgroundColor(const TQColor& v) { SET_VAR(background, m_color, v) }
-
- void setBorderLeftWidth(unsigned short v) { SET_VAR(surround,border.left.width,v) }
- void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround,border.left.style,v) }
- void setBorderLeftColor(const TQColor & v) { SET_VAR(surround,border.left.color,v) }
- void setBorderRightWidth(unsigned short v) { SET_VAR(surround,border.right.width,v) }
- void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround,border.right.style,v) }
- void setBorderRightColor(const TQColor & v) { SET_VAR(surround,border.right.color,v) }
- void setBorderTopWidth(unsigned short v) { SET_VAR(surround,border.top.width,v) }
- void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround,border.top.style,v) }
- void setBorderTopColor(const TQColor & v) { SET_VAR(surround,border.top.color,v) }
- void setBorderBottomWidth(unsigned short v) { SET_VAR(surround,border.bottom.width,v) }
- void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround,border.bottom.style,v) }
- void setBorderBottomColor(const TQColor & v) { SET_VAR(surround,border.bottom.color,v) }
- void setOutlineWidth(unsigned short v) { SET_VAR(background,m_outline.width,v) }
- void setOutlineStyle(EBorderStyle v, bool isAuto = false)
- {
- SET_VAR(background,m_outline.style,v)
- SET_VAR(background,m_outline._auto, isAuto)
- }
- void setOutlineColor(const TQColor & v) { SET_VAR(background,m_outline.color,v) }
-
- void setOverflowX(EOverflow v) { noninherited_flags.f._overflowX = v; }
- void setOverflowY(EOverflow v) { noninherited_flags.f._overflowY = v; }
- void setVisibility(EVisibility v) { inherited_flags.f._visibility = v; }
- void setVerticalAlign(EVerticalAlign v) { noninherited_flags.f._vertical_align = v; }
- void setVerticalAlignLength(Length l) { SET_VAR(box, vertical_align, l ) }
-
- void setClipLeft(Length v) { SET_VAR(visual,clip.left,v) }
- void setClipRight(Length v) { SET_VAR(visual,clip.right,v) }
- void setClipTop(Length v) { SET_VAR(visual,clip.top,v) }
- void setClipBottom(Length v) { SET_VAR(visual,clip.bottom,v) }
- void setClip( Length top, Length right, Length bottom, Length left );
- void setHasClip( bool b ) { noninherited_flags.f._hasClip = b; }
-
- void setUnicodeBidi( EUnicodeBidi b ) { noninherited_flags.f._unicodeBidi = b; }
-
- void setClear(EClear v) { noninherited_flags.f._clear = v; }
- void setTableLayout(ETableLayout v) { noninherited_flags.f._table_layout = v; }
- bool setFontDef(const khtml::FontDef & v) {
- // bah, this doesn't compare pointers. broken! (Dirk)
- if (!(inherited->font.fontDef == v)) {
- inherited.access()->font = Font( v );
- return true;
- }
- return false;
- }
-
- void setColor(const TQColor & v) { SET_VAR(inherited,color,v) }
- void setTextIndent(Length v) { SET_VAR(inherited,indent,v) }
- void setTextAlign(ETextAlign v) { inherited_flags.f._text_align = v; }
- void setTextTransform(ETextTransform v) { inherited_flags.f._text_transform = v; }
- void addToTextDecorationsInEffect(int v) { inherited_flags.f._text_decorations |= v; }
- void setTextDecorationsInEffect(int v) { inherited_flags.f._text_decorations = v; }
- void setTextDecoration(unsigned v) { SET_VAR(visual, textDecoration, v); }
- void setDirection(EDirection v) { inherited_flags.f._direction = v; }
- void setLineHeight(Length v) { SET_VAR(inherited,line_height,v) }
-
- void setWhiteSpace(EWhiteSpace v) { inherited_flags.f._white_space = v; }
-
- void setWordSpacing(int v) { SET_VAR(inherited,font.wordSpacing,v) }
- void setLetterSpacing(int v) { SET_VAR(inherited,font.letterSpacing,v) }
-
- void clearBackgroundLayers() { background.access()->m_background = BackgroundLayer(); }
- void inheritBackgroundLayers(const BackgroundLayer& parent) { background.access()->m_background = parent; }
- void adjustBackgroundLayers();
-
- void setBorderCollapse(bool collapse) { inherited_flags.f._border_collapse = collapse; }
- void setBorderHorizontalSpacing(short v) { SET_VAR(inherited,border_hspacing,v) }
- void setBorderVerticalSpacing(short v) { SET_VAR(inherited,border_vspacing,v) }
-
- void setEmptyCells(EEmptyCell v) { inherited_flags.f._empty_cells = v; }
- void setCaptionSide(ECaptionSide v) { inherited_flags.f._caption_side = v; }
-
- void setListStyleType(EListStyleType v) { inherited_flags.f._list_style_type = v; }
- void setListStyleImage(CachedImage *v) { SET_VAR(inherited,style_image,v)}
- void setListStylePosition(EListStylePosition v) { inherited_flags.f._list_style_position = v; }
-
- void resetMargin() { SET_VAR(surround, margin, LengthBox(Fixed)) }
- void setMarginTop(Length v) { SET_VAR(surround,margin.top,v) }
- void setMarginBottom(Length v) { SET_VAR(surround,margin.bottom,v) }
- void setMarginLeft(Length v) { SET_VAR(surround,margin.left,v) }
- void setMarginRight(Length v) { SET_VAR(surround,margin.right,v) }
-
- void resetPadding() { SET_VAR(surround, padding, LengthBox(Variable)) }
- void setPaddingTop(Length v) { SET_VAR(surround,padding.top,v) }
- void setPaddingBottom(Length v) { SET_VAR(surround,padding.bottom,v) }
- void setPaddingLeft(Length v) { SET_VAR(surround,padding.left,v) }
- void setPaddingRight(Length v) { SET_VAR(surround,padding.right,v) }
-
- void setCursor( ECursor c ) { inherited_flags.f._cursor_style = c; }
-
- bool htmlHacks() const { return inherited_flags.f._htmlHacks; }
- void setHtmlHacks(bool b=true) { inherited_flags.f._htmlHacks = b; }
-
- bool flowAroundFloats() const { return noninherited_flags.f._flowAroundFloats; }
- void setFlowAroundFloats(bool b=true) { noninherited_flags.f._flowAroundFloats = b; }
-
- int zIndex() const { return box->z_auto? 0 : box->z_index; }
- void setZIndex(int v) { SET_VAR(box,z_auto,false ); SET_VAR(box, z_index, v); }
- bool hasAutoZIndex() const { return box->z_auto; }
- void setHasAutoZIndex() { SET_VAR(box, z_auto, true ); }
-
- void setWidows(short w) { SET_VAR(inherited, widows, w); }
- void setOrphans(short o) { SET_VAR(inherited, orphans, o); }
- void setPageBreakInside(bool b) { inherited_flags.f._page_break_inside = b; }
- void setPageBreakBefore(EPageBreak b) { noninherited_flags.f._page_break_before = b; }
- void setPageBreakAfter(EPageBreak b) { noninherited_flags.f._page_break_after = b; }
-
- void setQuotes(DOM::QuotesValueImpl* q);
-
- // CSS3 Setters
- void setBoxSizing( EBoxSizing b ) { SET_VAR(box,box_sizing,b); }
- void setOutlineOffset(unsigned short v) { SET_VAR(background,m_outline._offset,v) }
- void setWordWrap(EWordWrap w) { SET_VAR(css3InheritedData, wordWrap, w); }
- void setTextShadow(ShadowData* val, bool add=false);
- void setOpacity(float f) { SET_VAR(css3NonInheritedData, opacity, f); }
- void setUserInput(EUserInput ui) { inherited_flags.f._user_input = ui; }
-
- void setMarqueeIncrement(const Length& f) { SET_VAR(css3NonInheritedData.access()->marquee, increment, f); }
- void setMarqueeSpeed(int f) { SET_VAR(css3NonInheritedData.access()->marquee, speed, f); }
- void setMarqueeDirection(EMarqueeDirection d) { SET_VAR(css3NonInheritedData.access()->marquee, direction, d); }
- void setMarqueeBehavior(EMarqueeBehavior b) { SET_VAR(css3NonInheritedData.access()->marquee, behavior, b); }
- void setMarqueeLoopCount(int i) { SET_VAR(css3NonInheritedData.access()->marquee, loops, i); }
- void setTextOverflow(bool b) { noninherited_flags.f._textOverflow = b; }
- // End CSS3 Setters
-
- TQPalette palette() const { return visual->palette; }
- void setPaletteColor(TQPalette::ColorGroup g, TQColorGroup::ColorRole r, const TQColor& c);
- void resetPalette() // Called when the desktop color scheme changes.
- {
- const_cast<StyleVisualData *>(visual.get())->palette = TQApplication::palette();
- }
-
- bool useNormalContent() const { return generated->content == 0; }
- ContentData* contentData() const { return generated->content; }
- bool contentDataEquivalent(const RenderStyle* otherStyle) const
- {
- return generated->contentDataEquivalent(otherStyle->generated.get());
- }
- void addContent(DOM::DOMStringImpl* s);
- void addContent(CachedObject* o);
- void addContent(DOM::CounterImpl* c);
- void addContent(EQuoteContent q);
- void setContentNone();
- void setContentNormal();
- void setContentData(ContentData* content);
-
- DOM::CSSValueListImpl* counterReset() const { return generated->counter_reset; }
- DOM::CSSValueListImpl* counterIncrement() const { return generated->counter_increment; }
- void setCounterReset(DOM::CSSValueListImpl* v);
- void setCounterIncrement(DOM::CSSValueListImpl* v);
- bool hasCounterReset(const DOM::DOMString& c) const;
- bool hasCounterIncrement(const DOM::DOMString& c) const;
- short counterReset(const DOM::DOMString& c) const;
- short counterIncrement(const DOM::DOMString& c) const;
-
-
- bool inheritedNotEqual( RenderStyle *other ) const;
-
- enum Diff { Equal, NonVisible = Equal, Visible, Position, Layout, CbLayout };
- Diff diff( const RenderStyle *other ) const;
-
- bool isDisplayReplacedType() {
- return display() == INLINE_BLOCK ||/* display() == INLINE_BOX ||*/ display() == INLINE_TABLE;
- }
- bool isDisplayInlineType() {
- return display() == INLINE || isDisplayReplacedType();
- }
- bool isOriginalDisplayInlineType() {
- return originalDisplay() == INLINE || originalDisplay() == INLINE_BLOCK ||
- /*originalDisplay() == INLINE_BOX ||*/ originalDisplay() == INLINE_TABLE;
- }
-
-
-#ifdef ENABLE_DUMP
- TQString createDiff( const RenderStyle &parent ) const;
-#endif
-
- // Initial values for all the properties
- static bool initialBackgroundAttachment() { return true; }
- static EBackgroundBox initialBackgroundClip() { return BGBORDER; }
- static EBackgroundBox initialBackgroundOrigin() { return BGPADDING; }
- static EBackgroundRepeat initialBackgroundRepeat() { return REPEAT; }
- static LengthSize initialBackgroundSize() { return LengthSize(); }
- static bool initialBorderCollapse() { return false; }
- static EBorderStyle initialBorderStyle() { return BNONE; }
- static ECaptionSide initialCaptionSide() { return CAPTOP; }
- static EClear initialClear() { return CNONE; }
- static EDirection initialDirection() { return LTR; }
- static EDisplay initialDisplay() { return INLINE; }
- static EEmptyCell initialEmptyCells() { return SHOW; }
- static EFloat initialFloating() { return FNONE; }
- static EWordWrap initialWordWrap() { return WWNORMAL; }
- static EListStylePosition initialListStylePosition() { return OUTSIDE; }
- static EListStyleType initialListStyleType() { return LDISC; }
- static EOverflow initialOverflowX() { return OVISIBLE; }
- static EOverflow initialOverflowY() { return OVISIBLE; }
- static EPageBreak initialPageBreak() { return PBAUTO; }
- static bool initialPageBreakInside() { return true; }
- static EPosition initialPosition() { return STATIC; }
- static ETableLayout initialTableLayout() { return TAUTO; }
- static EUnicodeBidi initialUnicodeBidi() { return UBNormal; }
- static DOM::QuotesValueImpl* initialQuotes() { return 0; }
- static EBoxSizing initialBoxSizing() { return CONTENT_BOX; }
- static ETextTransform initialTextTransform() { return TTNONE; }
- static EVisibility initialVisibility() { return VISIBLE; }
- static EWhiteSpace initialWhiteSpace() { return NORMAL; }
- static Length initialBackgroundXPosition() { return Length(); }
- static Length initialBackgroundYPosition() { return Length(); }
- static short initialBorderHorizontalSpacing() { return 0; }
- static short initialBorderVerticalSpacing() { return 0; }
- static ECursor initialCursor() { return CURSOR_AUTO; }
- static TQColor initialColor() { return Qt::black; }
- static CachedImage* initialBackgroundImage() { return 0; }
- static CachedImage* initialListStyleImage() { return 0; }
- static unsigned short initialBorderWidth() { return 3; }
- static int initialLetterWordSpacing() { return 0; }
- static Length initialSize() { return Length(); }
- static Length initialMinSize() { return Length(0, Fixed); }
- static Length initialMaxSize() { return Length(UNDEFINED, Fixed); }
- static Length initialOffset() { return Length(); }
- static Length initialMargin() { return Length(Fixed); }
- static Length initialPadding() { return Length(Variable); }
- static Length initialTextIndent() { return Length(Fixed); }
- static EVerticalAlign initialVerticalAlign() { return BASELINE; }
- static int initialWidows() { return 2; }
- static int initialOrphans() { return 2; }
- static Length initialLineHeight() { return Length(-100, Percent); }
- static ETextAlign initialTextAlign() { return TAAUTO; }
- static ETextDecoration initialTextDecoration() { return TDNONE; }
- static bool initialFlowAroundFloats() { return false; }
- static int initialOutlineOffset() { return 0; }
- static float initialOpacity() { return 1.0f; }
- static int initialMarqueeLoopCount() { return -1; }
- static int initialMarqueeSpeed() { return 85; }
- static Length initialMarqueeIncrement() { return Length(6, Fixed); }
- static EMarqueeBehavior initialMarqueeBehavior() { return MSCROLL; }
- static EMarqueeDirection initialMarqueeDirection() { return MAUTO; }
- static bool initialTextOverflow() { return false; }
-};
-
-class RenderPageStyle {
- friend class CSSStyleSelector;
-public:
- enum PageType { NO_PAGE = 0, ANY_PAGE, FIRST_PAGE, LEFT_PAGES, RIGHT_PAGES };
-
- RenderPageStyle();
- ~RenderPageStyle();
-
- PageType pageType() { return m_pageType; }
-
- RenderPageStyle* getPageStyle(PageType type);
- RenderPageStyle* addPageStyle(PageType type);
- void removePageStyle(PageType type);
-
- Length marginTop() const { return margin.top; }
- Length marginBottom() const { return margin.bottom; }
- Length marginLeft() const { return margin.left; }
- Length marginRight() const { return margin.right; }
-
- Length pageWidth() const { return m_pageWidth; }
- Length pageHeight() const { return m_pageHeight; }
-
- void setMarginTop(Length v) { margin.top = v; }
- void setMarginBottom(Length v) { margin.bottom = v; }
- void setMarginLeft(Length v) { margin.left = v; }
- void setMarginRight(Length v) { margin.right = v; }
-
- void setPageWidth(Length v) { m_pageWidth = v; }
- void setPageHeight(Length v) { m_pageHeight = v; }
-
-protected:
- RenderPageStyle *next;
- PageType m_pageType;
-
- LengthBox margin;
- Length m_pageWidth;
- Length m_pageHeight;
-};
-
-} // namespace
-
-#endif
-
diff --git a/khtml/rendering/render_table.cpp b/khtml/rendering/render_table.cpp
deleted file mode 100644
index d98aa2072..000000000
--- a/khtml/rendering/render_table.cpp
+++ /dev/null
@@ -1,3070 +0,0 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- * (C) 1997 Torben Weis (weis@kde.org)
- * (C) 1998 Waldo Bastian (bastian@kde.org)
- * (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2003 Apple Computer, Inc.
- * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-//#define TABLE_DEBUG
-//#define TABLE_PRINT
-//#define DEBUG_LAYOUT
-//#define BOX_DEBUG
-#include "rendering/render_table.h"
-#include "rendering/render_replaced.h"
-#include "rendering/render_canvas.h"
-#include "rendering/table_layout.h"
-#include "html/html_tableimpl.h"
-#include "html/html_formimpl.h"
-#include "misc/htmltags.h"
-#include "misc/htmlattrs.h"
-#include "rendering/render_line.h"
-#include "xml/dom_docimpl.h"
-
-#include <kglobal.h>
-
-#include <tqapplication.h>
-#include <tqstyle.h>
-
-#include <kdebug.h>
-#include <assert.h>
-
-using namespace khtml;
-using namespace DOM;
-
-RenderTable::RenderTable(DOM::NodeImpl* node)
- : RenderBlock(node)
-{
-
- tCaption = 0;
- head = foot = firstBody = 0;
- tableLayout = 0;
- m_currentBorder = 0;
-
- has_col_elems = false;
- hspacing = vspacing = 0;
- padding = 0;
- needSectionRecalc = false;
- padding = 0;
-
- columnPos.resize( 2 );
- columnPos.fill( 0 );
- columns.resize( 1 );
- columns.fill( ColumnStruct() );
-
- columnPos[0] = 0;
-}
-
-RenderTable::~RenderTable()
-{
- delete tableLayout;
-}
-
-void RenderTable::setStyle(RenderStyle *_style)
-{
- ETableLayout oldTableLayout = style() ? style()->tableLayout() : TAUTO;
- if ( _style->display() == INLINE ) _style->setDisplay( INLINE_TABLE );
- if ( _style->display() != INLINE_TABLE ) _style->setDisplay(TABLE);
- if ( !_style->flowAroundFloats() ) _style->setFlowAroundFloats(true);
- RenderBlock::setStyle(_style);
-
- // init RenderObject attributes
- setInline(style()->display()==INLINE_TABLE && !isPositioned());
- setReplaced(style()->display()==INLINE_TABLE);
-
- // In the collapsed border model, there is no cell spacing.
- hspacing = collapseBorders() ? 0 : style()->borderHorizontalSpacing();
- vspacing = collapseBorders() ? 0 : style()->borderVerticalSpacing();
- columnPos[0] = hspacing;
-
- if ( !tableLayout || style()->tableLayout() != oldTableLayout ) {
- delete tableLayout;
-
- // According to the CSS2 spec, you only use fixed table layout if an
- // explicit width is specified on the table. Auto width implies auto table layout.
- if (style()->tableLayout() == TFIXED && !style()->width().isVariable()) {
- tableLayout = new FixedTableLayout(this);
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "using fixed table layout" << endl;
-#endif
- } else
- tableLayout = new AutoTableLayout(this);
- }
-}
-
-short RenderTable::lineHeight(bool b) const
-{
- // Inline tables are replaced elements. Otherwise, just pass off to
- // the base class.
- if (isReplaced())
- return height()+marginTop()+marginBottom();
- return RenderBlock::lineHeight(b);
-}
-
-short RenderTable::baselinePosition(bool b) const
-{
- // Inline tables are replaced elements. Otherwise, just pass off to
- // the base class.
- if (isReplaced())
- return height()+marginTop()+marginBottom();
- return RenderBlock::baselinePosition(b);
-}
-
-
-void RenderTable::addChild(RenderObject *child, RenderObject *beforeChild)
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(Table)::addChild( " << child->renderName() << ", " <<
- (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
-#endif
- bool wrapInAnonymousSection = false;
-
- switch(child->style()->display())
- {
- case TABLE_CAPTION:
- if (child->isRenderBlock())
- tCaption = static_cast<RenderBlock *>(child);
- break;
- case TABLE_COLUMN:
- case TABLE_COLUMN_GROUP:
- has_col_elems = true;
- break;
- case TABLE_HEADER_GROUP:
- if ( !head ) {
- if (child->isTableSection())
- head = static_cast<RenderTableSection *>(child);
- }
- else if ( !firstBody )
- if (child->isTableSection())
- firstBody = static_cast<RenderTableSection *>(child);
- break;
- case TABLE_FOOTER_GROUP:
- if ( !foot ) {
- if (child->isTableSection())
- foot = static_cast<RenderTableSection *>(child);
- break;
- }
- // fall through
- case TABLE_ROW_GROUP:
- if(!firstBody)
- if (child->isTableSection())
- firstBody = static_cast<RenderTableSection *>(child);
- break;
- case TABLE_CELL:
- case TABLE_ROW:
- wrapInAnonymousSection = true;
- break;
- case BLOCK:
-// case BOX:
- case COMPACT:
- case INLINE:
- case INLINE_BLOCK:
-// case INLINE_BOX:
- case INLINE_TABLE:
- case LIST_ITEM:
- case NONE:
- case RUN_IN:
- case TABLE:
- // The special TABLE > FORM quirk allows the form to sit directly under the table
- if (child->element() && child->element()->isHTMLElement() && child->element()->id() == ID_FORM)
- wrapInAnonymousSection = !static_cast<HTMLFormElementImpl*>(child->element())->isMalformed();
- else
- wrapInAnonymousSection = true;
- break;
- }
-
- if (!wrapInAnonymousSection) {
- RenderContainer::addChild(child, beforeChild);
- return;
- }
-
- if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous()) {
- lastChild()->addChild(child);
- return;
- }
-
- RenderObject *lastBox = beforeChild;
- RenderObject *nextToLastBox = beforeChild;
- while (lastBox && lastBox->parent()->isAnonymous() &&
- !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION) {
- nextToLastBox = lastBox;
- lastBox = lastBox->parent();
- }
- if (lastBox && lastBox->isAnonymous()) {
- lastBox->addChild(child, nextToLastBox);
- return;
- }
-
- if (beforeChild && !beforeChild->isTableSection())
- beforeChild = 0;
- RenderTableSection* section = new (renderArena()) RenderTableSection(document() /* anonymous */);
- RenderStyle* newStyle = new RenderStyle();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(TABLE_ROW_GROUP);
- section->setStyle(newStyle);
- addChild(section, beforeChild);
- section->addChild(child);
-}
-
-void RenderTable::calcWidth()
-{
- if ( isPositioned() ) {
- calcAbsoluteHorizontal();
- }
-
- RenderBlock *cb = containingBlock();
- int availableWidth = cb->lineWidth( m_y );
-
- LengthType widthType = style()->width().type();
- if(widthType > Relative && style()->width().value() > 0) {
- // Percent or fixed table
- // Percent is calculated from contentWidth, not available width
- m_width = calcBoxWidth(style()->width().minWidth( cb->contentWidth() ));
- } else {
- // Subtract out any fixed margins from our available width for auto width tables.
- int marginTotal = 0;
- if (!style()->marginLeft().isVariable())
- marginTotal += style()->marginLeft().width(availableWidth);
- if (!style()->marginRight().isVariable())
- marginTotal += style()->marginRight().width(availableWidth);
-
- // Subtract out our margins to get the available content width.
- int availContentWidth = kMax(0, availableWidth - marginTotal);
-
- // Ensure we aren't bigger than our max width or smaller than our min width.
- m_width = kMin(availContentWidth, m_maxWidth);
- }
-
- m_width = kMax (m_width, m_minWidth);
-
- // Finally, with our true width determined, compute our margins for real.
- m_marginRight=0;
- m_marginLeft=0;
-
- calcHorizontalMargins(style()->marginLeft(),style()->marginRight(),availableWidth);
-}
-
-void RenderTable::layout()
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
- KHTMLAssert( !needSectionRecalc );
-
- if (posChildNeedsLayout() && !normalChildNeedsLayout() && !selfNeedsLayout()) {
- // All we have to is lay out our positioned objects.
- layoutPositionedObjects(true);
- setNeedsLayout(false);
- return;
- }
-
- if (markedForRepaint()) {
- repaintDuringLayout();
- setMarkedForRepaint(false);
- }
-
- m_height = 0;
- initMaxMarginValues();
-
- int oldWidth = m_width;
- calcWidth();
- m_overflowWidth = m_width;
-
- if (tCaption && (oldWidth != m_width || tCaption->style()->height().isPercent()))
- tCaption->setChildNeedsLayout(true);
-
- // the optimization below doesn't work since the internal table
- // layout could have changed. we need to add a flag to the table
- // layout that tells us if something has changed in the min max
- // calculations to do it correctly.
-// if ( oldWidth != m_width || columns.size() + 1 != columnPos.size() )
- tableLayout->layout();
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(Table)::layout1() width=" << width() << ", marginLeft=" << marginLeft() << " marginRight=" << marginRight() << endl;
-#endif
-
- setCellWidths();
-
- // layout child objects
- int calculatedHeight = 0;
-
- RenderObject *child = firstChild();
- while( child ) {
- // FIXME: What about a form that has a display value that makes it a table section?
- if ( child->needsLayout() && !(child->element() && child->element()->id() == ID_FORM) )
- child->layout();
- if ( child->isTableSection() ) {
- static_cast<RenderTableSection *>(child)->calcRowHeight();
- calculatedHeight += static_cast<RenderTableSection *>(child)->layoutRows( 0 );
- }
- child = child->nextSibling();
- }
-
- // ### collapse caption margin
- if(tCaption && tCaption->style()->captionSide() != CAPBOTTOM) {
- tCaption->setPos(tCaption->marginLeft(), tCaption->marginTop()+m_height);
- m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();
- }
-
- int bpTop = borderTop() + (collapseBorders() ? 0 : paddingTop());
- int bpBottom = borderBottom() + (collapseBorders() ? 0 : paddingBottom());
-
- m_height += bpTop;
-
- int oldHeight = m_height;
- if (isPositioned())
- m_height += calculatedHeight + bpBottom;
- calcHeight();
- int newHeight = m_height;
- m_height = oldHeight;
-
- Length h = style()->height();
- int th = -(bpTop + bpBottom); // Tables size as though CSS height includes border/padding.
- if (isPositioned())
- th += newHeight;
- else if (h.isFixed())
- th += h.value();
- else if (h.isPercent())
- th += calcPercentageHeight(h);
-
- // layout rows
- if ( th > calculatedHeight ) {
- // we have to redistribute that height to get the constraint correctly
- // just force the first body to the height needed
- // ### FIXME This should take height constraints on all table sections into account and distribute
- // accordingly. For now this should be good enough
- if (firstBody) {
- firstBody->calcRowHeight();
- firstBody->layoutRows( th - calculatedHeight );
- }
- else if (!style()->htmlHacks()) {
- // Completely empty tables (with no sections or anything) should at least honor specified height
- // in strict mode.
- m_height += th;
- }
- }
-
- int bl = borderLeft();
- if (!collapseBorders())
- bl += paddingLeft();
-
- // position the table sections
- if ( head ) {
- head->setPos(bl, m_height);
- m_height += head->height();
- }
- RenderObject *body = firstBody;
- while ( body ) {
- if ( body != head && body != foot && body->isTableSection() ) {
- body->setPos(bl, m_height);
- m_height += body->height();
- }
- body = body->nextSibling();
- }
- if ( foot ) {
- foot->setPos(bl, m_height);
- m_height += foot->height();
- }
-
- m_height += bpBottom;
-
- if(tCaption && tCaption->style()->captionSide()==CAPBOTTOM) {
- tCaption->setPos(tCaption->marginLeft(), tCaption->marginTop()+m_height);
- m_height += tCaption->height() + tCaption->marginTop() + tCaption->marginBottom();
- }
-
- if (canvas()->pagedMode()) {
- RenderObject *child = firstChild();
- // relayout taking real position into account
- while( child ) {
- if ( !(child->element() && child->element()->id() == ID_FORM) ) {
- child->setNeedsLayout(true);
- child->layout();
- if (child->containsPageBreak()) setContainsPageBreak(true);
- if (child->needsPageClear()) setNeedsPageClear(true);
- }
- child = child->nextSibling();
- }
- }
-
- //kdDebug(0) << "table height: " << m_height << endl;
-
- // table can be containing block of positioned elements.
- // ### only pass true if width or height changed.
- layoutPositionedObjects( true );
-
- m_overflowHeight = m_height;
-
- setNeedsLayout(false);
-}
-
-void RenderTable::setCellWidths()
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;
-#endif
-
- RenderObject *child = firstChild();
- while( child ) {
- if ( child->isTableSection() )
- static_cast<RenderTableSection *>(child)->setCellWidths();
- child = child->nextSibling();
- }
-}
-
-void RenderTable::paint( PaintInfo& pI, int _tx, int _ty)
-{
- if(needsLayout()) return;
-
- _tx += xPos();
- _ty += yPos();
-
-#ifdef TABLE_PRINT
- kdDebug( 6040 ) << "RenderTable::paint() w/h = (" << width() << "/" << height() << ")" << endl;
-#endif
- if (!overhangingContents() && !isRelPositioned() && !isPositioned())
- {
- int os = 2*maximalOutlineSize(pI.phase);
- if((_ty > pI.r.y() + pI.r.height() + os) || (_ty + height() < pI.r.y() - os)) return;
- if((_tx > pI.r.x() + pI.r.width() + os) || (_tx + width() < pI.r.x() - os)) return;
- }
-
-#ifdef TABLE_PRINT
- kdDebug( 6040 ) << "RenderTable::paint(2) " << _tx << "/" << _ty << " (" << _y << "/" << _h << ")" << endl;
-#endif
-
- if (pI.phase == PaintActionOutline)
- paintOutline(pI.p, _tx, _ty, width(), height(), style());
-
- if(( pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground )
- && shouldPaintBackgroundOrBorder() && style()->visibility() == VISIBLE)
- paintBoxDecorations(pI, _tx, _ty);
-
- if ( pI.phase == PaintActionElementBackground )
- return;
-
- PaintAction oldphase = pI.phase;
- if ( pI.phase == PaintActionChildBackgrounds )
- pI.phase = PaintActionChildBackground;
-
- for( RenderObject *child = firstChild(); child; child = child->nextSibling())
- if ( child->isTableSection() || child == tCaption )
- child->paint( pI, _tx, _ty );
-
- if (collapseBorders() &&
- (pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground)
- && style()->visibility() == VISIBLE) {
- // Collect all the unique border styles that we want to paint in a sorted list. Once we
- // have all the styles sorted, we then do individual passes, painting each style of border
- // from lowest precedence to highest precedence.
- pI.phase = PaintActionCollapsedTableBorders;
- TQValueList<CollapsedBorderValue> borderStyles;
- collectBorders(borderStyles);
-#if 0
- TQString m;
- for (uint i = 0; i < borderStyles.count(); i++)
- m += TQString("%1 ").arg((*borderStyles.at(i)).width());
- kdDebug(6040) << m << endl;
-#endif
- TQValueListIterator<CollapsedBorderValue> it = borderStyles.begin();
- TQValueListIterator<CollapsedBorderValue> end = borderStyles.end();
- for (; it != end; ++it) {
- m_currentBorder = &*it;
- for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableSection())
- child->paint(pI, _tx, _ty);
- }
- }
- m_currentBorder = 0;
- }
-
- pI.phase = oldphase;
-#ifdef BOX_DEBUG
- outlineBox(p, _tx, _ty, "blue");
-#endif
-}
-
-void RenderTable::paintBoxDecorations(PaintInfo &pI, int _tx, int _ty)
-{
- int w = width();
- int h = height();
-
- // Account for the caption.
- if (tCaption) {
- int captionHeight = (tCaption->height() + tCaption->marginBottom() + tCaption->marginTop());
- h -= captionHeight;
- if (tCaption->style()->captionSide() != CAPBOTTOM)
- _ty += captionHeight;
- }
-
- int my = kMax(_ty,pI.r.y());
- int mh;
- if (_ty<pI.r.y())
- mh= kMax(0,h-(pI.r.y()-_ty));
- else
- mh = kMin(pI.r.height(),h);
-
- paintBackground(pI.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h);
-
- if (style()->hasBorder() && !collapseBorders())
- paintBorder(pI.p, _tx, _ty, w, h, style());
-}
-
-void RenderTable::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- if ( needSectionRecalc )
- recalcSections();
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(Table " << this << ")::calcMinMaxWidth()" << endl;
-#endif
-
- tableLayout->calcMinMaxWidth();
-
- if (tCaption) {
- tCaption->calcWidth();
- if (tCaption->marginLeft()+tCaption->marginRight()+tCaption->minWidth() > m_minWidth)
- m_minWidth = tCaption->marginLeft()+tCaption->marginRight()+tCaption->minWidth();
- }
-
- setMinMaxKnown();
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << " END: (Table " << this << ")::calcMinMaxWidth() min = " << m_minWidth << " max = " << m_maxWidth << endl;
-#endif
-}
-
-void RenderTable::close()
-{
-// kdDebug( 6040 ) << "RenderTable::close()" << endl;
- setNeedsLayoutAndMinMaxRecalc();
-}
-
-void RenderTable::splitColumn( int pos, int firstSpan )
-{
- // we need to add a new columnStruct
- int oldSize = columns.size();
- columns.resize( oldSize + 1 );
- int oldSpan = columns[pos].span;
-// tqDebug("splitColumn( %d,%d ), oldSize=%d, oldSpan=%d", pos, firstSpan, oldSize, oldSpan );
- KHTMLAssert( oldSpan > firstSpan );
- columns[pos].span = firstSpan;
- memmove( columns.data()+pos+1, columns.data()+pos, (oldSize-pos)*sizeof(ColumnStruct) );
- columns[pos+1].span = oldSpan - firstSpan;
-
- // change width of all rows.
- RenderObject *child = firstChild();
- while ( child ) {
- if ( child->isTableSection() ) {
- RenderTableSection *section = static_cast<RenderTableSection *>(child);
- int size = section->grid.size();
- int row = 0;
- if ( section->cCol > pos )
- section->cCol++;
- while ( row < size ) {
- section->grid[row].row->resize( oldSize+1 );
- RenderTableSection::Row &r = *section->grid[row].row;
- memmove( r.data()+pos+1, r.data()+pos, (oldSize-pos)*sizeof( RenderTableCell * ) );
-// tqDebug("moving from %d to %d, num=%d", pos, pos+1, (oldSize-pos-1) );
- r[pos+1] = r[pos] ? (RenderTableCell *)-1 : 0;
- row++;
- }
- }
- child = child->nextSibling();
- }
- columnPos.resize( numEffCols()+1 );
- setNeedsLayoutAndMinMaxRecalc();
-}
-
-void RenderTable::appendColumn( int span )
-{
- // easy case.
- int pos = columns.size();
-// tqDebug("appendColumn( %d ), size=%d", span, pos );
- int newSize = pos + 1;
- columns.resize( newSize );
- columns[pos].span = span;
- //tqDebug("appending column at %d, span %d", pos, span );
-
- // change width of all rows.
- RenderObject *child = firstChild();
- while ( child ) {
- if ( child->isTableSection() ) {
- RenderTableSection *section = static_cast<RenderTableSection *>(child);
- int size = section->grid.size();
- int row = 0;
- while ( row < size ) {
- section->grid[row].row->resize( newSize );
- section->cellAt( row, pos ) = 0;
- row++;
- }
-
- }
- child = child->nextSibling();
- }
- columnPos.resize( numEffCols()+1 );
- setNeedsLayoutAndMinMaxRecalc();
-}
-
-RenderTableCol *RenderTable::colElement( int col ) {
- if ( !has_col_elems )
- return 0;
- RenderObject *child = firstChild();
- int cCol = 0;
- while ( child ) {
- if ( child->isTableCol() ) {
- RenderTableCol *colElem = static_cast<RenderTableCol *>(child);
- int span = colElem->span();
- if ( !colElem->firstChild() ) {
- cCol += span;
- if ( cCol > col )
- return colElem;
- }
-
- RenderObject *next = child->firstChild();
- if ( !next )
- next = child->nextSibling();
- if ( !next && child->parent()->isTableCol() )
- next = child->parent()->nextSibling();
- child = next;
- } else if (child == tCaption) {
- child = child->nextSibling();
- } else
- break;
- }
- return 0;
-}
-
-void RenderTable::recalcSections()
-{
- tCaption = 0;
- head = foot = firstBody = 0;
- has_col_elems = false;
-
- RenderObject *child = firstChild();
- // We need to get valid pointers to caption, head, foot and firstbody again
- while ( child ) {
- switch(child->style()->display()) {
- case TABLE_CAPTION:
- if ( !tCaption && child->isRenderBlock() ) {
- tCaption = static_cast<RenderBlock*>(child);
- tCaption->setNeedsLayout(true);
- }
- break;
- case TABLE_COLUMN:
- case TABLE_COLUMN_GROUP:
- has_col_elems = true;
- break;
- case TABLE_HEADER_GROUP:
- if (child->isTableSection()) {
- RenderTableSection *section = static_cast<RenderTableSection *>(child);
- if (!head)
- head = section;
- else if (!firstBody)
- firstBody = section;
- if (section->needCellRecalc)
- section->recalcCells();
- }
- break;
- case TABLE_FOOTER_GROUP:
- if (child->isTableSection()) {
- RenderTableSection *section = static_cast<RenderTableSection *>(child);
- if (!foot)
- foot = section;
- else if (!firstBody)
- firstBody = section;
- if (section->needCellRecalc)
- section->recalcCells();
- }
- break;
- case TABLE_ROW_GROUP:
- if (child->isTableSection()) {
- RenderTableSection *section = static_cast<RenderTableSection *>(child);
- if (!firstBody)
- firstBody = section;
- if (section->needCellRecalc)
- section->recalcCells();
- }
- break;
- default:
- break;
- }
- child = child->nextSibling();
- }
- needSectionRecalc = false;
- setNeedsLayout(true);
-}
-
-RenderObject* RenderTable::removeChildNode(RenderObject* child)
-{
- setNeedSectionRecalc();
- return RenderContainer::removeChildNode( child );
-}
-
-int RenderTable::borderLeft() const
-{
- if (collapseBorders()) {
- // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
- // but I'm working to get this changed. For now, follow the spec.
- return 0;
- }
- return RenderBlock::borderLeft();
-}
-
-int RenderTable::borderRight() const
-{
- if (collapseBorders()) {
- // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
- // but I'm working to get this changed. For now, follow the spec.
- return 0;
- }
- return RenderBlock::borderRight();
-}
-
-int RenderTable::borderTop() const
-{
- if (collapseBorders()) {
- // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
- // but I'm working to get this changed. For now, follow the spec.
- return 0;
- }
- return RenderBlock::borderTop();
-}
-
-int RenderTable::borderBottom() const
-{
- if (collapseBorders()) {
- // FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
- // but I'm working to get this changed. For now, follow the spec.
- return 0;
- }
- return RenderBlock::borderBottom();
-}
-
-RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, bool skipEmptySections) const
-{
- if (section == head)
- return 0;
- RenderObject *prevSection = (section == foot ? lastChild() : const_cast<RenderTableSection *>(section))->previousSibling();
- while (prevSection) {
- if (prevSection->isTableSection() && prevSection != head && prevSection != foot && (!skipEmptySections || static_cast<RenderTableSection*>(prevSection)->numRows()))
- break;
- prevSection = prevSection->previousSibling();
- }
- if (!prevSection && head && (!skipEmptySections || head->numRows()))
- prevSection = head;
- return static_cast<RenderTableSection*>(prevSection);
-}
-
-RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, bool skipEmptySections) const
-{
- if (section == foot)
- return 0;
- RenderObject *nextSection = (section == head ? firstChild() : const_cast<RenderTableSection *>(section))->nextSibling();
- while (nextSection) {
- if (nextSection->isTableSection() && nextSection != head && nextSection != foot && (!skipEmptySections || static_cast<RenderTableSection*>(nextSection)->numRows()))
- break;
- nextSection = nextSection->nextSibling();
- }
- if (!nextSection && foot && (!skipEmptySections || foot->numRows()))
- nextSection = foot;
- return static_cast<RenderTableSection*>(nextSection);
-}
-
-RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
-{
- // Find the section and row to look in
- int r = cell->row();
- RenderTableSection* section = 0;
- int rAbove = 0;
- if (r > 0) {
- // cell is not in the first row, so use the above row in its own section
- section = cell->section();
- rAbove = r-1;
- } else {
- section = sectionAbove(cell->section(), true);
- if (section)
- rAbove = section->numRows() - 1;
- }
-
- // Look up the cell in the section's grid, which requires effective col index
- if (section) {
- int effCol = colToEffCol(cell->col());
- RenderTableCell* aboveCell;
- // If we hit a span back up to a real cell.
- do {
- aboveCell = section->cellAt(rAbove, effCol);
- effCol--;
- } while (aboveCell == (RenderTableCell *)-1 && effCol >=0);
- return (aboveCell == (RenderTableCell *)-1) ? 0 : aboveCell;
- } else {
- return 0;
- }
-}
-
-RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
-{
- // Find the section and row to look in
- int r = cell->row() + cell->rowSpan() - 1;
- RenderTableSection* section = 0;
- int rBelow = 0;
- if (r < cell->section()->numRows()-1) {
- // The cell is not in the last row, so use the next row in the section.
- section = cell->section();
- rBelow= r+1;
- } else {
- section = sectionBelow(cell->section(), true);
- if (section)
- rBelow = 0;
- }
-
- // Look up the cell in the section's grid, which requires effective col index
- if (section) {
- int effCol = colToEffCol(cell->col());
- RenderTableCell* belowCell;
- // If we hit a colspan back up to a real cell.
- do {
- belowCell = section->cellAt(rBelow, effCol);
- effCol--;
- } while (belowCell == (RenderTableCell *)-1 && effCol >=0);
- return (belowCell == (RenderTableCell *)-1) ? 0 : belowCell;
- } else {
- return 0;
- }
-}
-
-RenderTableCell* RenderTable::cellLeft(const RenderTableCell* cell) const
-{
- RenderTableSection* section = cell->section();
- int effCol = colToEffCol(cell->col());
- if (effCol == 0)
- return 0;
-
- // If we hit a colspan back up to a real cell.
- RenderTableCell* prevCell;
- do {
- prevCell = section->cellAt(cell->row(), effCol-1);
- effCol--;
- } while (prevCell == (RenderTableCell *)-1 && effCol >=0);
- return (prevCell == (RenderTableCell *)-1) ? 0 : prevCell;
-}
-
-RenderTableCell* RenderTable::cellRight(const RenderTableCell* cell) const
-{
- int effCol = colToEffCol(cell->col()+cell->colSpan());
- if (effCol >= numEffCols())
- return 0;
- RenderTableCell* result = cell->section()->cellAt(cell->row(), effCol);
- return (result == (RenderTableCell*)-1) ? 0 : result;
-}
-
-#ifdef ENABLE_DUMP
-void RenderTable::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderBlock::dump(stream, ind);
-
- if (tCaption)
- stream << " tCaption";
- if (head)
- stream << " head";
- if (foot)
- stream << " foot";
-
- stream << " [cspans:";
- for ( unsigned int i = 0; i < columns.size(); i++ )
- stream << " " << columns[i].span;
- stream << "]";
-}
-
-#endif
-
-FindSelectionResult RenderTable::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state )
-{
- int off = offset;
- DOM::NodeImpl* nod = node;
-
- FindSelectionResult pos;
- TableSectionIterator it(this);
- for (; *it; ++it) {
- pos = (*it)->checkSelectionPoint(_x, _y, _tx + m_x, _ty + m_y, nod, off, state);
- switch(pos) {
- case SelectionPointBeforeInLine:
- case SelectionPointInside:
- //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " returning SelectionPointInside offset=" << offset << endl;
- node = nod;
- offset = off;
- return SelectionPointInside;
- case SelectionPointBefore:
- //x,y is before this element -> stop here
- if ( state.m_lastNode ) {
- node = state.m_lastNode;
- offset = state.m_lastOffset;
- //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " before this child "
- // << node << "-> returning SelectionPointInside, offset=" << offset << endl;
- return SelectionPointInside;
- } else {
- node = nod;
- offset = off;
- //kdDebug(6030) << "RenderTable::checkSelectionPoint " << this << " before us -> returning SelectionPointBefore " << node << "/" << offset << endl;
- return SelectionPointBefore;
- }
- break;
- case SelectionPointAfter:
- if (state.m_afterInLine) break;
- // fall through
- case SelectionPointAfterInLine:
- if (pos == SelectionPointAfterInLine) state.m_afterInLine = true;
- //kdDebug(6030) << "RenderTable::checkSelectionPoint: selection after: " << nod << " offset: " << off << " afterInLine: " << state.m_afterInLine << endl;
- state.m_lastNode = nod;
- state.m_lastOffset = off;
- // No "return" here, obviously. We must keep looking into the children.
- break;
- }
- }
- // If we are after the last child, return lastNode/lastOffset
- // But lastNode can be 0L if there is no child, for instance.
- if ( state.m_lastNode )
- {
- node = state.m_lastNode;
- offset = state.m_lastOffset;
- }
- // Fallback
- return SelectionPointAfter;
-}
-
-// --------------------------------------------------------------------------
-
-RenderTableSection::RenderTableSection(DOM::NodeImpl* node)
- : RenderBox(node)
-{
- // init RenderObject attributes
- setInline(false); // our object is not Inline
- cCol = 0;
- cRow = -1;
- needCellRecalc = false;
-}
-
-RenderTableSection::~RenderTableSection()
-{
- clearGrid();
-}
-
-void RenderTableSection::detach()
-{
- // recalc cell info because RenderTable has unguarded pointers
- // stored that point to this RenderTableSection.
- if (table())
- table()->setNeedSectionRecalc();
-
- RenderBox::detach();
-}
-
-void RenderTableSection::setStyle(RenderStyle* _style)
-{
- // we don't allow changing this one
- if (style())
- _style->setDisplay(style()->display());
- else if (_style->display() != TABLE_FOOTER_GROUP && _style->display() != TABLE_HEADER_GROUP)
- _style->setDisplay(TABLE_ROW_GROUP);
-
- RenderBox::setStyle(_style);
-}
-
-void RenderTableSection::addChild(RenderObject *child, RenderObject *beforeChild)
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(TableSection)::addChild( " << child->renderName() << ", beforeChild=" <<
- (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
-#endif
- if ( !child->isTableRow() ) {
- // TBODY > FORM quirk (???)
- if (child->element() && child->element()->isHTMLElement() && child->element()->id() == ID_FORM &&
- static_cast<HTMLFormElementImpl*>(child->element())->isMalformed())
- {
- RenderContainer::addChild(child, beforeChild);
- return;
- }
-
- RenderObject* last = beforeChild;
- if (!last)
- last = lastChild();
- if (last && last->isAnonymous()) {
- last->addChild(child);
- return;
- }
-
- // If beforeChild is inside an anonymous cell/row, insert into the cell or into
- // the anonymous row containing it, if there is one.
- RenderObject* lastBox = last;
- while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
- lastBox = lastBox->parent();
- if (lastBox && lastBox->isAnonymous()) {
- lastBox->addChild(child, beforeChild);
- return;
- }
-
- RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table */);
- RenderStyle* newStyle = new RenderStyle();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(TABLE_ROW);
- row->setStyle(newStyle);
- addChild(row, beforeChild);
- row->addChild(child);
- return;
- }
-
- if (beforeChild)
- setNeedCellRecalc();
-
- cRow++;
- cCol = 0;
-
- ensureRows( cRow+1 );
- KHTMLAssert( child->isTableRow() );
- grid[cRow].rowRenderer = static_cast<RenderTableRow*>(child);
-
- if (!beforeChild) {
- grid[cRow].height = child->style()->height();
- if ( grid[cRow].height.isRelative() )
- grid[cRow].height = Length();
- }
-
-
- RenderContainer::addChild(child,beforeChild);
-}
-
-void RenderTableSection::ensureRows( int numRows )
-{
- int nRows = grid.size();
- int nCols = table()->numEffCols();
- if ( numRows > nRows ) {
- grid.resize( numRows );
- for ( int r = nRows; r < numRows; r++ ) {
- grid[r].row = new Row( nCols );
- grid[r].row->fill( 0 );
- grid[r].rowRenderer = 0;
- grid[r].baseLine = 0;
- grid[r].height = Length();
- }
- }
-
-}
-
-void RenderTableSection::addCell( RenderTableCell *cell, RenderTableRow *row )
-{
- int rSpan = cell->rowSpan();
- int cSpan = cell->colSpan();
- TQMemArray<RenderTable::ColumnStruct> &columns = table()->columns;
- int nCols = columns.size();
-
- // ### mozilla still seems to do the old HTML way, even for strict DTD
- // (see the annotation on table cell layouting in the CSS specs and the testcase below:
- // <TABLE border>
- // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
- // <TR><TD colspan="2">5
- // </TABLE>
- while ( cCol < nCols && cellAt( cRow, cCol ) )
- cCol++;
-
-// tqDebug("adding cell at %d/%d span=(%d/%d)", cRow, cCol, rSpan, cSpan );
-
- if ( rSpan == 1 ) {
- // we ignore height settings on rowspan cells
- Length height = cell->style()->height();
- if ( height.value() > 0 || (height.isRelative() && height.value() >= 0) ) {
- Length cRowHeight = grid[cRow].height;
- switch( height.type() ) {
- case Percent:
- if ( !cRowHeight.isPercent() ||
- (cRowHeight.isPercent() && cRowHeight.value() < height.value() ) )
- grid[cRow].height = height;
- break;
- case Fixed:
- if ( cRowHeight.type() < Percent ||
- ( cRowHeight.isFixed() && cRowHeight.value() < height.value() ) )
- grid[cRow].height = height;
- break;
- case Relative:
-#if 0
- // we treat this as variable. This is correct according to HTML4, as it only specifies length for the height.
- if ( cRowHeight.type == Variable ||
- ( cRowHeight.type == Relative && cRowHeight.value < height.value ) )
- grid[cRow].height = height;
- break;
-#endif
- default:
- break;
- }
- }
- }
-
- // make sure we have enough rows
- ensureRows( cRow + rSpan );
-
- grid[cRow].rowRenderer = row;
-
- int col = cCol;
- // tell the cell where it is
- RenderTableCell *set = cell;
- while ( cSpan ) {
- int currentSpan;
- if ( cCol >= nCols ) {
- table()->appendColumn( cSpan );
- currentSpan = cSpan;
- } else {
- if ( cSpan < columns[cCol].span )
- table()->splitColumn( cCol, cSpan );
- currentSpan = columns[cCol].span;
- }
- int r = 0;
- while ( r < rSpan ) {
- if ( !cellAt( cRow + r, cCol ) ) {
-// tqDebug(" adding cell at %d, %d", cRow + r, cCol );
- cellAt( cRow + r, cCol ) = set;
- }
- r++;
- }
- cCol++;
- cSpan -= currentSpan;
- set = (RenderTableCell *)-1;
- }
- if ( cell ) {
- cell->setRow( cRow );
- cell->setCol( table()->effColToCol( col ) );
- }
-}
-
-
-
-void RenderTableSection::setCellWidths()
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(Table, this=0x" << this << ")::setCellWidths()" << endl;
-#endif
- TQMemArray<int> &columnPos = table()->columnPos;
-
- int rows = grid.size();
- for ( int i = 0; i < rows; i++ ) {
- Row &row = *grid[i].row;
- int cols = row.size();
- for ( int j = 0; j < cols; j++ ) {
- RenderTableCell *cell = row[j];
-// tqDebug("cell[%d,%d] = %p", i, j, cell );
- if ( !cell || cell == (RenderTableCell *)-1 )
- continue;
- int endCol = j;
- int cspan = cell->colSpan();
- while ( cspan && endCol < cols ) {
- cspan -= table()->columns[endCol].span;
- endCol++;
- }
- int w = columnPos[endCol] - columnPos[j] - table()->borderHSpacing();
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "setting width of cell " << cell << " " << cell->row() << "/" << cell->col() << " to " << w << " colspan=" << cell->colSpan() << " start=" << j << " end=" << endCol << endl;
-#endif
- int oldWidth = cell->width();
- if ( w != oldWidth ) {
- cell->setNeedsLayout(true);
- cell->setWidth( w );
- }
- }
- }
-}
-
-short RenderTableSection::width() const
-{
- return table()->width();
-}
-
-
-void RenderTableSection::calcRowHeight()
-{
- int indx;
- RenderTableCell *cell;
-
- int totalRows = grid.size();
- int vspacing = table()->borderVSpacing();
-
- rowPos.resize( totalRows + 1 );
- rowPos[0] = vspacing + borderTop();
-
- for ( int r = 0; r < totalRows; r++ ) {
- rowPos[r+1] = 0;
-
- int baseline=0;
- int bdesc = 0;
-// tqDebug("height of row %d is %d/%d", r, grid[r].height.value, grid[r].height.type );
- int ch = grid[r].height.minWidth( 0 );
- int pos = rowPos[r] + ch + (grid[r].rowRenderer ? vspacing : 0);
-
- if ( pos > rowPos[r+1] )
- rowPos[r+1] = pos;
-
- Row *row = grid[r].row;
- int totalCols = row->size();
- int totalRows = grid.size();
- bool pagedMode = canvas()->pagedMode();
-
- grid[r].needFlex = false;
-
- for ( int c = 0; c < totalCols; c++ ) {
- cell = cellAt(r, c);
- if ( !cell || cell == (RenderTableCell *)-1 )
- continue;
- if ( r < totalRows - 1 && cellAt(r+1, c) == cell )
- continue;
-
- if ( ( indx = r - cell->rowSpan() + 1 ) < 0 )
- indx = 0;
-
- if (cell->cellPercentageHeight() != -1) {
- cell->setCellPercentageHeight(-1);
- cell->setChildNeedsLayout(true, false);
- if (cell->hasFlexedAnonymous()) {
- for (RenderObject* o = cell->firstChild(); o ; o = o->nextSibling())
- if (o->isAnonymousBlock())
- o->setChildNeedsLayout(true, false);
- }
- if (pagedMode) cell->setNeedsLayout(true);
- cell->layoutIfNeeded();
- }
-
- ch = cell->style()->height().width(0);
- if ( cell->height() > ch)
- ch = cell->height();
-
- if (!cell->style()->height().isVariable())
- grid[r].needFlex = true;
-
- pos = rowPos[indx] + ch + (grid[r].rowRenderer ? vspacing : 0);
-
- if ( pos > rowPos[r+1] )
- rowPos[r+1] = pos;
-
- // find out the baseline
- EVerticalAlign va = cell->style()->verticalAlign();
- if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP
- || va == SUPER || va == SUB)
- {
- int b=cell->baselinePosition();
- if (b > cell->borderTop() + cell->paddingTop()) {
- if (b>baseline)
- baseline=b;
-
- int td = rowPos[ indx ] + ch - b;
- if (td>bdesc)
- bdesc = td;
- }
- }
- }
-
- //do we have baseline aligned elements?
- if (baseline) {
- // increase rowheight if baseline requires
- int bRowPos = baseline + bdesc + (grid[r].rowRenderer ? vspacing : 0);
- if (rowPos[r+1]<bRowPos)
- rowPos[r+1]=bRowPos;
-
- grid[r].baseLine = baseline;
- }
-
- if ( rowPos[r+1] < rowPos[r] )
- rowPos[r+1] = rowPos[r];
-// tqDebug("rowpos(%d)=%d", r, rowPos[r] );
- }
-}
-
-int RenderTableSection::layoutRows( int toAdd )
-{
- int rHeight;
- int rindx;
- int totalRows = grid.size();
- int hspacing = table()->borderHSpacing();
- int vspacing = table()->borderVSpacing();
-
- // Set the width of our section now. The rows will also be this width.
- m_width = table()->contentWidth();
-
- if (markedForRepaint()) {
- repaintDuringLayout();
- setMarkedForRepaint(false);
- }
-
- if (toAdd && totalRows && (rowPos[totalRows] || !nextSibling())) {
-
- int totalHeight = rowPos[totalRows] + toAdd;
-// tqDebug("layoutRows: totalHeight = %d", totalHeight );
-
- int dh = toAdd;
- int totalPercent = 0;
- int numVariable = 0;
- for ( int r = 0; r < totalRows; r++ ) {
- if ( grid[r].height.isVariable() && !emptyRow(r))
- numVariable++;
- else if ( grid[r].height.isPercent() )
- totalPercent += grid[r].height.value();
- }
- if ( totalPercent ) {
-// tqDebug("distributing %d over percent rows totalPercent=%d", dh, totalPercent );
- // try to satisfy percent
- int add = 0;
- if ( totalPercent > 100 )
- totalPercent = 100;
- int rh = rowPos[1]-rowPos[0];
- for ( int r = 0; r < totalRows; r++ ) {
- if ( totalPercent > 0 && grid[r].height.isPercent() ) {
- int toAdd = kMin( dh, (totalHeight * grid[r].height.value() / 100)-rh );
- // If toAdd is negative, then we don't want to shrink the row (this bug
- // affected Outlook Web Access).
- toAdd = kMax(0, toAdd);
- add += toAdd;
- dh -= toAdd;
- totalPercent -= grid[r].height.value();
-// tqDebug( "adding %d to row %d", toAdd, r );
- }
- if ( r < totalRows-1 )
- rh = rowPos[r+2] - rowPos[r+1];
- rowPos[r+1] += add;
- }
- }
- if ( numVariable ) {
- // distribute over non-empty variable rows
-// tqDebug("distributing %d over variable rows numVariable=%d", dh, numVariable );
- int add = 0;
- int toAdd = dh/numVariable;
- for ( int r = 0; r < totalRows; r++ ) {
- if ( grid[r].height.isVariable() && !emptyRow(r)) {
- add += toAdd;
- }
- rowPos[r+1] += add;
- }
- dh -= add;
- }
- if (dh>0 && rowPos[totalRows]) {
- // if some left overs, distribute weighted.
- int tot=rowPos[totalRows];
- int add=0;
- int prev=rowPos[0];
- for ( int r = 0; r < totalRows; r++ ) {
- //weight with the original height
- add+=dh*(rowPos[r+1]-prev)/tot;
- prev=rowPos[r+1];
- rowPos[r+1]+=add;
- }
- dh -= add;
- }
- if (dh > totalRows) {
- // distribute to tables with all empty rows
- int add=0;
- int toAdd = dh/totalRows;
- for ( int r = 0; r < totalRows; r++ ) {
- add += toAdd;
- rowPos[r+1] += add;
- }
- dh -= add;
- }
- // Finally distribute round-off values
- if (dh > 0) {
- // There is not enough for every row
- int add=0;
- for ( int r = 0; r < totalRows; r++ ) {
- if (add < dh) add++;
- rowPos[r+1] += add;
- }
- dh -= add;
- }
- assert (dh == 0);
- }
-
- int leftOffset = borderLeft() + hspacing;
-
- int nEffCols = table()->numEffCols();
- for ( int r = 0; r < totalRows; r++ )
- {
- Row *row = grid[r].row;
- int totalCols = row->size();
-
-#ifdef APPLE_CHANGES
- // in WC, rows and cells share the same coordinate space, so that rows can have
- // dimensions in the layer system. This is of dubious value, and a heavy maintenance burden
- // (RenderObject's coordinates can't be used deterministically anymore) so we'll consider other options.
-
- // Set the row's x/y position and width/height.
- if (grid[r].rowRenderer) {
- grid[r].rowRenderer->setPos(0, rowPos[r]);
- grid[r].rowRenderer->setWidth(m_width);
- grid[r].rowRenderer->setHeight(rowPos[r+1] - rowPos[r] - vspacing);
- }
-#endif
-
- for ( int c = 0; c < nEffCols; c++ )
- {
- RenderTableCell *cell = cellAt(r, c);
- if (!cell || cell == (RenderTableCell *)-1 )
- continue;
- if ( r < totalRows - 1 && cell == cellAt(r+1, c) )
- continue;
-
- if ( ( rindx = r-cell->rowSpan()+1 ) < 0 )
- rindx = 0;
-
- rHeight = rowPos[r+1] - rowPos[rindx] - vspacing;
-
- // Force percent height children to lay themselves out again.
- // This will cause, e.g., textareas to grow to
- // fill the area. FIXME: <div>s and blocks still don't
- // work right. We'll need to have an efficient way of
- // invalidating all percent height objects in a render subtree.
- // For now, we just handle immediate children. -dwh
-
- bool flexAllChildren = grid[r].needFlex || (!table()->style()->height().isVariable() && rHeight != cell->height());
- cell->setHasFlexedAnonymous(false);
- if ( flexAllChildren && flexCellChildren(cell) ) {
- cell->setCellPercentageHeight(kMax(0,
- rHeight - cell->borderTop() - cell->paddingTop() -
- cell->borderBottom() - cell->paddingBottom()));
- cell->layoutIfNeeded();
-
- }
- {
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << "setting position " << r << "/" << c << ": "
- << table()->columnPos[c] /*+ padding */ << "/" << rowPos[rindx] << " height=" << rHeight<< endl;
-#endif
-
- EVerticalAlign va = cell->style()->verticalAlign();
- int te=0;
- switch (va)
- {
- case SUB:
- case SUPER:
- case TEXT_TOP:
- case TEXT_BOTTOM:
- case BASELINE:
- te = getBaseline(r) - cell->baselinePosition() ;
- break;
- case TOP:
- te = 0;
- break;
- case MIDDLE:
- te = (rHeight - cell->height())/2;
- break;
- case BOTTOM:
- te = rHeight - cell->height();
- break;
- default:
- break;
- }
- te = kMax( 0, te );
-#ifdef DEBUG_LAYOUT
- // kdDebug( 6040 ) << "CELL " << cell << " te=" << te << ", be=" << rHeight - cell->height() - te << ", rHeight=" << rHeight << ", valign=" << va << endl;
-#endif
- cell->setCellTopExtra( te );
- cell->setCellBottomExtra( rHeight - cell->height() - te);
- }
- if (style()->direction()==RTL) {
- cell->setPos(
- table()->columnPos[(int)totalCols] -
- table()->columnPos[table()->colToEffCol(cell->col()+cell->colSpan())] +
- leftOffset,
- rowPos[rindx] );
- } else {
- cell->setPos( table()->columnPos[c] + leftOffset, rowPos[rindx] );
- }
- }
- }
-
- m_height = rowPos[totalRows];
- return m_height;
-}
-
-bool RenderTableSection::flexCellChildren(RenderObject* p) const
-{
- if (!p)
- return false;
- RenderObject* o = p->firstChild();
- bool didFlex = false;
- while (o) {
- if (!o->isText() && o->style()->height().isPercent()) {
- if (o->isWidget()) {
- // cancel resizes from transitory relayouts
- static_cast<RenderWidget *>(o)->cancelPendingResize();
- }
- o->setNeedsLayout(true, false);
- p->setChildNeedsLayout(true, false);
- didFlex = true;
- } else if (o->isAnonymousBlock() && flexCellChildren( o )) {
- p->setChildNeedsLayout(true, false);
- if (p->isTableCell())
- static_cast<RenderTableCell*>(p)->setHasFlexedAnonymous();
- didFlex = true;
- }
- o = o->nextSibling();
- }
- return didFlex;
-}
-
-inline static RenderTableRow *firstTableRow(RenderObject *row)
-{
- while (row && !row->isTableRow())
- row = row->nextSibling();
- return static_cast<RenderTableRow *>(row);
-}
-
-inline static RenderTableRow *nextTableRow(RenderObject *row)
-{
- row = row ? row->nextSibling() : row;
- while (row && !row->isTableRow())
- row = row->nextSibling();
- return static_cast<RenderTableRow *>(row);
-}
-
-int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int bottom = RenderBox::lowestPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return bottom;
-
- for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
- for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
- if (cell->isTableCell()) {
- int bp = cell->yPos() + cell->lowestPosition(false);
- bottom = kMax(bottom, bp);
- }
- }
-
- return bottom;
-}
-
-int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int right = RenderBox::rightmostPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return right;
-
- for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
- for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
- if (cell->isTableCell()) {
- int rp = cell->xPos() + cell->rightmostPosition(false);
- right = kMax(right, rp);
- }
- }
-
- return right;
-}
-
-int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int left = RenderBox::leftmostPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return left;
-
- for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
- for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
- if (cell->isTableCell()) {
- int lp = cell->xPos() + cell->leftmostPosition(false);
- left = kMin(left, lp);
- }
- }
-
- return left;
-}
-
-int RenderTableSection::highestPosition(bool includeOverflowInterior, bool includeSelf) const
-{
- int top = RenderBox::highestPosition(includeOverflowInterior, includeSelf);
- if (!includeOverflowInterior && hasOverflowClip())
- return top;
-
- for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
- for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
- if (cell->isTableCell()) {
- int hp = cell->yPos() + cell->highestPosition(false);
- top = kMin(top, hp);
- }
- }
-
- return top;
-}
-
-// Search from first_row to last_row for the row containing y
-static unsigned int findRow(unsigned int first_row, unsigned int last_row,
- const TQMemArray<int> &rowPos, int y)
-{
- unsigned int under = first_row;
- unsigned int over = last_row;
- int offset = (over - under)/2;
- while (over-under > 1) {
- if (rowPos[under+offset] <= y)
- under = under+offset;
- else
- over = under+offset;
- offset = (over - under)/2;
- }
-
- assert(under == first_row || rowPos[under] <= y);
- assert(over == last_row || rowPos[over] > y);
-
- return under;
-}
-
-static void findRowCover(unsigned int &startrow, unsigned int &endrow,
- const TQMemArray<int> &rowPos,
- int min_y, int max_y)
-{
- assert(max_y >= min_y);
- unsigned int totalRows = endrow;
-
- unsigned int index = 0;
- // Initial binary search boost:
- if (totalRows >= 8) {
- int offset = (endrow - startrow)/2;
- while (endrow - startrow > 1) {
- index = startrow+offset;
- if (rowPos[index] <= min_y )
- // index is below both min_y and max_y
- startrow = index;
- else
- if (rowPos[index] > max_y)
- // index is above both min_y and max_y
- endrow = index;
- else
- // index is within the selection
- break;
- offset = (endrow - startrow)/2;
- }
- }
-
- // Binary search for startrow
- startrow = findRow(startrow, endrow, rowPos, min_y);
- // Binary search for endrow
- endrow = findRow(startrow, endrow, rowPos, max_y) + 1;
- if (endrow > totalRows) endrow = totalRows;
-}
-
-void RenderTableSection::paint( PaintInfo& pI, int tx, int ty )
-{
- unsigned int totalRows = grid.size();
- unsigned int totalCols = table()->columns.size();
-
- tx += m_x;
- ty += m_y;
-
- if (pI.phase == PaintActionOutline)
- paintOutline(pI.p, tx, ty, width(), height(), style());
-
- CollapsedBorderValue *cbs = table()->currentBorderStyle();
- int cbsw2 = cbs ? cbs->width()/2 : 0;
- int cbsw21 = cbs ? (cbs->width()+1)/2 : 0;
-
- int x = pI.r.x(), y = pI.r.y(), w = pI.r.width(), h = pI.r.height();
- // check which rows and cols are visible and only paint these
- int os = 2*maximalOutlineSize(pI.phase);
- unsigned int startrow = 0;
- unsigned int endrow = totalRows;
- findRowCover(startrow, endrow, rowPos, y - os - ty - kMax(cbsw21, os), y + h + os - ty + kMax(cbsw2, os));
-
- // A binary search is probably not worthwhile for coloumns
- unsigned int startcol = 0;
- unsigned int endcol = totalCols;
- if ( style()->direction() == LTR ) {
- for ( ; startcol < totalCols; startcol++ ) {
- if ( tx + table()->columnPos[startcol+1] + kMax(cbsw21, os) > x - os )
- break;
- }
- for ( ; endcol > 0; endcol-- ) {
- if ( tx + table()->columnPos[endcol-1] - kMax(cbsw2, os) < x + w + os )
- break;
- }
- }
- if ( startcol < endcol ) {
- // draw the cells
- for ( unsigned int r = startrow; r < endrow; r++ ) {
- // paint the row
- if (grid[r].rowRenderer) {
- int height = rowPos[r+1] - rowPos[r] - table()->borderVSpacing();
- grid[r].rowRenderer->paintRow(pI, tx, ty + rowPos[r], width(), height);
- }
-
- unsigned int c = startcol;
- Row *row = grid[r].row;
- Row *nextrow = (r < endrow - 1) ? grid[r+1].row : 0;
- // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
- while ( c && (*row)[c] == (RenderTableCell *)-1 )
- c--;
- for ( ; c < endcol; c++ ) {
- RenderTableCell *cell = (*row)[c];
- if ( !cell || cell == (RenderTableCell *)-1 || nextrow && (*nextrow)[c] == cell )
- continue;
-#ifdef TABLE_PRINT
- kdDebug( 6040 ) << "painting cell " << r << "/" << c << endl;
-#endif
- if (pI.phase == PaintActionElementBackground || pI.phase == PaintActionChildBackground) {
- // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of
- // the column group, column, row group, row, and then the cell.
- RenderObject* col = table()->colElement(c);
- RenderObject* colGroup = 0;
- if (col) {
- RenderStyle *style = col->parent()->style();
- if (style->display() == TABLE_COLUMN_GROUP)
- colGroup = col->parent();
- }
- RenderObject* row = cell->parent();
-
- // ###
- // Column groups and columns first.
- // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
- // the stack, since we have already opened a transparency layer (potentially) for the table row group.
- // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
- // cell.
- cell->paintBackgroundsBehindCell(pI, tx, ty, colGroup);
- cell->paintBackgroundsBehindCell(pI, tx, ty, col);
-
- // Paint the row group next.
- cell->paintBackgroundsBehindCell(pI, tx, ty, this);
-
- // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
- // painting the row background for the cell.
- if (!row->layer())
- cell->paintBackgroundsBehindCell(pI, tx, ty, row);
- }
-
- if ((!cell->layer() && !cell->parent()->layer()) || pI.phase == PaintActionCollapsedTableBorders)
- cell->paint(pI, tx, ty);
- }
- }
- }
-}
-
-void RenderTableSection::recalcCells()
-{
- cCol = 0;
- cRow = -1;
- clearGrid();
- grid.resize( 0 );
-
- for (RenderObject *row = firstChild(); row; row = row->nextSibling()) {
- if (row->isTableRow()) {
- cRow++;
- cCol = 0;
- ensureRows( cRow+1 );
- grid[cRow].rowRenderer = static_cast<RenderTableRow*>(row);
-
- for (RenderObject *cell = row->firstChild(); cell; cell = cell->nextSibling())
- if (cell->isTableCell())
- addCell( static_cast<RenderTableCell *>(cell), static_cast<RenderTableRow *>(row) );
- }
- }
- needCellRecalc = false;
- setNeedsLayout(true);
-}
-
-void RenderTableSection::clearGrid()
-{
- int rows = grid.size();
- while ( rows-- ) {
- delete grid[rows].row;
- }
-}
-
-bool RenderTableSection::emptyRow(int rowNum) {
- Row &r = *grid[rowNum].row;
- const int s = r.size();
- RenderTableCell *cell;
- for(int i=0; i<s; i++) {
- cell = r[i];
- if (!cell || cell==(RenderTableCell*)-1)
- continue;
- return false;
- }
- return true;
-}
-
-RenderObject* RenderTableSection::removeChildNode(RenderObject* child)
-{
- setNeedCellRecalc();
- return RenderContainer::removeChildNode( child );
-}
-
-bool RenderTableSection::canClear(RenderObject */*child*/, PageBreakLevel level)
-{
- // We cannot clear rows yet.
- return parent()->canClear(this, level);
-}
-
-void RenderTableSection::addSpaceAt(int pos, int dy)
-{
- const int nEffCols = table()->numEffCols();
- const int totalRows = numRows();
- for ( int r = 0; r < totalRows; r++ ) {
- if (rowPos[r] >= pos) {
- rowPos[r] += dy;
- int rindx;
- for ( int c = 0; c < nEffCols; c++ )
- {
- RenderTableCell *cell = cellAt(r, c);
- if (!cell || cell == (RenderTableCell *)-1 )
- continue;
- if ( r > 0 && cell == cellAt(r-1, c) )
- continue;
-
- if ( ( rindx = r-cell->rowSpan()+1 ) < 0 )
- rindx = 0;
-
- cell->setPos(cell->xPos(), rowPos[r]);
- }
- }
- }
- if (rowPos[totalRows] >= pos)
- rowPos[totalRows] += dy;
- m_height = rowPos[totalRows];
-
- setContainsPageBreak(true);
-}
-
-
-#ifdef ENABLE_DUMP
-void RenderTableSection::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderContainer::dump(stream,ind);
-
- stream << " grid=(" << grid.size() << "," << table()->numEffCols() << ")";
- for ( unsigned int r = 0; r < grid.size(); r++ ) {
- for ( int c = 0; c < table()->numEffCols(); c++ ) {
- if ( cellAt( r, c ) && cellAt( r, c ) != (RenderTableCell *)-1 )
- stream << " (" << cellAt( r, c )->row() << "," << cellAt( r, c )->col() << ","
- << cellAt(r, c)->rowSpan() << "," << cellAt(r, c)->colSpan() << ") ";
- else
- stream << " null cell";
- }
- }
-}
-#endif
-
-static RenderTableCell *seekCell(RenderTableSection *section, int row, int col)
-{
- if (row < 0 || col < 0 || row >= section->numRows()) return 0;
- // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
- while ( col && section->cellAt( row, col ) == (RenderTableCell *)-1 )
- col--;
-
- return section->cellAt(row, col);
-}
-
-/** Looks for the first element suitable for text selection, beginning from
- * the last.
- * @param base search is restricted within this node. This node must have
- * a renderer.
- * @return the element or @p base if no suitable element found.
- */
-static NodeImpl *findLastSelectableNode(NodeImpl *base)
-{
- NodeImpl *last = base;
- // Look for last text/cdata node that has a renderer,
- // or last childless replaced element
- while ( last && !(last->renderer()
- && ((last->nodeType() == Node::TEXT_NODE || last->nodeType() == Node::CDATA_SECTION_NODE)
- || (last->renderer()->isReplaced() && !last->renderer()->lastChild()))))
- {
- NodeImpl *next = last->lastChild();
- if ( !next ) next = last->previousSibling();
- while ( last && last != base && !next )
- {
- last = last->parentNode();
- if ( last && last != base )
- next = last->previousSibling();
- }
- last = next;
- }
-
- return last ? last : base;
-}
-
-FindSelectionResult RenderTableSection::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state )
-{
- // Table sections need extra treatment for selections. The rows are scanned
- // from top to bottom, and within each row, only the cell that matches
- // the given position best is descended into.
-
- unsigned int totalRows = grid.size();
- unsigned int totalCols = table()->columns.size();
-
-// absolutePosition(_tx, _ty, false);
-
- _tx += m_x;
- _ty += m_y;
-
-// bool save_last = false; // true to save last investigated cell
-
- if (needsLayout() || _y < _ty) return SelectionPointBefore;
-// else if (_y >= _ty + height()) save_last = true;
-
- // Find the row containing the pointer
- int row_idx = findRow(0, totalRows, rowPos, _y - _ty);
-
- int col_idx;
- if ( style()->direction() == LTR ) {
- for ( col_idx = (int)totalCols - 1; col_idx >= 0; col_idx-- ) {
- if ( _tx + table()->columnPos[col_idx] < _x )
- break;
- }
- if (col_idx < 0) col_idx = 0;
- } else {
- for ( col_idx = 0; col_idx < (int)totalCols; col_idx++ ) {
- if ( _tx + table()->columnPos[col_idx] > _x )
- break;
- }
- if (col_idx >= (int)totalCols) col_idx = (int)totalCols + 1;
- }
-
- FindSelectionResult pos = SelectionPointBefore;
-
- RenderTableCell *cell = seekCell(this, row_idx, col_idx);
- // ### dunno why cell can be 0, maybe due to weird spans? (LS)
- if (cell) {
- SelPointState localState;
- pos = cell->checkSelectionPoint(_x, _y, _tx, _ty, node, offset, localState);
- }
-
- if (pos != SelectionPointBefore) return pos;
-
- // store last column of last line
- row_idx--;
- col_idx = totalCols - 1;
- cell = seekCell(this, row_idx, col_idx);
-
- // end of section? take previous section
- RenderTableSection *sec = this;
- if (!cell) {
- sec = *--TableSectionIterator(sec);
- if (!sec) return pos;
-
- cell = seekCell(sec, sec->grid.size() - 1, col_idx);
- if (!cell) return pos;
- }
-
- // take last child of previous cell, and store this one as last node
- NodeImpl *element = cell->element();
- if (!element) return SelectionPointBefore;
-
- element = findLastSelectableNode(element);
-
- state.m_lastNode = element;
- state.m_lastOffset = element->maxOffset();
- return SelectionPointBefore;
-}
-
-// Hit Testing
-bool RenderTableSection::nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside)
-{
- // Table sections cannot ever be hit tested. Effectively they do not exist.
- // Just forward to our children always.
- tx += m_x;
- ty += m_y;
-
- for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- // FIXME: We have to skip over inline flows, since they can show up inside table rows
- // at the moment (a demoted inline <form> for example). If we ever implement a
- // table-specific hit-test method (which we should do for performance reasons anyway),
- // then we can remove this check.
- if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(info, x, y, tx, ty, action, inside)) {
- return true;
- }
- }
-
- return false;
-}
-
-
-// -------------------------------------------------------------------------
-
-RenderTableRow::RenderTableRow(DOM::NodeImpl* node)
- : RenderContainer(node)
-{
- // init RenderObject attributes
- setInline(false); // our object is not Inline
-}
-
-RenderObject* RenderTableRow::removeChildNode(RenderObject* child)
-{
- RenderTableSection *s = section();
- if (s)
- s->setNeedCellRecalc();
-
- return RenderContainer::removeChildNode( child );
-}
-
-void RenderTableRow::detach()
-{
- RenderTableSection *s = section();
- if (s)
- s->setNeedCellRecalc();
-
- RenderContainer::detach();
-}
-
-void RenderTableRow::setStyle(RenderStyle* newStyle)
-{
- if (section() && style() && style()->height() != newStyle->height())
- section()->setNeedCellRecalc();
-
- newStyle->setDisplay(TABLE_ROW);
- RenderContainer::setStyle(newStyle);
-}
-
-void RenderTableRow::addChild(RenderObject *child, RenderObject *beforeChild)
-{
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(TableRow)::addChild( " << child->renderName() << " )" << ", " <<
- (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
-#endif
-
- if ( !child->isTableCell() ) {
- // TR > FORM quirk (???)
- if (child->element() && child->element()->isHTMLElement() && child->element()->id() == ID_FORM &&
- static_cast<HTMLFormElementImpl*>(child->element())->isMalformed())
- {
- RenderContainer::addChild(child, beforeChild);
- return;
- }
-
- RenderObject* last = beforeChild;
- if (!last)
- last = lastChild();
- if (last && last->isAnonymous() && last->isTableCell()) {
- last->addChild(child);
- return;
- }
-
- // If beforeChild is inside an anonymous cell, insert into the cell.
- if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous()) {
- last->parent()->addChild(child, beforeChild);
- return;
- }
-
- RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
- RenderStyle* newStyle = new RenderStyle();
- newStyle->inheritFrom(style());
- newStyle->setDisplay(TABLE_CELL);
- cell->setStyle(newStyle);
- addChild(cell, beforeChild);
- cell->addChild(child);
- return;
- }
-
- RenderTableCell* cell = static_cast<RenderTableCell*>(child);
-
- section()->addCell( cell, this );
-
- RenderContainer::addChild(cell,beforeChild);
-
- if ( beforeChild || nextSibling() )
- section()->setNeedCellRecalc();
-}
-
-void RenderTableRow::layout()
-{
- KHTMLAssert( needsLayout() );
- KHTMLAssert( minMaxKnown() );
-
- RenderObject *child = firstChild();
- const bool pagedMode = canvas()->pagedMode();
- while( child ) {
- if ( child->isTableCell() ) {
- RenderTableCell *cell = static_cast<RenderTableCell *>(child);
- if (pagedMode) {
- cell->setNeedsLayout(true);
- int oldHeight = child->height();
- cell->layout();
- if (oldHeight > 0 && child->containsPageBreak() && child->height() != oldHeight)
- section()->addSpaceAt(child->yPos()+1, child->height() - oldHeight);
- } else
- if ( child->needsLayout() ) {
- if (markedForRepaint())
- cell->setMarkedForRepaint( true );
- cell->calcVerticalMargins();
- cell->layout();
- cell->setCellTopExtra(0);
- cell->setCellBottomExtra(0);
- if (child->containsPageBreak()) setContainsPageBreak(true);
- }
- }
- child = child->nextSibling();
- }
- setMarkedForRepaint(false);
- setNeedsLayout(false);
-}
-
-int RenderTableRow::offsetLeft() const
-{
- RenderObject *child = firstChild();
- while (child && !child->isTableCell())
- child = child->nextSibling();
-
- if (!child)
- return 0;
-
- return child->offsetLeft();
-}
-
-int RenderTableRow::offsetTop() const
-{
- RenderObject *child = firstChild();
- while (child && !child->isTableCell())
- child = child->nextSibling();
-
- if (!child)
- return 0;
-
- return child->offsetTop() -
- static_cast<RenderTableCell*>(child)->cellTopExtra();
-}
-
-int RenderTableRow::offsetHeight() const
-{
- RenderObject *child = firstChild();
- while (child && !child->isTableCell())
- child = child->nextSibling();
-
- if (!child)
- return 0;
-
- return child->offsetHeight() +
- static_cast<RenderTableCell*>(child)->cellTopExtra() +
- static_cast<RenderTableCell*>(child)->cellBottomExtra();
-}
-
-short RenderTableRow::offsetWidth() const
-{
- RenderObject *fc = firstChild();
- RenderObject *lc = lastChild();
- while (fc && !fc->isTableCell())
- fc = fc->nextSibling();
- while (lc && !lc->isTableCell())
- lc = lc->previousSibling();
- if (!lc || !fc)
- return 0;
-
- return lc->xPos()+lc->width()-fc->xPos();
-}
-
-void RenderTableRow::paintRow( PaintInfo& pI, int tx, int ty, int w, int h )
-{
- if (pI.phase == PaintActionOutline)
- paintOutline(pI.p, tx, ty, w, h, style());
-}
-
-void RenderTableRow::paint(PaintInfo& i, int tx, int ty)
-{
- KHTMLAssert(layer());
- if (!layer())
- return;
-
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableCell()) {
- // Paint the row background behind the cell.
- if (i.phase == PaintActionElementBackground || i.phase == PaintActionChildBackground) {
- RenderTableCell* cell = static_cast<RenderTableCell*>(child);
- cell->paintBackgroundsBehindCell(i, tx, ty, this);
- }
- if (!child->layer())
- child->paint(i, tx, ty);
- }
- }
-}
-
-// Hit Testing
-bool RenderTableRow::nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside)
-{
- // Table rows cannot ever be hit tested. Effectively they do not exist.
- // Just forward to our children always.
- for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- // FIXME: We have to skip over inline flows, since they can show up inside table rows
- // at the moment (a demoted inline <form> for example). If we ever implement a
- // table-specific hit-test method (which we should do for performance reasons anyway),
- // then we can remove this check.
- if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(info, x, y, tx, ty, action, inside)) {
- return true;
- }
- }
-
- return false;
-}
-
-// -------------------------------------------------------------------------
-
-RenderTableCell::RenderTableCell(DOM::NodeImpl* _node)
- : RenderBlock(_node)
-{
- _col = -1;
- _row = -1;
- updateFromElement();
- setShouldPaintBackgroundOrBorder(true);
- _topExtra = 0;
- _bottomExtra = 0;
- m_percentageHeight = -1;
- m_hasFlexedAnonymous = false;
- m_widthChanged = false;
-}
-
-void RenderTableCell::detach()
-{
- if (parent() && section())
- section()->setNeedCellRecalc();
-
- RenderBlock::detach();
-}
-
-void RenderTableCell::updateFromElement()
-{
- DOM::NodeImpl *node = element();
- if ( node && (node->id() == ID_TD || node->id() == ID_TH) ) {
- DOM::HTMLTableCellElementImpl *tc = static_cast<DOM::HTMLTableCellElementImpl *>(node);
- cSpan = tc->colSpan();
- rSpan = tc->rowSpan();
- } else {
- cSpan = rSpan = 1;
- }
-}
-
-Length RenderTableCell::styleOrColWidth()
-{
- Length w = style()->width();
- if (colSpan() > 1 || !w.isVariable())
- return w;
- RenderTableCol* col = table()->colElement(_col);
- if (col)
- w = col->style()->width();
- return w;
-}
-
-void RenderTableCell::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(TableCell)::calcMinMaxWidth() known=" << minMaxKnown() << endl;
-#endif
-
- if (section()->needCellRecalc)
- section()->recalcCells();
-
- RenderBlock::calcMinMaxWidth();
- if (element() && style()->whiteSpace() == NORMAL) {
- // See if nowrap was set.
- Length w = styleOrColWidth();
- DOMString nowrap = static_cast<ElementImpl*>(element())->getAttribute(ATTR_NOWRAP);
- if (!nowrap.isNull() && w.isFixed() &&
- m_minWidth < w.value() )
- // Nowrap is set, but we didn't actually use it because of the
- // fixed width set on the cell. Even so, it is a WinIE/Moz trait
- // to make the minwidth of the cell into the fixed width. They do this
- // even in strict mode, so do not make this a quirk. Affected the top
- // of hiptop.com.
- m_minWidth = w.value();
- }
-
- setMinMaxKnown();
-}
-
-void RenderTableCell::calcWidth()
-{
-}
-
-void RenderTableCell::setWidth( int width )
-{
- if ( width != m_width ) {
- m_width = width;
- m_widthChanged = true;
- }
-}
-
-void RenderTableCell::layout()
-{
- layoutBlock( m_widthChanged );
- m_widthChanged = false;
-}
-
-void RenderTableCell::close()
-{
- RenderBlock::close();
-
-#ifdef DEBUG_LAYOUT
- kdDebug( 6040 ) << renderName() << "(RenderTableCell)::close() total height =" << m_height << endl;
-#endif
-}
-
-bool RenderTableCell::requiresLayer() const {
- // table-cell display is never positioned (css 2.1-9.7), so the only time a layer is needed
- // is when overflow != visible (or when there is opacity when we support it)
- return /* style()->opacity() < 1.0f || */ hasOverflowClip() || isRelPositioned();
-}
-
-void RenderTableCell::repaintRectangle(int x, int y, int w, int h, Priority p, bool f)
-{
- RenderBlock::repaintRectangle(x, y, w, h + _topExtra + _bottomExtra, p, f);
-}
-
-bool RenderTableCell::absolutePosition(int &xPos, int &yPos, bool f) const
-{
- bool result = RenderBlock::absolutePosition(xPos, yPos, f);
- xPos -= parent()->xPos(); // Rows are in the same coordinate space, so don't add their offset in.
- yPos -= parent()->yPos();
- return result;
-}
-
-int RenderTableCell::pageTopAfter(int y) const
-{
- return section()->pageTopAfter(y+m_y + _topExtra) - (m_y + _topExtra);
-}
-
-short RenderTableCell::baselinePosition( bool ) const
-{
- RenderObject* o = firstChild();
- int offset = paddingTop() + borderTop();
- if (!o) return offset + contentHeight();
- while (o->firstChild()) {
- if (!o->isInline())
- offset += o->paddingTop() + o->borderTop();
- o = o->firstChild();
- }
-
- if (!o->isInline())
- return paddingTop() + borderTop() + contentHeight();
-
- offset += o->baselinePosition( true );
- return offset;
-}
-
-
-void RenderTableCell::setStyle( RenderStyle *newStyle )
-{
- if (parent() && section() && style() && style()->height() != newStyle->height())
- section()->setNeedCellRecalc();
-
- newStyle->setDisplay(TABLE_CELL);
- RenderBlock::setStyle( newStyle );
- setShouldPaintBackgroundOrBorder(true);
-
- if (newStyle->whiteSpace() == KHTML_NOWRAP) {
- // Figure out if we are really nowrapping or if we should just
- // use normal instead. If the width of the cell is fixed, then
- // we don't actually use NOWRAP.
- if (newStyle->width().isFixed())
- newStyle->setWhiteSpace(NORMAL);
- else
- newStyle->setWhiteSpace(NOWRAP);
- }
-}
-
-bool RenderTableCell::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside)
-{
- int tx = _tx + m_x;
- int ty = _ty + m_y;
-
- // also include the top and bottom extra space
- inside |= style()->visibility() != HIDDEN
- && (_y >= ty) && (_y < ty + height() + _topExtra + _bottomExtra)
- && (_x >= tx) && (_x < tx + width());
-
- return RenderBlock::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
-}
-
-// The following rules apply for resolving conflicts and figuring out which border
-// to use.
-// (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting
-// borders. Any border with this value suppresses all borders at this location.
-// (2) Borders with a style of 'none' have the lowest priority. Only if the border properties of all
-// the elements meeting at this edge are 'none' will the border be omitted (but note that 'none' is
-// the default value for the border style.)
-// (3) If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders
-// are discarded in favor of wider ones. If several have the same 'border-width' then styles are preferred
-// in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.
-// (4) If border styles differ only in color, then a style set on a cell wins over one on a row,
-// which wins over a row group, column, column group and, lastly, table. It is undefined which color
-// is used when two elements of the same type disagree.
-static CollapsedBorderValue compareBorders(const CollapsedBorderValue& border1,
- const CollapsedBorderValue& border2)
-{
- // Sanity check the values passed in. If either is null, return the other.
- if (!border2.exists()) return border1;
- if (!border1.exists()) return border2;
-
- // Rule #1 above.
- if (border1.style() == BHIDDEN || border2.style() == BHIDDEN)
- return CollapsedBorderValue(); // No border should exist at this location.
-
- // Rule #2 above. A style of 'none' has lowest priority and always loses to any other border.
- if (border2.style() == BNONE) return border1;
- if (border1.style() == BNONE) return border2;
-
- // The first part of rule #3 above. Wider borders win.
- if (border1.width() != border2.width())
- return border1.width() > border2.width() ? border1 : border2;
-
- // The borders have equal width. Sort by border style.
- if (border1.style() != border2.style())
- return border1.style() > border2.style() ? border1 : border2;
-
- // The border have the same width and style. Rely on precedence (cell over row over row group, etc.)
- return border1.precedence >= border2.precedence ? border1 : border2;
-}
-
-CollapsedBorderValue RenderTableCell::collapsedLeftBorder() const
-{
- // For border left, we need to check, in order of precedence:
- // (1) Our left border.
- CollapsedBorderValue result(&style()->borderLeft(), BCELL);
-
- // (2) The previous cell's right border.
- RenderTableCell* prevCell = table()->cellLeft(this);
- if (prevCell) {
- result = compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL));
- if (!result.exists()) return result;
- }
- else if (col() == 0) {
- // (3) Our row's left border.
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderLeft(), BROW));
- if (!result.exists()) return result;
-
- // (4) Our row group's left border.
- result = compareBorders(result, CollapsedBorderValue(&section()->style()->borderLeft(), BROWGROUP));
- if (!result.exists()) return result;
- }
-
- // (5) Our column's left border.
- RenderTableCol* colElt = table()->colElement(col());
- if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
- if (!result.exists()) return result;
- }
-
- // (6) The previous column's right border.
- if (col() > 0) {
- colElt = table()->colElement(col()-1);
- if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
- if (!result.exists()) return result;
- }
- }
-
- if (col() == 0) {
- // (7) The table's left border.
- result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderLeft(), BTABLE));
- if (!result.exists()) return result;
- }
-
- return result;
-}
-
-CollapsedBorderValue RenderTableCell::collapsedRightBorder() const
-{
- RenderTable* tableElt = table();
- bool inLastColumn = false;
- int effCol = tableElt->colToEffCol(col()+colSpan()-1);
- if (effCol == tableElt->numEffCols()-1)
- inLastColumn = true;
-
- // For border right, we need to check, in order of precedence:
- // (1) Our right border.
- CollapsedBorderValue result = CollapsedBorderValue(&style()->borderRight(), BCELL);
-
- // (2) The next cell's left border.
- if (!inLastColumn) {
- RenderTableCell* nextCell = tableElt->cellRight(this);
- if (nextCell) {
- result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL));
- if (!result.exists()) return result;
- }
- }
- else {
- // (3) Our row's right border.
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderRight(), BROW));
- if (!result.exists()) return result;
-
- // (4) Our row group's right border.
- result = compareBorders(result, CollapsedBorderValue(&section()->style()->borderRight(), BROWGROUP));
- if (!result.exists()) return result;
- }
-
- // (5) Our column's right border.
- RenderTableCol* colElt = table()->colElement(col()+colSpan()-1);
- if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
- if (!result.exists()) return result;
- }
-
- // (6) The next column's left border.
- if (!inLastColumn) {
- colElt = tableElt->colElement(col()+colSpan());
- if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
- if (!result.exists()) return result;
- }
- }
- else {
- // (7) The table's right border.
- result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderRight(), BTABLE));
- if (!result.exists()) return result;
- }
-
- return result;
-}
-
-CollapsedBorderValue RenderTableCell::collapsedTopBorder() const
-{
- // For border top, we need to check, in order of precedence:
- // (1) Our top border.
- CollapsedBorderValue result = CollapsedBorderValue(&style()->borderTop(), BCELL);
-
- RenderTableCell* prevCell = table()->cellAbove(this);
- if (prevCell) {
- // (2) A previous cell's bottom border.
- result = compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderBottom(), BCELL));
- if (!result.exists()) return result;
- }
-
- // (3) Our row's top border.
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderTop(), BROW));
- if (!result.exists()) return result;
-
- // (4) The previous row's bottom border.
- if (prevCell) {
- RenderObject* prevRow = 0;
- if (prevCell->section() == section())
- prevRow = parent()->previousSibling();
- else
- prevRow = prevCell->section()->lastChild();
-
- if (prevRow) {
- result = compareBorders(result, CollapsedBorderValue(&prevRow->style()->borderBottom(), BROW));
- if (!result.exists()) return result;
- }
- }
-
- // Now check row groups.
- RenderTableSection* currSection = section();
- if (row() == 0) {
- // (5) Our row group's top border.
- result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
- if (!result.exists()) return result;
-
- // (6) Previous row group's bottom border.
- currSection = table()->sectionAbove(currSection);
- if (currSection) {
- result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP));
- if (!result.exists())
- return result;
- }
- }
-
- if (!currSection) {
- // (8) Our column's top border.
- RenderTableCol* colElt = table()->colElement(col());
- if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderTop(), BCOL));
- if (!result.exists()) return result;
- }
-
- // (9) The table's top border.
- result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderTop(), BTABLE));
- if (!result.exists()) return result;
- }
-
- return result;
-}
-
-CollapsedBorderValue RenderTableCell::collapsedBottomBorder() const
-{
- // For border top, we need to check, in order of precedence:
- // (1) Our bottom border.
- CollapsedBorderValue result = CollapsedBorderValue(&style()->borderBottom(), BCELL);
-
- RenderTableCell* nextCell = table()->cellBelow(this);
- if (nextCell) {
- // (2) A following cell's top border.
- result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderTop(), BCELL));
- if (!result.exists()) return result;
- }
-
- // (3) Our row's bottom border. (FIXME: Deal with rowspan!)
- result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderBottom(), BROW));
- if (!result.exists()) return result;
-
- // (4) The next row's top border.
- if (nextCell) {
- result = compareBorders(result, CollapsedBorderValue(&nextCell->parent()->style()->borderTop(), BROW));
- if (!result.exists()) return result;
- }
-
- // Now check row groups.
- RenderTableSection* currSection = section();
- if (row()+rowSpan() >= static_cast<RenderTableSection*>(currSection)->numRows()) {
- // (5) Our row group's bottom border.
- result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderBottom(), BROWGROUP));
- if (!result.exists()) return result;
-
- // (6) Following row group's top border.
- currSection = table()->sectionBelow(currSection);
- if (currSection) {
- result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
- if (!result.exists())
- return result;
- }
- }
-
- if (!currSection) {
- // (8) Our column's bottom border.
- RenderTableCol* colElt = table()->colElement(col());
- if (colElt) {
- result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderBottom(), BCOL));
- if (!result.exists()) return result;
- }
-
- // (9) The table's bottom border.
- result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderBottom(), BTABLE));
- if (!result.exists()) return result;
- }
-
- return result;
-}
-
-int RenderTableCell::borderLeft() const
-{
- if (table()->collapseBorders()) {
- CollapsedBorderValue border = collapsedLeftBorder();
- if (border.exists())
- return (border.width()+1)/2; // Give the extra pixel to top and left.
- return 0;
- }
- return RenderBlock::borderLeft();
-}
-
-int RenderTableCell::borderRight() const
-{
- if (table()->collapseBorders()) {
- CollapsedBorderValue border = collapsedRightBorder();
- if (border.exists())
- return border.width()/2;
- return 0;
- }
- return RenderBlock::borderRight();
-}
-
-int RenderTableCell::borderTop() const
-{
- if (table()->collapseBorders()) {
- CollapsedBorderValue border = collapsedTopBorder();
- if (border.exists())
- return (border.width()+1)/2; // Give the extra pixel to top and left.
- return 0;
- }
- return RenderBlock::borderTop();
-}
-
-int RenderTableCell::borderBottom() const
-{
- if (table()->collapseBorders()) {
- CollapsedBorderValue border = collapsedBottomBorder();
- if (border.exists())
- return border.width()/2;
- return 0;
- }
- return RenderBlock::borderBottom();
-}
-
-#ifdef BOX_DEBUG
-#include <tqpainter.h>
-
-static void outlineBox(TQPainter *p, int _tx, int _ty, int w, int h)
-{
- p->setPen(TQPen(TQColor("yellow"), 3, Qt::DotLine));
- p->setBrush( Qt::NoBrush );
- p->drawRect(_tx, _ty, w, h );
-}
-#endif
-
-void RenderTableCell::paint(PaintInfo& pI, int _tx, int _ty)
-{
-
-#ifdef TABLE_PRINT
- kdDebug( 6040 ) << renderName() << "(RenderTableCell)::paint() w/h = (" << width() << "/" << height() << ")" << " _y/_h=" << pI.r.y() << "/" << pI.r.height() << endl;
-#endif
-
- if (needsLayout()) return;
-
- _tx += m_x;
- _ty += m_y/* + _topExtra*/;
-
- RenderTable *tbl = table();
-
- // check if we need to do anything at all...
- int os = kMax(tbl->currentBorderStyle() ? (tbl->currentBorderStyle()->border->width+1)/2 : 0, 2*maximalOutlineSize(pI.phase));
- if (!overhangingContents() && ((_ty >= pI.r.y() + pI.r.height() + os)
- || (_ty + _topExtra + m_height + _bottomExtra <= pI.r.y() - os))) return;
-
- if (pI.phase == PaintActionOutline) {
- paintOutline( pI.p, _tx, _ty, width(), height() + borderTopExtra() + borderBottomExtra(), style());
- }
-
- if (pI.phase == PaintActionCollapsedTableBorders && style()->visibility() == VISIBLE) {
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- paintCollapsedBorder(pI.p, _tx, _ty, w, h);
- }
- else
- RenderBlock::paintObject(pI, _tx, _ty + _topExtra, false);
-
-#ifdef BOX_DEBUG
- ::outlineBox( p, _tx, _ty - _topExtra, width(), height() + borderTopExtra() + borderBottomExtra());
-#endif
-}
-
-static EBorderStyle collapsedBorderStyle(EBorderStyle style)
-{
- if (style == OUTSET)
- style = GROOVE;
- else if (style == INSET)
- style = RIDGE;
- return style;
-}
-
-struct CollapsedBorder {
- CollapsedBorder(){}
-
- CollapsedBorderValue border;
- RenderObject::BorderSide side;
- bool shouldPaint;
- int x1;
- int y1;
- int x2;
- int y2;
- EBorderStyle style;
-};
-
-class CollapsedBorders
-{
-public:
- CollapsedBorders() :count(0) {}
-
- void addBorder(const CollapsedBorderValue& b, RenderObject::BorderSide s, bool paint,
- int _x1, int _y1, int _x2, int _y2,
- EBorderStyle _style)
- {
- if (b.exists() && paint) {
- borders[count].border = b;
- borders[count].side = s;
- borders[count].shouldPaint = paint;
- borders[count].x1 = _x1;
- borders[count].x2 = _x2;
- borders[count].y1 = _y1;
- borders[count].y2 = _y2;
- borders[count].style = _style;
- count++;
- }
- }
-
- CollapsedBorder* nextBorder() {
- for (int i = 0; i < count; i++) {
- if (borders[i].border.exists() && borders[i].shouldPaint) {
- borders[i].shouldPaint = false;
- return &borders[i];
- }
- }
-
- return 0;
- }
-
- CollapsedBorder borders[4];
- int count;
-};
-
-static void addBorderStyle(TQValueList<CollapsedBorderValue>& borderStyles, CollapsedBorderValue borderValue)
-{
- if (!borderValue.exists() || borderStyles.contains(borderValue))
- return;
-
- TQValueListIterator<CollapsedBorderValue> it = borderStyles.begin();
- TQValueListIterator<CollapsedBorderValue> end = borderStyles.end();
- for (; it != end; ++it) {
- CollapsedBorderValue result = compareBorders(*it, borderValue);
- if (result == *it) {
- borderStyles.insert(it, borderValue);
- return;
- }
- }
-
- borderStyles.append(borderValue);
-}
-
-void RenderTableCell::collectBorders(TQValueList<CollapsedBorderValue>& borderStyles)
-{
- addBorderStyle(borderStyles, collapsedLeftBorder());
- addBorderStyle(borderStyles, collapsedRightBorder());
- addBorderStyle(borderStyles, collapsedTopBorder());
- addBorderStyle(borderStyles, collapsedBottomBorder());
-}
-
-void RenderTableCell::paintCollapsedBorder(TQPainter* p, int _tx, int _ty, int w, int h)
-{
- if (!table()->currentBorderStyle())
- return;
-
- CollapsedBorderValue leftVal = collapsedLeftBorder();
- CollapsedBorderValue rightVal = collapsedRightBorder();
- CollapsedBorderValue topVal = collapsedTopBorder();
- CollapsedBorderValue bottomVal = collapsedBottomBorder();
-
- // Adjust our x/y/width/height so that we paint the collapsed borders at the correct location.
- int topWidth = topVal.width();
- int bottomWidth = bottomVal.width();
- int leftWidth = leftVal.width();
- int rightWidth = rightVal.width();
-
- _tx -= leftWidth/2;
- _ty -= topWidth/2;
- w += leftWidth/2 + (rightWidth+1)/2;
- h += topWidth/2 + (bottomWidth+1)/2;
-
- bool tt = topVal.isTransparent();
- bool bt = bottomVal.isTransparent();
- bool rt = rightVal.isTransparent();
- bool lt = leftVal.isTransparent();
-
- EBorderStyle ts = collapsedBorderStyle(topVal.style());
- EBorderStyle bs = collapsedBorderStyle(bottomVal.style());
- EBorderStyle ls = collapsedBorderStyle(leftVal.style());
- EBorderStyle rs = collapsedBorderStyle(rightVal.style());
-
- bool render_t = ts > BHIDDEN && !tt && (topVal.precedence != BCELL || *topVal.border == style()->borderTop());
- bool render_l = ls > BHIDDEN && !lt && (leftVal.precedence != BCELL || *leftVal.border == style()->borderLeft());
- bool render_r = rs > BHIDDEN && !rt && (rightVal.precedence != BCELL || *rightVal.border == style()->borderRight());
- bool render_b = bs > BHIDDEN && !bt && (bottomVal.precedence != BCELL || *bottomVal.border == style()->borderBottom());
-
- // We never paint diagonals at the joins. We simply let the border with the highest
- // precedence paint on top of borders with lower precedence.
- CollapsedBorders borders;
- borders.addBorder(topVal, BSTop, render_t, _tx, _ty, _tx + w, _ty + topWidth, ts);
- borders.addBorder(bottomVal, BSBottom, render_b, _tx, _ty + h - bottomWidth, _tx + w, _ty + h, bs);
- borders.addBorder(leftVal, BSLeft, render_l, _tx, _ty, _tx + leftWidth, _ty + h, ls);
- borders.addBorder(rightVal, BSRight, render_r, _tx + w - rightWidth, _ty, _tx + w, _ty + h, rs);
-
- for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
- if (border->border == *table()->currentBorderStyle())
- drawBorder(p, border->x1, border->y1, border->x2, border->y2, border->side,
- border->border.color(), style()->color(), border->style, 0, 0);
- }
-}
-
-void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& pI, int _tx, int _ty, RenderObject* backgroundObject)
-{
- if (!backgroundObject)
- return;
-
- RenderTable* tableElt = table();
- if (backgroundObject != this) {
- _tx += m_x;
- _ty += m_y + _topExtra;
- }
-
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- _ty -= borderTopExtra();
-
- int my = kMax(_ty,pI.r.y());
- int end = kMin( pI.r.y() + pI.r.height(), _ty + h );
- int mh = end - my;
-
- TQColor c = backgroundObject->style()->backgroundColor();
- const BackgroundLayer* bgLayer = backgroundObject->style()->backgroundLayers();
-
- if (bgLayer->hasImage() || c.isValid()) {
- // We have to clip here because the background would paint
- // on top of the borders otherwise. This only matters for cells and rows.
- bool hasLayer = backgroundObject->layer() && (backgroundObject == this || backgroundObject == parent());
- if (hasLayer && tableElt->collapseBorders()) {
- pI.p->save();
- TQRect clipRect(_tx + borderLeft(), _ty + borderTop(), w - borderLeft() - borderRight(), h - borderTop() - borderBottom());
- clipRect = pI.p->xForm(clipRect);
- TQRegion creg(clipRect);
- TQRegion old = pI.p->clipRegion();
- if (!old.isNull())
- creg = old.intersect(creg);
- pI.p->setClipRegion(creg);
- }
- paintBackground(pI.p, c, bgLayer, my, mh, _tx, _ty, w, h);
- if (hasLayer && tableElt->collapseBorders())
- pI.p->restore();
- }
-}
-
-void RenderTableCell::paintBoxDecorations(PaintInfo& pI, int _tx, int _ty)
-{
- RenderTable* tableElt = table();
- bool drawBorders = true;
- // Moz paints bgcolor/bgimage on <td>s in quirks mode even if
- // empty-cells are on. Fixes regression on #43426, attachment #354
- if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
- drawBorders = false;
- if (!style()->htmlHacks() && !drawBorders) return;
-
- // Paint our cell background.
- paintBackgroundsBehindCell(pI, _tx, _ty, this);
-
- int w = width();
- int h = height() + borderTopExtra() + borderBottomExtra();
- _ty -= borderTopExtra();
-
- if (drawBorders && style()->hasBorder() && !tableElt->collapseBorders())
- paintBorder(pI.p, _tx, _ty, w, h, style());
-}
-
-
-#ifdef ENABLE_DUMP
-void RenderTableCell::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderFlow::dump(stream,ind);
- stream << " row=" << _row;
- stream << " col=" << _col;
- stream << " rSpan=" << rSpan;
- stream << " cSpan=" << cSpan;
-// *stream << " nWrap=" << nWrap;
-}
-#endif
-
-// -------------------------------------------------------------------------
-
-RenderTableCol::RenderTableCol(DOM::NodeImpl* node)
- : RenderContainer(node), m_span(1)
-{
- // init RenderObject attributes
- setInline(true); // our object is not Inline
- updateFromElement();
-}
-
-void RenderTableCol::updateFromElement()
-{
- DOM::NodeImpl *node = element();
- if ( node && (node->id() == ID_COL || node->id() == ID_COLGROUP) ) {
- DOM::HTMLTableColElementImpl *tc = static_cast<DOM::HTMLTableColElementImpl *>(node);
- m_span = tc->span();
- } else
- m_span = ! ( style() && style()->display() == TABLE_COLUMN_GROUP );
-}
-
-#ifdef ENABLE_DUMP
-void RenderTableCol::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderContainer::dump(stream,ind);
- stream << " _span=" << m_span;
-}
-#endif
-
-// -------------------------------------------------------------------------
-
-TableSectionIterator::TableSectionIterator(RenderTable *table, bool fromEnd)
-{
- if (fromEnd) {
- sec = table->foot;
- if (sec) return;
-
- sec = static_cast<RenderTableSection *>(table->lastChild());
- while (sec && (!sec->isTableSection()
- || sec == table->head || sec == table->foot))
- sec = static_cast<RenderTableSection *>(sec->previousSibling());
- if (sec) return;
-
- sec = table->head;
- } else {
- sec = table->head;
- if (sec) return;
-
- sec = static_cast<RenderTableSection *>(table->firstChild());
- while (sec && (!sec->isTableSection()
- || sec == table->head || sec == table->foot))
- sec = static_cast<RenderTableSection *>(sec->nextSibling());
- if (sec) return;
-
- sec = table->foot;
- }/*end if*/
-
-}
-
-TableSectionIterator &TableSectionIterator::operator ++()
-{
- RenderTable *table = sec->table();
- if (sec == table->head) {
-
- sec = static_cast<RenderTableSection *>(table->firstChild());
- while (sec && (!sec->isTableSection()
- || sec == table->head || sec == table->foot))
- sec = static_cast<RenderTableSection *>(sec->nextSibling());
- if (sec) return *this;
-
- } else if (sec == table->foot) {
- sec = 0;
- return *this;
-
- } else {
-
- do {
- sec = static_cast<RenderTableSection *>(sec->nextSibling());
- } while (sec && (!sec->isTableSection() || sec == table->head || sec == table->foot));
- if (sec) return *this;
-
- }/*end if*/
-
- sec = table->foot;
- return *this;
-}
-
-TableSectionIterator &TableSectionIterator::operator --()
-{
- RenderTable *table = sec->table();
- if (sec == table->foot) {
-
- sec = static_cast<RenderTableSection *>(table->lastChild());
- while (sec && (!sec->isTableSection()
- || sec == table->head || sec == table->foot))
- sec = static_cast<RenderTableSection *>(sec->previousSibling());
- if (sec) return *this;
-
- } else if (sec == table->head) {
- sec = 0;
- return *this;
-
- } else {
-
- do {
- sec = static_cast<RenderTableSection *>(sec->previousSibling());
- } while (sec && (!sec->isTableSection() || sec == table->head || sec == table->foot));
- if (sec) return *this;
-
- }/*end if*/
-
- sec = table->foot;
- return *this;
-}
-
-#undef TABLE_DEBUG
-#undef DEBUG_LAYOUT
-#undef BOX_DEBUG
diff --git a/khtml/rendering/render_table.h b/khtml/rendering/render_table.h
deleted file mode 100644
index a6de6cfaf..000000000
--- a/khtml/rendering/render_table.h
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1997 Martin Jones (mjones@kde.org)
- * (C) 1997 Torben Weis (weis@kde.org)
- * (C) 1998 Waldo Bastian (bastian@kde.org)
- * (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 1999 Antti Koivisto (koivisto@kde.org)
- * (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDER_TABLE_H
-#define RENDER_TABLE_H
-
-#include <tqcolor.h>
-#include <tqptrvector.h>
-
-#include "rendering/render_box.h"
-#include "rendering/render_block.h"
-#include "rendering/render_style.h"
-
-#include "misc/khtmllayout.h"
-
-namespace DOM {
- class DOMString;
-}
-
-namespace khtml {
-
-class RenderTable;
-class RenderTableSection;
-class RenderTableRow;
-class RenderTableCell;
-class RenderTableCol;
-class TableLayout;
-
-class RenderTable : public RenderBlock
-{
-public:
-
- RenderTable(DOM::NodeImpl* node);
- ~RenderTable();
-
- virtual const char *renderName() const { return "RenderTable"; }
-
- virtual void setStyle(RenderStyle *style);
-
- virtual bool isTable() const { return true; }
-
- int getColumnPos(int col) const
- { return columnPos[col]; }
-
- int borderHSpacing() const { return hspacing; }
- int borderVSpacing() const { return vspacing; }
-
- bool collapseBorders() const { return style()->borderCollapse(); }
- int borderLeft() const;
- int borderRight() const;
- int borderTop() const;
- int borderBottom() const;
- int paddingLeft() const { return collapseBorders() ? 0 : RenderBlock::paddingLeft(); }
- int paddingRight() const { return collapseBorders() ? 0 : RenderBlock::paddingRight(); }
- int paddingTop() const { return collapseBorders() ? 0 : RenderBlock::paddingTop(); }
- int paddingBottom() const { return collapseBorders() ? 0 : RenderBlock::paddingBottom(); }
-
- const TQColor &bgColor() const { return style()->backgroundColor(); }
-
- uint cellPadding() const { return padding; }
- void setCellPadding( uint p ) { padding = p; }
-
- // overrides
- virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
- virtual void paint( PaintInfo&, int tx, int ty);
- virtual void paintBoxDecorations(PaintInfo&, int _tx, int _ty);
- virtual void layout();
- virtual void calcMinMaxWidth();
- virtual void close();
-
- virtual short lineHeight(bool b) const;
- virtual short baselinePosition(bool b) const;
-
- virtual void setCellWidths( );
-
- virtual void calcWidth();
-
- virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
- DOM::NodeImpl*& node, int & offset,
- SelPointState & );
-
-#ifdef ENABLE_DUMP
- virtual void dump(TQTextStream &stream, const TQString &ind) const;
-#endif
- struct ColumnStruct {
- enum {
- WidthUndefined = 0xffff
- };
- ColumnStruct() {
- span = 1;
- width = WidthUndefined;
- }
- ushort span;
- ushort width; // the calculated position of the column
- };
-
- TQMemArray<int> columnPos;
- TQMemArray<ColumnStruct> columns;
-
- void splitColumn( int pos, int firstSpan );
- void appendColumn( int span );
- int numEffCols() const { return columns.size(); }
- int spanOfEffCol( int effCol ) const { return columns[effCol].span; }
- int colToEffCol( int col ) const {
- int c = 0;
- int i = 0;
- while ( c < col && i < (int)columns.size() ) {
- c += columns[i].span;
- i++;
- }
- return i;
- }
- int effColToCol( int effCol ) const {
- int c = 0;
- for ( int i = 0; i < effCol; i++ )
- c += columns[i].span;
- return c;
- }
-
- int bordersPaddingAndSpacing() const {
- return borderLeft() + borderRight() +
- (collapseBorders() ? 0 : (paddingLeft() + paddingRight() + (numEffCols()+1) * borderHSpacing()));
- }
-
- RenderTableCol *colElement( int col );
-
- void setNeedSectionRecalc() { needSectionRecalc = true; }
-
- virtual RenderObject* removeChildNode(RenderObject* child);
-
- RenderTableSection* sectionAbove(const RenderTableSection*, bool skipEmptySections = false) const;
- RenderTableSection* sectionBelow(const RenderTableSection*, bool skipEmptySections = false) const;
-
- RenderTableCell* cellAbove(const RenderTableCell* cell) const;
- RenderTableCell* cellBelow(const RenderTableCell* cell) const;
- RenderTableCell* cellLeft(const RenderTableCell* cell) const;
- RenderTableCell* cellRight(const RenderTableCell* cell) const;
-
- CollapsedBorderValue* currentBorderStyle() { return m_currentBorder; }
-
- RenderTableSection *firstBodySection() const { return firstBody; }
- RenderFlow* caption() const { return tCaption; }
-
-protected:
-
- void recalcSections();
-
- friend class AutoTableLayout;
- friend class FixedTableLayout;
-
- RenderFlow *tCaption;
- RenderTableSection *head;
- RenderTableSection *foot;
- RenderTableSection *firstBody;
-
- TableLayout *tableLayout;
-
- CollapsedBorderValue* m_currentBorder;
-
- bool has_col_elems : 1;
- uint needSectionRecalc : 1;
- uint padding : 22;
-
- ushort hspacing;
- ushort vspacing;
-
- friend class TableSectionIterator;
-};
-
-// -------------------------------------------------------------------------
-
-class RenderTableSection : public RenderBox
-{
-public:
- RenderTableSection(DOM::NodeImpl* node);
- ~RenderTableSection();
- virtual void detach();
-
- virtual void setStyle(RenderStyle *style);
-
- virtual const char *renderName() const { return "RenderTableSection"; }
-
- // overrides
- virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
- virtual bool isTableSection() const { return true; }
-
- virtual short lineHeight(bool) const { return 0; }
- virtual void position(InlineBox*, int, int, bool) {}
-
- virtual short width() const;
-
- virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
- DOM::NodeImpl*& node, int & offset,
- SelPointState & );
-
-#ifdef ENABLE_DUMP
- virtual void dump(TQTextStream &stream, const TQString &ind) const;
-#endif
-
- void addCell( RenderTableCell *cell, RenderTableRow *row );
-
- void setCellWidths();
- void calcRowHeight();
- int layoutRows( int height );
-
- RenderTable *table() const { return static_cast<RenderTable *>(parent()); }
-
- typedef TQMemArray<RenderTableCell *> Row;
- struct RowStruct {
- Row *row;
- RenderTableRow* rowRenderer;
- int baseLine;
- Length height;
- bool needFlex;
- };
-
- RenderTableCell *&cellAt( int row, int col ) {
- return (*(grid[row].row))[col];
- }
- RenderTableCell *cellAt( int row, int col ) const {
- return (*(grid[row].row))[col];
- }
-
- virtual int lowestPosition(bool includeOverflowInterior, bool includeSelf) const;
- virtual int rightmostPosition(bool includeOverflowInterior, bool includeSelf) const;
- virtual int leftmostPosition(bool includeOverflowInterior, bool includeSelf) const;
- virtual int highestPosition(bool includeOverflowInterior, bool includeSelf) const;
-
- int borderLeft() const { return table()->collapseBorders() ? 0 : RenderBox::borderLeft(); }
- int borderRight() const { return table()->collapseBorders() ? 0 : RenderBox::borderRight(); }
- int borderTop() const { return table()->collapseBorders() ? 0 : RenderBox::borderTop(); }
- int borderBottom() const { return table()->collapseBorders() ? 0 : RenderBox::borderBottom(); }
-
- virtual void paint( PaintInfo& i, int tx, int ty);
-
- int numRows() const { return grid.size(); }
- int getBaseline(int row) {return grid[row].baseLine;}
-
- void setNeedCellRecalc() {
- needCellRecalc = true;
- table()->setNeedSectionRecalc();
- }
-
- virtual RenderObject* removeChildNode(RenderObject* child);
-
- virtual bool canClear(RenderObject *child, PageBreakLevel level);
- void addSpaceAt(int pos, int dy);
-
- virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside);
-
- // this gets a cell grid data structure. changing the number of
- // columns is done by the table
- TQMemArray<RowStruct> grid;
- TQMemArray<int> rowPos;
-
- signed short cRow;
- ushort cCol;
- bool needCellRecalc;
-
- void recalcCells();
-protected:
- void ensureRows( int numRows );
- void clearGrid();
- bool emptyRow(int rowNum);
- bool flexCellChildren(RenderObject* p) const;
-
-
- friend class TableSectionIterator;
-};
-
-// -------------------------------------------------------------------------
-
-class RenderTableRow : public RenderContainer
-{
-public:
- RenderTableRow(DOM::NodeImpl* node);
-
- virtual void detach();
-
- virtual void setStyle( RenderStyle* );
- virtual const char *renderName() const { return "RenderTableRow"; }
- virtual bool isTableRow() const { return true; }
- virtual void addChild(RenderObject *child, RenderObject *beforeChild = 0);
-
- virtual short offsetWidth() const;
- virtual int offsetHeight() const;
- virtual int offsetLeft() const;
- virtual int offsetTop() const;
-
- virtual short lineHeight( bool ) const { return 0; }
- virtual void position(InlineBox*, int, int, bool) {}
-
- virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction action, bool inside);
-
- virtual void layout();
-
- virtual RenderObject* removeChildNode(RenderObject* child);
-
- // The only time rows get a layer is when they have transparency.
- virtual bool requiresLayer() const { return /* style()->opacity() < 1.0f; */ false ; }
- virtual void paint(PaintInfo& i, int tx, int ty);
-
- void paintRow( PaintInfo& i, int tx, int ty, int w, int h);
-
- RenderTable *table() const { return static_cast<RenderTable *>(parent()->parent()); }
- RenderTableSection *section() const { return static_cast<RenderTableSection *>(parent()); }
-};
-
-// -------------------------------------------------------------------------
-
-class RenderTableCell : public RenderBlock
-{
-public:
- RenderTableCell(DOM::NodeImpl* node);
-
- virtual void layout();
- virtual void detach();
-
- virtual const char *renderName() const { return "RenderTableCell"; }
- virtual bool isTableCell() const { return true; }
-
- // ### FIX these two...
- long cellIndex() const { return 0; }
- void setCellIndex( long ) { }
-
- unsigned short colSpan() const { return cSpan; }
- void setColSpan( unsigned short c ) { cSpan = c; }
-
- unsigned short rowSpan() const { return rSpan; }
- void setRowSpan( unsigned short r ) { rSpan = r; }
-
- int col() const { return _col; }
- void setCol(int col) { _col = col; }
- int row() const { return _row; }
- void setRow(int r) { _row = r; }
-
- Length styleOrColWidth();
-
- // overrides
- virtual void calcMinMaxWidth();
- virtual void calcWidth();
- virtual void setWidth( int width );
- virtual void setStyle( RenderStyle *style );
- virtual bool requiresLayer() const;
-
- int borderLeft() const;
- int borderRight() const;
- int borderTop() const;
- int borderBottom() const;
-
- CollapsedBorderValue collapsedLeftBorder() const;
- CollapsedBorderValue collapsedRightBorder() const;
- CollapsedBorderValue collapsedTopBorder() const;
- CollapsedBorderValue collapsedBottomBorder() const;
- virtual void collectBorders(TQValueList<CollapsedBorderValue>& borderStyles);
-
- virtual void updateFromElement();
-
- void setCellTopExtra(int p) { _topExtra = p; }
- void setCellBottomExtra(int p) { _bottomExtra = p; }
- int cellTopExtra() const { return _topExtra; }
- int cellBottomExtra() const { return _bottomExtra; }
-
- int pageTopAfter(int x) const;
-
- virtual void paint( PaintInfo& i, int tx, int ty);
-
- void paintCollapsedBorder(TQPainter* p, int x, int y, int w, int h);
- void paintBackgroundsBehindCell(PaintInfo& i, int _tx, int _ty, RenderObject* backgroundObject);
-
- virtual void close();
-
- // lie position to outside observers
- virtual int yPos() const { return m_y + _topExtra; }
-
- virtual void repaintRectangle(int x, int y, int w, int h, Priority p=NormalPriority, bool f=false);
- virtual bool absolutePosition(int &xPos, int &yPos, bool f = false) const;
-
- virtual short baselinePosition( bool = false ) const;
-
- virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside);
-
- RenderTable *table() const { return static_cast<RenderTable *>(parent()->parent()->parent()); }
- RenderTableSection *section() const { return static_cast<RenderTableSection *>(parent()->parent()); }
-
-#ifdef ENABLE_DUMP
- virtual void dump(TQTextStream &stream, const TQString &ind) const;
-#endif
-
- bool widthChanged() {
- bool retval = m_widthChanged;
- m_widthChanged = false;
- return retval;
- }
-
- int cellPercentageHeight() const
- { return m_percentageHeight; }
- void setCellPercentageHeight(int h)
- { m_percentageHeight = h; }
- bool hasFlexedAnonymous() const
- { return m_hasFlexedAnonymous; }
- void setHasFlexedAnonymous(bool b=true)
- { m_hasFlexedAnonymous = b; }
-
-protected:
- virtual void paintBoxDecorations(PaintInfo& p, int _tx, int _ty);
- virtual int borderTopExtra() const { return _topExtra; }
- virtual int borderBottomExtra() const { return _bottomExtra; }
-
- short _row;
- short _col;
- ushort rSpan;
- ushort cSpan;
- int _topExtra;
- signed int _bottomExtra : 30;
- bool m_widthChanged : 1;
- bool m_hasFlexedAnonymous : 1;
- int m_percentageHeight;
-};
-
-
-// -------------------------------------------------------------------------
-
-class RenderTableCol : public RenderContainer
-{
-public:
- RenderTableCol(DOM::NodeImpl* node);
-
- virtual const char *renderName() const { return "RenderTableCol"; }
-
- virtual bool isTableCol() const { return true; }
-
- virtual short lineHeight( bool ) const { return 0; }
- virtual void position(InlineBox*, int, int, bool) {}
- virtual void layout() {}
- virtual bool requiresLayer() const { return false; }
-
- virtual void updateFromElement();
-
-#ifdef ENABLE_DUMP
- virtual void dump(TQTextStream &stream, const TQString& ind) const;
-#endif
-
- int span() const { return m_span; }
- void setSpan( int s ) { m_span = s; }
-
-private:
- int m_span;
-};
-
-// -------------------------------------------------------------------------
-
-/** This class provides an iterator to iterate through the sections of a
- * render table in their visual order.
- *
- * In HTML, sections are specified in the order of THEAD, TFOOT, and TBODY.
- * Visually, TBODY sections appear between THEAD and TFOOT, which this iterator
- * takes into regard.
- * @author Leo Savernik
- * @internal
- * @since 3.2
- */
-class TableSectionIterator {
-public:
-
- /**
- * Initializes a new iterator
- * @param table table whose sections to iterate
- * @param fromEnd @p true, begin with last section, @p false, begin with
- * first section.
- */
- TableSectionIterator(RenderTable *table, bool fromEnd = false);
-
- /**
- * Initializes a new iterator
- * @param start table section to start with.
- */
- TableSectionIterator(RenderTableSection *start) : sec(start) {}
-
- /**
- * Uninitialized iterator.
- */
- TableSectionIterator() {}
-
- /** Returns the current section, or @p 0 if the end has been reached.
- */
- RenderTableSection *operator *() const { return sec; }
-
- /** Moves to the next section in visual order. */
- TableSectionIterator &operator ++();
-
- /** Moves to the previous section in visual order. */
- TableSectionIterator &operator --();
-
-private:
- RenderTableSection *sec;
-};
-
-}
-#endif
-
diff --git a/khtml/rendering/render_text.cpp b/khtml/rendering/render_text.cpp
deleted file mode 100644
index 770e8cd4d..000000000
--- a/khtml/rendering/render_text.cpp
+++ /dev/null
@@ -1,1546 +0,0 @@
-/**
- * This file is part of the DOM implementation for KDE.
- *
- * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- * (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-//#define DEBUG_LAYOUT
-//#define BIDI_DEBUG
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "rendering/render_text.h"
-#include "rendering/render_canvas.h"
-#include "rendering/break_lines.h"
-#include "rendering/render_arena.h"
-#include "xml/dom_nodeimpl.h"
-
-#include "misc/loader.h"
-#include "misc/helper.h"
-
-#include <tqbitmap.h>
-#include <tqimage.h>
-#include <tqpainter.h>
-#include <kdebug.h>
-#include <kglobal.h>
-#include <assert.h>
-#include <limits.h>
-#include <math.h>
-
-#ifdef HAVE_ALLOCA_H
-// explicitly included for systems that don't provide it in stdlib.h
-#include <alloca.h>
-#else
-#include <stdlib.h>
-#endif
-
-using namespace khtml;
-using namespace DOM;
-
-#ifndef NDEBUG
-static bool inInlineTextBoxDetach;
-#endif
-
-void InlineTextBox::detach(RenderArena* renderArena)
-{
- if (m_parent)
- m_parent->removeFromLine(this);
-
-#ifndef NDEBUG
- inInlineTextBoxDetach = true;
-#endif
- delete this;
-#ifndef NDEBUG
- inInlineTextBoxDetach = false;
-#endif
-
- // Recover the size left there for us by operator delete and free the memory.
- renderArena->free(*(size_t *)this, this);
-}
-
-void* InlineTextBox::operator new(size_t sz, RenderArena* renderArena) throw()
-{
- return renderArena->allocate(sz);
-}
-
-void InlineTextBox::operator delete(void* ptr, size_t sz)
-{
- assert(inInlineTextBoxDetach);
-
- // Stash size where detach can find it.
- *(size_t *)ptr = sz;
-}
-
-void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
-{
- int startPos, endPos;
- if (object()->selectionState() == RenderObject::SelectionInside) {
- startPos = 0;
- endPos = renderText()->string()->l;
- } else {
- renderText()->selectionStartEnd(startPos, endPos);
- if (object()->selectionState() == RenderObject::SelectionStart)
- endPos = renderText()->string()->l;
- else if (object()->selectionState() == RenderObject::SelectionEnd)
- startPos = 0;
- }
-
- sPos = kMax(startPos - m_start, 0);
- ePos = kMin(endPos - m_start, (int)m_len);
-}
-
-RenderObject::SelectionState InlineTextBox::selectionState()
-{
- RenderObject::SelectionState state = object()->selectionState();
- if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd ||
- state == RenderObject::SelectionBoth) {
- int startPos, endPos;
- renderText()->selectionStartEnd(startPos, endPos);
-
- bool start = (state != RenderObject::SelectionEnd && startPos >= m_start && startPos < m_start + m_len);
- bool end = (state != RenderObject::SelectionStart && endPos > m_start && endPos <= m_start + m_len);
- if (start && end)
- state = RenderObject::SelectionBoth;
- else if (start)
- state = RenderObject::SelectionStart;
- else if (end)
- state = RenderObject::SelectionEnd;
- else if ((state == RenderObject::SelectionEnd || startPos < m_start) &&
- (state == RenderObject::SelectionStart || endPos > m_start + m_len))
- state = RenderObject::SelectionInside;
- }
- return state;
-}
-
-void InlineTextBox::paint(RenderObject::PaintInfo& i, int tx, int ty)
-{
- if (object()->isBR() || object()->style()->visibility() != VISIBLE ||
- m_truncation == cFullTruncation || i.phase == PaintActionOutline)
- return;
-
- if (i.phase == PaintActionSelection && object()->selectionState() == RenderObject::SelectionNone)
- // When only painting the selection, don't bother to paint if there is none.
- return;
-
- int xPos = tx + m_x;
- int w = width();
- if ((xPos >= i.r.x() + i.r.width()) || (xPos + w <= i.r.x()))
- return;
-
- // Set our font.
- RenderStyle* styleToUse = object()->style(m_firstLine);
- int d = styleToUse->textDecorationsInEffect();
- if (styleToUse->font() != i.p->font())
- i.p->setFont(styleToUse->font());
- const Font *font = &styleToUse->htmlFont();
- bool haveSelection = selectionState() != RenderObject::SelectionNone;
-
- // Now calculate startPos and endPos, for painting selection.
- // We paint selection while endPos > 0
- int ePos = 0, sPos = 0;
- if (haveSelection && !object()->canvas()->staticMode()) {
- selectionStartEnd(sPos, ePos);
- }
- if (styleToUse->color() != i.p->pen().color())
- i.p->setPen(styleToUse->color());
-
- if (m_len > 0 && i.phase != PaintActionSelection) {
- int endPoint = m_len;
- if (m_truncation != cNoTruncation)
- endPoint = m_truncation - m_start;
- if (styleToUse->textShadow())
- paintShadow(i.p, font, tx, ty, styleToUse->textShadow());
- if (!haveSelection || sPos != 0 || ePos != m_len) {
- font->drawText(i.p, m_x + tx, m_y + ty + m_baseline, renderText()->string()->s, renderText()->string()->l, m_start, endPoint,
- m_toAdd, m_reversed ? TQPainter::RTL : TQPainter::LTR);
- }
- }
-
- if (d != TDNONE && i.phase != PaintActionSelection && styleToUse->htmlHacks()) {
- i.p->setPen(styleToUse->color());
- paintDecoration(i.p, font, tx, ty, d);
- }
-
- if (haveSelection && i.phase == PaintActionSelection) {
- //kdDebug(6040) << this << " paintSelection with startPos=" << sPos << " endPos=" << ePos << endl;
- if ( sPos < ePos )
- paintSelection(font, renderText(), i.p, styleToUse, tx, ty, sPos, ePos, d);
- }
-}
-
-/** returns the proper ::selection pseudo style for the given element
- * @return the style or 0 if no ::selection pseudo applies.
- */
-inline const RenderStyle *retrieveSelectionPseudoStyle(const RenderObject *obj)
-{
- // http://www.w3.org/Style/CSS/Test/CSS3/Selectors/20021129/html/tests/css3-modsel-162.html
- // is of the opinion that ::selection of parent elements is also to be applied
- // to children, so let's do it.
- while (obj) {
- const RenderStyle *style = obj->style()->getPseudoStyle(RenderStyle::SELECTION);
- if (style) return style;
-
- obj = obj->parent();
- }/*wend*/
- return 0;
-}
-
-void InlineTextBox::paintSelection(const Font *f, RenderText *text, TQPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos, int deco)
-{
- if(startPos > m_len) return;
- if(startPos < 0) startPos = 0;
-
- TQColor hc;
- TQColor hbg;
- const RenderStyle* pseudoStyle = retrieveSelectionPseudoStyle(text);
- if (pseudoStyle) {
- // ### support outline (mandated by CSS3)
- // ### support background-image? (optional by CSS3)
- if (pseudoStyle->backgroundColor().isValid())
- hbg = pseudoStyle->backgroundColor();
- hc = pseudoStyle->color();
- } else {
- const TQColorGroup &grp = style->palette().active();
- hc = grp.highlightedText();
- hbg = grp.highlight();
- // ### should be at most retrieved once per render text
- TQColor bg = khtml::retrieveBackgroundColor(text);
- // It may happen that the contrast is -- well -- virtually non existent.
- // In this case, simply swap the colors, thus in compliance with
- // NN4 (win32 only), IE, and Mozilla.
- if (!khtml::hasSufficientContrast(hbg, bg))
- tqSwap(hc, hbg);
- }
-
- p->setPen(hc);
-
- //kdDebug( 6040 ) << "textRun::painting(" << TQConstString(text->str->s + m_start, m_len).string().left(30) << ") at(" << m_x+tx << "/" << m_y+ty << ")" << endl;
-
- const bool needClipping = startPos != 0 || endPos != m_len;
-
- if (needClipping) {
- p->save();
-
- int visualSelectionStart = f->width(text->str->s, text->str->l, m_start, startPos, m_start, m_start + m_len, m_toAdd);
- int visualSelectionEnd = f->width(text->str->s, text->str->l, m_start, endPos, m_start, m_start + m_len, m_toAdd);
- int visualSelectionWidth = visualSelectionEnd - visualSelectionStart;
- if (m_reversed) {
- visualSelectionStart = f->width(text->str->s, text->str->l, m_start, m_len) - visualSelectionEnd;
- }
-
- TQRect selectionRect(m_x + tx + visualSelectionStart, m_y + ty, visualSelectionWidth, height());
- TQRegion r(selectionRect);
- if (p->hasClipping())
- r &= p->clipRegion(TQPainter::CoordPainter);
- p->setClipRegion(r, TQPainter::CoordPainter);
- }
-
- f->drawText(p, m_x + tx, m_y + ty + m_baseline, text->str->s, text->str->l,
- m_start, m_len, m_toAdd,
- m_reversed ? TQPainter::RTL : TQPainter::LTR,
- needClipping ? 0 : startPos, needClipping ? m_len : endPos,
- hbg, m_y + ty, height(), deco);
-
- if (needClipping) p->restore();
-}
-
-void InlineTextBox::paintDecoration( TQPainter *pt, const Font *f, int _tx, int _ty, int deco)
-{
- _tx += m_x;
- _ty += m_y;
-
- if (m_truncation == cFullTruncation)
- return;
-
- int width = m_width - 1;
- if (m_truncation != cNoTruncation) {
- width = static_cast<RenderText*>(m_object)->width(m_start, m_truncation - m_start, m_firstLine);
- }
-
- RenderObject *p = object();
-
- TQColor underline, overline, linethrough;
- p->getTextDecorationColors(deco, underline, overline, linethrough, p->style()->htmlHacks());
-
- if(deco & UNDERLINE){
- pt->setPen(underline);
- f->drawDecoration(pt, _tx, _ty, baseline(), width, height(), Font::UNDERLINE);
- }
- if (deco & OVERLINE) {
- pt->setPen(overline);
- f->drawDecoration(pt, _tx, _ty, baseline(), width, height(), Font::OVERLINE);
- }
- if(deco & LINE_THROUGH) {
- pt->setPen(linethrough);
- f->drawDecoration(pt, _tx, _ty, baseline(), width, height(), Font::LINE_THROUGH);
- }
- // NO! Do NOT add BLINK! It is the most annouing feature of Netscape, and IE has a reason not to
- // support it. Lars
-}
-
-void InlineTextBox::paintShadow(TQPainter *pt, const Font *f, int _tx, int _ty, const ShadowData *shadow )
-{
- int x = m_x + _tx + shadow->x;
- int y = m_y + _ty + shadow->y;
- const RenderText* text = renderText();
-
- if (shadow->blur <= 0) {
- TQColor c = pt->pen().color();
- pt->setPen(shadow->color);
- f->drawText(pt, x, y+m_baseline, text->str->s, text->str->l,
- m_start, m_len, m_toAdd,
- m_reversed ? TQPainter::RTL : TQPainter::LTR);
- pt->setPen(c);
-
- }
- else {
- const int thickness = shadow->blur;
- const int w = m_width+2*thickness;
- const int h = m_height+2*thickness;
- const TQRgb color = shadow->color.rgb();
- const int gray = tqGray(color);
- const bool inverse = (gray < 100);
- const TQRgb bgColor = (inverse) ? tqRgb(255,255,255) : tqRgb(0,0,0);
- TQPixmap pixmap(w, h);
- pixmap.fill(bgColor);
- TQPainter p;
-
- p.begin(&pixmap);
- p.setPen(shadow->color);
- p.setFont(pt->font());
- f->drawText(&p, thickness, thickness+m_baseline, text->str->s, text->str->l,
- m_start, m_len, m_toAdd,
- m_reversed ? TQPainter::RTL : TQPainter::LTR);
-
- p.end();
- TQImage img = TQT_TQIMAGE_OBJECT(pixmap.convertToImage()).convertDepth(32);
-
- int md = thickness*thickness; // max-dist^2
-
- // blur map (division cache)
- float *bmap = (float*)alloca(sizeof(float)*(md+1));
- for(int n=0; n<=md; n++) {
- float f;
- f = n/(float)(md+1);
- f = 1.0 - f*f;
- bmap[n] = f;
- }
-
- float factor = 0.0; // maximal potential opacity-sum
- for(int n=-thickness; n<=thickness; n++)
- for(int m=-thickness; m<=thickness; m++) {
- int d = n*n+m*m;
- if (d<=md)
- factor += bmap[d];
- }
-
- // arbitratry factor adjustment to make shadows solid.
- factor = factor/1.333;
-
- // alpha map
- float* amap = (float*)alloca(sizeof(float)*(h*w));
- memset(amap, 0, h*w*(sizeof(float)));
- for(int j=thickness; j<h-thickness; j++) {
- for(int i=thickness; i<w-thickness; i++) {
- TQRgb col= img.pixel(i,j);
- if (col == bgColor) continue;
- float g = tqGray(col);
- if (inverse)
- g = (255-g)/(255-gray);
- else
- g = g/gray;
- for(int n=-thickness; n<=thickness; n++) {
- for(int m=-thickness; m<=thickness; m++) {
- int d = n*n+m*m;
- if (d>md) continue;
- float f = bmap[d];
- amap[(i+m)+(j+n)*w] += (g*f);
- }
- }
- }
- }
-
- TQImage res(w,h,32);
- res.setAlphaBuffer(true);
- int r = tqRed(color);
- int g = tqGreen(color);
- int b = tqBlue(color);
-
- // divide by factor
- factor = 1.0/factor;
-
- for(int j=0; j<h; j++) {
- for(int i=0; i<w; i++) {
- int a = (int)(amap[i+j*w] * factor * 255.0);
- if (a > 255) a = 255;
- res.setPixel(i,j, tqRgba(r,g,b,a));
- }
- }
-
- pt->drawImage(x-thickness, y-thickness, res, 0, 0, -1, -1, Qt::DiffuseAlphaDither | Qt::ColorOnly | Qt::PreferDither);
- }
- // Paint next shadow effect
- if (shadow->next) paintShadow(pt, f, _tx, _ty, shadow->next);
-}
-
-/**
- * Distributes pixels to justify text.
- * @param numSpaces spaces left, will be decremented by one
- * @param toAdd number of pixels left to be distributed, will have the
- * amount of pixels distributed during this call subtracted.
- * @return number of pixels to distribute
- */
-static inline int justifyWidth(int &numSpaces, int &toAdd) {
- int a = 0;
- if ( numSpaces ) {
- a = toAdd/numSpaces;
- toAdd -= a;
- numSpaces--;
- }/*end if*/
- return a;
-}
-
-FindSelectionResult InlineTextBox::checkSelectionPoint(int _x, int _y, int _tx, int _ty, const Font *f, RenderText *text, int & offset, short lineHeight)
-{
-// kdDebug(6040) << "InlineTextBox::checkSelectionPoint " << this << " _x=" << _x << " _y=" << _y
-// << " _tx+m_x=" << _tx+m_x << " _ty+m_y=" << _ty+m_y << endl;
- offset = 0;
-
- if ( _y < _ty + m_y )
- return SelectionPointBefore; // above -> before
-
- if ( _y > _ty + m_y + lineHeight ) {
- // below -> after
- // Set the offset to the max
- offset = m_len;
- return SelectionPointAfter;
- }
- if ( _x > _tx + m_x + m_width ) {
- // to the right
- return SelectionPointAfterInLine;
- }
-
- // The Y matches, check if we're on the left
- if ( _x < _tx + m_x ) {
- return SelectionPointBeforeInLine;
- }
-
- // consider spacing for justified text
- int toAdd = m_toAdd;
- bool justified = text->style()->textAlign() == JUSTIFY && toAdd > 0;
- int numSpaces = 0;
- if (justified) {
-
- for( int i = 0; i < m_len; i++ )
- if ( text->str->s[m_start+i].category() == TQChar::Separator_Space )
- numSpaces++;
-
- }/*end if*/
-
- int delta = _x - (_tx + m_x);
- //kdDebug(6040) << "InlineTextBox::checkSelectionPoint delta=" << delta << endl;
- int pos = 0;
- if ( m_reversed ) {
- delta -= m_width;
- while(pos < m_len) {
- int w = f->width( text->str->s, text->str->l, m_start + pos);
- if (justified && text->str->s[m_start + pos].category() == TQChar::Separator_Space)
- w += justifyWidth(numSpaces, toAdd);
- int w2 = w/2;
- w -= w2;
- delta += w2;
- if(delta >= 0) break;
- pos++;
- delta += w;
- }
- } else {
- while(pos < m_len) {
- int w = f->width( text->str->s, text->str->l, m_start + pos);
- if (justified && text->str->s[m_start + pos].category() == TQChar::Separator_Space)
- w += justifyWidth(numSpaces, toAdd);
- int w2 = w/2;
- w -= w2;
- delta -= w2;
- if(delta <= 0) break;
- pos++;
- delta -= w;
- }
- }
-// kdDebug( 6040 ) << " Text --> inside at position " << pos << endl;
- offset = pos;
- return SelectionPointInside;
-}
-
-int InlineTextBox::offsetForPoint(int _x, int &ax) const
-{
- // Do binary search for finding out offset, saves some time for long
- // runs.
- int start = 0;
- int end = m_len;
- ax = m_x;
- int offset = (start + end) / 2;
- while (end - start > 0) {
- // always snap to the right column. This makes up for "jumpy" vertical
- // navigation.
- if (end - start == 1) start = end;
-
- offset = (start + end) / 2;
- ax = m_x + widthFromStart(offset);
- if (ax > _x) end = offset;
- else if (ax < _x) start = offset;
- else break;
- }
- return m_start + offset;
-}
-
-int InlineTextBox::widthFromStart(int pos) const
-{
- // gasp! sometimes pos is i < 0 which crashes Font::width
- pos = kMax(pos, 0);
-
- const RenderText *t = renderText();
- Q_ASSERT(t->isText());
- const Font *f = t->htmlFont(m_firstLine);
- const TQFontMetrics &fm = t->fontMetrics(m_firstLine);
-
- int numSpaces = 0;
- // consider spacing for justified text
- bool justified = t->style()->textAlign() == JUSTIFY;
- //kdDebug(6000) << "InlineTextBox::width(int)" << endl;
- if (justified && m_toAdd > 0) do {
- //kdDebug(6000) << "justify" << endl;
-
-// TQConstString cstr = TQConstString(t->str->s + m_start, m_len);
- for( int i = 0; i < m_len; i++ )
- if ( t->str->s[m_start+i].category() == TQChar::Separator_Space )
- numSpaces++;
- if (numSpaces == 0) break;
-
- int toAdd = m_toAdd;
- int w = 0; // accumulated width
- int start = 0; // start of non-space sequence
- int current = 0; // current position
- while (current < pos) {
- // add spacing
- while (current < pos && t->str->s[m_start + current].category() == TQChar::Separator_Space) {
- w += f->getWordSpacing();
- w += f->getLetterSpacing();
- w += justifyWidth(numSpaces, toAdd);
- w += fm.width(' '); // ### valid assumption? (LS)
- current++; start++;
- }/*wend*/
- if (current >= pos) break;
-
- // seek next space
- while (current < pos && t->str->s[m_start + current].category() != TQChar::Separator_Space)
- current++;
-
- // check run without spaces
- if ( current > start ) {
- w += f->width(t->str->s + m_start, m_len, start, current - start);
- start = current;
- }
- }
-
- return w;
-
- } while(false);/*end if*/
-
- //kdDebug(6000) << "default" << endl;
- // else use existing width function
- return f->width(t->str->s + m_start, m_len, 0, pos);
-
-}
-
-long InlineTextBox::minOffset() const
-{
- return m_start;
-}
-
-long InlineTextBox::maxOffset() const
-{
- return m_start + m_len;
-}
-
-int InlineTextBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox)
-{
- if (foundBox) {
- m_truncation = cFullTruncation;
- return -1;
- }
-
- int ellipsisX = ltr ? blockEdge - ellipsisWidth : blockEdge + ellipsisWidth;
-
- // For LTR, if the left edge of the ellipsis is to the left of our text run, then we are the run that will get truncated.
- if (ltr) {
- if (ellipsisX <= m_x) {
- // Too far. Just set full truncation, but return -1 and let the ellipsis just be placed at the edge of the box.
- m_truncation = cFullTruncation;
- foundBox = true;
- return -1;
- }
-
- if (ellipsisX < m_x + m_width) {
- if (m_reversed)
- return -1; // FIXME: Support LTR truncation when the last run is RTL someday.
-
- foundBox = true;
-
- int ax;
- int offset = offsetForPoint(ellipsisX, ax) - 1;
- if (offset <= m_start) {
- // No characters should be rendered. Set ourselves to full truncation and place the ellipsis at the min of our start
- // and the ellipsis edge.
- m_truncation = cFullTruncation;
- return kMin(ellipsisX, (int)m_x);
- }
-
- // Set the truncation index on the text run. The ellipsis needs to be placed just after the last visible character.
- m_truncation = offset;
- return widthFromStart(offset - m_start);
- }
- }
- else {
- // FIXME: Support RTL truncation someday, including both modes (when the leftmost run on the line is either RTL or LTR)
- }
- return -1;
-}
-
-// -----------------------------------------------------------------------------
-
-InlineTextBoxArray::InlineTextBoxArray()
-{
- setAutoDelete(false);
-}
-
-int InlineTextBoxArray::compareItems( Item d1, Item d2 )
-{
- assert(d1);
- assert(d2);
-
- return static_cast<InlineTextBox*>(d1)->m_y - static_cast<InlineTextBox*>(d2)->m_y;
-}
-
-// remove this once TQVector::bsearch is fixed
-int InlineTextBoxArray::findFirstMatching(Item d) const
-{
- int len = count();
-
- if ( !len )
- return -1;
- if ( !d )
- return -1;
- int n1 = 0;
- int n2 = len - 1;
- int mid = 0;
- bool found = false;
- while ( n1 <= n2 ) {
- int res;
- mid = (n1 + n2)/2;
- if ( (*this)[mid] == 0 ) // null item greater
- res = -1;
- else
- res = ((TQGVector*)this)->compareItems( d, (*this)[mid] );
- if ( res < 0 )
- n2 = mid - 1;
- else if ( res > 0 )
- n1 = mid + 1;
- else { // found it
- found = true;
- break;
- }
- }
- /* if ( !found )
- return -1; */
- // search to first one equal or bigger
- while ( found && (mid > 0) && !((TQGVector*)this)->compareItems(d, (*this)[mid-1]) )
- mid--;
- return mid;
-}
-
-// -------------------------------------------------------------------------------------
-
-RenderText::RenderText(DOM::NodeImpl* node, DOMStringImpl *_str)
- : RenderObject(node)
-{
- // init RenderObject attributes
- setRenderText(); // our object inherits from RenderText
-
- m_minWidth = -1;
- m_maxWidth = -1;
- str = _str;
- if(str) str->ref();
- KHTMLAssert(!str || !str->l || str->s);
-
- m_selectionState = SelectionNone;
- m_hasReturn = true;
-
-#ifdef DEBUG_LAYOUT
- TQConstString cstr(str->s, str->l);
- kdDebug( 6040 ) << "RenderText ctr( "<< cstr.string().length() << " ) '" << cstr.string() << "'" << endl;
-#endif
-}
-
-void RenderText::setStyle(RenderStyle *_style)
-{
- if ( style() != _style ) {
- bool changedText = ((!style() && ( _style->textTransform() != TTNONE ||
- !_style->preserveLF() || !_style->preserveWS() )) ||
- (style() && (style()->textTransform() != _style->textTransform() ||
- style()->whiteSpace() != _style->whiteSpace())));
-
- RenderObject::setStyle( _style );
- m_lineHeight = RenderObject::lineHeight(false);
-
- if (!isBR() && changedText) {
- DOM::DOMStringImpl* textToTransform = originalString();
- if (textToTransform)
- setText(textToTransform, true);
- }
- }
-}
-
-RenderText::~RenderText()
-{
- KHTMLAssert(m_lines.count() == 0);
- if(str) str->deref();
-}
-
-void RenderText::deleteInlineBoxes(RenderArena* arena)
-{
- // this is a slight variant of TQArray::clear().
- // We don't delete the array itself here because its
- // likely to be used in the same size later again, saves
- // us resize() calls
- unsigned int len = m_lines.size();
- if (len) {
- if (!arena)
- arena = renderArena();
- for(unsigned int i=0; i < len; i++) {
- InlineTextBox* s = m_lines.at(i);
- if (s)
- s->detach(arena);
- m_lines.remove(i);
- }
- }
-
- KHTMLAssert(m_lines.count() == 0);
-}
-
-bool RenderText::isTextFragment() const
-{
- return false;
-}
-
-DOM::DOMStringImpl* RenderText::originalString() const
-{
- return element() ? element()->string() : 0;
-}
-
-InlineTextBox * RenderText::findInlineTextBox( int offset, int &pos, bool checkFirstLetter )
-{
- // The text boxes point to parts of the rendertext's str string
- // (they don't include '\n')
- // Find the text box that includes the character at @p offset
- // and return pos, which is the position of the char in the run.
-
- // FIXME: make this use binary search? Dirk says it won't work :-( (LS)
- (void)checkFirstLetter;
-#if 0
- if (checkFirstLetter && forcedMinOffset()) {
-// kdDebug(6040) << "checkFirstLetter: forcedMinOffset: " << forcedMinOffset() << endl;
- RenderFlow *firstLetter = static_cast<RenderFlow *>(previousSibling());
- if (firstLetter && firstLetter->isFlow() && firstLetter->isFirstLetter()) {
- RenderText *letterText = static_cast<RenderText *>(firstLetter->firstChild());
- //kdDebug(6040) << "lettertext: " << letterText << " minOfs: " << letterText->minOffset() << " maxOfs: " << letterText->maxOffset() << endl;
- if (offset >= letterText->minOffset() && offset <= letterText->maxOffset()) {
- InlineTextBox *result = letterText->findInlineTextBox(offset, pos, false);
- //kdDebug(6040) << "result: " << result << endl;
- if (result) return result;
- }
- }
- }
-#endif
-
- if ( m_lines.isEmpty() )
- return 0L;
-
- // The text boxes don't resemble a contiguous coverage of the text, there
- // may be holes. Therefore, we snap to the nearest previous text box if
- // the given offset happens to point to such a hole.
-
- InlineTextBox* s = m_lines[0];
- uint count = m_lines.count();
- uint si = 0;
- uint nearest_idx = 0; // index of nearest text box
- int nearest = INT_MAX; // nearest distance
-//kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl;
- while(!(offset >= s->m_start && offset <= s->m_start + s->m_len)
- && ++si < count)
- {
- int dist = offset - (s->m_start + s->m_len);
-//kdDebug(6040) << "dist " << dist << " nearest " << nearest << endl;
- if (dist >= 0 && dist <= nearest) {
- nearest = dist;
- nearest_idx = si - 1;
- }/*end if*/
- s = m_lines[si];
-//kdDebug(6040) << "s[" << si << "] m_start " << s->m_start << " m_end " << (s->m_start + s->m_len) << endl;
- }
-//kdDebug(6040) << "nearest_idx " << nearest_idx << " count " << count << endl;
- if (si >= count) s = m_lines[nearest_idx];
- // we are now in the correct text box
- pos = kMin(offset - s->m_start, int( s->m_len ));
- //kdDebug(6040) << "offset=" << offset << " s->m_start=" << s->m_start << endl;
- return s;
-}
-
-bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction /*hitTestAction*/, bool /*inBox*/)
-{
- assert(parent());
-
- bool inside = false;
- if (style()->visibility() != HIDDEN) {
- InlineTextBox *s = m_lines.count() ? m_lines[0] : 0;
- int si = 0;
- while(s) {
- if((_y >=_ty + s->m_y) && (_y < _ty + s->m_y + s->m_height) &&
- (_x >= _tx + s->m_x) && (_x <_tx + s->m_x + s->m_width) ) {
- inside = true;
- break;
- }
-
- s = si < (int) m_lines.count()-1 ? m_lines[++si] : 0;
- }
- }
-
- // #### ported over from Safari. Can this happen at all? (lars)
-
- if (inside && element()) {
- if (info.innerNode() && info.innerNode()->renderer() &&
- !info.innerNode()->renderer()->isInline()) {
- // Within the same layer, inlines are ALWAYS fully above blocks. Change inner node.
- info.setInnerNode(element());
-
- // Clear everything else.
- info.setInnerNonSharedNode(0);
- info.setURLElement(0);
- }
-
- if (!info.innerNode())
- info.setInnerNode(element());
-
- if(!info.innerNonSharedNode())
- info.setInnerNonSharedNode(element());
- }
-
- return inside;
-}
-
-FindSelectionResult RenderText::checkSelectionPoint(int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int &offset, SelPointState &)
-{
-// kdDebug(6040) << "RenderText::checkSelectionPoint " << this << " _x=" << _x << " _y=" << _y
-// << " _tx=" << _tx << " _ty=" << _ty << endl;
-//kdDebug(6040) << renderName() << "::checkSelectionPoint x=" << xPos() << " y=" << yPos() << " w=" << width() << " h=" << height() << " m_lines.count=" << m_lines.count() << endl;
-
- NodeImpl *lastNode = 0;
- int lastOffset = 0;
- FindSelectionResult lastResult = SelectionPointAfter;
-
- for(unsigned int si = 0; si < m_lines.count(); si++)
- {
- InlineTextBox* s = m_lines[si];
- FindSelectionResult result;
- const Font *f = htmlFont( si==0 );
- result = s->checkSelectionPoint(_x, _y, _tx, _ty, f, this, offset, m_lineHeight);
-
-// kdDebug(6040) << "RenderText::checkSelectionPoint " << this << " line " << si << " result=" << result << " offset=" << offset << endl;
- if ( result == SelectionPointInside ) // x,y is inside the textrun
- {
- offset += s->m_start; // add the offset from the previous lines
-// kdDebug(6040) << "RenderText::checkSelectionPoint inside -> " << offset << endl;
- node = element();
- return SelectionPointInside;
- } else if ( result == SelectionPointBefore ) {
- if (!lastNode) {
- // x,y is before the textrun -> stop here
- offset = 0;
-// kdDebug(6040) << "RenderText::checkSelectionPoint " << this << "before us -> returning Before" << endl;
- node = element();
- return SelectionPointBefore;
- }
- } else if ( result == SelectionPointBeforeInLine ) {
- offset = s->m_start;
- node = element();
- return SelectionPointInside;
- } else if ( result == SelectionPointAfterInLine ) {
- lastOffset = s->m_start + s->m_len;
- lastNode = element();
- lastResult = result;
- // no return here
- }
-
- }
-
- if (lastNode) {
- offset = lastOffset;
- node = lastNode;
-// kdDebug(6040) << "RenderText::checkSelectionPoint: lastNode " << lastNode << " lastOffset " << lastOffset << endl;
- return lastResult;
- }
-
- // set offset to max
- offset = str->l;
- //tqDebug("setting node to %p", element());
- node = element();
-// kdDebug(6040) << "RenderText::checkSelectionPoint: node " << node << " offset " << offset << endl;
- return SelectionPointAfter;
-}
-
-void RenderText::caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height)
-{
- if (!m_lines.count()) {
- _x = _y = height = -1;
- width = 1;
- return;
- }
-
- int pos;
- InlineTextBox * s = findInlineTextBox( offset, pos, true );
- RenderText *t = s->renderText();
-// kdDebug(6040) << "offset="<<offset << " pos="<<pos << endl;
-
- const TQFontMetrics &fm = t->metrics( s->m_firstLine );
- height = fm.height(); // s->m_height;
-
- _x = s->m_x + s->widthFromStart(pos);
- _y = s->m_y + s->baseline() - fm.ascent();
- width = 1;
- if (flags & CFOverride) {
- width = offset < maxOffset() ? fm.width(str->s[offset]) : 1;
- }/*end if*/
-#if 0
- kdDebug(6040) << "_x="<<_x << " s->m_x="<<s->m_x
- << " s->m_start"<<s->m_start
- << " s->m_len" << s->m_len << " _y=" << _y << endl;
-#endif
-
- int absx, absy;
-
- if (absolutePosition(absx,absy))
- {
- //kdDebug(6040) << "absx=" << absx << " absy=" << absy << endl;
- _x += absx;
- _y += absy;
- } else {
- // we don't know our absolute position, and there is no point returning
- // just a relative one
- _x = _y = -1;
- }
-}
-
-long RenderText::minOffset() const
-{
- if (!m_lines.count()) return 0;
- // FIXME: it is *not* guaranteed that the first run contains the lowest offset
- // Either make this a linear search (slow),
- // or maintain an index (needs much mem),
- // or calculate and store it in bidi.cpp (needs calculation even if not needed)
- // (LS)
- return m_lines[0]->m_start;
-}
-
-long RenderText::maxOffset() const
-{
- int count = m_lines.count();
- if (!count) return str->l;
- // FIXME: it is *not* guaranteed that the last run contains the highest offset
- // Either make this a linear search (slow),
- // or maintain an index (needs much mem),
- // or calculate and store it in bidi.cpp (needs calculation even if not needed)
- // (LS)
- return m_lines[count - 1]->m_start + m_lines[count - 1]->m_len;
-}
-
-bool RenderText::absolutePosition(int &xPos, int &yPos, bool) const
-{
- return RenderObject::absolutePosition(xPos, yPos, false);
-}
-
-bool RenderText::posOfChar(int chr, int &x, int &y)
-{
- if (!parent())
- return false;
- parent()->absolutePosition( x, y, false );
-
- int pos;
- InlineTextBox * s = findInlineTextBox( chr, pos );
-
- if ( s ) {
- // s is the line containing the character
- x += s->m_x; // this is the x of the beginning of the line, but it's good enough for now
- y += s->m_y;
- return true;
- }
-
- return false;
-}
-
-void RenderText::paint( PaintInfo& /*pI*/, int /*tx*/, int /*ty*/)
-{
- KHTMLAssert( false );
-}
-
-void RenderText::calcMinMaxWidth()
-{
- KHTMLAssert( !minMaxKnown() );
-
- // ### calc Min and Max width...
- m_minWidth = m_beginMinWidth = m_endMinWidth = 0;
- m_maxWidth = 0;
-
- if (isBR())
- return;
-
- int currMinWidth = 0;
- int currMaxWidth = 0;
- m_hasBreakableChar = m_hasBreak = m_hasBeginWS = m_hasEndWS = false;
-
- // ### not 100% correct for first-line
- const Font *f = htmlFont( false );
- int wordSpacing = style()->wordSpacing();
- int len = str->l;
- bool isSpace = false;
- bool firstWord = true;
- bool firstLine = true;
- for(int i = 0; i < len; i++)
- {
- unsigned short c = str->s[i].unicode();
- bool isNewline = false;
-
- // If line-breaks survive to here they are preserved
- if ( c == '\n' ) {
- m_hasBreak = true;
- isNewline = true;
- isSpace = false;
- } else
- isSpace = c == ' ';
-
- if ((isSpace || isNewline) && i == 0)
- m_hasBeginWS = true;
- if ((isSpace || isNewline) && i == len-1)
- m_hasEndWS = true;
-
- if (i && c == SOFT_HYPHEN)
- continue;
-
- int wordlen = 0;
- while( i+wordlen < len && (i+wordlen == 0 || str->s[i+wordlen].unicode() != SOFT_HYPHEN) &&
- !(isBreakable( str->s, i+wordlen, str->l )) )
- wordlen++;
-
- if (wordlen)
- {
-#ifndef APPLE_CHANGES
- int w = f->width(str->s, str->l, i, wordlen);
-#else
- int w = widthFromCache(f, i, wordlen);
-#endif
- currMinWidth += w;
- currMaxWidth += w;
-
- // Add in wordspacing to our maxwidth, but not if this is the last word.
- if (wordSpacing && !containsOnlyWhitespace(i+wordlen, len-(i+wordlen)))
- currMaxWidth += wordSpacing;
-
- if (firstWord) {
- firstWord = false;
- m_beginMinWidth = w;
- }
- m_endMinWidth = w;
-
- if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
- currMinWidth = 0;
-
- i += wordlen-1;
- }
- else {
- // Nowrap can never be broken, so don't bother setting the
- // breakable character boolean. Pre can only be broken if we encounter a newline.
- if (style()->autoWrap() || isNewline)
- m_hasBreakableChar = true;
-
- if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
- currMinWidth = 0;
-
- if (isNewline) // Only set if isPre was true and we saw a newline.
- {
- if ( firstLine ) {
- firstLine = false;
- m_beginMinWidth = currMaxWidth;
- }
-
- if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
- currMaxWidth = 0;
- }
- else
- {
- currMaxWidth += f->width( str->s, str->l, i + wordlen );
- }
- }
- }
-
- if(currMinWidth > m_minWidth) m_minWidth = currMinWidth;
- if(currMaxWidth > m_maxWidth) m_maxWidth = currMaxWidth;
-
- if (!style()->autoWrap()) {
- m_minWidth = m_maxWidth;
- if (style()->preserveLF()) {
- if (firstLine)
- m_beginMinWidth = m_maxWidth;
- m_endMinWidth = currMaxWidth;
- }
- }
-
- setMinMaxKnown();
- //kdDebug( 6040 ) << "Text::calcMinMaxWidth(): min = " << m_minWidth << " max = " << m_maxWidth << endl;
-
-}
-
-int RenderText::minXPos() const
-{
- if (!m_lines.count())
- return 0;
- int retval=6666666;
- for (unsigned i=0;i < m_lines.count(); i++)
- {
- retval = kMin ( retval, int( m_lines[i]->m_x ));
- }
- return retval;
-}
-
-int RenderText::inlineXPos() const
-{
- return minXPos();
-}
-
-int RenderText::inlineYPos() const
-{
- return m_lines.isEmpty() ? 0 : m_lines[0]->yPos();
-}
-
-const TQFont &RenderText::font()
-{
- return style()->font();
-}
-
-void RenderText::setText(DOMStringImpl *text, bool force)
-{
- if( !force && str == text ) return;
-
- DOMStringImpl *oldstr = str;
- if(text && style())
- str = text->collapseWhiteSpace(style()->preserveLF(), style()->preserveWS());
- else
- str = text;
- if(str) str->ref();
- if(oldstr) oldstr->deref();
-
- if ( str && style() ) {
- oldstr = str;
- switch(style()->textTransform()) {
- case CAPITALIZE:
- {
- RenderObject *o;
- bool runOnString = false;
-
- // find previous non-empty text renderer if one exists
- for (o = previousRenderer(); o; o = o->previousRenderer()) {
- if (!o->isInlineFlow()) {
- if (!o->isText())
- break;
-
- DOMStringImpl *prevStr = static_cast<RenderText*>(o)->string();
- // !prevStr can happen with css like "content:open-quote;"
- if (!prevStr)
- break;
-
- if (prevStr->length() == 0)
- continue;
- TQChar c = (*prevStr)[prevStr->length() - 1];
- if (!c.isSpace())
- runOnString = true;
-
- break;
- }
- }
-
- str = str->capitalize(runOnString);
- }
- break;
-
-
-
- case UPPERCASE: str = str->upper(); break;
- case LOWERCASE: str = str->lower(); break;
- case NONE:
- default:;
- }
- str->ref();
- oldstr->deref();
- }
-
- // ### what should happen if we change the text of a
- // RenderBR object ?
- KHTMLAssert(!isBR() || (str->l == 1 && (*str->s) == '\n'));
- KHTMLAssert(!str->l || str->s);
-
- setNeedsLayoutAndMinMaxRecalc();
-#ifdef BIDI_DEBUG
- TQConstString cstr(str->s, str->l);
- kdDebug( 6040 ) << "RenderText::setText( " << cstr.string().length() << " ) '" << cstr.string() << "'" << endl;
-#endif
-}
-
-int RenderText::height() const
-{
- int retval;
- if ( m_lines.count() )
- retval = m_lines[m_lines.count()-1]->m_y + m_lineHeight - m_lines[0]->m_y;
- else
- retval = metrics( false ).height();
-
- return retval;
-}
-
-short RenderText::lineHeight( bool firstLine ) const
-{
- if ( firstLine )
- return RenderObject::lineHeight( firstLine );
-
- return m_lineHeight;
-}
-
-short RenderText::baselinePosition( bool firstLine ) const
-{
- const TQFontMetrics &fm = metrics( firstLine );
- return fm.ascent() +
- ( lineHeight( firstLine ) - fm.height() ) / 2;
-}
-
-InlineBox* RenderText::createInlineBox(bool, bool isRootLineBox)
-{
- KHTMLAssert( !isRootLineBox );
- return new (renderArena()) InlineTextBox(this);
-}
-
-void RenderText::position(InlineBox* box, int from, int len, bool reverse)
-{
-//kdDebug(6040) << "position: from="<<from<<" len="<<len<<endl;
- // ### should not be needed!!!
- // asserts sometimes with pre (that unibw-hamburg testcase). ### find out why
- //KHTMLAssert(!(len == 0 || (str->l && len == 1 && *(str->s+from) == '\n') ));
- // It is now needed. BRs need text boxes too otherwise caret navigation
- // gets stuck (LS)
- // if (len == 0 || (str->l && len == 1 && *(str->s+from) == '\n') ) return;
-
- reverse = reverse && !style()->visuallyOrdered();
-
-#ifdef DEBUG_LAYOUT
- TQChar *ch = str->s+from;
- TQConstString cstr(ch, len);
-#endif
-
- KHTMLAssert(box->isInlineTextBox());
- InlineTextBox *s = static_cast<InlineTextBox *>(box);
- s->m_start = from;
- s->m_len = len;
- s->m_reversed = reverse;
- //kdDebug(6040) << "m_start: " << s->m_start << " m_len: " << s->m_len << endl;
-
- if(m_lines.count() == m_lines.size())
- m_lines.resize(m_lines.size()*2+1);
-
- m_lines.insert(m_lines.count(), s);
- //kdDebug(6040) << this << " " << renderName() << "::position inserted" << endl;
-}
-
-unsigned int RenderText::width(unsigned int from, unsigned int len, bool firstLine) const
-{
- if(!str->s || from > str->l ) return 0;
- if ( from + len > str->l ) len = str->l - from;
-
- const Font *f = htmlFont( firstLine );
- return width( from, len, f );
-}
-
-unsigned int RenderText::width(unsigned int from, unsigned int len, const Font *f) const
-{
- if(!str->s || from > str->l ) return 0;
- if ( from + len > str->l ) len = str->l - from;
-
- if ( f == &style()->htmlFont() && from == 0 && len == str->l )
- return m_maxWidth;
-
- int w = f->width(str->s, str->l, from, len );
-
- //kdDebug( 6040 ) << "RenderText::width(" << from << ", " << len << ") = " << w << endl;
- return w;
-}
-
-short RenderText::width() const
-{
- int w;
- int minx = 100000000;
- int maxx = 0;
- // slooow
- for(unsigned int si = 0; si < m_lines.count(); si++) {
- InlineTextBox* s = m_lines[si];
- if(s->m_x < minx)
- minx = s->m_x;
- if(s->m_x + s->m_width > maxx)
- maxx = s->m_x + s->m_width;
- }
-
- w = kMax(0, maxx-minx);
-
- return w;
-}
-
-void RenderText::repaint(Priority p)
-{
- RenderObject *cb = containingBlock();
- if(cb)
- cb->repaint(p);
-}
-
-bool RenderText::isFixedWidthFont() const
-{
- return TQFontInfo(style()->font()).fixedPitch();
-}
-
-short RenderText::verticalPositionHint( bool firstLine ) const
-{
- return parent()->verticalPositionHint( firstLine );
-}
-
-const TQFontMetrics &RenderText::metrics(bool firstLine) const
-{
- if( firstLine && hasFirstLine() ) {
- RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
- if ( pseudoStyle )
- return pseudoStyle->fontMetrics();
- }
- return style()->fontMetrics();
-}
-
-const Font *RenderText::htmlFont(bool firstLine) const
-{
- const Font *f = 0;
- if( firstLine && hasFirstLine() ) {
- RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE);
- if ( pseudoStyle )
- f = &pseudoStyle->htmlFont();
- } else {
- f = &style()->htmlFont();
- }
- return f;
-}
-
-bool RenderText::containsOnlyWhitespace(unsigned int from, unsigned int len) const
-{
- unsigned int currPos;
- for (currPos = from;
- currPos < from+len && (str->s[currPos] == '\n' || str->s[currPos].direction() == TQChar::DirWS);
- currPos++);
- return currPos >= (from+len);
-}
-
-void RenderText::trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
- short& endMinW, bool& endWS,
- bool& hasBreakableChar, bool& hasBreak,
- short& beginMaxW, short& endMaxW,
- short& minW, short& maxW, bool& stripFrontSpaces)
-{
- bool preserveWS = style()->preserveWS();
- bool preserveLF = style()->preserveLF();
- bool autoWrap = style()->autoWrap();
- if (preserveWS)
- stripFrontSpaces = false;
-
- int len = str->l;
- if (len == 0 || (stripFrontSpaces && str->containsOnlyWhitespace())) {
- maxW = 0;
- hasBreak = false;
- return;
- }
-
- minW = m_minWidth;
- maxW = m_maxWidth;
- beginWS = stripFrontSpaces ? false : m_hasBeginWS;
- endWS = m_hasEndWS;
-
- beginMinW = m_beginMinWidth;
- endMinW = m_endMinWidth;
-
- hasBreakableChar = m_hasBreakableChar;
- hasBreak = m_hasBreak;
-
- if (stripFrontSpaces && (str->s[0].direction() == TQChar::DirWS || (!preserveLF && str->s[0] == '\n'))) {
- const Font *f = htmlFont( false );
- TQChar space[1]; space[0] = ' ';
- int spaceWidth = f->width(space, 1, 0);
- maxW -= spaceWidth;
- }
-
- stripFrontSpaces = !preserveWS && m_hasEndWS;
-
- if (!autoWrap)
- minW = maxW;
- else if (minW > maxW)
- minW = maxW;
-
- // Compute our max widths by scanning the string for newlines.
- if (hasBreak) {
- const Font *f = htmlFont( false );
- bool firstLine = true;
- beginMaxW = endMaxW = maxW;
- for(int i = 0; i < len; i++)
- {
- int linelen = 0;
- while( i+linelen < len && str->s[i+linelen] != '\n')
- linelen++;
-
- if (linelen)
- {
-#ifndef APPLE_CHANGES
- endMaxW = f->width(str->s, str->l, i, linelen);
-#else
- endMaxW = widthFromCache(f, i, linelen);
-#endif
- if (firstLine) {
- firstLine = false;
- beginMaxW = endMaxW;
- }
- i += linelen;
- }
- else if (firstLine) {
- beginMaxW = 0;
- firstLine = false;
- }
- if (i == len-1)
- // A <pre> run that ends with a newline, as in, e.g.,
- // <pre>Some text\n\n<span>More text</pre>
- endMaxW = 0;
- }
- }
-}
-
-#ifdef ENABLE_DUMP
-
-static TQString quoteAndEscapeNonPrintables(const TQString &s)
-{
- TQString result;
- result += '"';
- for (uint i = 0; i != s.length(); ++i) {
- TQChar c = s.at(i);
- if (c == '\\') {
- result += "\\\\";
- } else if (c == '"') {
- result += "\\\"";
- } else {
- ushort u = c.unicode();
- if (u >= 0x20 && u < 0x7F) {
- result += c;
- } else {
- TQString hex;
- hex.sprintf("\\x{%X}", u);
- result += hex;
- }
- }
- }
- result += '"';
- return result;
-}
-
-static void writeTextRun(TQTextStream &ts, const RenderText &o, const InlineTextBox &run)
-{
- ts << "text run at (" << run.m_x << "," << run.m_y << ") width " << run.m_width << ": "
- << quoteAndEscapeNonPrintables(o.data().string().mid(run.m_start, run.m_len));
-}
-
-void RenderText::dump(TQTextStream &stream, const TQString &ind) const
-{
- RenderObject::dump( stream, ind );
-
- for (unsigned int i = 0; i < m_lines.count(); i++) {
- stream << endl << ind << " ";
- writeTextRun(stream, *this, *m_lines[i]);
- }
-}
-#endif
-
-RenderTextFragment::RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str,
- int startOffset, int endOffset)
-:RenderText(_node, _str->substring(startOffset, endOffset)),
-m_start(startOffset), m_end(endOffset), m_generatedContentStr(0)
-{}
-
-RenderTextFragment::RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str)
-:RenderText(_node, _str), m_start(0)
-{
- m_generatedContentStr = _str;
- if (_str) {
- _str->ref();
- m_end = _str->l;
- }
- else
- m_end = 0;
-}
-
-RenderTextFragment::~RenderTextFragment()
-{
- if (m_generatedContentStr)
- m_generatedContentStr->deref();
-}
-
-bool RenderTextFragment::isTextFragment() const
-{
- return true;
-}
-
-DOM::DOMStringImpl* RenderTextFragment::originalString() const
-{
- DOM::DOMStringImpl* result = 0;
- if (element())
- result = element()->string();
- else
- result = contentString();
- if (result && (start() > 0 || start() < result->l))
- result = result->substring(start(), end());
- return result;
-}
-
-#undef BIDI_DEBUG
-#undef DEBUG_LAYOUT
diff --git a/khtml/rendering/render_text.h b/khtml/rendering/render_text.h
deleted file mode 100644
index 50132fbc7..000000000
--- a/khtml/rendering/render_text.h
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
- * This file is part of the DOM implementation for KDE.
- *
- * (C) 1999-2003 Lars Knoll (knoll@kde.org)
- * (C) 2000-2003 Dirk Mueller (mueller@kde.org)
- * (C) 2003 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef RENDERTEXT_H
-#define RENDERTEXT_H
-
-#include "dom/dom_string.h"
-#include "xml/dom_stringimpl.h"
-#include "xml/dom_textimpl.h"
-#include "rendering/render_object.h"
-#include "rendering/render_line.h"
-
-#include <tqptrvector.h>
-#include <assert.h>
-
-class TQPainter;
-class TQFontMetrics;
-
-// Define a constant for soft hyphen's unicode value.
-#define SOFT_HYPHEN 173
-
-const int cNoTruncation = -1;
-const int cFullTruncation = -2;
-
-namespace khtml
-{
- class RenderText;
- class RenderStyle;
-
-class InlineTextBox : public InlineBox
-{
-public:
- InlineTextBox(RenderObject *obj)
- :InlineBox(obj),
- // ### necessary as some codepaths (<br>) do *not* initialize these (LS)
- m_start(0), m_len(0), m_truncation(cNoTruncation), m_reversed(false), m_toAdd(0)
- {
- }
-
- void detach(RenderArena* renderArena);
-
- virtual void clearTruncation() { m_truncation = cNoTruncation; }
- virtual int placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox);
-
- // Overloaded new operator. Derived classes must override operator new
- // in order to allocate out of the RenderArena.
- void* operator new(size_t sz, RenderArena* renderArena) throw();
-
- // Overridden to prevent the normal delete from being called.
- void operator delete(void* ptr, size_t sz);
-
-private:
- // The normal operator new is disallowed.
- void* operator new(size_t sz) throw();
-
-public:
- void setSpaceAdd(int add) { m_width -= m_toAdd; m_toAdd = add; m_width += m_toAdd; }
- int spaceAdd() { return m_toAdd; }
-
- virtual bool isInlineTextBox() const { return true; }
-
- void paint(RenderObject::PaintInfo& i, int tx, int ty);
- void paintDecoration(TQPainter *pt, const Font *f, int _tx, int _ty, int decoration);
- void paintShadow(TQPainter *pt, const Font* f, int _tx, int _ty, const ShadowData *shadow );
- void paintSelection(const Font *f, RenderText *text, TQPainter *p, RenderStyle* style, int tx, int ty, int startPos, int endPos, int deco);
-
- void selectionStartEnd(int& sPos, int& ePos);
- RenderObject::SelectionState selectionState();
-
- // Return before, after (offset set to max), or inside the text, at @p offset
- FindSelectionResult checkSelectionPoint(int _x, int _y, int _tx, int _ty, const Font *f, RenderText *text, int & offset, short lineheight);
-
- bool checkVerticalPoint(int _y, int _ty, int _h, int height)
- { if((_ty + m_y > _y + _h) || (_ty + m_y + m_baseline + height < _y)) return false; return true; }
-
- /**
- * determines the offset into the DOMString of the character the given
- * coordinate points to.
- * The returned offset is never out of range.
- * @param _x given coordinate (relative to containing block)
- * @param ax returns exact coordinate the offset corresponds to
- * (relative to containing block)
- * @return the offset (relative to the RenderText object, not to this run)
- */
- int offsetForPoint(int _x, int &ax) const;
-
- /**
- * calculates the with of the specified chunk in this text box.
- * @param pos zero-based position within the text box up to which
- * the width is to be determined
- * @return the width in pixels
- */
- int widthFromStart(int pos) const;
-
- /** returns the lowest possible value the caret offset may have to
- * still point to a valid position.
- */
- virtual long minOffset() const;
- /** returns the highest possible value the caret offset may have to
- * still point to a valid position.
- */
- virtual long maxOffset() const;
-
- /** returns the associated render text
- */
- const RenderText *renderText() const;
- RenderText *renderText();
-
- int m_start;
- unsigned short m_len;
-
- int m_truncation; // Where to truncate when text overflow is applied.
- // We use special constants to denote no truncation (the whole run paints)
- // and full truncation (nothing paints at all).
-
- bool m_reversed : 1;
- unsigned m_toAdd : 14; // for justified text
-private:
- // this is just for TQVector::bsearch. Don't use it otherwise
- InlineTextBox(int _x, int _y)
- :InlineBox(0)
- {
- m_x = _x;
- m_y = _y;
- m_reversed = false;
- };
- friend class RenderText;
-};
-
-class InlineTextBoxArray : public TQPtrVector<InlineTextBox>
-{
-public:
- InlineTextBoxArray();
-
- InlineTextBox* first();
-
- int findFirstMatching( Item ) const;
- virtual int compareItems( Item, Item );
-};
-
-class RenderText : public RenderObject
-{
- friend class InlineTextBox;
-
-public:
- RenderText(DOM::NodeImpl* node, DOM::DOMStringImpl *_str);
- virtual ~RenderText();
-
- virtual bool isTextFragment() const;
- virtual DOM::DOMStringImpl* originalString() const;
-
- virtual const char *renderName() const { return "RenderText"; }
-
- virtual void setStyle(RenderStyle *style);
-
-
- virtual void paint( PaintInfo& i, int tx, int ty );
-
- virtual void deleteInlineBoxes(RenderArena* arena=0);
-
- DOM::DOMString data() const { return str; }
- DOM::DOMStringImpl *string() const { return str; }
-
- virtual InlineBox* createInlineBox(bool, bool);
-
- virtual void layout() {assert(false);}
-
- virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, HitTestAction hitTestAction, bool inBox);
-
- // Return before, after (offset set to max), or inside the text, at @p offset
- virtual FindSelectionResult checkSelectionPoint( int _x, int _y, int _tx, int _ty,
- DOM::NodeImpl*& node, int & offset,
- SelPointState & );
-
- unsigned int length() const { if (str) return str->l; else return 0; }
- TQChar *text() const { if (str) return str->s; else return 0; }
- unsigned int stringLength() const { return str->l; } // non virtual implementation of length()
- virtual void position(InlineBox* box, int from, int len, bool reverse);
-
- virtual unsigned int width(unsigned int from, unsigned int len, const Font *f) const;
- virtual unsigned int width(unsigned int from, unsigned int len, bool firstLine = false) const;
- virtual short width() const;
- virtual int height() const;
-
- // height of the contents (without paddings, margins and borders)
- virtual short lineHeight( bool firstLine ) const;
- virtual short baselinePosition( bool firstLine ) const;
-
- // overrides
- virtual void calcMinMaxWidth();
- virtual short minWidth() const { return m_minWidth; }
- virtual int maxWidth() const { return m_maxWidth; }
-
- void trimmedMinMaxWidth(short& beginMinW, bool& beginWS,
- short& endMinW, bool& endWS,
- bool& hasBreakableChar, bool& hasBreak,
- short& beginMaxW, short& endMaxW,
- short& minW, short& maxW, bool& stripFrontSpaces);
-
- bool containsOnlyWhitespace(unsigned int from, unsigned int len) const;
-
- ushort startMin() const { return m_startMin; }
- ushort endMin() const { return m_endMin; }
-
- // returns the minimum x position of all runs relative to the parent.
- // defaults to 0.
- int minXPos() const;
-
- virtual int inlineXPos() const;
- virtual int inlineYPos() const;
-
- bool hasReturn() const { return m_hasReturn; }
-
- virtual const TQFont &font();
- virtual short verticalPositionHint( bool firstLine ) const;
-
- bool isFixedWidthFont() const;
-
- void setText(DOM::DOMStringImpl *text, bool force=false);
-
- virtual SelectionState selectionState() const {return m_selectionState;}
- virtual void setSelectionState(SelectionState s) {m_selectionState = s; }
- virtual void caretPos(int offset, int flags, int &_x, int &_y, int &width, int &height);
- virtual bool absolutePosition(int &/*xPos*/, int &/*yPos*/, bool f = false) const;
- bool posOfChar(int ch, int &x, int &y);
-
- virtual short marginLeft() const { return style()->marginLeft().minWidth(0); }
- virtual short marginRight() const { return style()->marginRight().minWidth(0); }
-
- virtual void repaint(Priority p=NormalPriority);
-
- bool hasBreakableChar() const { return m_hasBreakableChar; }
- const TQFontMetrics &metrics(bool firstLine) const;
- const Font *htmlFont(bool firstLine) const;
-
- DOM::TextImpl *element() const
- { return static_cast<DOM::TextImpl*>(RenderObject::element()); }
-
- /** returns the lowest possible value the caret offset may have to
- * still point to a valid position.
- */
- virtual long minOffset() const;
-
- /** returns the highest possible value the caret offset may have to
- * still point to a valid position.
- */
- virtual long maxOffset() const;
-
- /** returns the number of inline text boxes
- */
- unsigned inlineTextBoxCount() const { return m_lines.count(); }
- /** returns the array of inline text boxes for this render text.
- */
- const InlineTextBoxArray &inlineTextBoxes() const { return m_lines; }
-
-#ifdef ENABLE_DUMP
- virtual void dump(TQTextStream &stream, const TQString &ind) const;
-#endif
-
- /** Find the text box that includes the character at @p offset
- * and return pos, which is the position of the char in the run.
- * @param offset zero-based offset into DOM string
- * @param pos returns relative position within text box
- * @param checkFirstLetter passing @p true will also regard :first-letter
- * boxes, if available.
- * @return the text box, or 0 if no match has been found
- */
- InlineTextBox * findInlineTextBox( int offset, int &pos,
- bool checkFirstLetter = false );
-
-protected: // members
- InlineTextBoxArray m_lines;
- DOM::DOMStringImpl *str; //
-
- short m_lineHeight;
- short m_minWidth;
- int m_maxWidth;
- short m_beginMinWidth;
- short m_endMinWidth;
-
- SelectionState m_selectionState : 3 ;
- bool m_hasReturn : 1;
- bool m_hasBreakableChar : 1;
- bool m_hasBreak : 1;
- bool m_hasBeginWS : 1;
- bool m_hasEndWS : 1;
-
- ushort m_startMin : 8;
- ushort m_endMin : 8;
-};
-
-inline const RenderText* InlineTextBox::renderText() const
-{ return static_cast<RenderText*>( object() ); }
-
-inline RenderText* InlineTextBox::renderText()
-{ return static_cast<RenderText*>( object() ); }
-
-// Used to represent a text substring of an element, e.g., for text runs that are split because of
-// first letter and that must therefore have different styles (and positions in the render tree).
-// We cache offsets so that text transformations can be applied in such a way that we can recover
-// the original unaltered string from our corresponding DOM node.
-class RenderTextFragment : public RenderText
-{
-public:
- RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str,
- int startOffset, int endOffset);
- RenderTextFragment(DOM::NodeImpl* _node, DOM::DOMStringImpl* _str);
- ~RenderTextFragment();
-
- virtual bool isTextFragment() const;
- virtual const char *renderName() const { return "RenderTextFragment"; }
-
- uint start() const { return m_start; }
- uint end() const { return m_end; }
-
- DOM::DOMStringImpl* contentString() const { return m_generatedContentStr; }
- virtual DOM::DOMStringImpl* originalString() const;
-
-private:
- uint m_start;
- uint m_end;
- DOM::DOMStringImpl* m_generatedContentStr;
-};
-} // end namespace
-#endif
diff --git a/khtml/rendering/table_layout.cpp b/khtml/rendering/table_layout.cpp
deleted file mode 100644
index f745640e7..000000000
--- a/khtml/rendering/table_layout.cpp
+++ /dev/null
@@ -1,1193 +0,0 @@
-/*
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
- * (C) 2002 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#include "table_layout.h"
-#include "render_table.h"
-
-#include <kglobal.h>
-
-using namespace khtml;
-
-// #define DEBUG_LAYOUT
-
-/*
- The text below is from the CSS 2.1 specs.
-
- Fixed table layout
- ------------------
-
- With this (fast) algorithm, the horizontal layout of the table does
- not depend on the contents of the cells; it only depends on the
- table's width, the width of the columns, and borders or cell
- spacing.
-
- The table's width may be specified explicitly with the 'width'
- property. A value of 'auto' (for both 'display: table' and 'display:
- inline-table') means use the automatic table layout algorithm.
-
- In the fixed table layout algorithm, the width of each column is
- determined as follows:
-
- 1. A column element with a value other than 'auto' for the 'width'
- property sets the width for that column.
-
- 2. Otherwise, a cell in the first row with a value other than
- 'auto' for the 'width' property sets the width for that column. If
- the cell spans more than one column, the width is divided over the
- columns.
-
- 3. Any remaining columns equally divide the remaining horizontal
- table space (minus borders or cell spacing).
-
- The width of the table is then the greater of the value of the
- 'width' property for the table element and the sum of the column
- widths (plus cell spacing or borders). If the table is wider than
- the columns, the extra space should be distributed over the columns.
-
-
- In this manner, the user agent can begin to lay out the table once
- the entire first row has been received. Cells in subsequent rows do
- not affect column widths. Any cell that has content that overflows
- uses the 'overflow' property to determine whether to clip the
- overflow content.
-
-_____________________________________________________
-
- This is not quite true when comparing to IE. IE always honors
- table-layout:fixed and treats a variable table width as 100%. Makes
- a lot of sense, and is implemented here the same way.
-
-*/
-
-FixedTableLayout::FixedTableLayout( RenderTable *table )
- : TableLayout ( table )
-{
-}
-
-FixedTableLayout::~FixedTableLayout()
-{
-}
-
-int FixedTableLayout::calcWidthArray()
-{
- int usedWidth = 0;
-
- // iterate over all <col> elements
- RenderObject *child = table->firstChild();
- int cCol = 0;
- int nEffCols = table->numEffCols();
- width.resize( nEffCols );
- width.fill( Length( Variable ) );
-
-#ifdef DEBUG_LAYOUT
- tqDebug("FixedTableLayout::calcWidthArray()" );
- tqDebug(" col elements:");
-#endif
-
- Length grpWidth;
- while ( child ) {
- if ( child->isTableCol() ) {
- RenderTableCol *col = static_cast<RenderTableCol *>(child);
- int span = col->span();
- if ( col->firstChild() ) {
- grpWidth = col->style()->width();
- } else {
- Length w = col->style()->width();
- if ( w.isVariable() )
- w = grpWidth;
- int effWidth = 0;
- if ( w.isFixed() && w.value() > 0 ) {
- effWidth = w.value();
- effWidth = KMIN( effWidth, 32760 );
- }
-#ifdef DEBUG_LAYOUT
- tqDebug(" col element: effCol=%d, span=%d: %d w=%d type=%d",
- cCol, span, effWidth, w.value(), w.type());
-#endif
- int usedSpan = 0;
- int i = 0;
- while ( usedSpan < span ) {
- if( cCol + i >= nEffCols ) {
- table->appendColumn( span - usedSpan );
- nEffCols++;
- width.resize( nEffCols );
- width[nEffCols-1] = Length();
- }
- int eSpan = table->spanOfEffCol( cCol+i );
- if ( (w.isFixed() || w.isPercent()) && w.value() > 0 ) {
- width[cCol+i] = Length( w.value() * eSpan, w.type() );
- usedWidth += effWidth * eSpan;
-#ifdef DEBUG_LAYOUT
- tqDebug(" setting effCol %d (span=%d) to width %d(type=%d)",
- cCol+i, eSpan, width[cCol+i].value(), width[cCol+i].type() );
-#endif
- }
- usedSpan += eSpan;
- i++;
- }
- cCol += i;
- }
- } else {
- break;
- }
-
- RenderObject *next = child->firstChild();
- if ( !next )
- next = child->nextSibling();
- if ( !next && child->parent()->isTableCol() ) {
- next = child->parent()->nextSibling();
- grpWidth = Length();
- }
- child = next;
- }
-
-#ifdef DEBUG_LAYOUT
- tqDebug(" first row:");
-#endif
- // iterate over the first row in case some are unspecified.
- RenderTableSection *section = table->head;
- if ( !section )
- section = table->firstBody;
- if ( !section )
- section = table->foot;
- if ( section && section->firstChild() ) {
- cCol = 0;
- // get the first cell in the first row
- child = section->firstChild()->firstChild();
- while ( child ) {
- if ( child->isTableCell() ) {
- RenderTableCell *cell = static_cast<RenderTableCell *>(child);
- Length w = cell->styleOrColWidth();
- int span = cell->colSpan();
- int effWidth = 0;
- if ( (w.isFixed() || w.isPercent()) && w.value() > 0 ) {
- effWidth = w.value();
- effWidth = kMin( effWidth, 32760 );
- }
-#ifdef DEBUG_LAYOUT
- tqDebug(" table cell: effCol=%d, span=%d: %d", cCol, span, effWidth);
-#endif
- int usedSpan = 0;
- int i = 0;
- while ( usedSpan < span ) {
- Q_ASSERT( cCol + i < nEffCols );
- int eSpan = table->spanOfEffCol( cCol+i );
- // only set if no col element has already set it.
- if ( width[cCol+i].isVariable() && !w.isVariable() ) {
- width[cCol+i] = Length( w.value()*eSpan, w.type() );
- usedWidth += effWidth*eSpan;
-#ifdef DEBUG_LAYOUT
- tqDebug(" setting effCol %d (span=%d) to width %d(type=%d)",
- cCol+i, eSpan, width[cCol+i].value(), width[cCol+i].type() );
-#endif
- }
-#ifdef DEBUG_LAYOUT
- else {
- tqDebug(" width of col %d already defined (span=%d)", cCol, table->spanOfEffCol( cCol ) );
- }
-#endif
- usedSpan += eSpan;
- i++;
- }
- cCol += i;
- } else {
- Q_ASSERT( false );
- }
- child = child->nextSibling();
- }
- }
-
- return usedWidth;
-
-}
-
-void FixedTableLayout::calcMinMaxWidth()
-{
- // we might want to wait until we have all of the first row before
- // layouting for the first time.
-
- // only need to calculate the minimum width as the sum of the
- // cols/cells with a fixed width.
- //
- // The maximum width is kMax( minWidth, tableWidth ) if table
- // width is fixed. If table width is percent, we set maxWidth to
- // unlimited.
-
- int bs = table->bordersPaddingAndSpacing();
- int tableWidth = 0;
- if (table->style()->width().isFixed()) {
- tableWidth = table->calcBoxWidth(table->style()->width().value());
- }
-
- int mw = calcWidthArray() + bs;
- table->m_minWidth = kMin( kMax( mw, tableWidth ), 0x7fff );
- table->m_maxWidth = table->m_minWidth;
-
- if ( !tableWidth ) {
- bool haveNonFixed = false;
- for ( unsigned int i = 0; i < width.size(); i++ ) {
- if ( !width[i].isFixed() ) {
- haveNonFixed = true;
- break;
- }
- }
- if ( haveNonFixed )
- table->m_maxWidth = 0x7fff;
- }
-#ifdef DEBUG_LAYOUT
- tqDebug("FixedTableLayout::calcMinMaxWidth: minWidth=%d, maxWidth=%d", table->m_minWidth, table->m_maxWidth );
-#endif
-}
-
-void FixedTableLayout::layout()
-{
- int tableWidth = table->width() - table->bordersPaddingAndSpacing();
- int available = tableWidth;
- int nEffCols = table->numEffCols();
-#ifdef DEBUG_LAYOUT
- tqDebug("FixedTableLayout::layout: tableWidth=%d, numEffCols=%d", tableWidth, nEffCols);
-#endif
-
-
- TQMemArray<int> calcWidth;
- calcWidth.resize( nEffCols );
- calcWidth.fill( -1 );
-
- // first assign fixed width
- for ( int i = 0; i < nEffCols; i++ ) {
- if ( width[i].isFixed() ) {
- calcWidth[i] = width[i].value();
- available -= width[i].value();
- }
- }
-
- // assign percent width
- if ( available > 0 ) {
- int totalPercent = 0;
- for ( int i = 0; i < nEffCols; i++ )
- if ( width[i].isPercent() )
- totalPercent += width[i].value();
-
- // calculate how much to distribute to percent cells.
- int base = tableWidth * totalPercent / 100;
- if ( base > available )
- base = available;
-
-#ifdef DEBUG_LAYOUT
- tqDebug("FixedTableLayout::layout: assigning percent width, base=%d, totalPercent=%d", base, totalPercent);
-#endif
- for ( int i = 0; available > 0 && i < nEffCols; i++ ) {
- if ( width[i].isPercent() ) {
- // totalPercent may be 0 below if all %-width specifed are 0%. (#172557)
- int w = totalPercent ? base * width[i].value() / totalPercent : 0;
- available -= w;
- calcWidth[i] = w;
- }
- }
- }
-
- // assign variable width
- if ( available > 0 ) {
- int totalVariable = 0;
- for ( int i = 0; i < nEffCols; i++ )
- if ( width[i].isVariable() )
- totalVariable++;
-
- for ( int i = 0; available > 0 && i < nEffCols; i++ ) {
- if ( width[i].isVariable() ) {
- // totalVariable may be 0 below if all the variable widths specified are 0.
- int w = totalVariable ? available / totalVariable : 0;
- available -= w;
- calcWidth[i] = w;
- totalVariable--;
- }
- }
- }
-
- for ( int i = 0; i < nEffCols; i++ )
- if ( calcWidth[i] < 0 )
- calcWidth[i] = 0; // IE gives min 1 px...
-
- // spread extra space over columns
- if ( available > 0 ) {
- int total = nEffCols;
- // still have some width to spread
- int i = nEffCols;
- while ( i-- ) {
- int w = available / total;
- available -= w;
- total--;
- calcWidth[i] += w;
- }
- }
-
- int pos = 0;
- int hspacing = table->borderHSpacing();
- for ( int i = 0; i < nEffCols; i++ ) {
-#ifdef DEBUG_LAYOUT
- tqDebug("col %d: %d (width %d)", i, pos, calcWidth[i] );
-#endif
- table->columnPos[i] = pos;
- pos += calcWidth[i] + hspacing;
- }
- table->columnPos[table->columnPos.size()-1] = pos;
-}
-
-// -------------------------------------------------------------------------
-// -------------------------------------------------------------------------
-
-
-AutoTableLayout::AutoTableLayout( RenderTable* table )
- : TableLayout( table )
-{
- percentagesDirty = true;
- effWidthDirty = true;
- total_percent = 0;
- hasPercent = false;
-}
-
-AutoTableLayout::~AutoTableLayout()
-{
-}
-
-/* recalculates the full structure needed to do layouting and minmax calculations.
- This is usually calculated on the fly, but needs to be done fully when table cells change
- dynamically
-*/
-void AutoTableLayout::recalcColumn( int effCol )
-{
- Layout &l = layoutStruct[effCol];
-
- RenderObject *child = table->firstChild();
- // first we iterate over all rows.
-
- RenderTableCell *fixedContributor = 0;
- RenderTableCell *maxContributor = 0;
-
- while ( child ) {
- if ( child->isTableSection() ) {
- RenderTableSection *section = static_cast<RenderTableSection *>(child);
- int numRows = section->numRows();
- RenderTableCell *last = 0;
- for ( int i = 0; i < numRows; i++ ) {
- RenderTableCell *cell = section->cellAt( i, effCol );
- if ( cell == (RenderTableCell *)-1 )
- continue;
- if ( cell && cell->colSpan() == 1 ) {
- // A cell originates in this column. Ensure we have
- // a min/max width of at least 1px for this column now.
- l.minWidth = kMax(int( l.minWidth ), 1);
- l.maxWidth = kMax(int( l.maxWidth ), 1);
-
- if ( !cell->minMaxKnown() )
- cell->calcMinMaxWidth();
- if ( cell->minWidth() > l.minWidth )
- l.minWidth = cell->minWidth();
- if ( cell->maxWidth() > l.maxWidth ) {
- l.maxWidth = cell->maxWidth();
- maxContributor = cell;
- }
-
- Length w = cell->styleOrColWidth();
- w.l.value = kMin( 32767, kMax( 0, w.value() ) );
- switch( w.type() ) {
- case Fixed:
- // ignore width=0
- if ( w.value() > 0 && !l.width.isPercent() ) {
- int wval = cell->calcBoxWidth(w.value());
- if ( l.width.isFixed() ) {
- // Nav/IE weirdness
- if ((wval > l.width.value()) ||
- ((l.width.value() == wval) && (maxContributor == cell))) {
- l.width.l.value = wval;
- fixedContributor = cell;
- }
- } else {
- l.width = Length( wval, Fixed );
- fixedContributor = cell;
- }
- }
- break;
- case Percent:
- hasPercent = true;
- if ( w.value() > 0 && (!l.width.isPercent() || w.value() > l.width.value() ) )
- l.width = w;
- break;
- case Relative:
- if ( w.isVariable() || (w.isRelative() && w.value() > l.width.value() ) )
- l.width = w;
- default:
- break;
- }
- } else {
- if ( cell && (!effCol || section->cellAt( i, effCol-1 ) != cell) ) {
- // This spanning cell originates in this column. Ensure we have
- // a min/max width of at least 1px for this column now.
- l.minWidth = kMax(int( l.minWidth ), 1);
- l.maxWidth = kMax(int( l.maxWidth ), 1);
- insertSpanCell( cell );
- }
- last = cell;
- }
- }
- }
- child = child->nextSibling();
- }
-
- // Nav/IE weirdness
- if ( l.width.isFixed() ) {
- if ( table->style()->htmlHacks()
- && (l.maxWidth > l.width.value()) && (fixedContributor != maxContributor)) {
- l.width = Length();
- fixedContributor = 0;
- }
- }
-
- l.maxWidth = kMax(l.maxWidth, int(l.minWidth));
-#ifdef DEBUG_LAYOUT
- tqDebug("col %d, final min=%d, max=%d, width=%d(%d)", effCol, l.minWidth, l.maxWidth, l.width.value(), l.width.type() );
-#endif
-
- // ### we need to add col elements aswell
-}
-
-
-void AutoTableLayout::fullRecalc()
-{
- percentagesDirty = true;
- hasPercent = false;
- effWidthDirty = true;
-
- int nEffCols = table->numEffCols();
- layoutStruct.resize( nEffCols );
- layoutStruct.fill( Layout() );
- spanCells.fill( 0 );
-
- RenderObject *child = table->firstChild();
- Length grpWidth;
- int cCol = 0;
- while ( child ) {
- if ( child->isTableCol() ) {
- RenderTableCol *col = static_cast<RenderTableCol *>(child);
- int span = col->span();
- if ( col->firstChild() ) {
- grpWidth = col->style()->width();
- } else {
- Length w = col->style()->width();
- if ( w.isVariable() )
- w = grpWidth;
- if ( (w.isFixed() && w.value() == 0) ||
- (w.isPercent() && w.value() == 0) )
- w = Length();
- int cEffCol = table->colToEffCol( cCol );
-#ifdef DEBUG_LAYOUT
- tqDebug(" col element %d (eff=%d): Length=%d(%d), span=%d, effColSpan=%d", cCol, cEffCol, w.value(), w.type(), span, table->spanOfEffCol(cEffCol ) );
-#endif
- if ( !w.isVariable() && span == 1 && cEffCol < nEffCols ) {
- if ( table->spanOfEffCol( cEffCol ) == 1 ) {
- layoutStruct[cEffCol].width = w;
- if (w.isFixed() && layoutStruct[cEffCol].maxWidth < w.value())
- layoutStruct[cEffCol].maxWidth = w.value();
- }
- }
- cCol += span;
- }
- } else {
- break;
- }
-
- RenderObject *next = child->firstChild();
- if ( !next )
- next = child->nextSibling();
- if ( !next && child->parent()->isTableCol() ) {
- next = child->parent()->nextSibling();
- grpWidth = Length();
- }
- child = next;
- }
-
-
- for ( int i = 0; i < nEffCols; i++ )
- recalcColumn( i );
-}
-
-static bool shouldScaleColumns(RenderTable* table)
-{
- // A special case. If this table is not fixed width and contained inside
- // a cell, then don't bloat the maxwidth by examining percentage growth.
- bool scale = true;
- while (table) {
- Length tw = table->style()->width();
- if ((tw.isVariable() || tw.isPercent()) && !table->isPositioned()) {
- RenderBlock* cb = table->containingBlock();
- while (cb && !cb->isCanvas() && !cb->isTableCell() &&
- cb->style()->width().isVariable() && !cb->isPositioned())
- cb = cb->containingBlock();
-
- table = 0;
- if (cb && cb->isTableCell() &&
- (cb->style()->width().isVariable() || cb->style()->width().isPercent())) {
- if (tw.isPercent())
- scale = false;
- else {
- RenderTableCell* cell = static_cast<RenderTableCell*>(cb);
- if (cell->colSpan() > 1 || cell->table()->style()->width().isVariable())
- scale = false;
- else
- table = cell->table();
- }
- }
- }
- else
- table = 0;
- }
- return scale;
-}
-
-void AutoTableLayout::calcMinMaxWidth()
-{
-#ifdef DEBUG_LAYOUT
- tqDebug("AutoTableLayout::calcMinMaxWidth");
-#endif
- fullRecalc();
-
- int spanMaxWidth = calcEffectiveWidth();
- int minWidth = 0;
- int maxWidth = 0;
- int maxPercent = 0;
- int maxNonPercent = 0;
-
- int remainingPercent = 100;
- for ( unsigned int i = 0; i < layoutStruct.size(); i++ ) {
- minWidth += layoutStruct[i].effMinWidth;
- maxWidth += layoutStruct[i].effMaxWidth;
- if ( layoutStruct[i].effWidth.isPercent() ) {
- int percent = kMin(layoutStruct[i].effWidth.value(), remainingPercent);
- int pw = ( layoutStruct[i].effMaxWidth * 100) / kMax(percent, 1);
- remainingPercent -= percent;
- maxPercent = kMax( pw, maxPercent );
- } else {
- maxNonPercent += layoutStruct[i].effMaxWidth;
- }
- }
-
- if (shouldScaleColumns(table)) {
- maxNonPercent = (maxNonPercent * 100 + 50) / kMax(remainingPercent, 1);
- maxWidth = kMax( maxNonPercent, maxWidth );
- maxWidth = kMax( maxWidth, maxPercent );
- }
-
- maxWidth = kMax( maxWidth, spanMaxWidth );
-
- int bs = table->bordersPaddingAndSpacing();
- minWidth += bs;
- maxWidth += bs;
-
- Length tw = table->style()->width();
- if ( tw.isFixed() && tw.value() > 0 ) {
- int width = table->calcBoxWidth(tw.value());
- minWidth = kMax( minWidth, width );
- maxWidth = minWidth;
- }
-
- table->m_maxWidth = kMin(maxWidth, 0x7fff);
- table->m_minWidth = kMin(minWidth, 0x7fff);
-#ifdef DEBUG_LAYOUT
- tqDebug(" minWidth=%d, maxWidth=%d", table->m_minWidth, table->m_maxWidth );
-#endif
-}
-
-/*
- This method takes care of colspans.
- effWidth is the same as width for cells without colspans. If we have colspans, they get modified.
- */
-int AutoTableLayout::calcEffectiveWidth()
-{
- int tMaxWidth = 0;
-
- unsigned int nEffCols = layoutStruct.size();
- int hspacing = table->borderHSpacing();
-#ifdef DEBUG_LAYOUT
- tqDebug("AutoTableLayout::calcEffectiveWidth for %d cols", nEffCols );
-#endif
- for ( unsigned int i = 0; i < nEffCols; i++ ) {
- layoutStruct[i].effWidth = layoutStruct[i].width;
- layoutStruct[i].effMinWidth = layoutStruct[i].minWidth;
- layoutStruct[i].effMaxWidth = layoutStruct[i].maxWidth;
- }
-
- for ( unsigned int i = 0; i < spanCells.size(); i++ ) {
- RenderTableCell *cell = spanCells[i];
- if ( !cell || cell == (RenderTableCell *)-1 )
- break;
- int span = cell->colSpan();
-
- Length w = cell->styleOrColWidth();
- if ( !w.isRelative() && w.value() == 0 )
- w = Length(); // make it Variable
-
- int col = table->colToEffCol( cell->col() );
- unsigned int lastCol = col;
- int cMinWidth = cell->minWidth() + hspacing;
- int cMaxWidth = cell->maxWidth() + hspacing;
- int totalPercent = 0;
- int minWidth = 0;
- int maxWidth = 0;
- bool allColsArePercent = true;
- bool allColsAreFixed = true;
- bool haveVariable = false;
- int fixedWidth = 0;
-#ifdef DEBUG_LAYOUT
- int cSpan = span;
-#endif
- while ( lastCol < nEffCols && span > 0 ) {
- switch( layoutStruct[lastCol].width.type() ) {
- case Percent:
- totalPercent += layoutStruct[lastCol].width.value();
- allColsAreFixed = false;
- break;
- case Fixed:
- if (layoutStruct[lastCol].width.value() > 0) {
- fixedWidth += layoutStruct[lastCol].width.value();
- allColsArePercent = false;
- // IE resets effWidth to Variable here, but this breaks the konqueror about page and seems to be some bad
- // legacy behavior anyway. mozilla doesn't do this so I decided we don't either.
- break;
- }
- // fall through
- case Variable:
- haveVariable = true;
- // fall through
- default:
- // If the column is a percentage width, do not let the spanning cell overwrite the
- // width value. This caused a mis-rendering on amazon.com.
- // Sample snippet:
- // <table border=2 width=100%><
- // <tr><td>1</td><td colspan=2>2-3</tr>
- // <tr><td>1</td><td colspan=2 width=100%>2-3</td></tr>
- // </table>
- if (!layoutStruct[lastCol].effWidth.isPercent()) {
- layoutStruct[lastCol].effWidth = Length();
- allColsArePercent = false;
- }
- else
- totalPercent += layoutStruct[lastCol].effWidth.value();
- allColsAreFixed = false;
- }
- span -= table->spanOfEffCol( lastCol );
- minWidth += layoutStruct[lastCol].effMinWidth;
- maxWidth += layoutStruct[lastCol].effMaxWidth;
- lastCol++;
- cMinWidth -= hspacing;
- cMaxWidth -= hspacing;
- }
-#ifdef DEBUG_LAYOUT
- tqDebug(" colspan cell %p at effCol %d, span %d, type %d, value %d cmin=%d min=%d fixedwidth=%d", cell, col, cSpan, w.type(), w.value(), cMinWidth, minWidth, fixedWidth );
-#endif
-
- // adjust table max width if needed
- if ( w.isPercent() ) {
- if ( totalPercent > w.value() || allColsArePercent ) {
- // can't satify this condition, treat as variable
- w = Length();
- } else {
- int spanMax = kMax( maxWidth, cMaxWidth );
-#ifdef DEBUG_LAYOUT
- tqDebug(" adjusting tMaxWidth (%d): spanMax=%d, value=%d, totalPercent=%d", tMaxWidth, spanMax, w.value(), totalPercent );
-#endif
- tMaxWidth = kMax( tMaxWidth, spanMax * 100 / w.value() );
-
- // all non percent columns in the span get percent values to sum up correctly.
- int percentMissing = w.value() - totalPercent;
- int totalWidth = 0;
- for ( unsigned int pos = col; pos < lastCol; pos++ ) {
- if ( !(layoutStruct[pos].width.isPercent() ) )
- totalWidth += layoutStruct[pos].effMaxWidth;
- }
-
- for ( unsigned int pos = col; pos < lastCol && totalWidth > 0; pos++ ) {
- if ( !(layoutStruct[pos].width.isPercent() ) ) {
- int percent = percentMissing * layoutStruct[pos].effMaxWidth / totalWidth;
-#ifdef DEBUG_LAYOUT
- tqDebug(" col %d: setting percent value %d effMaxWidth=%d totalWidth=%d", pos, percent, layoutStruct[pos].effMaxWidth, totalWidth );
-#endif
- totalWidth -= layoutStruct[pos].effMaxWidth;
- percentMissing -= percent;
- if ( percent > 0 )
- layoutStruct[pos].effWidth = Length( percent, Percent );
- else
- layoutStruct[pos].effWidth = Length();
- }
- }
-
- }
- }
-
- // make sure minWidth and maxWidth of the spanning cell are honoured
- if ( cMinWidth > minWidth ) {
- if ( allColsAreFixed ) {
-#ifdef DEBUG_LAYOUT
- tqDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d accroding to fixed sum %d", col, lastCol-1, cMinWidth, minWidth, fixedWidth );
-#endif
- for ( unsigned int pos = col; fixedWidth > 0 && pos < lastCol; pos++ ) {
- int w = kMax( int( layoutStruct[pos].effMinWidth ), cMinWidth * layoutStruct[pos].width.value() / fixedWidth );
-#ifdef DEBUG_LAYOUT
- tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
-#endif
- fixedWidth -= layoutStruct[pos].width.value();
- cMinWidth -= w;
- layoutStruct[pos].effMinWidth = w;
- }
-
- } else if ( allColsArePercent ) {
- int maxw = maxWidth;
- int minw = minWidth;
- int cminw = cMinWidth;
-
- for ( unsigned int pos = col; maxw > 0 && pos < lastCol; pos++ ) {
- if ( layoutStruct[pos].effWidth.isPercent() && layoutStruct[pos].effWidth.value()>0 && fixedWidth <= cMinWidth) {
- int w = layoutStruct[pos].effMinWidth;
- w = kMax( w, cminw*layoutStruct[pos].effWidth.value()/totalPercent );
- w = kMin(layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);
-#ifdef DEBUG_LAYOUT
- tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
-#endif
- maxw -= layoutStruct[pos].effMaxWidth;
- minw -= layoutStruct[pos].effMinWidth;
- cMinWidth -= w;
- layoutStruct[pos].effMinWidth = w;
- }
- }
- } else {
-#ifdef DEBUG_LAYOUT
- tqDebug("extending minWidth of cols %d-%d to %dpx currentMin=%d", col, lastCol-1, cMinWidth, minWidth );
-#endif
- int maxw = maxWidth;
- int minw = minWidth;
-
- // Give min to variable first, to fixed second, and to others third.
- for ( unsigned int pos = col; maxw > 0 && pos < lastCol; pos++ ) {
- if ( layoutStruct[pos].width.isFixed() && haveVariable && fixedWidth <= cMinWidth ) {
- int w = kMax( int( layoutStruct[pos].effMinWidth ), layoutStruct[pos].width.value() );
- fixedWidth -= layoutStruct[pos].width.value();
- minw -= layoutStruct[pos].effMinWidth;
-#ifdef DEBUG_LAYOUT
- tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
-#endif
- maxw -= layoutStruct[pos].effMaxWidth;
- cMinWidth -= w;
- layoutStruct[pos].effMinWidth = w;
- }
- }
-
- for ( unsigned int pos = col; maxw > 0 && pos < lastCol && minw < cMinWidth; pos++ ) {
- if ( !(layoutStruct[pos].width.isFixed() && haveVariable && fixedWidth <= cMinWidth) ) {
- int w = kMax( int( layoutStruct[pos].effMinWidth ), cMinWidth * layoutStruct[pos].effMaxWidth / maxw );
- w = kMin(layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);
-
-#ifdef DEBUG_LAYOUT
- tqDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );
-#endif
- maxw -= layoutStruct[pos].effMaxWidth;
- minw -= layoutStruct[pos].effMinWidth;
- cMinWidth -= w;
- layoutStruct[pos].effMinWidth = w;
- }
- }
- }
- }
- if ( !w.isPercent() ) {
- if ( cMaxWidth > maxWidth ) {
-#ifdef DEBUG_LAYOUT
- tqDebug("extending maxWidth of cols %d-%d to %dpx", col, lastCol-1, cMaxWidth );
-#endif
- for ( unsigned int pos = col; maxWidth > 0 && pos < lastCol; pos++ ) {
- int w = kMax( int( layoutStruct[pos].effMaxWidth ), cMaxWidth * layoutStruct[pos].effMaxWidth / maxWidth );
-#ifdef DEBUG_LAYOUT
- tqDebug(" col %d: max=%d, effMax=%d, new=%d", pos, layoutStruct[pos].effMaxWidth, layoutStruct[pos].effMaxWidth, w );
-#endif
- maxWidth -= layoutStruct[pos].effMaxWidth;
- cMaxWidth -= w;
- layoutStruct[pos].effMaxWidth = w;
- }
- }
- } else {
- for ( unsigned int pos = col; pos < lastCol; pos++ )
- layoutStruct[pos].maxWidth = kMax(layoutStruct[pos].maxWidth, int(layoutStruct[pos].minWidth) );
- }
- }
- effWidthDirty = false;
-
-// tqDebug("calcEffectiveWidth: tMaxWidth=%d", tMaxWidth );
- return tMaxWidth;
-}
-
-/* gets all cells that originate in a column and have a cellspan > 1
- Sorts them by increasing cellspan
-*/
-void AutoTableLayout::insertSpanCell( RenderTableCell *cell )
-{
- if ( !cell || cell == (RenderTableCell *)-1 || cell->colSpan() == 1 )
- return;
-
-// tqDebug("inserting span cell %p with span %d", cell, cell->colSpan() );
- int size = spanCells.size();
- if ( !size || spanCells[size-1] != 0 ) {
- spanCells.resize( size + 10 );
- for ( int i = 0; i < 10; i++ )
- spanCells[size+i] = 0;
- size += 10;
- }
-
- // add them in sort. This is a slow algorithm, and a binary search or a fast sorting after collection would be better
- unsigned int pos = 0;
- int span = cell->colSpan();
- while ( pos < spanCells.size() && spanCells[pos] && span > spanCells[pos]->colSpan() )
- pos++;
- memmove( spanCells.data()+pos+1, spanCells.data()+pos, (size-pos-1)*sizeof( RenderTableCell * ) );
- spanCells[pos] = cell;
-}
-
-
-void AutoTableLayout::layout()
-{
- // table layout based on the values collected in the layout structure.
- int tableWidth = table->width() - table->bordersPaddingAndSpacing();
- int available = tableWidth;
- int nEffCols = table->numEffCols();
-
- if ( nEffCols != (int)layoutStruct.size() ) {
- tqWarning("WARNING: nEffCols is not equal to layoutstruct!" );
- fullRecalc();
- nEffCols = table->numEffCols();
- }
-#ifdef DEBUG_LAYOUT
- tqDebug("AutoTableLayout::layout()");
-#endif
-
- if ( effWidthDirty )
- calcEffectiveWidth();
-
-#ifdef DEBUG_LAYOUT
- tqDebug(" tableWidth=%d, nEffCols=%d", tableWidth, nEffCols );
- for ( int i = 0; i < nEffCols; i++ ) {
- tqDebug(" effcol %d is of type %d value %d, minWidth=%d, maxWidth=%d",
- i, layoutStruct[i].width.type(), layoutStruct[i].width.value(),
- layoutStruct[i].minWidth, layoutStruct[i].maxWidth );
- tqDebug(" effective: type %d value %d, minWidth=%d, maxWidth=%d",
- layoutStruct[i].effWidth.type(), layoutStruct[i].effWidth.value(),
- layoutStruct[i].effMinWidth, layoutStruct[i].effMaxWidth );
- }
-#endif
-
- bool havePercent = false;
- bool haveRelative = false;
- int totalRelative = 0;
- int numVariable = 0;
- int numFixed = 0;
- int totalVariable = 0;
- int totalFixed = 0;
- int totalPercent = 0;
- int allocVariable = 0;
-
- // fill up every cell with it's minWidth
- for ( int i = 0; i < nEffCols; i++ ) {
- int w = layoutStruct[i].effMinWidth;
- layoutStruct[i].calcWidth = w;
- available -= w;
- Length& width = layoutStruct[i].effWidth;
- switch( width.type()) {
- case Percent:
- havePercent = true;
- totalPercent += width.value();
- break;
- case Relative:
- haveRelative = true;
- totalRelative += width.value();
- break;
- case Fixed:
- numFixed++;
- totalFixed += layoutStruct[i].effMaxWidth;
- // fall through
- break;
- case Variable:
- case Static:
- numVariable++;
- totalVariable += layoutStruct[i].effMaxWidth;
- allocVariable += w;
- }
- }
-
- // allocate width to percent cols
- if ( available > 0 && havePercent ) {
- for ( int i = 0; i < nEffCols; i++ ) {
- const Length &width = layoutStruct[i].effWidth;
- if ( width.isPercent() ) {
- int w = kMax ( int( layoutStruct[i].effMinWidth ), width.minWidth( tableWidth ) );
- available += layoutStruct[i].calcWidth - w;
- layoutStruct[i].calcWidth = w;
- }
- }
- if ( totalPercent > 100 ) {
- // remove overallocated space from the last columns
- int excess = tableWidth*(totalPercent-100)/100;
- for ( int i = nEffCols-1; i >= 0; i-- ) {
- if ( layoutStruct[i].effWidth.isPercent() ) {
- int w = layoutStruct[i].calcWidth;
- int reduction = kMin( w, excess );
- // the lines below might look inconsistent, but that's the way it's handled in mozilla
- excess -= reduction;
- int newWidth = kMax( int (layoutStruct[i].effMinWidth), w - reduction );
- available += w - newWidth;
- layoutStruct[i].calcWidth = newWidth;
- //tqDebug("col %d: reducing to %d px (reduction=%d)", i, newWidth, reduction );
- }
- }
- }
- }
-#ifdef DEBUG_LAYOUT
- tqDebug("percent satisfied: available is %d", available);
-#endif
-
- // then allocate width to fixed cols
- if ( available > 0 ) {
- for ( int i = 0; i < nEffCols; ++i ) {
- const Length &width = layoutStruct[i].effWidth;
- if ( width.isFixed() && width.value() > layoutStruct[i].calcWidth ) {
- available += layoutStruct[i].calcWidth - width.value();
- layoutStruct[i].calcWidth = width.value();
- }
- }
- }
-#ifdef DEBUG_LAYOUT
- tqDebug("fixed satisfied: available is %d", available);
-#endif
-
- // now satisfy relative
- if ( available > 0 ) {
- for ( int i = 0; i < nEffCols; i++ ) {
- const Length &width = layoutStruct[i].effWidth;
- if ( width.isRelative() && width.value() ) {
- // width=0* gets effMinWidth.
- int w = width.value()*tableWidth/totalRelative;
- available += layoutStruct[i].calcWidth - w;
- layoutStruct[i].calcWidth = w;
- }
- }
- }
-
- // now satisfy variable
- if ( available > 0 && numVariable ) {
- available += allocVariable; // this gets redistributed
- //tqDebug("redistributing %dpx to %d variable columns. totalVariable=%d", available, numVariable, totalVariable );
- for ( int i = 0; i < nEffCols; i++ ) {
- const Length &width = layoutStruct[i].effWidth;
- if ( width.isVariable() && totalVariable != 0 ) {
- int w = kMax( int ( layoutStruct[i].calcWidth ),
- available * layoutStruct[i].effMaxWidth / totalVariable );
- available -= w;
- totalVariable -= layoutStruct[i].effMaxWidth;
- layoutStruct[i].calcWidth = w;
- }
- }
- }
-#ifdef DEBUG_LAYOUT
- tqDebug("variable satisfied: available is %d", available );
-#endif
-
- // spread over fixed colums
- if ( available > 0 && numFixed) {
- // still have some width to spread, distribute to fixed columns
- for ( int i = 0; i < nEffCols; i++ ) {
- const Length &width = layoutStruct[i].effWidth;
- if ( width.isFixed() ) {
- int w = available * layoutStruct[i].effMaxWidth / totalFixed;
- available -= w;
- totalFixed -= layoutStruct[i].effMaxWidth;
- layoutStruct[i].calcWidth += w;
- }
- }
- }
-
-#ifdef DEBUG_LAYOUT
- tqDebug("after fixed distribution: available=%d", available );
-#endif
-
- // spread over percent colums
- if ( available > 0 && hasPercent && totalPercent < 100) {
- // still have some width to spread, distribute weighted to percent columns
- for ( int i = 0; i < nEffCols; i++ ) {
- const Length &width = layoutStruct[i].effWidth;
- if ( width.isPercent() ) {
- int w = available * width.value() / totalPercent;
- available -= w;
- totalPercent -= width.value();
- layoutStruct[i].calcWidth += w;
- if (!available || !totalPercent) break;
- }
- }
- }
-
-#ifdef DEBUG_LAYOUT
- tqDebug("after percent distribution: available=%d", available );
-#endif
-
- // spread over the rest
- if ( available > 0 ) {
- int total = nEffCols;
- // still have some width to spread
- int i = nEffCols;
- while ( i-- ) {
- int w = available / total;
- available -= w;
- total--;
- layoutStruct[i].calcWidth += w;
- }
- }
-
-#ifdef DEBUG_LAYOUT
- tqDebug("after equal distribution: available=%d", available );
-#endif
- // if we have overallocated, reduce every cell according to the difference between desired width and minwidth
- // this seems to produce to the pixel exaxt results with IE. Wonder is some of this also holds for width distributing.
- if ( available < 0 ) {
- // Need to reduce cells with the following prioritization:
- // (1) Variable
- // (2) Relative
- // (3) Fixed
- // (4) Percent
- // This is basically the reverse of how we grew the cells.
- if (available < 0) {
- int mw = 0;
- for ( int i = nEffCols-1; i >= 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isVariable())
- mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
- }
-
- for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isVariable()) {
- int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
- int reduce = available * minMaxDiff / mw;
- layoutStruct[i].calcWidth += reduce;
- available -= reduce;
- mw -= minMaxDiff;
- if ( available >= 0 )
- break;
- }
- }
- }
-
- if (available < 0) {
- int mw = 0;
- for ( int i = nEffCols-1; i >= 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isRelative())
- mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
- }
-
- for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isRelative()) {
- int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
- int reduce = available * minMaxDiff / mw;
- layoutStruct[i].calcWidth += reduce;
- available -= reduce;
- mw -= minMaxDiff;
- if ( available >= 0 )
- break;
- }
- }
- }
-
- if (available < 0) {
- int mw = 0;
- for ( int i = nEffCols-1; i >= 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isFixed())
- mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
- }
-
- for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isFixed()) {
- int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
- int reduce = available * minMaxDiff / mw;
- layoutStruct[i].calcWidth += reduce;
- available -= reduce;
- mw -= minMaxDiff;
- if ( available >= 0 )
- break;
- }
- }
- }
-
- if (available < 0) {
- int mw = 0;
- for ( int i = nEffCols-1; i >= 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isPercent())
- mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
- }
-
- for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
- Length &width = layoutStruct[i].effWidth;
- if (width.isPercent()) {
- int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
- int reduce = available * minMaxDiff / mw;
- layoutStruct[i].calcWidth += reduce;
- available -= reduce;
- mw -= minMaxDiff;
- if ( available >= 0 )
- break;
- }
- }
- }
- }
-
- //tqDebug( " final available=%d", available );
-
- int pos = 0;
- for ( int i = 0; i < nEffCols; i++ ) {
-#ifdef DEBUG_LAYOUT
- tqDebug("col %d: %d (width %d)", i, pos, layoutStruct[i].calcWidth );
-#endif
- table->columnPos[i] = pos;
- pos += layoutStruct[i].calcWidth + table->borderHSpacing();
- }
- table->columnPos[table->columnPos.size()-1] = pos;
-
-}
-
-
-void AutoTableLayout::calcPercentages() const
-{
- total_percent = 0;
- for ( unsigned int i = 0; i < layoutStruct.size(); i++ ) {
- if ( layoutStruct[i].width.isPercent() )
- total_percent += layoutStruct[i].width.value();
- }
- percentagesDirty = false;
-}
-
-#undef DEBUG_LAYOUT
diff --git a/khtml/rendering/table_layout.h b/khtml/rendering/table_layout.h
deleted file mode 100644
index cbaf6d3a7..000000000
--- a/khtml/rendering/table_layout.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * This file is part of the HTML rendering engine for KDE.
- *
- * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
- * (C) 2002 Dirk Mueller (mueller@kde.org)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-#ifndef TABLE_LAYOUT_H
-#define TABLE_LAYOUT_H
-
-#include <tqmemarray.h>
-#include <misc/khtmllayout.h>
-
-namespace khtml {
-
-class RenderTable;
-class RenderTableCell;
-
-// -------------------------------------------------------------------------
-
-class TableLayout
-{
-public:
- TableLayout( RenderTable *t ) : table( t ) {}
- virtual ~TableLayout() {}
-
- virtual void calcMinMaxWidth() = 0;
- virtual void layout() = 0;
-
-protected:
- RenderTable *table;
-};
-
-// -------------------------------------------------------------------------
-
-class FixedTableLayout : public TableLayout
-{
-public:
- FixedTableLayout( RenderTable *table );
- ~FixedTableLayout();
-
- void calcMinMaxWidth();
- void layout();
-
-protected:
- int calcWidthArray();
-
- TQMemArray<Length> width;
-};
-
-// -------------------------------------------------------------------------
-
-class AutoTableLayout : public TableLayout
-{
-public:
- AutoTableLayout( RenderTable *table );
- ~AutoTableLayout();
-
- void calcMinMaxWidth();
- void layout();
-
-
-protected:
- void fullRecalc();
- void recalcColumn( int effCol );
- int totalPercent() const {
- if ( percentagesDirty )
- calcPercentages();
- return total_percent;
- }
- void calcPercentages() const;
- int calcEffectiveWidth();
- void insertSpanCell( RenderTableCell *cell );
-
- struct Layout {
- Layout() : minWidth( 1 ), maxWidth( 1 ),
- effMinWidth( 0 ), effMaxWidth( 0 ),
- calcWidth( 0 ) {}
- Length width;
- Length effWidth;
- short minWidth;
- int maxWidth;
- short effMinWidth;
- int effMaxWidth;
- short calcWidth;
- };
-
- TQMemArray<Layout> layoutStruct;
- TQMemArray<RenderTableCell *>spanCells;
- bool hasPercent : 1;
- mutable bool percentagesDirty : 1;
- mutable bool effWidthDirty : 1;
- mutable unsigned short total_percent;
-};
-
-}
-#endif
diff --git a/khtml/rendering/table_layout.txt b/khtml/rendering/table_layout.txt
deleted file mode 100644
index 14a74bd1e..000000000
--- a/khtml/rendering/table_layout.txt
+++ /dev/null
@@ -1,74 +0,0 @@
-CSS describes two ways of layouting tables. Auto layout (the NS4
-compliant HTML table layout) and fixed layout. The fixed layout
-strategy is described in detail in the CSS specs and will not be
-repeated here.
-
-Due to the fact that two layout strategies exist, it is rather natural
-to encapsulate the layouting process in a TableLayout class. Two types
-(FixedTableLayout and AutoTableLayout) exist. AutoTableLayout is the
-default and also need a quirks flags for NS compatibility
-mode. FixedTableLayout will be used if a style rule sets the
-table-layout property to fixed.
-
-The grid of table cells is stored in each table section, as spans
-can't pass section borders. Changing the number of cols in the grid
-has to be done by the table to keep all grids (for all sections) in
-sync. The grid only stores effective columns. The table below would
-only result in one column being allocated in the grid:
-
-<table><tr><td colspan=1000>foo</td></tr></table>
-
-Once a colspan get's used, the column is split into its subparts. To
-do this, the table has to store the colspans of effective columns in a
-structure.
-
-
-
-
-NS & Mozilla compliant table layouting algorithm (AutoTableLayout)
-------------------------------------------------------------------
-
-The table layout algorithm computes a set of layout hints from the
-informations in the table cells, <col> elements and style
-sheets. Hints from different sources are treated a bit differently in
-the collection stage.
-
-In addition certain operations are only done in quirks (NS4 compat)
-mode.
-
-Resizing the table doesn't require you to build up this information
-again. All that is needed is a list of layout hints for each column.
-
-The algorithm below describes to the best of our knowledge the way
-table alyouting is handled in a NS compatible way.
-
-There are two stages, the collection stage (assocaited with
-calcMinMaxWidth() in khtml) and the stage assigning width to cells
-(associated with layout()).
-
-A set of hinted widths are used to determine the final table layout in
-the layouting stage.
-
-enum hintType {
- MinWidth,
- DesiredWidth,
- FixedWidth,
- MinWidthAdjusted,
- DesiredWidthAdjusted,
- FixedWidthAdjusted,
- PercentWidth,
- PercentWidthAdjusted,
- ProportionalWidth
-};
-
-One width (in pixels) for each hintType describes how the column
-wishes to be layouted. The layouting stage operates only on an array
-of hints for each column.
-
-An additional totalCellSpacing variable is used to know about the
-remaining width to distribute.
-
-Collection stage:
------------------
-
-