00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <opie2/odebug.h>
00039 using namespace Opie::Core;
00040
00041 #include "qrichtext_p.h"
00042
00043 using namespace Qt3;
00044
00045 QTextCommand::~QTextCommand() {}
00046 QTextCommand::Commands QTextCommand::type() const { return Invalid; }
00047
00048
00049 QTextCustomItem::~QTextCustomItem() {}
00050 void QTextCustomItem::adjustToPainter( QPainter* p){ if ( p ) width = 0; }
00051 QTextCustomItem::Placement QTextCustomItem::placement() const { return PlaceInline; }
00052
00053 bool QTextCustomItem::ownLine() const { return FALSE; }
00054 void QTextCustomItem::resize( int nwidth ){ width = nwidth; }
00055 void QTextCustomItem::invalidate() {}
00056
00057 bool QTextCustomItem::isNested() const { return FALSE; }
00058 int QTextCustomItem::minimumWidth() const { return 0; }
00059
00060 QString QTextCustomItem::richText() const { return QString::null; }
00061
00062 bool QTextCustomItem::enter( QTextCursor *, QTextDocument*&, QTextParagraph *&, int &, int &, int &, bool )
00063 {
00064 return TRUE;
00065 }
00066 bool QTextCustomItem::enterAt( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int &, const QPoint & )
00067 {
00068 return TRUE;
00069 }
00070 bool QTextCustomItem::next( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
00071 {
00072 return TRUE;
00073 }
00074 bool QTextCustomItem::prev( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
00075 {
00076 return TRUE;
00077 }
00078 bool QTextCustomItem::down( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
00079 {
00080 return TRUE;
00081 }
00082 bool QTextCustomItem::up( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
00083 {
00084 return TRUE;
00085 }
00086
00087 void QTextFlow::setPageSize( int ps ) { pagesize = ps; }
00088 bool QTextFlow::isEmpty() { return leftItems.isEmpty() && rightItems.isEmpty(); }
00089
00090 void QTextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; }
00091
00092 void QTextTable::invalidate() { cachewidth = -1; }
00093
00094 QTextParagraphData::~QTextParagraphData() {}
00095 void QTextParagraphData::join( QTextParagraphData * ) {}
00096
00097 QTextFormatter::~QTextFormatter() {}
00098 void QTextFormatter::setWrapEnabled( bool b ) { wrapEnabled = b; }
00099 void QTextFormatter::setWrapAtColumn( int c ) { wrapColumn = c; }
00100
00101
00102
00103 int QTextCursor::x() const
00104 {
00105 QTextStringChar *c = para->at( idx );
00106 int curx = c->x;
00107 if ( !c->rightToLeft &&
00108 c->c.isSpace() &&
00109 idx > 0 &&
00110 !c->lineStart &&
00111 ( para->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify )
00112 curx = para->at( idx - 1 )->x + para->string()->width( idx - 1 );
00113 if ( c->rightToLeft )
00114 curx += para->string()->width( idx );
00115 return curx;
00116 }
00117
00118 int QTextCursor::y() const
00119 {
00120 int dummy, line;
00121 para->lineStartOfChar( idx, &dummy, &line );
00122 return para->lineY( line );
00123 }
00124
00125 int QTextCursor::globalX() const { return totalOffsetX() + para->rect().x() + x(); }
00126 int QTextCursor::globalY() const { return totalOffsetY() + para->rect().y() + y(); }
00127
00128 QTextDocument *QTextCursor::document() const
00129 {
00130 return para ? para->document() : 0;
00131 }
00132
00133 void QTextCursor::gotoPosition( QTextParagraph* p, int index )
00134 {
00135 if ( para && p != para ) {
00136 while ( para->document() != p->document() && !indices.isEmpty() )
00137 pop();
00138 Q_ASSERT( indices.isEmpty() || para->document() == p->document() );
00139 }
00140 para = p;
00141 if ( index < 0 || index >= para->length() ) {
00142 #if defined(QT_CHECK_RANGE)
00143 owarn << "QTextCursor::gotoParagraph Index: " << index << " out of range" << oendl;
00144 #endif
00145 index = index < 0 ? 0 : para->length() - 1;
00146 }
00147
00148 tmpIndex = -1;
00149 idx = index;
00150 }
00151
00152 bool QTextDocument::hasSelection( int id, bool visible ) const
00153 {
00154 return ( selections.find( id ) != selections.end() &&
00155 ( !visible ||
00156 ( (QTextDocument*)this )->selectionStartCursor( id ) !=
00157 ( (QTextDocument*)this )->selectionEndCursor( id ) ) );
00158 }
00159
00160 void QTextDocument::setSelectionStart( int id, const QTextCursor &cursor )
00161 {
00162 QTextDocumentSelection sel;
00163 sel.startCursor = cursor;
00164 sel.endCursor = cursor;
00165 sel.swapped = FALSE;
00166 selections[ id ] = sel;
00167 }
00168
00169 QTextParagraph *QTextDocument::paragAt( int i ) const
00170 {
00171 QTextParagraph* p = curParag;
00172 if ( !p || p->paragId() > i )
00173 p = fParag;
00174 while ( p && p->paragId() != i )
00175 p = p->next();
00176 ((QTextDocument*)this)->curParag = p;
00177 return p;
00178 }
00179
00180
00181 QTextFormat::~QTextFormat()
00182 {
00183 }
00184
00185 QTextFormat::QTextFormat()
00186 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() )
00187 {
00188 ref = 0;
00189
00190 usePixelSizes = FALSE;
00191 if ( stdSize == -1 ) {
00192 stdSize = qApp->font().pixelSize();
00193 usePixelSizes = TRUE;
00194 }
00195
00196 missp = FALSE;
00197 ha = AlignNormal;
00198 collection = 0;
00199 }
00200
00201 QTextFormat::QTextFormat( const QStyleSheetItem *style )
00202 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() )
00203 {
00204 ref = 0;
00205
00206 usePixelSizes = FALSE;
00207 if ( stdSize == -1 ) {
00208 stdSize = qApp->font().pixelSize();
00209 usePixelSizes = TRUE;
00210 }
00211
00212 missp = FALSE;
00213 ha = AlignNormal;
00214 collection = 0;
00215 fn = QFont( style->fontFamily(),
00216 style->fontSize(),
00217 style->fontWeight(),
00218 style->fontItalic() );
00219 fn.setUnderline( style->fontUnderline() );
00220 fn.setStrikeOut( style->fontStrikeOut() );
00221 col = style->color();
00222 fm = QFontMetrics( fn );
00223 leftBearing = fm.minLeftBearing();
00224 rightBearing = fm.minRightBearing();
00225 hei = fm.lineSpacing();
00226 asc = fm.ascent() + (fm.leading()+1)/2;
00227 dsc = fm.descent();
00228 missp = FALSE;
00229 ha = AlignNormal;
00230 memset( widths, 0, 256 );
00231 generateKey();
00232 addRef();
00233 }
00234
00235 QTextFormat::QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent )
00236 : fn( f ), col( c ), fm( QFontMetrics( f ) ), linkColor( TRUE ),
00237 logicalFontSize( 3 ), stdSize( f.pointSize() )
00238 {
00239 ref = 0;
00240 usePixelSizes = FALSE;
00241 if ( stdSize == -1 ) {
00242 stdSize = f.pixelSize();
00243 usePixelSizes = TRUE;
00244 }
00245 collection = parent;
00246 leftBearing = fm.minLeftBearing();
00247 rightBearing = fm.minRightBearing();
00248 hei = fm.lineSpacing();
00249 asc = fm.ascent() + (fm.leading()+1)/2;
00250 dsc = fm.descent();
00251 missp = FALSE;
00252 ha = AlignNormal;
00253 memset( widths, 0, 256 );
00254 generateKey();
00255 addRef();
00256 }
00257
00258 QTextFormat::QTextFormat( const QTextFormat &f )
00259 : fm( f.fm )
00260 {
00261 ref = 0;
00262 collection = 0;
00263 fn = f.fn;
00264 col = f.col;
00265 leftBearing = f.leftBearing;
00266 rightBearing = f.rightBearing;
00267 memset( widths, 0, 256 );
00268 hei = f.hei;
00269 asc = f.asc;
00270 dsc = f.dsc;
00271 stdSize = f.stdSize;
00272 usePixelSizes = f.usePixelSizes;
00273 logicalFontSize = f.logicalFontSize;
00274 missp = f.missp;
00275 ha = f.ha;
00276 k = f.k;
00277 linkColor = f.linkColor;
00278 addRef();
00279 }
00280
00281 QTextFormat& QTextFormat::operator=( const QTextFormat &f )
00282 {
00283 ref = 0;
00284 collection = f.collection;
00285 fn = f.fn;
00286 col = f.col;
00287 fm = f.fm;
00288 leftBearing = f.leftBearing;
00289 rightBearing = f.rightBearing;
00290 memset( widths, 0, 256 );
00291 hei = f.hei;
00292 asc = f.asc;
00293 dsc = f.dsc;
00294 stdSize = f.stdSize;
00295 usePixelSizes = f.usePixelSizes;
00296 logicalFontSize = f.logicalFontSize;
00297 missp = f.missp;
00298 ha = f.ha;
00299 k = f.k;
00300 linkColor = f.linkColor;
00301 addRef();
00302 return *this;
00303 }
00304
00305 void QTextFormat::update()
00306 {
00307 fm = QFontMetrics( fn );
00308 leftBearing = fm.minLeftBearing();
00309 rightBearing = fm.minRightBearing();
00310 hei = fm.lineSpacing();
00311 asc = fm.ascent() + (fm.leading()+1)/2;
00312 dsc = fm.descent();
00313 memset( widths, 0, 256 );
00314 generateKey();
00315 }
00316
00317
00318 QPainter* QTextFormat::pntr = 0;
00319
00320 void QTextFormat::setPainter( QPainter *p )
00321 {
00322 pntr = p;
00323 }
00324
00325 QPainter* QTextFormat::painter()
00326 {
00327 return pntr;
00328 }
00329
00330
00331 int QTextFormat::minLeftBearing() const
00332 {
00333 if ( !pntr || !pntr->isActive() )
00334 return leftBearing;
00335 pntr->setFont( fn );
00336 return pntr->fontMetrics().minLeftBearing();
00337 }
00338
00339 int QTextFormat::minRightBearing() const
00340 {
00341 if ( !pntr || !pntr->isActive() )
00342 return rightBearing;
00343 pntr->setFont( fn );
00344 return pntr->fontMetrics().minRightBearing();
00345 }
00346
00347 int QTextFormat::height() const
00348 {
00349 if ( !pntr || !pntr->isActive() )
00350 return hei;
00351 pntr->setFont( fn );
00352 return pntr->fontMetrics().lineSpacing();
00353 }
00354
00355 int QTextFormat::ascent() const
00356 {
00357 if ( !pntr || !pntr->isActive() )
00358 return asc;
00359 pntr->setFont( fn );
00360 return pntr->fontMetrics().ascent() + (pntr->fontMetrics().leading()+1)/2;
00361 }
00362
00363 int QTextFormat::descent() const
00364 {
00365 if ( !pntr || !pntr->isActive() )
00366 return dsc;
00367 pntr->setFont( fn );
00368 return pntr->fontMetrics().descent();
00369 }
00370
00371 int QTextFormat::leading() const
00372 {
00373 if ( !pntr || !pntr->isActive() )
00374 return fm.leading();
00375 pntr->setFont( fn );
00376 return pntr->fontMetrics().leading();
00377 }
00378
00379 void QTextFormat::generateKey()
00380 {
00381 k = getKey( fn, col, isMisspelled(), vAlign() );
00382 }
00383
00384 QString QTextFormat::getKey( const QFont &fn, const QColor &col, bool misspelled, VerticalAlignment a )
00385 {
00386 QString k = fn.key();
00387 k += '/';
00388 k += QString::number( (uint)col.rgb() );
00389 k += '/';
00390 k += QString::number( (int)misspelled );
00391 k += '/';
00392 k += QString::number( (int)a );
00393 return k;
00394 }
00395
00396 QString QTextString::toString( const QMemArray<QTextStringChar> &data )
00397 {
00398 QString s;
00399 int l = data.size();
00400 s.setUnicode( 0, l );
00401 QTextStringChar *c = data.data();
00402 QChar *uc = (QChar *)s.unicode();
00403 while ( l-- ) {
00404 *uc = c->c;
00405
00406
00407 if ( *uc == (char)0xa0 )
00408 *uc = 0x20;
00409 uc++;
00410 c++;
00411 }
00412
00413 return s;
00414 }
00415
00416 QString QTextString::toString() const
00417 {
00418 return toString( data );
00419 }
00420
00421 void QTextParagraph::setSelection( int id, int start, int end )
00422 {
00423 QMap<int, QTextParagraphSelection>::ConstIterator it = selections().find( id );
00424 if ( it != mSelections->end() ) {
00425 if ( start == ( *it ).start && end == ( *it ).end )
00426 return;
00427 }
00428
00429 QTextParagraphSelection sel;
00430 sel.start = start;
00431 sel.end = end;
00432 (*mSelections)[ id ] = sel;
00433 setChanged( TRUE, TRUE );
00434 }
00435
00436 void QTextParagraph::removeSelection( int id )
00437 {
00438 if ( !hasSelection( id ) )
00439 return;
00440 if ( mSelections )
00441 mSelections->remove( id );
00442 setChanged( TRUE, TRUE );
00443 }
00444
00445 int QTextParagraph::selectionStart( int id ) const
00446 {
00447 if ( !mSelections )
00448 return -1;
00449 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
00450 if ( it == mSelections->end() )
00451 return -1;
00452 return ( *it ).start;
00453 }
00454
00455 int QTextParagraph::selectionEnd( int id ) const
00456 {
00457 if ( !mSelections )
00458 return -1;
00459 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
00460 if ( it == mSelections->end() )
00461 return -1;
00462 return ( *it ).end;
00463 }
00464
00465 bool QTextParagraph::hasSelection( int id ) const
00466 {
00467 return mSelections ? mSelections->contains( id ) : FALSE;
00468 }
00469
00470 bool QTextParagraph::fullSelected( int id ) const
00471 {
00472 if ( !mSelections )
00473 return FALSE;
00474 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
00475 if ( it == mSelections->end() )
00476 return FALSE;
00477 return ( *it ).start == 0 && ( *it ).end == str->length() - 1;
00478 }
00479
00480 int QTextParagraph::lineY( int l ) const
00481 {
00482 if ( l > (int)lineStarts.count() - 1 ) {
00483 owarn << "QTextParagraph::lineY: line " << l << " out of range!" << oendl;
00484 return 0;
00485 }
00486
00487 if ( !isValid() )
00488 ( (QTextParagraph*)this )->format();
00489
00490 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
00491 while ( l-- > 0 )
00492 ++it;
00493 return ( *it )->y;
00494 }
00495
00496 int QTextParagraph::lineBaseLine( int l ) const
00497 {
00498 if ( l > (int)lineStarts.count() - 1 ) {
00499 owarn << "QTextParagraph::lineBaseLine: line " << l << " out of range!" << oendl;
00500 return 10;
00501 }
00502
00503 if ( !isValid() )
00504 ( (QTextParagraph*)this )->format();
00505
00506 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
00507 while ( l-- > 0 )
00508 ++it;
00509 return ( *it )->baseLine;
00510 }
00511
00512 int QTextParagraph::lineHeight( int l ) const
00513 {
00514 if ( l > (int)lineStarts.count() - 1 ) {
00515 owarn << "QTextParagraph::lineHeight: line " << l << " out of range!" << oendl;
00516 return 15;
00517 }
00518
00519 if ( !isValid() )
00520 ( (QTextParagraph*)this )->format();
00521
00522 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
00523 while ( l-- > 0 )
00524 ++it;
00525 return ( *it )->h;
00526 }
00527
00528 void QTextParagraph::lineInfo( int l, int &y, int &h, int &bl ) const
00529 {
00530 if ( l > (int)lineStarts.count() - 1 ) {
00531 owarn << "QTextParagraph::lineInfo: line " << l << " out of range!" << oendl;
00532 odebug << "" << (int)lineStarts.count() - 1 << " " << l << "" << oendl;
00533 y = 0;
00534 h = 15;
00535 bl = 10;
00536 return;
00537 }
00538
00539 if ( !isValid() )
00540 ( (QTextParagraph*)this )->format();
00541
00542 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
00543 while ( l-- > 0 )
00544 ++it;
00545 y = ( *it )->y;
00546 h = ( *it )->h;
00547 bl = ( *it )->baseLine;
00548 }
00549
00550
00551 void QTextParagraph::setAlignment( int a )
00552 {
00553 if ( a == (int)align )
00554 return;
00555 align = a;
00556 invalidate( 0 );
00557 }
00558
00559 QTextFormatter *QTextParagraph::formatter() const
00560 {
00561 if ( hasdoc )
00562 return document()->formatter();
00563 if ( pseudoDocument()->pFormatter )
00564 return pseudoDocument()->pFormatter;
00565 return ( ( (QTextParagraph*)this )->pseudoDocument()->pFormatter = new QTextFormatterBreakWords );
00566 }
00567
00568 void QTextParagraph::setTabArray( int *a )
00569 {
00570 delete [] tArray;
00571 tArray = a;
00572 }
00573
00574 void QTextParagraph::setTabStops( int tw )
00575 {
00576 if ( hasdoc )
00577 document()->setTabStops( tw );
00578 else
00579 tabStopWidth = tw;
00580 }
00581
00582 QMap<int, QTextParagraphSelection> &QTextParagraph::selections() const
00583 {
00584 if ( !mSelections )
00585 ((QTextParagraph *)this)->mSelections = new QMap<int, QTextParagraphSelection>;
00586 return *mSelections;
00587 }
00588
00589
00590 QPtrList<QTextCustomItem> &QTextParagraph::floatingItems() const
00591 {
00592 if ( !mFloatingItems )
00593 ((QTextParagraph *)this)->mFloatingItems = new QPtrList<QTextCustomItem>;
00594 return *mFloatingItems;
00595 }
00596
00597 QTextStringChar::~QTextStringChar()
00598 {
00599 if ( format() )
00600 format()->removeRef();
00601 if ( type )
00602 delete d.custom;
00603 }
00604
00605 QTextParagraphPseudoDocument::QTextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0){}
00606 QTextParagraphPseudoDocument::~QTextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; }