Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qrichtext_p.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** $Id: qrichtext_p.cpp,v 1.3 2004/04/04 13:54:45 mickeyl Exp $
00003 **
00004 ** Implementation of the internal Qt classes dealing with rich text
00005 **
00006 ** Created : 990101
00007 **
00008 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
00009 **
00010 ** This file is part of the kernel module of the Qt GUI Toolkit.
00011 **
00012 ** This file may be distributed under the terms of the Q Public License
00013 ** as defined by Trolltech AS of Norway and appearing in the file
00014 ** LICENSE.QPL included in the packaging of this file.
00015 **
00016 ** This file may be distributed and/or modified under the terms of the
00017 ** GNU General Public License version 2 as published by the Free Software
00018 ** Foundation and appearing in the file LICENSE.GPL included in the
00019 ** packaging of this file.
00020 **
00021 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
00022 ** licenses may use this file in accordance with the Qt Commercial License
00023 ** Agreement provided with the Software.
00024 **
00025 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00026 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00027 **
00028 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
00029 **   information about Qt Commercial License Agreements.
00030 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
00031 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00032 **
00033 ** Contact info@trolltech.com if any conditions of this licensing are
00034 ** not clear to you.
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         // ### workaround so that non-breaking whitespaces are drawn
00406         // properly, actually this should be fixed in QFont somewhere
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 ) // not Regular
00602         delete d.custom;
00603 }
00604 
00605 QTextParagraphPseudoDocument::QTextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0){}
00606 QTextParagraphPseudoDocument::~QTextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; }

Generated on Sat Nov 5 16:17:04 2005 for OPIE by  doxygen 1.4.2