summaryrefslogtreecommitdiffstats
path: root/khtml/rendering/render_text.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khtml/rendering/render_text.cpp')
-rw-r--r--khtml/rendering/render_text.cpp1546
1 files changed, 0 insertions, 1546 deletions
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