⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 htmltable.cpp

📁 PIXIL is a small footprint operating environment, complete with PDA PIM applications, a browser and
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* 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., 59 Temple Place - Suite 330,    Boston, MA 02111-1307, USA.*///// KDE HTML Widget//#include <kurl.h>#include "htmlchain.h"#include "htmlobj.h"#include "htmlclue.h"#include "htmltable.h"#include "html.h"#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <string.h>#include <qimage.h>#include <qdrawutil.h>//#define CLUE_DEBUG//#define DEBUG_ALIGN//-----------------------------------------------------------------------------HTMLTableCell::HTMLTableCell( int _x, int _y, int _max_width, int _percent,	int rs, int cs, int pad )	 : HTMLClueV( _x, _y, _max_width, _percent ){	refcount = 0;	rspan = rs;	cspan = cs;	padding = pad;	width = _max_width;	if(percent == 0) setFixedWidth(true);}void HTMLTableCell::setMaxWidth( int _max_width ){    HTMLObject *obj;    max_width = _max_width;    if (max_width > 0)    {	if ( percent > 0 )            width = _max_width * percent / 100;	else if ( !isFixedWidth() )	    width = max_width;    }    for ( obj = head; obj != 0; obj = obj->next() )	obj->setMaxWidth( max_width );}void HTMLTableCell::setWidth(int _width){    HTMLObject *obj;    width = _width;    if(!isFixedWidth())	max_width = width;    for ( obj = head; obj != 0; obj = obj->next() )	obj->setMaxWidth( width );}int HTMLTableCell::calcMinWidth(){    HTMLObject *obj;    int minWidth = 0;    for ( obj = head; obj != 0; obj = obj->next() )    {	int w = obj->calcMinWidth();	if ( w > minWidth )	    minWidth = w;    }    if ( isFixedWidth() )    {        // Our minimum width is at least our fixed width        if (max_width > minWidth)            minWidth = max_width;        // And our actual width is at least our minimum width.        if (width < minWidth)            width = minWidth;    }                                                                        return minWidth;}bool HTMLTableCell::print( QPainter *_painter, int _x, int _y, int _width,	int _height, int _tx, int _ty, bool toPrinter ){	if ( _y + _height < y - getAscent() || _y > y + descent )		return false; 	if ( bg.isValid() )	{		int top = _y - ( y - getAscent() );		int bottom = top + _height;		if ( top < -padding )			top = -padding;		if ( bottom > getAscent() + padding )			bottom = getAscent() + padding; 		QBrush brush( bg );		_painter->fillRect( _tx + x - padding, _ty + y - ascent + top,			width + padding * 2, bottom - top, brush );	    // another hack... 	    HTMLObject *obj;	    for ( obj = head; obj != 0; obj = obj->next() )		obj->setBgColor(bg);	}	return HTMLClueV::print( _painter, _x, _y, _width, _height, _tx, _ty, toPrinter );}void HTMLTableCell::print( QPainter *_painter, HTMLChain *_chain, int _x,	int _y, int _width, int _height, int _tx, int _ty ){    if ( bg.isValid() )    {	    int top = _y - ( y - getAscent() );	    int bottom = top + _height;	    if ( top < -padding )		    top = -padding;	    if ( bottom > getAscent() + padding )		    bottom = getAscent() + padding;	    int left = _x - x;	    int right = left + _width;	    if ( left < -padding )		left = -padding;	    if ( right > width + padding )		right = width + padding;	    QBrush brush( bg );	    _painter->fillRect( _tx + x + left, _ty + y - ascent + top,		    right - left, bottom - top, brush );	    // another hack...	    HTMLObject *obj;	    for ( obj = head; obj != 0; obj = obj->next() )		obj->setBgColor(bg);    }    HTMLClue::print( _painter, _chain, _x, _y, _width, _height, _tx, _ty );}//-----------------------------------------------------------------------------HTMLTable::HTMLTable( int _x, int _y, int _max_width, int _width, int _percent,	int _padding, int _spacing, int _border ) : HTMLObject(){    x = _x;    y = _y;    max_width = _max_width;    width = _width;    percent = _percent;    padding = _padding;    spacing = _spacing;    border  = _border;    caption = 0L;    setFixedWidth( false );    row = 0;    col = 0;    totalCols = 1;	// this should be expanded to the maximum number of cols				    // by the first row parsed    totalRows = 1;    allocRows = 5;	// allocate five rows initially    cells = new HTMLTableCell ** [allocRows];    for ( unsigned int r = 0; r < allocRows; r++ )    {	cells[r] = new HTMLTableCell * [totalCols];	memset( cells[r], 0, totalCols * sizeof( HTMLTableCell * ) );    }    if ( percent > 0 )	width = max_width * percent / 100;    else if ( width == 0 )	width = max_width;    else    {//WABA does this make sense? //Lars: sorry... no, it makes some tbales look _really_ ugly    	max_width = width; 	setFixedWidth( TRUE );    }}void HTMLTable::startRow(){    col = 0;}void HTMLTable::addCell( HTMLTableCell *cell ){    while ( col < totalCols && cells[row][col] != 0L )	col++;    setCells( row, col, cell );    col++;}void HTMLTable::endRow(){    while ( col < totalCols && cells[row][col] != 0 )	col++;    if ( col )	row++;}void HTMLTable::setCells( unsigned int r, unsigned int c, HTMLTableCell *cell ){    unsigned int endRow = r + cell->rowSpan();    unsigned int endCol = c + cell->colSpan();    // The first row sets the number of columns.  Do not allow subsequent    // rows to change the number of columns.//WABA: Why not? Let's give crappy HTML a chance//    if ( row != 0 && endCol > totalCols )//	endCol = totalCols;    if ( endCol > totalCols )	addColumns( endCol - totalCols );    if ( endRow >= allocRows )	addRows( endRow - allocRows + 10 );    if ( endRow > totalRows )	totalRows = endRow;    for ( ; r < endRow; r++ )    {	for ( unsigned int tc = c; tc < endCol; tc++ )	{	    // WABA: We do semi-automatic reference counting :]	    if (cells[r][tc])		cells[r][tc]->unlink();	    cells[r][tc] = cell;	    cell->link();	}    }}void HTMLTable::addRows( int num ){    HTMLTableCell ***newRows = new HTMLTableCell ** [allocRows + num];    memcpy( newRows, cells, allocRows * sizeof(HTMLTableCell **) );    delete [] cells;    cells = newRows;    for ( unsigned int r = allocRows; r < allocRows + num; r++ )    {	cells[r] = new HTMLTableCell * [totalCols];	memset( cells[r], 0, totalCols * sizeof( HTMLTableCell * ) );    }    allocRows += num;}void HTMLTable::addColumns( int num ){    HTMLTableCell **newCells;    for ( unsigned int r = 0; r < allocRows; r++ )    {	newCells = new HTMLTableCell * [totalCols+num];	memcpy( newCells, cells[r], totalCols * sizeof( HTMLTableCell * ) );	memset( newCells + totalCols, 0, num * sizeof( HTMLTableCell * ) );	delete [] cells[r];	cells[r] = newCells;    }    totalCols += num;}void HTMLTable::endTable(){//    totalRows = row;    // calculate min/max widths    calcColInfo();    calcColumnWidths();}void HTMLTable::calcAbsolutePos( int _x, int _y ){    int lx = _x + x;    int ly = _y + y - ascent;    HTMLTableCell *cell;    unsigned int r, c;    for ( r = 0; r < totalRows; r++ )    {	for ( c = 0; c < totalCols; c++ )	{	    if ( ( cell = cells[r][c] ) == 0 )		continue;	    if ( c < totalCols - 1 && cell == cells[r][c+1] )		continue;	    if ( r < totalRows - 1 && cells[r+1][c] == cell )		continue;	    cell->calcAbsolutePos( lx, ly );	}    }}bool HTMLTable::getObjectPosition( const HTMLObject *objp, int &xp, int &yp ){    HTMLTableCell *cell;    xp += x;    yp += (y - ascent);    unsigned int r, c;    for ( r = 0; r < totalRows; r++ )    {	for ( c = 0; c < totalCols; c++ )	{	    if ( ( cell = cells[r][c] ) == 0 )		continue;	    if ( c < totalCols - 1 && cell == cells[r][c+1] )		continue;	    if ( r < totalRows - 1 && cells[r+1][c] == cell )		continue;	    if ( cell->getObjectPosition( objp, xp, yp ) )		return true;	}    }        xp -= x;    yp -= (y - ascent);    return false;}HTMLAnchor* HTMLTable::findAnchor( const char *_name, QPoint *_p ){    HTMLAnchor *ret;    HTMLTableCell *cell;    _p->setX( _p->x() + x );    _p->setY( _p->y() + y - ascent );     unsigned int r, c;    for ( r = 0; r < totalRows; r++ )    {	for ( c = 0; c < totalCols; c++ )	{	    if ( ( cell = cells[r][c] ) == 0 )		continue;	    if ( c < totalCols - 1 && cell == cells[r][c+1] )		continue;	    if ( r < totalRows - 1 && cells[r+1][c] == cell )		continue;	    ret = cell->findAnchor( _name, _p );	    if ( ret != 0 )		return ret;	}    }	    _p->setX( _p->x() - x );    _p->setY( _p->y() - y + ascent );    return 0;}void HTMLTable::reset(){    unsigned int r, c;    HTMLTableCell *cell;    for ( r = 0; r < totalRows; r++ )    {	for ( c = 0; c < totalCols; c++ )	{	    if ( ( cell = cells[r][c] ) == 0 )		continue;	    if ( c < totalCols - 1 && cell == cells[r][c+1] )		continue;	    if ( r < totalRows - 1 && cells[r+1][c] == cell )		continue;	    cell->reset();	}    }    calcColInfo();}void HTMLTable::calcSize( HTMLClue * ){    unsigned int r, c;    int indx;    HTMLTableCell *cell;    // recalculate min/max widths    calcColumnWidths();    // If it doesn't fit... MAKE IT FIT!    for ( c = 0; c < totalCols; c++ )    {        if (columnPos[c+1] > max_width-border)	    columnPos[c+1] = max_width-border;    }    // Attempt to get sensible cell widths    optimiseCellWidth();    // set cell widths and then calculate cell sizes    for ( r = 0; r < totalRows; r++ )    {	for ( c = 0; c < totalCols; c++ )	{	    if ( ( cell = cells[r][c] ) == 0 )		continue;	    if ( c < totalCols - 1 && cell == cells[r][c+1] )		continue;	    if ( r < totalRows - 1 && cell == cells[r+1][c] )		continue;	    if ( ( indx = c-cell->colSpan()+1 ) < 0 )		indx = 0;	    int w = columnOpt[c+1] - columnOpt[ indx ] - spacing -		padding - padding;	    cell->setWidth( w );	    cell->calcSize();	}    }    if ( caption )    {	caption->setMaxWidth( columnOpt[ totalCols ] + border );	caption->calcSize();	if ( capAlign == HTMLClue::Top )	    caption->setPos( 0, caption->getAscent() );    }    // We have the cell sizes now, so calculate the vertical positions    calcRowHeights();    // set cell positions    for ( r = 0; r < totalRows; r++ )    {	int cellHeight;	ascent = rowHeights[r+1] - padding - spacing;	if ( caption && capAlign == HTMLClue::Top )	    ascent += caption->getHeight();	for ( c = 0; c < totalCols; c++ )	{	    if ( ( cell = cells[r][c] ) == 0 )		continue;	    if ( c < totalCols - 1 && cell == cells[r][c+1] )		continue;	    if ( r < totalRows - 1 && cell == cells[r+1][c] )		continue;	    if ( ( indx = c-cell->colSpan()+1 ) < 0 )		indx = 0;	    cell->setPos( columnOpt[indx] + padding,		ascent - cell->getDescent() );	    if ( ( indx = r-cell->rowSpan()+1 ) < 0 )		indx = 0;	    cellHeight = rowHeights[r+1] - rowHeights[indx] -		padding - padding - spacing;	    cell->setMaxAscent( cellHeight );	}    }    if ( caption && capAlign == HTMLClue::Bottom )	caption->setPos( 0, rowHeights[ totalRows ] + border + caption->getAscent() );// CRH 2 borders for size//    width = columnOpt[ totalCols ] + border;//    ascent = rowHeights[ totalRows ] + border;    width = columnOpt[ totalCols ] + (border * 2);    ascent = rowHeights[ totalRows ] + (border * 2);    if ( caption )	ascent += caption->getHeight();}// Both the minimum and preferred column sizes are calculated here.// The hard part is choosing the actual sizes based on these two.void HTMLTable::calcColumnWidths(){    unsigned int r, c;    int indx, borderExtra = ( border == 0 ) ? 0 : 1;    colType.resize( totalCols+1 );    colType.fill( Variable );    columnPos.resize( totalCols+1 );    columnPos[0] = border + spacing;    columnPrefPos.resize( totalCols+1 );    columnPrefPos[0] = border + spacing;    colSpan.resize( totalCols+1 );    colSpan.fill( 1 );    for ( c = 0; c < totalCols; c++ )    {	columnPos[c+1] = 0;	columnPrefPos[c+1] = 0;	for ( r = 0; r < totalRows; r++ )	{	    HTMLTableCell *cell = cells[r][c];	    int colPos;	    if ( cell == 0 )		continue; 	    if ( c < totalCols - 1 && cells[r][c+1] == cell )		continue;	    if ( r < totalRows - 1 && cells[r+1][c] == cell )		continue;	    if ( ( indx = c-cell->colSpan()+1 ) < 0 )		indx = 0;	    // calculate minimum pos.	    colPos = columnPos[indx] + cell->calcMinWidth() +		    padding + padding + spacing + borderExtra;	    if ( columnPos[c + 1] < colPos )		columnPos[c + 1] = colPos;	    if ( colType[c + 1] != Variable )	    {		continue;	    }	    // calculate preferred pos	    if ( cell->getPercent() > 0 )	    {		colPos = columnPrefPos[indx] +			( max_width * cell->getPercent() / 100 ) + padding +			padding + spacing + borderExtra;		colType[c + 1] = Percent;		colSpan[c + 1] = cell->colSpan();		columnPrefPos[c + 1] = colPos;	    }	    else if ( cell->isFixedWidth() )	    {		colPos = columnPrefPos[indx] + cell->getWidth() + padding +			padding + spacing + borderExtra;		colType[c + 1] = Fixed;		colSpan[c + 1] = cell->colSpan();		columnPrefPos[c + 1] = colPos;	    }	    else	    {		colPos = cell->calcPreferredWidth();		colPos += columnPrefPos[indx] + padding + padding + 			  spacing + borderExtra;		if ( columnPrefPos[c + 1] < colPos )		    columnPrefPos[c + 1] = colPos;	    }	    if ( columnPrefPos[c + 1] < columnPos[c + 1] )		columnPrefPos[c + 1] = columnPos[c + 1];	}	if (columnPos[c + 1] <= columnPos[c])	    columnPos[c + 1] = columnPos[c];	if (columnPrefPos[c + 1] <= columnPrefPos[c])	    columnPrefPos[c + 1] = columnPrefPos[c]+1;    }}// Use the minimum and preferred cell widths to produce an optimum// cell spacing.  When this has been done columnOpt contains// the optimum cell widths.void HTMLTable::optimiseCellWidth()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -