author | leseb <leseb> | 2002-07-15 23:22:50 (UTC) |
---|---|---|
committer | leseb <leseb> | 2002-07-15 23:22:50 (UTC) |
commit | 72eb74051ed8f1b7696041e241ab99df3af5b08d (patch) (side-by-side diff) | |
tree | bf9beee9469bc4384cb8178fbd6565cf161b4708 /noncore/apps | |
parent | dcea0e50a00ed9efb988ded5abf5d39de1bea393 (diff) | |
download | opie-72eb74051ed8f1b7696041e241ab99df3af5b08d.zip opie-72eb74051ed8f1b7696041e241ab99df3af5b08d.tar.gz opie-72eb74051ed8f1b7696041e241ab99df3af5b08d.tar.bz2 |
Sync with Qt 3.0.5
-rw-r--r-- | noncore/apps/opie-write/qcleanuphandler.h | 12 | ||||
-rw-r--r-- | noncore/apps/opie-write/qcomplextext.cpp | 3 | ||||
-rw-r--r-- | noncore/apps/opie-write/qrichtext.cpp | 3945 | ||||
-rw-r--r-- | noncore/apps/opie-write/qrichtext_p.cpp | 301 | ||||
-rw-r--r-- | noncore/apps/opie-write/qrichtext_p.h | 576 | ||||
-rw-r--r-- | noncore/apps/opie-write/qstylesheet.cpp | 750 | ||||
-rw-r--r-- | noncore/apps/opie-write/qstylesheet.h | 12 | ||||
-rw-r--r-- | noncore/apps/opie-write/qt3namespace.h | 1 | ||||
-rw-r--r-- | noncore/apps/opie-write/qtextedit.cpp | 1375 | ||||
-rw-r--r-- | noncore/apps/opie-write/qtextedit.h | 30 |
10 files changed, 3347 insertions, 3658 deletions
diff --git a/noncore/apps/opie-write/qcleanuphandler.h b/noncore/apps/opie-write/qcleanuphandler.h index 5c5bf16..2d6eb7c 100644 --- a/noncore/apps/opie-write/qcleanuphandler.h +++ b/noncore/apps/opie-write/qcleanuphandler.h @@ -42,9 +42,5 @@ template<class Type> -#ifdef Q_NO_TEMPLATE_EXPORT class QCleanupHandler -#else -class Q_EXPORT QCleanupHandler -#endif { public: @@ -89,9 +85,5 @@ private: template<class Type> -#ifdef Q_NO_TEMPLATE_EXPORT class QSingleCleanupHandler -#else -class Q_EXPORT QSingleCleanupHandler -#endif { public: @@ -113,9 +105,5 @@ private: template<class Type> -#ifdef Q_NO_TEMPLATE_EXPORT class QSharedCleanupHandler -#else -class Q_EXPORT QSharedCleanupHandler -#endif { public: diff --git a/noncore/apps/opie-write/qcomplextext.cpp b/noncore/apps/opie-write/qcomplextext.cpp index 0fa6c2e..e8b94da 100644 --- a/noncore/apps/opie-write/qcomplextext.cpp +++ b/noncore/apps/opie-write/qcomplextext.cpp @@ -67,7 +67,4 @@ QBidiContext::~QBidiContext() } -static QChar *shapeBuffer = 0; -static int shapeBufSize = 0; - /* Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on diff --git a/noncore/apps/opie-write/qrichtext.cpp b/noncore/apps/opie-write/qrichtext.cpp index 7901000..3b044c3 100644 --- a/noncore/apps/opie-write/qrichtext.cpp +++ b/noncore/apps/opie-write/qrichtext.cpp @@ -42,12 +42,9 @@ #include "qtextstream.h" #include "qfile.h" -#include "qregexp.h" #include "qapplication.h" -#include "qclipboard.h" #include "qmap.h" #include "qfileinfo.h" #include "qstylesheet.h" #include "qmime.h" -#include "qregexp.h" #include "qimage.h" #include "qdragobject.h" @@ -65,23 +62,17 @@ using namespace Qt3; -//#define PARSER_DEBUG -//#define DEBUG_COLLECTION// ---> also in qrichtext_p.h -//#define DEBUG_TABLE_RENDERING +static QTextCursor* richTextExportStart = 0; +static QTextCursor* richTextExportEnd = 0; static QTextFormatCollection *qFormatCollection = 0; -const int QStyleSheetItem_WhiteSpaceNoCompression = 3; // ### belongs in QStyleSheetItem, fix 3.1 -const int QStyleSheetItem_WhiteSpaceNormalWithNewlines = 4; // ### belongs in QStyleSheetItem, fix 3.1 - const int border_tolerance = 2; -#if defined(PARSER_DEBUG) -static QString debug_indent; -#endif - #ifdef Q_WS_WIN #include "qt_windows.h" #endif +#define QChar_linesep QChar(0x2028U) + static inline bool is_printer( QPainter *p ) { @@ -178,8 +169,6 @@ bool QTextCommandHistory::isRedoAvailable() QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, - const QValueList< QPtrVector<QStyleSheetItem> > &os, - const QValueList<QStyleSheetItem::ListStyle> &ols, - const QMemArray<int> &oas) - : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), oldStyles( os ), oldListStyles( ols ), oldAligns( oas ) + const QByteArray& oldStyleInfo ) + : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo ) { for ( int j = 0; j < (int)text.size(); ++j ) { @@ -189,5 +178,5 @@ QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const } -QTextDeleteCommand::QTextDeleteCommand( QTextParag *p, int idx, const QMemArray<QTextStringChar> &str ) +QTextDeleteCommand::QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ) : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str ) { @@ -209,11 +198,11 @@ QTextDeleteCommand::~QTextDeleteCommand() QTextCursor *QTextDeleteCommand::execute( QTextCursor *c ) { - QTextParag *s = doc ? doc->paragAt( id ) : parag; + QTextParagraph *s = doc ? doc->paragAt( id ) : parag; if ( !s ) { - qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParag()->paragId() ); + qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() ); return 0; } - cursor.setParag( s ); + cursor.setParagraph( s ); cursor.setIndex( index ); int len = text.size(); @@ -221,8 +210,8 @@ QTextCursor *QTextDeleteCommand::execute( QTextCursor *c ) *c = cursor; if ( doc ) { - doc->setSelectionStart( QTextDocument::Temp, &cursor ); + doc->setSelectionStart( QTextDocument::Temp, cursor ); for ( int i = 0; i < len; ++i ) cursor.gotoNextLetter(); - doc->setSelectionEnd( QTextDocument::Temp, &cursor ); + doc->setSelectionEnd( QTextDocument::Temp, cursor ); doc->removeSelectedText( QTextDocument::Temp, &cursor ); if ( c ) @@ -237,18 +226,18 @@ QTextCursor *QTextDeleteCommand::execute( QTextCursor *c ) QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c ) { - QTextParag *s = doc ? doc->paragAt( id ) : parag; + QTextParagraph *s = doc ? doc->paragAt( id ) : parag; if ( !s ) { - qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParag()->paragId() ); + qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() ); return 0; } - cursor.setParag( s ); + cursor.setParagraph( s ); cursor.setIndex( index ); QString str = QTextString::toString( text ); cursor.insert( str, TRUE, &text ); - cursor.setParag( s ); + cursor.setParagraph( s ); cursor.setIndex( index ); if ( c ) { - c->setParag( s ); + c->setParagraph( s ); c->setIndex( index ); for ( int i = 0; i < (int)text.size(); ++i ) @@ -256,35 +245,19 @@ QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c ) } - QValueList< QPtrVector<QStyleSheetItem> >::Iterator it = oldStyles.begin(); - QValueList<QStyleSheetItem::ListStyle>::Iterator lit = oldListStyles.begin(); - int i = 0; - QTextParag *p = s; - bool end = FALSE; - while ( p ) { - if ( it != oldStyles.end() ) - p->setStyleSheetItems( *it ); - else - end = TRUE; - if ( lit != oldListStyles.end() ) - p->setListStyle( *lit ); - else - end = TRUE; - if ( i < (int)oldAligns.size() ) - p->setAlignment( oldAligns.at( i ) ); - else - end = TRUE; - if ( end ) - break; + if ( !styleInformation.isEmpty() ) { + QDataStream styleStream( styleInformation, IO_ReadOnly ); + int num; + styleStream >> num; + QTextParagraph *p = s; + while ( num-- && p ) { + p->readStyleInformation( styleStream ); p = p->next(); - ++it; - ++lit; - ++i; } - - s = cursor.parag(); + } + s = cursor.paragraph(); while ( s ) { s->format(); s->setChanged( TRUE ); - if ( s == c->parag() ) + if ( s == c->paragraph() ) break; s = s->next(); @@ -316,18 +289,18 @@ QTextFormatCommand::~QTextFormatCommand() QTextCursor *QTextFormatCommand::execute( QTextCursor *c ) { - QTextParag *sp = doc->paragAt( startId ); - QTextParag *ep = doc->paragAt( endId ); + QTextParagraph *sp = doc->paragAt( startId ); + QTextParagraph *ep = doc->paragAt( endId ); if ( !sp || !ep ) return c; QTextCursor start( doc ); - start.setParag( sp ); + start.setParagraph( sp ); start.setIndex( startIndex ); QTextCursor end( doc ); - end.setParag( ep ); + end.setParagraph( ep ); end.setIndex( endIndex ); - doc->setSelectionStart( QTextDocument::Temp, &start ); - doc->setSelectionEnd( QTextDocument::Temp, &end ); + doc->setSelectionStart( QTextDocument::Temp, start ); + doc->setSelectionEnd( QTextDocument::Temp, end ); doc->setFormat( QTextDocument::Temp, format, flags ); doc->removeSelection( QTextDocument::Temp ); @@ -340,6 +313,6 @@ QTextCursor *QTextFormatCommand::execute( QTextCursor *c ) QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c ) { - QTextParag *sp = doc->paragAt( startId ); - QTextParag *ep = doc->paragAt( endId ); + QTextParagraph *sp = doc->paragAt( startId ); + QTextParagraph *ep = doc->paragAt( endId ); if ( !sp || !ep ) return 0; @@ -374,5 +347,5 @@ QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c ) QTextCursor end( doc ); - end.setParag( ep ); + end.setParagraph( ep ); end.setIndex( endIndex ); if ( endIndex == ep->length() ) @@ -382,79 +355,50 @@ QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c ) } -QTextAlignmentCommand::QTextAlignmentCommand( QTextDocument *d, int fParag, int lParag, int na, const QMemArray<int> &oa ) - : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), newAlign( na ), oldAligns( oa ) +QTextStyleCommand::QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange ) + : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange ) { + after = readStyleInformation( d, fParag, lParag ); } -QTextCursor *QTextAlignmentCommand::execute( QTextCursor *c ) + +QByteArray QTextStyleCommand::readStyleInformation( QTextDocument* doc, int fParag, int lParag ) { - QTextParag *p = doc->paragAt( firstParag ); + QByteArray style; + QTextParagraph *p = doc->paragAt( fParag ); if ( !p ) - return c; - while ( p ) { - p->setAlignment( newAlign ); - if ( p->paragId() == lastParag ) - break; + return style; + QDataStream styleStream( style, IO_WriteOnly ); + int num = lParag - fParag + 1; + styleStream << num; + while ( num -- && p ) { + p->writeStyleInformation( styleStream ); p = p->next(); } - return c; + return style; } -QTextCursor *QTextAlignmentCommand::unexecute( QTextCursor *c ) +void QTextStyleCommand::writeStyleInformation( QTextDocument* doc, int fParag, const QByteArray& style ) { - QTextParag *p = doc->paragAt( firstParag ); + QTextParagraph *p = doc->paragAt( fParag ); if ( !p ) - return c; - int i = 0; - while ( p ) { - if ( i < (int)oldAligns.size() ) - p->setAlignment( oldAligns.at( i ) ); - if ( p->paragId() == lastParag ) - break; + return; + QDataStream styleStream( style, IO_ReadOnly ); + int num; + styleStream >> num; + while ( num-- && p ) { + p->readStyleInformation( styleStream ); p = p->next(); - ++i; } - return c; } -QTextParagTypeCommand::QTextParagTypeCommand( QTextDocument *d, int fParag, int lParag, bool l, - QStyleSheetItem::ListStyle s, const QValueList< QPtrVector<QStyleSheetItem> > &os, - const QValueList<QStyleSheetItem::ListStyle> &ols ) - : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), list( l ), listStyle( s ), oldStyles( os ), oldListStyles( ols ) +QTextCursor *QTextStyleCommand::execute( QTextCursor *c ) { -} - -QTextCursor *QTextParagTypeCommand::execute( QTextCursor *c ) -{ - QTextParag *p = doc->paragAt( firstParag ); - if ( !p ) - return c; - while ( p ) { - p->setList( list, (int)listStyle ); - if ( p->paragId() == lastParag ) - break; - p = p->next(); - } + writeStyleInformation( doc, firstParag, after ); return c; } -QTextCursor *QTextParagTypeCommand::unexecute( QTextCursor *c ) +QTextCursor *QTextStyleCommand::unexecute( QTextCursor *c ) { - QTextParag *p = doc->paragAt( firstParag ); - if ( !p ) - return c; - QValueList< QPtrVector<QStyleSheetItem> >::Iterator it = oldStyles.begin(); - QValueList<QStyleSheetItem::ListStyle>::Iterator lit = oldListStyles.begin(); - while ( p ) { - if ( it != oldStyles.end() ) - p->setStyleSheetItems( *it ); - if ( lit != oldListStyles.end() ) - p->setListStyle( *lit ); - if ( p->paragId() == lastParag ) - break; - p = p->next(); - ++it; - ++lit; - } + writeStyleInformation( doc, firstParag, before ); return c; } @@ -463,28 +407,19 @@ QTextCursor *QTextParagTypeCommand::unexecute( QTextCursor *c ) QTextCursor::QTextCursor( QTextDocument *d ) - : doc( d ), ox( 0 ), oy( 0 ) -{ - nested = FALSE; - idx = 0; - string = doc ? doc->firstParag() : 0; - tmpIndex = -1; - valid = TRUE; -} - -QTextCursor::QTextCursor() + : idx( 0 ), tmpIndex( -1 ), ox( 0 ), oy( 0 ), + valid( TRUE ) { + para = d ? d->firstParagraph() : 0; } QTextCursor::QTextCursor( const QTextCursor &c ) { - doc = c.doc; ox = c.ox; oy = c.oy; - nested = c.nested; idx = c.idx; - string = c.string; + para = c.para; tmpIndex = c.tmpIndex; indices = c.indices; - parags = c.parags; + paras = c.paras; xOffsets = c.xOffsets; yOffsets = c.yOffsets; @@ -494,13 +429,11 @@ QTextCursor::QTextCursor( const QTextCursor &c ) QTextCursor &QTextCursor::operator=( const QTextCursor &c ) { - doc = c.doc; ox = c.ox; oy = c.oy; - nested = c.nested; idx = c.idx; - string = c.string; + para = c.para; tmpIndex = c.tmpIndex; indices = c.indices; - parags = c.parags; + paras = c.paras; xOffsets = c.xOffsets; yOffsets = c.yOffsets; @@ -512,14 +445,11 @@ QTextCursor &QTextCursor::operator=( const QTextCursor &c ) bool QTextCursor::operator==( const QTextCursor &c ) const { - return doc == c.doc && string == c.string && idx == c.idx; + return para == c.para && idx == c.idx; } int QTextCursor::totalOffsetX() const { - if ( !nested ) - return 0; - QValueStack<int>::ConstIterator xit = xOffsets.begin(); int xoff = ox; - for ( ; xit != xOffsets.end(); ++xit ) + for ( QValueStack<int>::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit ) xoff += *xit; return xoff; @@ -528,9 +458,6 @@ int QTextCursor::totalOffsetX() const int QTextCursor::totalOffsetY() const { - if ( !nested ) - return 0; - QValueStack<int>::ConstIterator yit = yOffsets.begin(); int yoff = oy; - for ( ; yit != yOffsets.end(); ++yit ) + for ( QValueStack<int>::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit ) yoff += *yit; return yoff; @@ -539,25 +466,25 @@ int QTextCursor::totalOffsetY() const void QTextCursor::gotoIntoNested( const QPoint &globalPos ) { - if ( !doc ) + if ( !para ) return; push(); ox = 0; int bl, y; - string->lineHeightOfChar( idx, &bl, &y ); - oy = y + string->rect().y(); - nested = TRUE; + para->lineHeightOfChar( idx, &bl, &y ); + oy = y + para->rect().y(); QPoint p( globalPos.x() - offsetX(), globalPos.y() - offsetY() ); - Q_ASSERT( string->at( idx )->isCustom() ); - ox = string->at( idx )->x; - string->at( idx )->customItem()->enterAt( this, doc, string, idx, ox, oy, p ); + Q_ASSERT( para->at( idx )->isCustom() ); + ox = para->at( idx )->x; + + QTextDocument* doc = document(); + para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, p ); } void QTextCursor::invalidateNested() { - if ( nested ) { - QValueStack<QTextParag*>::Iterator it = parags.begin(); + QValueStack<QTextParagraph*>::Iterator it = paras.begin(); QValueStack<int>::Iterator it2 = indices.begin(); - for ( ; it != parags.end(); ++it, ++it2 ) { - if ( *it == string ) + for ( ; it != paras.end(); ++it, ++it2 ) { + if ( *it == para ) continue; (*it)->invalidate( 0 ); @@ -566,5 +493,4 @@ void QTextCursor::invalidateNested() } } -} void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting ) @@ -574,63 +500,61 @@ void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QText QString s( str ); #if defined(Q_WS_WIN) - if ( checkNewLine ) - s = s.replace( QRegExp( "\\r" ), "" ); + if ( checkNewLine ) { + int i = 0; + while ( ( i = s.find( '\r', i ) ) != -1 ) + s.remove( i ,1 ); + } #endif if ( checkNewLine ) justInsert = s.find( '\n' ) == -1; - if ( justInsert ) { - string->insert( idx, s ); + if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index + para->insert( idx, s.unicode(), s.length() ); if ( formatting ) { for ( int i = 0; i < (int)s.length(); ++i ) { if ( formatting->at( i ).format() ) { formatting->at( i ).format()->addRef(); - string->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE ); + para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE ); } } } idx += s.length(); - } else { - QStringList lst = QStringList::split( '\n', s, TRUE ); - QStringList::Iterator it = lst.begin(); - int y = string->rect().y() + string->rect().height(); + } else { // we split at new lines + int start = -1; + int end; + int y = para->rect().y() + para->rect().height(); int lastIndex = 0; - QTextFormat *lastFormat = 0; - for ( ; it != lst.end(); ) { - if ( it != lst.begin() ) { - splitAndInsertEmptyParag( FALSE, TRUE ); - string->setEndState( -1 ); - string->prev()->format( -1, FALSE ); - if ( lastFormat && formatting && string->prev() ) { - lastFormat->addRef(); - string->prev()->string()->setFormat( string->prev()->length() - 1, lastFormat, TRUE ); - } - } - lastFormat = 0; - QString s = *it; - ++it; - if ( !s.isEmpty() ) - string->insert( idx, s ); + do { + end = s.find( '\n', start + 1 ); // find line break + if ( end == -1 ) // didn't find one, so end of line is end of string + end = s.length(); + int len = (start == -1 ? end : end - start - 1); + if ( len > 0 ) // insert the line + para->insert( idx, s.unicode() + start + 1, len ); else - string->invalidate( 0 ); - if ( formatting ) { - int len = s.length(); + para->invalidate( 0 ); + if ( formatting ) { // set formats to the chars of the line for ( int i = 0; i < len; ++i ) { if ( formatting->at( i + lastIndex ).format() ) { formatting->at( i + lastIndex ).format()->addRef(); - string->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE ); + para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE ); } } - if ( it != lst.end() ) - lastFormat = formatting->at( len + lastIndex ).format(); - ++len; lastIndex += len; } - - idx += s.length(); + start = end; // next start is at the end of this line + idx += len; // increase the index of the cursor to the end of the inserted text + if ( s[end] == '\n' ) { // if at the end was a line break, break the line + splitAndInsertEmptyParagraph( FALSE, TRUE ); + para->setEndState( -1 ); + para->prev()->format( -1, FALSE ); + lastIndex++; } - string->format( -1, FALSE ); - int dy = string->rect().y() + string->rect().height() - y; - QTextParag *p = string; - p->setParagId( p->prev()->paragId() + 1 ); + + } while ( end < (int)s.length() ); + + para->format( -1, FALSE ); + int dy = para->rect().y() + para->rect().height() - y; + QTextParagraph *p = para; + p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); p = p->next(); while ( p ) { @@ -643,15 +567,15 @@ void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QText } - int h = string->rect().height(); - string->format( -1, TRUE ); - if ( h != string->rect().height() ) + int h = para->rect().height(); + para->format( -1, TRUE ); + if ( h != para->rect().height() ) invalidateNested(); - else if ( doc && doc->parent() ) - doc->nextDoubleBuffered = TRUE; + else if ( para->document() && para->document()->parent() ) + para->document()->nextDoubleBuffered = TRUE; } void QTextCursor::gotoLeft() { - if ( string->string()->isRightToLeft() ) + if ( para->string()->isRightToLeft() ) gotoNextLetter(); else @@ -665,14 +589,13 @@ void QTextCursor::gotoPreviousLetter() if ( idx > 0 ) { idx--; - } else if ( string->prev() ) { - QTextParag *s = string->prev(); - while ( s && !s->isVisible() ) - s = s->prev(); - if ( s ) { - string = s; - idx = string->length() - 1; - } - } else { - if ( nested ) { + const QTextStringChar *tsc = para->at( idx ); + if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) + processNesting( EnterEnd ); + } else if ( para->prev() ) { + para = para->prev(); + while ( !para->isVisible() && para->prev() ) + para = para->prev(); + idx = para->length() - 1; + } else if ( nestedDepth() ) { pop(); processNesting( Prev ); @@ -681,7 +604,7 @@ void QTextCursor::gotoPreviousLetter() if ( idx > 0 ) { idx--; - } else if ( string->prev() ) { - string = string->prev(); - idx = string->length() - 1; + } else if ( para->prev() ) { + para = para->prev(); + idx = para->length() - 1; } } @@ -689,30 +612,20 @@ void QTextCursor::gotoPreviousLetter() } - const QTextStringChar *tsc = string->at( idx ); - if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) { - processNesting( EnterEnd ); - } -} - void QTextCursor::push() { indices.push( idx ); - parags.push( string ); + paras.push( para ); xOffsets.push( ox ); yOffsets.push( oy ); - nestedStack.push( nested ); } void QTextCursor::pop() { - if ( !doc ) + if ( indices.isEmpty() ) return; idx = indices.pop(); - string = parags.pop(); + para = paras.pop(); ox = xOffsets.pop(); oy = yOffsets.pop(); - if ( doc->parent() ) - doc = doc->parent(); - nested = nestedStack.pop(); } @@ -723,14 +636,14 @@ void QTextCursor::restoreState() } -bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link ) +bool QTextCursor::place( const QPoint &p, QTextParagraph *s, bool link ) { QPoint pos( p ); QRect r; - QTextParag *str = s; + QTextParagraph *str = s; if ( pos.y() < s->rect().y() ) pos.setY( s->rect().y() ); while ( s ) { r = s->rect(); - r.setWidth( doc ? doc->width() : QWIDGETSIZE_MAX ); + r.setWidth( document() ? document()->width() : QWIDGETSIZE_MAX ); if ( s->isVisible() ) str = s; @@ -745,5 +658,5 @@ bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link ) s = str; - setParag( s, FALSE ); + setParagraph( s ); int y = s->rect().y(); int lines = s->lines(); @@ -759,5 +672,5 @@ bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link ) if ( !chr ) return FALSE; - if ( pos.y() >= y + cy && pos.y() <= y + cy + ch ) + if ( pos.y() <= y + cy + ch ) break; } @@ -799,13 +712,13 @@ bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link ) i++; } - setIndex( curpos, FALSE ); + setIndex( curpos ); - if ( inCustom && doc && parag()->at( curpos )->isCustom() && parag()->at( curpos )->customItem()->isNested() ) { - QTextDocument *oldDoc = doc; + if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) { + QTextDocument *oldDoc = para->document(); gotoIntoNested( pos ); - if ( oldDoc == doc ) + if ( oldDoc == para->document() ) return TRUE; QPoint p( pos.x() - offsetX(), pos.y() - offsetY() ); - if ( !place( p, document()->firstParag(), link ) ) + if ( !place( p, document()->firstParagraph(), link ) ) pop(); } @@ -815,32 +728,32 @@ bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link ) void QTextCursor::processNesting( Operation op ) { - if ( !doc ) + if ( !para->document() ) return; + QTextDocument* doc = para->document(); push(); - ox = string->at( idx )->x; + ox = para->at( idx )->x; int bl, y; - string->lineHeightOfChar( idx, &bl, &y ); - oy = y + string->rect().y(); - nested = TRUE; + para->lineHeightOfChar( idx, &bl, &y ); + oy = y + para->rect().y(); bool ok = FALSE; switch ( op ) { case EnterBegin: - ok = string->at( idx )->customItem()->enter( this, doc, string, idx, ox, oy ); + ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy ); break; case EnterEnd: - ok = string->at( idx )->customItem()->enter( this, doc, string, idx, ox, oy, TRUE ); + ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE ); break; case Next: - ok = string->at( idx )->customItem()->next( this, doc, string, idx, ox, oy ); + ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy ); break; case Prev: - ok = string->at( idx )->customItem()->prev( this, doc, string, idx, ox, oy ); + ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy ); break; case Down: - ok = string->at( idx )->customItem()->down( this, doc, string, idx, ox, oy ); + ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy ); break; case Up: - ok = string->at( idx )->customItem()->up( this, doc, string, idx, ox, oy ); + ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy ); break; } @@ -851,5 +764,5 @@ void QTextCursor::processNesting( Operation op ) void QTextCursor::gotoRight() { - if ( string->string()->isRightToLeft() ) + if ( para->string()->isRightToLeft() ) gotoPreviousLetter(); else @@ -861,5 +774,5 @@ void QTextCursor::gotoNextLetter() tmpIndex = -1; - const QTextStringChar *tsc = string->at( idx ); + const QTextStringChar *tsc = para->at( idx ); if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) { processNesting( EnterBegin ); @@ -867,24 +780,20 @@ void QTextCursor::gotoNextLetter() } - if ( idx < string->length() - 1 ) { + if ( idx < para->length() - 1 ) { idx++; - } else if ( string->next() ) { - QTextParag *s = string->next(); - while ( s && !s->isVisible() ) - s = s->next(); - if ( s ) { - string = s; + } else if ( para->next() ) { + para = para->next(); + while ( !para->isVisible() && para->next() ) + para = para->next(); idx = 0; - } - } else { - if ( nested ) { + } else if ( nestedDepth() ) { pop(); processNesting( Next ); if ( idx == -1 ) { pop(); - if ( idx < string->length() - 1 ) { + if ( idx < para->length() - 1 ) { idx++; - } else if ( string->next() ) { - string = string->next(); + } else if ( para->next() ) { + para = para->next(); idx = 0; } @@ -892,5 +801,4 @@ void QTextCursor::gotoNextLetter() } } -} void QTextCursor::gotoUp() @@ -898,5 +806,5 @@ void QTextCursor::gotoUp() int indexOfLineStart; int line; - QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); + QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); if ( !c ) return; @@ -904,6 +812,6 @@ void QTextCursor::gotoUp() tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); if ( indexOfLineStart == 0 ) { - if ( !string->prev() ) { - if ( !nested ) + if ( !para->prev() ) { + if ( !nestedDepth() ) return; pop(); @@ -911,5 +819,5 @@ void QTextCursor::gotoUp() if ( idx == -1 ) { pop(); - if ( !string->prev() ) + if ( !para->prev() ) return; idx = tmpIndex = 0; @@ -919,20 +827,20 @@ void QTextCursor::gotoUp() } } - QTextParag *s = string->prev(); - while ( s && !s->isVisible() ) - s = s->prev(); - if ( s ) - string = s; - int lastLine = string->lines() - 1; - if ( !string->lineStartOfLine( lastLine, &indexOfLineStart ) ) + QTextParagraph *p = para->prev(); + while ( p && !p->isVisible() ) + p = p->prev(); + if ( p ) + para = p; + int lastLine = para->lines() - 1; + if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) ) return; - if ( indexOfLineStart + tmpIndex < string->length() ) + if ( indexOfLineStart + tmpIndex < para->length() ) idx = indexOfLineStart + tmpIndex; else - idx = string->length() - 1; + idx = para->length() - 1; } else { --line; int oldIndexOfLineStart = indexOfLineStart; - if ( !string->lineStartOfLine( line, &indexOfLineStart ) ) + if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) return; if ( indexOfLineStart + tmpIndex < oldIndexOfLineStart ) @@ -947,12 +855,12 @@ void QTextCursor::gotoDown() int indexOfLineStart; int line; - QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); + QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); if ( !c ) return; tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); - if ( line == string->lines() - 1 ) { - if ( !string->next() ) { - if ( !nested ) + if ( line == para->lines() - 1 ) { + if ( !para->next() ) { + if ( !nestedDepth() ) return; pop(); @@ -960,5 +868,5 @@ void QTextCursor::gotoDown() if ( idx == -1 ) { pop(); - if ( !string->next() ) + if ( !para->next() ) return; idx = tmpIndex = 0; @@ -968,16 +876,16 @@ void QTextCursor::gotoDown() } } - QTextParag *s = string->next(); + QTextParagraph *s = para->next(); while ( s && !s->isVisible() ) s = s->next(); if ( s ) - string = s; - if ( !string->lineStartOfLine( 0, &indexOfLineStart ) ) + para = s; + if ( !para->lineStartOfLine( 0, &indexOfLineStart ) ) return; int end; - if ( string->lines() == 1 ) - end = string->length(); + if ( para->lines() == 1 ) + end = para->length(); else - string->lineStartOfLine( 1, &end ); + para->lineStartOfLine( 1, &end ); if ( indexOfLineStart + tmpIndex < end ) idx = indexOfLineStart + tmpIndex; @@ -987,9 +895,9 @@ void QTextCursor::gotoDown() ++line; int end; - if ( line == string->lines() - 1 ) - end = string->length(); + if ( line == para->lines() - 1 ) + end = para->length(); else - string->lineStartOfLine( line + 1, &end ); - if ( !string->lineStartOfLine( line, &indexOfLineStart ) ) + para->lineStartOfLine( line + 1, &end ); + if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) return; if ( indexOfLineStart + tmpIndex < end ) @@ -1005,12 +913,12 @@ void QTextCursor::gotoLineEnd() int indexOfLineStart; int line; - QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); + QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); if ( !c ) return; - if ( line == string->lines() - 1 ) { - idx = string->length() - 1; + if ( line == para->lines() - 1 ) { + idx = para->length() - 1; } else { - c = string->lineStartOfLine( ++line, &indexOfLineStart ); + c = para->lineStartOfLine( ++line, &indexOfLineStart ); indexOfLineStart--; idx = indexOfLineStart; @@ -1023,5 +931,5 @@ void QTextCursor::gotoLineStart() int indexOfLineStart; int line; - QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); + QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); if ( !c ) return; @@ -1032,69 +940,42 @@ void QTextCursor::gotoLineStart() void QTextCursor::gotoHome() { - tmpIndex = -1; - if ( doc ) - string = doc->firstParag(); - idx = 0; + if ( topParagraph()->document() ) + gotoPosition( topParagraph()->document()->firstParagraph() ); + else + gotoLineStart(); } void QTextCursor::gotoEnd() { - if ( doc && !doc->lastParag()->isValid() ) - return; - - tmpIndex = -1; - if ( doc ) - string = doc->lastParag(); - idx = string->length() - 1; + if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() ) + gotoPosition( topParagraph()->document()->lastParagraph(), + topParagraph()->document()->lastParagraph()->length() - 1); + else + gotoLineEnd(); } void QTextCursor::gotoPageUp( int visibleHeight ) { - tmpIndex = -1; - QTextParag *s = string; - int h = visibleHeight; - int y = s->rect().y(); - while ( s ) { - if ( y - s->rect().y() >= h ) - break; - s = s->prev(); - } - - if ( !s && doc ) - s = doc->firstParag(); - - string = s; - idx = 0; + int targetY = globalY() - visibleHeight; + QTextParagraph* old; int index; + do { + old = para; index = idx; + gotoUp(); + } while ( (old != para || index != idx) && globalY() > targetY ); } void QTextCursor::gotoPageDown( int visibleHeight ) { - tmpIndex = -1; - QTextParag *s = string; - int h = visibleHeight; - int y = s->rect().y(); - while ( s ) { - if ( s->rect().y() - y >= h ) - break; - s = s->next(); - } - - if ( !s && doc ) { - s = doc->lastParag(); - string = s; - idx = string->length() - 1; - return; - } - - if ( !s->isValid() ) - return; - - string = s; - idx = 0; + int targetY = globalY() + visibleHeight; + QTextParagraph* old; int index; + do { + old = para; index = idx; + gotoDown(); + } while ( (old != para || index != idx) && globalY() < targetY ); } void QTextCursor::gotoWordRight() { - if ( string->string()->isRightToLeft() ) + if ( para->string()->isRightToLeft() ) gotoPreviousWord(); else @@ -1104,5 +985,5 @@ void QTextCursor::gotoWordRight() void QTextCursor::gotoWordLeft() { - if ( string->string()->isRightToLeft() ) + if ( para->string()->isRightToLeft() ) gotoNextWord(); else @@ -1114,5 +995,5 @@ void QTextCursor::gotoPreviousWord() gotoPreviousLetter(); tmpIndex = -1; - QTextString *s = string->string(); + QTextString *s = para->string(); bool allowSame = FALSE; if ( idx == ((int)s->length()-1) ) @@ -1136,5 +1017,5 @@ void QTextCursor::gotoNextWord() { tmpIndex = -1; - QTextString *s = string->string(); + QTextString *s = para->string(); bool allowSame = FALSE; for ( int i = idx; i < (int)s->length(); ++i ) { @@ -1154,10 +1035,10 @@ void QTextCursor::gotoNextWord() if ( idx < ((int)s->length()-1) ) { gotoLineEnd(); - } else if ( string->next() ) { - QTextParag *s = string->next(); - while ( s && !s->isVisible() ) - s = s->next(); + } else if ( para->next() ) { + QTextParagraph *p = para->next(); + while ( p && !p->isVisible() ) + p = p->next(); if ( s ) { - string = s; + para = p; idx = 0; } @@ -1174,73 +1055,77 @@ bool QTextCursor::atParagStart() bool QTextCursor::atParagEnd() { - return idx == string->length() - 1; + return idx == para->length() - 1; } -void QTextCursor::splitAndInsertEmptyParag( bool ind, bool updateIds ) +void QTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds ) { - if ( !doc ) + if ( !para->document() ) return; tmpIndex = -1; QTextFormat *f = 0; - if ( doc->useFormatCollection() ) { - f = string->at( idx )->format(); - if ( idx == string->length() - 1 && idx > 0 ) - f = string->at( idx - 1 )->format(); + if ( para->document()->useFormatCollection() ) { + f = para->at( idx )->format(); + if ( idx == para->length() - 1 && idx > 0 ) + f = para->at( idx - 1 )->format(); if ( f->isMisspelled() ) { f->removeRef(); - f = doc->formatCollection()->format( f->font(), f->color() ); + f = para->document()->formatCollection()->format( f->font(), f->color() ); } } if ( atParagEnd() ) { - QTextParag *n = string->next(); - QTextParag *s = doc->createParag( doc, string, n, updateIds ); + QTextParagraph *n = para->next(); + QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); if ( f ) s->setFormat( 0, 1, f, TRUE ); - s->copyParagData( string ); + s->copyParagData( para ); if ( ind ) { int oi, ni; s->indent( &oi, &ni ); - string = s; + para = s; idx = ni; } else { - string = s; + para = s; idx = 0; } } else if ( atParagStart() ) { - QTextParag *p = string->prev(); - QTextParag *s = doc->createParag( doc, p, string, updateIds ); + QTextParagraph *p = para->prev(); + QTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds ); if ( f ) s->setFormat( 0, 1, f, TRUE ); - s->copyParagData( string ); + s->copyParagData( para ); if ( ind ) { s->indent(); s->format(); indent(); - string->format(); + para->format(); } } else { - QString str = string->string()->toString().mid( idx, 0xFFFFFF ); - QTextParag *n = string->next(); - QTextParag *s = doc->createParag( doc, string, n, updateIds ); - s->copyParagData( string ); + QString str = para->string()->toString().mid( idx, 0xFFFFFF ); + QTextParagraph *n = para->next(); + QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); + s->copyParagData( para ); s->remove( 0, 1 ); s->append( str, TRUE ); for ( uint i = 0; i < str.length(); ++i ) { - s->setFormat( i, 1, string->at( idx + i )->format(), TRUE ); - if ( string->at( idx + i )->isCustom() ) { - QTextCustomItem * item = string->at( idx + i )->customItem(); + QTextStringChar* tsc = para->at( idx + i ); + s->setFormat( i, 1, tsc->format(), TRUE ); + if ( tsc->isCustom() ) { + QTextCustomItem * item = tsc->customItem(); s->at( i )->setCustomItem( item ); - string->at( idx + i )->loseCustomItem(); + tsc->loseCustomItem(); } + if ( tsc->isAnchor() ) + s->at( i )->setAnchor( tsc->anchorName(), + tsc->anchorHref() ); } - string->truncate( idx ); + para->truncate( idx ); if ( ind ) { int oi, ni; s->indent( &oi, &ni ); - string = s; + para = s; idx = ni; } else { - string = s; + para = s; idx = 0; } @@ -1254,33 +1139,14 @@ bool QTextCursor::remove() tmpIndex = -1; if ( !atParagEnd() ) { - string->remove( idx, 1 ); - int h = string->rect().height(); - string->format( -1, TRUE ); - if ( h != string->rect().height() ) + para->remove( idx, 1 ); + int h = para->rect().height(); + para->format( -1, TRUE ); + if ( h != para->rect().height() ) invalidateNested(); - else if ( doc && doc->parent() ) - doc->nextDoubleBuffered = TRUE; + else if ( para->document() && para->document()->parent() ) + para->document()->nextDoubleBuffered = TRUE; return FALSE; - } else if ( string->next() ) { - if ( string->length() == 1 ) { - string->next()->setPrev( string->prev() ); - if ( string->prev() ) - string->prev()->setNext( string->next() ); - QTextParag *p = string->next(); - delete string; - string = p; - string->invalidate( 0 ); - QTextParag *s = string; - while ( s ) { - s->id = s->p ? s->p->id + 1 : 0; - s->state = -1; - s->needPreProcess = TRUE; - s->changed = TRUE; - s = s->n; - } - string->format(); - } else { - string->join( string->next() ); - } + } else if ( para->next() ) { + para->join( para->next() ); invalidateNested(); return TRUE; @@ -1289,21 +1155,8 @@ bool QTextCursor::remove() } -void QTextCursor::killLine() -{ - if ( atParagEnd() ) - return; - string->remove( idx, string->length() - idx - 1 ); - int h = string->rect().height(); - string->format( -1, TRUE ); - if ( h != string->rect().height() ) - invalidateNested(); - else if ( doc && doc->parent() ) - doc->nextDoubleBuffered = TRUE; -} - void QTextCursor::indent() { int oi = 0, ni = 0; - string->indent( &oi, &ni ); + para->indent( &oi, &ni ); if ( oi == ni ) return; @@ -1315,18 +1168,8 @@ void QTextCursor::indent() } -void QTextCursor::setDocument( QTextDocument *d ) -{ - doc = d; - string = d->firstParag(); - idx = 0; - nested = FALSE; - restoreState(); - tmpIndex = -1; -} - // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ QTextDocument::QTextDocument( QTextDocument *p ) - : par( p ), parParag( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) + : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) { fCollection = new QTextFormatCollection; @@ -1335,5 +1178,5 @@ QTextDocument::QTextDocument( QTextDocument *p ) QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f ) - : par( p ), parParag( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) + : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) { fCollection = f; @@ -1343,7 +1186,4 @@ QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f ) void QTextDocument::init() { -#if defined(PARSER_DEBUG) - qDebug( debug_indent + "new QTextDocument (%p)", this ); -#endif oTextValid = TRUE; mightHaveCustomItems = FALSE; @@ -1364,10 +1204,8 @@ void QTextDocument::init() align = AlignAuto; nSelections = 1; - addMargs = FALSE; - sheet_ = QStyleSheet::defaultSheet(); + setStyleSheet( QStyleSheet::defaultSheet() ); factory_ = QMimeSourceFactory::defaultFactory(); contxt = QString::null; - fCollection->setStyleSheet( sheet_ ); underlLinks = par ? par->underlLinks : TRUE; @@ -1381,6 +1219,5 @@ void QTextDocument::init() withoutDoubleBuffer = FALSE; - lParag = fParag = createParag( this, 0, 0 ); - tmpCursor = 0; + lParag = fParag = createParagraph( this, 0, 0 ); cx = 0; @@ -1394,4 +1231,6 @@ void QTextDocument::init() leftmargin = rightmargin = 4; + scaleFontsFactor = 1; + selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight ); @@ -1424,5 +1263,5 @@ void QTextDocument::clear( bool createEmptyParag ) flow_->clear(); while ( fParag ) { - QTextParag *p = fParag->next(); + QTextParagraph *p = fParag->next(); delete fParag; fParag = p; @@ -1430,6 +1269,8 @@ void QTextDocument::clear( bool createEmptyParag ) fParag = lParag = 0; if ( createEmptyParag ) - fParag = lParag = createParag( this ); + fParag = lParag = createParagraph( this ); selections.clear(); + oText = QString::null; + oTextValid = TRUE; } @@ -1450,10 +1291,10 @@ int QTextDocument::height() const -QTextParag *QTextDocument::createParag( QTextDocument *d, QTextParag *pr, QTextParag *nx, bool updateIds ) +QTextParagraph *QTextDocument::createParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds ) { - return new QTextParag( d, pr, nx, updateIds ); + return new QTextParagraph( d, pr, nx, updateIds ); } -bool QTextDocument::setMinimumWidth( int needed, int used, QTextParag *p ) +bool QTextDocument::setMinimumWidth( int needed, int used, QTextParagraph *p ) { if ( needed == -1 ) { @@ -1486,5 +1327,5 @@ void QTextDocument::setPlainText( const QString &text ) int nl = text.find( '\n' ); if ( nl == -1 ) { - lParag = createParag( this, lParag, 0 ); + lParag = createParagraph( this, lParag, 0 ); if ( !fParag ) fParag = lParag; @@ -1497,5 +1338,5 @@ void QTextDocument::setPlainText( const QString &text ) } else { for (;;) { - lParag = createParag( this, lParag, 0 ); + lParag = createParagraph( this, lParag, 0 ); if ( !fParag ) fParag = lParag; @@ -1515,5 +1356,5 @@ void QTextDocument::setPlainText( const QString &text ) } if ( !lParag ) - lParag = fParag = createParag( this, 0, 0 ); + lParag = fParag = createParagraph( this, 0, 0 ); } @@ -1560,62 +1401,39 @@ struct Q_EXPORT QTextDocumentTag { }; -#define NEWPAR do{ if ( !hasNewPar ) curpar = createParag( this, curpar ); \ - if ( curpar->isBr ) curpar->isBr = FALSE; \ + +#define NEWPAR do{ if ( !hasNewPar) { \ + if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \ + curpar->remove( curpar->length()-2, 1 ); \ + curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); vec = 0;} \ hasNewPar = TRUE; \ - curpar->setAlignment( curtag.alignment ); \ - curpar->setDirection( (QChar::Direction)curtag.direction ); \ + curpar->rtext = TRUE; \ + curpar->align = curtag.alignment; \ + curpar->lstyle = curtag.liststyle; \ + curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \ + curpar->str->setDirection( (QChar::Direction)curtag.direction ); \ space = TRUE; \ - QPtrVector<QStyleSheetItem> vec( (uint)tags.count() + 1); \ + delete vec; vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \ int i = 0; \ for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \ - vec.insert( i++, (*it).style ); \ - vec.insert( i, curtag.style ); \ - curpar->setStyleSheetItems( vec ); }while(FALSE) + vec->insert( i++, (*it).style ); \ + vec->insert( i, curtag.style ); \ + }while(FALSE) void QTextDocument::setRichText( const QString &text, const QString &context ) { - setTextFormat( Qt::RichText ); if ( !context.isEmpty() ) setContext( context ); clear(); - fParag = lParag = createParag( this ); + fParag = lParag = createParagraph( this ); + oTextValid = TRUE; + oText = text; setRichTextInternal( text ); + fParag->rtext = TRUE; } -static QStyleSheetItem::ListStyle chooseListStyle( const QStyleSheetItem *nstyle, - const QMap<QString, QString> &attr, - QStyleSheetItem::ListStyle curListStyle ) -{ - if ( nstyle->name() == "ol" || nstyle->name() == "ul" ) { - curListStyle = nstyle->listStyle(); - QMap<QString, QString>::ConstIterator it = attr.find( "type" ); - if ( it != attr.end() ) { - QString sl = *it; - if ( sl == "1" ) { - curListStyle = QStyleSheetItem::ListDecimal; - } else if ( sl == "a" ) { - curListStyle = QStyleSheetItem::ListLowerAlpha; - } else if ( sl == "A" ) { - curListStyle = QStyleSheetItem::ListUpperAlpha; - } else { - sl = sl.lower(); - if ( sl == "square" ) - curListStyle = QStyleSheetItem::ListSquare; - else if ( sl == "disc" ) - curListStyle = QStyleSheetItem::ListDisc; - else if ( sl == "circle" ) - curListStyle = QStyleSheetItem::ListCircle; - } - } - } - return curListStyle; -} - -void QTextDocument::setRichTextInternal( const QString &text ) +void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* cursor ) { - oTextValid = TRUE; - oText = text; - QTextParag* curpar = lParag; + QTextParagraph* curpar = lParag; int pos = 0; QValueStack<QTextDocumentTag> tags; @@ -1623,10 +1441,35 @@ void QTextDocument::setRichTextInternal( const QString &text ) QTextDocumentTag curtag = initag; bool space = TRUE; + bool canMergeLi = FALSE; + + bool textEditMode = FALSE; const QChar* doc = text.unicode(); int length = text.length(); bool hasNewPar = curpar->length() <= 1; - QString lastClose; QString anchorName; + + // style sheet handling for margin and line spacing calculation below + QTextParagraph* stylesPar = curpar; + QPtrVector<QStyleSheetItem>* vec = 0; + QPtrList< QPtrVector<QStyleSheetItem> > styles; + styles.setAutoDelete( TRUE ); + + if ( cursor ) { + cursor->splitAndInsertEmptyParagraph(); + QTextCursor tmp = *cursor; + tmp.gotoPreviousLetter(); + stylesPar = curpar = tmp.paragraph(); + hasNewPar = TRUE; + textEditMode = TRUE; + } else { + NEWPAR; + } + + // set rtext spacing to FALSE for the initial paragraph. + curpar->rtext = FALSE; + + QString wellKnownTags = "br hr wsp table qt body meta title"; + while ( pos < length ) { if ( hasPrefix(doc, length, pos, '<' ) ){ @@ -1639,31 +1482,6 @@ void QTextDocument::setRichTextInternal( const QString &text ) continue; // nothing we could do with this, probably parse error - if ( tagname == "title" ) { - QString title; - while ( pos < length ) { - if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) && - parseCloseTag( doc, length, pos ) == "title" ) - break; - title += doc[ pos ]; - ++pos; - } - attribs.replace( "title", title ); - } - const QStyleSheetItem* nstyle = sheet_->item(tagname); - if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { -// if ( tagname == "br" ) { -// // our standard br emty-tag handling breaks -// // inside list items, we would get another -// // list item in this case. As workaround, fake -// // a new paragraph instead -// tagname = "p"; -// nstyle = sheet_->item( tagname ); -// } - if ( nstyle ) - hasNewPar = FALSE; // we want empty paragraphs in this case - } - if ( nstyle ) { // we might have to close some 'forgotten' tags @@ -1678,6 +1496,11 @@ void QTextDocument::setRichTextInternal( const QString &text ) } - // special handling for p. We do not want to nest there for HTML compatibility - if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { + /* special handling for p and li for HTML + compatibility. We do not want to embed blocks in + p, and we do not want new blocks inside non-empty + lis. Plus we want to merge empty lis sometimes. */ + if( nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) { + canMergeLi = TRUE; + } else if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { while ( curtag.style->name() == "p" ) { if ( tags.isEmpty() ) @@ -1685,48 +1508,60 @@ void QTextDocument::setRichTextInternal( const QString &text ) curtag = tags.pop(); } - } + if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { + // we are in a li and a new block comes along + if ( nstyle->name() == "ul" || nstyle->name() == "ol" ) + hasNewPar = FALSE; // we want an empty li (like most browsers) + if ( !hasNewPar ) { + /* do not add new blocks inside + non-empty lis */ + while ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { + if ( tags.isEmpty() ) + break; + curtag = tags.pop(); + } + } else if ( canMergeLi ) { + /* we have an empty li and a block + comes along, merge them */ + nstyle = curtag.style; + } + canMergeLi = FALSE; + } + } } QTextCustomItem* custom = 0; - // some well-known empty tags + + // some well-known tags, some have a nstyle, some not + if ( wellKnownTags.find( tagname ) != -1 ) { if ( tagname == "br" ) { - emptyTag = TRUE; - hasNewPar = FALSE; - if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { - // when linebreaking a list item, we do not - // actually want a new list item but just a - // new line. Fake this by pushing a paragraph - // onto the stack - tags.push( curtag ); - curtag.name = tagname; - curtag.style = nstyle; - } - NEWPAR; - curpar->isBr = TRUE; - curpar->setAlignment( curtag.alignment ); + emptyTag = space = TRUE; + int index = QMAX( curpar->length(),1) - 1; + QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); + curpar->append( QChar_linesep ); + curpar->setFormat( index, 1, &format ); } else if ( tagname == "hr" ) { - emptyTag = TRUE; + emptyTag = space = TRUE; custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); NEWPAR; } else if ( tagname == "table" ) { - QTextFormat format = curtag.format.makeTextFormat( nstyle, attr ); + emptyTag = space = TRUE; + QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); curpar->setAlignment( curtag.alignment ); custom = parseTable( attr, format, doc, length, pos, curpar ); - (void)eatSpace( doc, length, pos ); - emptyTag = TRUE; - } else if ( tagname == "qt" ) { - for ( QMap<QString, QString>::Iterator it = attr.begin(); it != attr.end(); ++it ) { - if ( it.key() == "bgcolor" ) { - QBrush *b = new QBrush( QColor( *it ) ); + } else if ( tagname == "qt" || tagname == "body" ) { + if ( attr.contains( "bgcolor" ) ) { + QBrush *b = new QBrush( QColor( attr["bgcolor"] ) ); setPaper( b ); - } else if ( it.key() == "background" ) { + } + if ( attr.contains( "background" ) ) { QImage img; - const QMimeSource* m = factory_->data( *it, contxt ); + QString bg = attr["background"]; + const QMimeSource* m = factory_->data( bg, contxt ); if ( !m ) { - qWarning("QRichText: no mimesource for %s", (*it).latin1() ); + qWarning("QRichText: no mimesource for %s", bg.latin1() ); } else { if ( !QImageDrag::decode( m, img ) ) { - qWarning("QTextImage: cannot decode %s", (*it).latin1() ); + qWarning("QTextImage: cannot decode %s", bg.latin1() ); } } @@ -1737,6 +1572,7 @@ void QTextDocument::setRichTextInternal( const QString &text ) setPaper( b ); } - } else if ( it.key() == "text" ) { - QColor c( *it ); + } + if ( attr.contains( "text" ) ) { + QColor c( attr["text"] ); if ( formatCollection()->defaultFormat()->color() != c ) { QDict<QTextFormat> formats = formatCollection()->dict(); @@ -1753,13 +1589,42 @@ void QTextDocument::setRichTextInternal( const QString &text ) curtag.format.setColor( c ); } - } else if ( it.key() == "link" ) { - linkColor = QColor( *it ); - } else if ( it.key() == "title" ) { - attribs.replace( it.key(), *it ); } + if ( attr.contains( "link" ) ) + linkColor = QColor( attr["link"] ); + if ( attr.contains( "title" ) ) + attribs.replace( "title", attr["title"] ); + + if ( textEditMode ) { + if ( attr.contains("style" ) ) { + QString a = attr["style"]; + for ( int s = 0; s < a.contains(';')+1; s++ ) { + QString style = QTextDocument::section( a, ";", s, s ); + if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) { + scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) / + style.mid( 10, style.length() - 12 ).toInt(); } - } else { - custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); } + } + nstyle = 0; // ignore body in textEditMode + } + // end qt- and body-tag handling + } else if ( tagname == "meta" ) { + if ( attr["name"] == "qrichtext" && attr["content"] == "1" ) + textEditMode = TRUE; + } else if ( tagname == "title" ) { + QString title; + while ( pos < length ) { + if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) && + parseCloseTag( doc, length, pos ) == "title" ) + break; + title += doc[ pos ]; + ++pos; + } + attribs.replace( "title", title ); + } + } // end of well-known tag handling + + if ( !custom ) // try generic custom item + custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it @@ -1767,8 +1632,6 @@ void QTextDocument::setRichTextInternal( const QString &text ) if ( custom ) { - int index = curpar->length() - 1; - if ( index < 0 ) - index = 0; - QTextFormat format = curtag.format.makeTextFormat( nstyle, attr ); + int index = QMAX( curpar->length(),1) - 1; + QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); curpar->append( QChar('*') ); curpar->setFormat( index, 1, &format ); @@ -1783,12 +1646,7 @@ void QTextDocument::setRichTextInternal( const QString &text ) hasNewPar = FALSE; } else if ( !emptyTag ) { - // ignore whitespace for inline elements if there was already one - if ( nstyle->whiteSpaceMode() == QStyleSheetItem::WhiteSpaceNormal - && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) ) - eatSpace( doc, length, pos ); - - // if we do nesting, push curtag on the stack, - // otherwise reinint curag. - if ( nstyle != curtag.style || nstyle->selfNesting() ) { + /* if we do nesting, push curtag on the stack, + otherwise reinint curag. */ + if ( curtag.style->name() != tagname || nstyle->selfNesting() ) { tags.push( curtag ); } else { @@ -1799,14 +1657,18 @@ void QTextDocument::setRichTextInternal( const QString &text ) } - const QStyleSheetItem* ostyle = curtag.style; - curtag.name = tagname; curtag.style = nstyle; curtag.name = tagname; curtag.style = nstyle; - if ( nstyle->whiteSpaceMode() != QStyleSheetItem::WhiteSpaceNormal ) + if ( int(nstyle->whiteSpaceMode()) != QStyleSheetItem::Undefined ) curtag.wsm = nstyle->whiteSpaceMode(); - curtag.liststyle = chooseListStyle( nstyle, attr, curtag.liststyle ); - curtag.format = curtag.format.makeTextFormat( nstyle, attr ); + + /* ignore whitespace for inline elements if there + was already one*/ + if ( !textEditMode && curtag.wsm == QStyleSheetItem::WhiteSpaceNormal + && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) ) + eatSpace( doc, length, pos ); + + curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); if ( nstyle->isAnchor() ) { if ( !anchorName.isEmpty() ) @@ -1820,26 +1682,44 @@ void QTextDocument::setRichTextInternal( const QString &text ) curtag.alignment = nstyle->alignment(); - if ( ostyle->displayMode() == QStyleSheetItem::DisplayListItem && - curpar->length() <= 1 - && nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { - // do not do anything, we reuse the paragraph we have - } else if ( nstyle->displayMode() != QStyleSheetItem::DisplayInline && nstyle->displayMode() != QStyleSheetItem::DisplayNone ) { - NEWPAR; + if ( (int) nstyle->listStyle() != QStyleSheetItem::Undefined ) + curtag.liststyle = nstyle->listStyle(); + + if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock + || nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) { + + if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") { + QString type = attr["type"]; + if ( !type.isEmpty() ) { + if ( type == "1" ) { + curtag.liststyle = QStyleSheetItem::ListDecimal; + } else if ( type == "a" ) { + curtag.liststyle = QStyleSheetItem::ListLowerAlpha; + } else if ( type == "A" ) { + curtag.liststyle = QStyleSheetItem::ListUpperAlpha; + } else { + type = type.lower(); + if ( type == "square" ) + curtag.liststyle = QStyleSheetItem::ListSquare; + else if ( type == "disc" ) + curtag.liststyle = QStyleSheetItem::ListDisc; + else if ( type == "circle" ) + curtag.liststyle = QStyleSheetItem::ListCircle; + } } - - if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { - curpar->setListStyle( curtag.liststyle ); - if ( attr.find( "value" ) != attr.end() ) - curpar->setListValue( (*attr.find( "value" )).toInt() ); } - if ( nstyle->displayMode() != QStyleSheetItem::DisplayInline ) - curpar->setFormat( &curtag.format ); - if ( attr.contains( "align" ) && - ( curtag.name == "p" || - curtag.name == "div" || - curtag.name == "li" || - curtag.name[ 0 ] == 'h' ) ) { + /* Internally we treat ordered and bullet + lists the same for margin calculations. In + order to have fast pointer compares in the + xMargin() functions we restrict ourselves to + <ol>. Once we calculate the margins in the + parser rathern than later, the unelegance of + this approach goes awy + */ + if ( nstyle->name() == "ul" ) + curtag.style = sheet_->item( "ol" ); + + if ( attr.contains( "align" ) ) { QString align = attr["align"]; if ( align == "center" ) @@ -1850,9 +1730,5 @@ void QTextDocument::setRichTextInternal( const QString &text ) curtag.alignment = Qt3::AlignJustify; } - if ( attr.contains( "dir" ) && - ( curtag.name == "p" || - curtag.name == "div" || - curtag.name == "li" || - curtag.name[ 0 ] == 'h' ) ) { + if ( attr.contains( "dir" ) ) { QString dir = attr["dir"]; if ( dir == "rtl" ) @@ -1861,12 +1737,35 @@ void QTextDocument::setRichTextInternal( const QString &text ) curtag.direction = QChar::DirL; } - if ( nstyle->displayMode() != QStyleSheetItem::DisplayInline ) { - curpar->setAlignment( curtag.alignment ); - curpar->setDirection( (QChar::Direction)curtag.direction ); + + NEWPAR; + + if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { + if ( attr.contains( "value " ) ) + curpar->setListValue( attr["value"].toInt() ); + } + + if ( attr.contains( "style" ) ) { + QString a = attr["style"]; + bool ok = TRUE; + for ( int s = 0; ok && s < a.contains(';')+1; s++ ) { + QString style = QTextDocument::section( a, ";", s, s ); + if ( style.startsWith("margin-top:" ) && QTextDocument::endsWith(style, "px") ) + curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); + else if ( style.startsWith("margin-bottom:" ) && QTextDocument::endsWith(style, "px") ) + curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); + else if ( style.startsWith("margin-left:" ) && QTextDocument::endsWith(style, "px") ) + curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); + else if ( style.startsWith("margin-right:" ) && QTextDocument::endsWith(style, "px") ) + curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); + else if ( style.startsWith("text-indent:" ) && QTextDocument::endsWith(style, "px") ) + curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok); + } + if ( !ok ) // be pressmistic + curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0; + } } } } else { QString tagname = parseCloseTag( doc, length, pos ); - lastClose = tagname; if ( tagname.isEmpty() ) continue; // nothing we could do with this, probably parse error @@ -1874,12 +1773,8 @@ void QTextDocument::setRichTextInternal( const QString &text ) continue; - // we close a block item. Since the text may continue, we need to have a new paragraph - bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock; + bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock + || curtag.style->displayMode() == QStyleSheetItem::DisplayListItem; - if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { - needNewPar = TRUE; - hasNewPar = FALSE; // we want empty paragraphs in this case - } // html slopiness: handle unbalanched tag closing @@ -1902,9 +1797,6 @@ void QTextDocument::setRichTextInternal( const QString &text ) if ( needNewPar ) { - if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { - tags.push( curtag ); - curtag.name = "p"; - curtag.style = sheet_->item( curtag.name ); // a list item continues, use p for that - } + if ( textEditMode && tagname == "p" ) // preserve empty paragraphs + hasNewPar = FALSE; NEWPAR; } @@ -1915,15 +1807,40 @@ void QTextDocument::setRichTextInternal( const QString &text ) QChar c; while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){ - QStyleSheetItem::WhiteSpaceMode wsm = curtag.wsm; - if ( s.length() > 4096 ) - wsm = (QStyleSheetItem::WhiteSpaceMode)QStyleSheetItem_WhiteSpaceNormalWithNewlines; - - c = parseChar( doc, length, pos, wsm ); + if ( textEditMode ) { + // text edit mode: we handle all white space but ignore newlines + c = parseChar( doc, length, pos, QStyleSheetItem::WhiteSpacePre ); + if ( c == QChar_linesep ) + break; + } else { + int l = pos; + c = parseChar( doc, length, pos, curtag.wsm ); + + // in white space pre mode: treat any space as non breakable + if ( c == ' ' && curtag.wsm == QStyleSheetItem::WhiteSpacePre ) + c = QChar::nbsp; + + if ( c == ' ' || c == QChar_linesep ) { + /* avoid overlong paragraphs by forcing a new + paragraph after 4096 characters. This case can + occur when loading undiscovered plain text + documents in rich text mode. Instead of hanging + forever, we do the trick. + */ + if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do { + if ( doc[l] == '\n' ) { + hasNewPar = FALSE; // for a new paragraph ... + NEWPAR; + hasNewPar = FALSE; // ... and make it non-reusable + c = '\n'; // make sure we break below + break; + } + } while ( ++l < pos ); + } + } - if ( c == '\n' ) // happens only in whitespacepre-mode or with WhiteSpaceNormalWithNewlines. - break; // we want a new line in this case + if ( c == '\n' ) + break; // break on newlines, pre delievers a QChar_linesep - bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && - curtag.wsm != QStyleSheetItem_WhiteSpaceNoCompression; + bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode; if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space ) @@ -1936,7 +1853,5 @@ void QTextDocument::setRichTextInternal( const QString &text ) if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) { hasNewPar = FALSE; - int index = curpar->length() - 1; - if ( index < 0 ) - index = 0; + int index = QMAX( curpar->length(),1) - 1; curpar->append( s ); QTextFormat* f = formatCollection()->format( &curtag.format ); @@ -1952,23 +1867,177 @@ void QTextDocument::setRichTextInternal( const QString &text ) } } - if ( c == '\n' ) { // happens in WhiteSpacePre mode - hasNewPar = FALSE; - tags.push( curtag ); - NEWPAR; - curtag = tags.pop(); - } } } - - if ( hasNewPar && curpar != fParag ) { + if ( hasNewPar && curpar != fParag && !cursor ) { // cleanup unused last paragraphs curpar = curpar->p; delete curpar->n; } - if ( !anchorName.isEmpty() ) { curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() ); anchorName = QString::null; } + + + setRichTextMarginsInternal( styles, stylesPar ); + + if ( cursor ) { + cursor->gotoPreviousLetter(); + cursor->remove(); + } + +} + +void QTextDocument::setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar ) +{ + // margin and line spacing calculation + QPtrVector<QStyleSheetItem>* prevStyle = 0; + QPtrVector<QStyleSheetItem>* curStyle = styles.first(); + QPtrVector<QStyleSheetItem>* nextStyle = styles.next(); + while ( stylesPar ) { + if ( !curStyle ) { + stylesPar = stylesPar->next(); + prevStyle = curStyle; + curStyle = nextStyle; + nextStyle = styles.next(); + continue; + } + + int i, mar; + QStyleSheetItem* mainStyle = curStyle->size() ? (*curStyle)[curStyle->size()-1] : 0; + if ( mainStyle && mainStyle->displayMode() == QStyleSheetItem::DisplayListItem ) + stylesPar->setListItem( TRUE ); + int numLists = 0; + for ( i = 0; i < (int)curStyle->size(); ++i ) { + if ( (*curStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock + && int((*curStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) + numLists++; + } + stylesPar->ldepth = numLists; + if ( stylesPar->next() && nextStyle ) { + // also set the depth of the next paragraph, required for the margin calculation + numLists = 0; + for ( i = 0; i < (int)nextStyle->size(); ++i ) { + if ( (*nextStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock + && int((*nextStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) + numLists++; + } + stylesPar->next()->ldepth = numLists; + } + + // do the top margin + QStyleSheetItem* item = mainStyle; + int m; + if (stylesPar->utm > 0 ) { + m = stylesPar->utm-1; + stylesPar->utm = 0; + } else { + m = QMAX(0, item->margin( QStyleSheetItem::MarginTop ) ); + if ( item->displayMode() == QStyleSheetItem::DisplayListItem + && stylesPar->ldepth ) + m /= stylesPar->ldepth; + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + if ( prevStyle && i < (int) prevStyle->size() && + ( item->displayMode() == QStyleSheetItem::DisplayBlock && + (*prevStyle)[ i ] == item ) ) + break; + // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags + if ( int(item->listStyle()) != QStyleSheetItem::Undefined && + ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) + continue; + mar = QMAX( 0, item->margin( QStyleSheetItem::MarginTop ) ); + m = QMAX( m, mar ); + } + stylesPar->utm = m - stylesPar->topMargin(); + + // do the bottom margin + item = mainStyle; + if (stylesPar->ubm > 0 ) { + m = stylesPar->ubm-1; + stylesPar->ubm = 0; + } else { + m = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); + if ( item->displayMode() == QStyleSheetItem::DisplayListItem + && stylesPar->ldepth ) + m /= stylesPar->ldepth; + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + if ( nextStyle && i < (int) nextStyle->size() && + ( item->displayMode() == QStyleSheetItem::DisplayBlock && + (*nextStyle)[ i ] == item ) ) + break; + // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags + if ( int(item->listStyle()) != QStyleSheetItem::Undefined && + ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) + continue; + mar = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); + m = QMAX( m, mar ); + } + stylesPar->ubm = m - stylesPar->bottomMargin(); + + // do the left margin, simplyfied + item = mainStyle; + if (stylesPar->ulm > 0 ) { + m = stylesPar->ulm-1; + stylesPar->ulm = 0; + } else { + m = QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + m += QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); + } + stylesPar->ulm = m - stylesPar->leftMargin(); + + // do the right margin, simplyfied + item = mainStyle; + if (stylesPar->urm > 0 ) { + m = stylesPar->urm-1; + stylesPar->urm = 0; + } else { + m = QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + m += QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); + } + stylesPar->urm = m - stylesPar->rightMargin(); + + // do the first line margin, which really should be called text-indent + item = mainStyle; + if (stylesPar->uflm > 0 ) { + m = stylesPar->uflm-1; + stylesPar->uflm = 0; + } else { + m = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); + } + for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + mar = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); + m = QMAX( m, mar ); + } + stylesPar->uflm =m - stylesPar->firstLineMargin(); + + // do the bogus line "spacing", which really is just an extra margin + item = mainStyle; + for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) { + item = (*curStyle)[ i ]; + if ( item->lineSpacing() != QStyleSheetItem::Undefined ) { + stylesPar->ulinespacing = item->lineSpacing(); + if ( formatCollection() && + stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() ) + stylesPar->ulinespacing += formatCollection()->defaultFormat()->height(); + break; + } + } + + stylesPar = stylesPar->next(); + prevStyle = curStyle; + curStyle = nextStyle; + nextStyle = styles.next(); + } } @@ -1984,10 +2053,9 @@ void QTextDocument::setText( const QString &text, const QString &context ) } -QString QTextDocument::plainText( QTextParag *p ) const +QString QTextDocument::plainText() const { - if ( !p ) { QString buffer; QString s; - QTextParag *p = fParag; + QTextParagraph *p = fParag; while ( p ) { if ( !p->mightHaveCustomItems ) { @@ -2016,98 +2084,160 @@ QString QTextDocument::plainText( QTextParag *p ) const } return buffer; - } else { - return p->string()->toString(); - } } -static QString align_to_string( const QString &tag, int a ) +static QString align_to_string( int a ) { - if ( tag == "p" || tag == "li" || ( tag[0] == 'h' && tag[1].isDigit() ) ) { if ( a & Qt::AlignRight ) return " align=\"right\""; - if ( a & Qt::AlignCenter ) + if ( a & Qt::AlignHCenter ) return " align=\"center\""; if ( a & Qt3::AlignJustify ) return " align=\"justify\""; - } - return ""; + return QString::null; } -static QString direction_to_string( const QString &tag, int d ) +static QString direction_to_string( int d ) { - if ( d != QChar::DirON && - ( tag == "p" || tag == "div" || tag == "li" || ( tag[0] == 'h' && tag[1].isDigit() ) ) ) + if ( d != QChar::DirON ) return ( d == QChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" ); - return ""; + return QString::null; } -QString QTextDocument::richText( QTextParag *p ) const +static QString list_value_to_string( int v ) { - QString s,n; - if ( !p ) { - p = fParag; - QPtrVector<QStyleSheetItem> lastItems, items; - while ( p ) { - items = p->styleSheetItems(); - if ( items.size() ) { - QStyleSheetItem *item = items[ items.size() - 1 ]; - items.resize( items.size() - 1 ); - if ( items.size() > lastItems.size() ) { - for ( int i = lastItems.size(); i < (int)items.size(); ++i ) { - n = items[i]->name(); - if ( n.isEmpty() || n == "li" ) - continue; - s += "<" + n + align_to_string( n, p->alignment() ) + ">"; + if ( v != -1 ) + return " listvalue=\"" + QString::number( v ) + "\""; + return QString::null; } - } else { - QString end; - for ( int i = items.size(); i < (int)lastItems.size(); ++i ) { - n = lastItems[i]->name(); - if ( n.isEmpty() || n == "li" || n == "br" ) - continue; - end.prepend( "</" + lastItems[ i ]->name() + ">" ); + +static QString list_style_to_string( int v ) +{ + switch( v ) { + case QStyleSheetItem::ListDecimal: return "\"1\""; + case QStyleSheetItem::ListLowerAlpha: return "\"a\""; + case QStyleSheetItem::ListUpperAlpha: return "\"A\""; + case QStyleSheetItem::ListDisc: return "\"disc\""; + case QStyleSheetItem::ListSquare: return "\"square\""; + case QStyleSheetItem::ListCircle: return "\"circle\""; + default: + return QString::null; } - s += end; } - lastItems = items; - n = item->name(); - if ( n == "li" && p->listValue() != -1 ) { - s += "<li value=\"" + QString::number( p->listValue() ) + "\">"; - } else { - QString ps = p->richText(); - if ( ps.isEmpty() ) - s += "<br>"; // empty paragraph - else if ( !n.isEmpty() ) { - s += "<" + n + align_to_string( n, p->alignment() ) - + direction_to_string( n, p->direction() ) + ">" + ps; - if ( n != "li" && n != "br") - s += "</" + n + ">"; - } else - s += ps; + +static inline bool list_is_ordered( int v ) +{ + return v == QStyleSheetItem::ListDecimal || + v == QStyleSheetItem::ListLowerAlpha || + v == QStyleSheetItem::ListUpperAlpha; } - } else { - QString end; - for ( int i = 0; i < (int)lastItems.size(); ++i ) { - QString n = lastItems[i]->name(); - if ( n.isEmpty() || n == "li" || n == "br" ) - continue; - end.prepend( "</" + n + ">" ); + + +static QString margin_to_string( QStyleSheetItem* style, int t, int b, int l, int r, int fl ) +{ + QString s; + if ( l > 0 ) + s += QString(!!s?";":"") + "margin-left:" + QString::number(l+QMAX(0,style->margin(QStyleSheetItem::MarginLeft))) + "px"; + if ( r > 0 ) + s += QString(!!s?";":"") + "margin-right:" + QString::number(r+QMAX(0,style->margin(QStyleSheetItem::MarginRight))) + "px"; + if ( t > 0 ) + s += QString(!!s?";":"") + "margin-top:" + QString::number(t+QMAX(0,style->margin(QStyleSheetItem::MarginTop))) + "px"; + if ( b > 0 ) + s += QString(!!s?";":"") + "margin-bottom:" + QString::number(b+QMAX(0,style->margin(QStyleSheetItem::MarginBottom))) + "px"; + if ( fl > 0 ) + s += QString(!!s?";":"") + "text-indent:" + QString::number(fl+QMAX(0,style->margin(QStyleSheetItem::MarginFirstLine))) + "px"; + if ( !!s ) + return " style=\"" + s + "\""; + return QString::null; } - s += end; - QString ps = p->richText(); - if ( ps.isEmpty() ) - s += "<br>"; // empty paragraph - else - s += "<p" + align_to_string( "p", p->alignment() ) + direction_to_string( "p", p->direction() ) - + ">" + ps + "</p>"; - lastItems = items; + +QString QTextDocument::richText() const +{ + QString s = ""; + if ( !par ) { + s += "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\"font-size:" ; + s += QString::number( formatCollection()->defaultFormat()->font().pointSize() ); + s += "pt;font-family:"; + s += formatCollection()->defaultFormat()->font().family(); + s +="\">"; } - if ( ( p = p->next() ) ) + QTextParagraph* p = fParag; + + QStyleSheetItem* item_p = styleSheet()->item("p"); + QStyleSheetItem* item_ul = styleSheet()->item("ul"); + QStyleSheetItem* item_ol = styleSheet()->item("ol"); + QStyleSheetItem* item_li = styleSheet()->item("li"); + if ( !item_p || !item_ul || !item_ol || !item_li ) { + qWarning( "QTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, ul, ol, or li)" ); + return QString::null; + } + int pastListDepth = 0; + int listDepth = 0; + int futureListDepth = 0; + QMemArray<int> listStyles(10); + + while ( p ) { + listDepth = p->listDepth(); + if ( listDepth < pastListDepth ) { + for ( int i = listDepth+1; i <= pastListDepth; i++ ) + s += list_is_ordered( listStyles[i] ) ? "</ol>" : "</ul>"; + s += '\n'; + } else if ( listDepth > pastListDepth ) { s += '\n'; + listStyles.resize( QMAX( (int)listStyles.size(), listDepth+1 ) ); + QString list_type; + listStyles[listDepth] = p->listStyle(); + if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() ) + list_type = " type=" + list_style_to_string( p->listStyle() ); + for ( int i = pastListDepth; i < listDepth; i++ ) { + s += list_is_ordered( p->listStyle() ) ? "<ol" : "<ul" ; + s += list_type + ">"; } } else { - s = p->richText(); + s += '\n'; } + QString ps = p->richText(); + + // for the bottom margin we need to know whether we are at the end of a list + futureListDepth = 0; + if ( listDepth > 0 && p->next() ) + futureListDepth = p->next()->listDepth(); + + if ( richTextExportStart && richTextExportStart->paragraph() ==p && + richTextExportStart->index() == 0 ) + s += "<selstart/>"; + + if ( p->isListItem() ) { + s += "<li"; + if ( p->listStyle() != listStyles[listDepth] ) + s += " type=" + list_style_to_string( p->listStyle() ); + s +=align_to_string( p->alignment() ); + s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); + s += list_value_to_string( p->listValue() ); + s += direction_to_string( p->direction() ); + s +=">"; + s += ps; + s += "</li>"; + } else { + // normal paragraph item + s += "<p"; + s += align_to_string( p->alignment() ); + s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); + s +=direction_to_string( p->direction() ); + s += ">"; + s += ps; + s += "</p>"; + } + pastListDepth = listDepth; + p = p->next(); + } + while ( listDepth > 0 ) { + s += list_is_ordered( listStyles[listDepth] ) ? "</ol>" : "</ul>"; + listDepth--; + } + + if ( !par ) + s += "\n</body></html>\n"; + return s; } @@ -2115,26 +2245,24 @@ QString QTextDocument::richText( QTextParag *p ) const QString QTextDocument::text() const { - if ( plainText().simplifyWhiteSpace().isEmpty() ) - return QString(""); if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) return richText(); - return plainText( 0 ); + return plainText(); } QString QTextDocument::text( int parag ) const { - QTextParag *p = paragAt( parag ); + QTextParagraph *p = paragAt( parag ); if ( !p ) return QString::null; if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) - return richText( p ); + return p->richText(); else - return plainText( p ); + return p->string()->toString(); } void QTextDocument::invalidate() { - QTextParag *s = fParag; + QTextParagraph *s = fParag; while ( s ) { s->invalidate( 0 ); @@ -2149,5 +2277,5 @@ void QTextDocument::selectionStart( int id, int ¶gId, int &index ) return; QTextDocumentSelection &sel = *it; - paragId = !sel.swapped ? sel.startCursor.parag()->paragId() : sel.endCursor.parag()->paragId(); + paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); } @@ -2181,30 +2309,8 @@ void QTextDocument::selectionEnd( int id, int ¶gId, int &index ) return; QTextDocumentSelection &sel = *it; - paragId = sel.swapped ? sel.startCursor.parag()->paragId() : sel.endCursor.parag()->paragId(); + paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); } -QTextParag *QTextDocument::selectionStart( int id ) -{ - QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return 0; - QTextDocumentSelection &sel = *it; - if ( sel.startCursor.parag()->paragId() < sel.endCursor.parag()->paragId() ) - return sel.startCursor.parag(); - return sel.endCursor.parag(); -} - -QTextParag *QTextDocument::selectionEnd( int id ) -{ - QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); - if ( it == selections.end() ) - return 0; - QTextDocumentSelection &sel = *it; - if ( sel.startCursor.parag()->paragId() > sel.endCursor.parag()->paragId() ) - return sel.startCursor.parag(); - return sel.endCursor.parag(); -} - void QTextDocument::addSelection( int id ) { @@ -2221,20 +2327,20 @@ static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCur } - c1.parag()->removeSelection( id ); - c2.parag()->removeSelection( id ); - if ( c1.parag() != c2.parag() ) { - c1.parag()->setSelection( id, c1.index(), c1.parag()->length() - 1 ); - c2.parag()->setSelection( id, 0, c2.index() ); + c1.paragraph()->removeSelection( id ); + c2.paragraph()->removeSelection( id ); + if ( c1.paragraph() != c2.paragraph() ) { + c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 ); + c2.paragraph()->setSelection( id, 0, c2.index() ); } else { - c1.parag()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) ); + c1.paragraph()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) ); } sel.startCursor = start; sel.endCursor = end; - if ( sel.startCursor.parag() == sel.endCursor.parag() ) + if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) sel.swapped = sel.startCursor.index() > sel.endCursor.index(); } -bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) +bool QTextDocument::setSelectionEnd( int id, const QTextCursor &cursor ) { QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); @@ -2244,5 +2350,5 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) QTextCursor start = sel.startCursor; - QTextCursor end = *cursor; + QTextCursor end = cursor; if ( start == end ) { @@ -2252,5 +2358,5 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) } - if ( sel.endCursor.parag() == end.parag() ) { + if ( sel.endCursor.paragraph() == end.paragraph() ) { setSelectionEndHelper( id, sel, start, end ); return TRUE; @@ -2263,8 +2369,7 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) tmp = sel.endCursor; tmp.restoreState(); - QTextCursor tmp2 = *cursor; + QTextCursor tmp2 = cursor; tmp2.restoreState(); - c.setParag( tmp.parag()->paragId() < tmp2.parag()->paragId() ? tmp.parag() : tmp2.parag() ); - QTextCursor old; + c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() ); bool hadStart = FALSE; bool hadEnd = FALSE; @@ -2280,7 +2385,7 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) if ( c == end ) hadEnd = TRUE; - if ( c.parag() == start.parag() ) + if ( c.paragraph() == start.paragraph() ) hadStartParag = TRUE; - if ( c.parag() == end.parag() ) + if ( c.paragraph() == end.paragraph() ) hadEndParag = TRUE; if ( c == sel.startCursor ) @@ -2291,5 +2396,5 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) if ( !sel.swapped && ( hadEnd && !hadStart || - hadEnd && hadStart && start.parag() == end.parag() && start.index() > end.index() ) ) + hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) ) sel.swapped = TRUE; @@ -2298,8 +2403,8 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) QTextCursor tmp = c; tmp.restoreState(); - if ( tmp.parag() != c.parag() ) { - int sstart = tmp.parag()->selectionStart( id ); - tmp.parag()->removeSelection( id ); - tmp.parag()->setSelection( id, sstart, tmp.index() ); + if ( tmp.paragraph() != c.paragraph() ) { + int sstart = tmp.paragraph()->selectionStart( id ); + tmp.paragraph()->removeSelection( id ); + tmp.paragraph()->setSelection( id, sstart, tmp.index() ); } } @@ -2311,19 +2416,19 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) inSelection = TRUE; - bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.parag()->hasSelection( id ) && c.atParagEnd(); - c.parag()->removeSelection( id ); + bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd(); + c.paragraph()->removeSelection( id ); if ( inSelection ) { - if ( c.parag() == start.parag() && start.parag() == end.parag() ) { - c.parag()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) ); - } else if ( c.parag() == start.parag() && !hadEndParag ) { - c.parag()->setSelection( id, start.index(), c.parag()->length() - 1 ); - } else if ( c.parag() == end.parag() && !hadStartParag ) { - c.parag()->setSelection( id, end.index(), c.parag()->length() - 1 ); - } else if ( c.parag() == end.parag() && hadEndParag ) { - c.parag()->setSelection( id, 0, end.index() ); - } else if ( c.parag() == start.parag() && hadStartParag ) { - c.parag()->setSelection( id, 0, start.index() ); + if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) { + c.paragraph()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) ); + } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) { + c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 ); + } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) { + c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 ); + } else if ( c.paragraph() == end.paragraph() && hadEndParag ) { + c.paragraph()->setSelection( id, 0, end.index() ); + } else if ( c.paragraph() == start.paragraph() && hadStartParag ) { + c.paragraph()->setSelection( id, 0, start.index() ); } else { - c.parag()->setSelection( id, 0, c.parag()->length() - 1 ); + c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 ); } } @@ -2332,16 +2437,28 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) inSelection = FALSE; - old = c; + if ( noSelectionAnymore ) + break; + // *ugle*hack optimization + QTextParagraph *p = c.paragraph(); + if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) { c.gotoNextLetter(); - if ( old == c || noSelectionAnymore ) + if ( p == lastParagraph() && c.atParagEnd() ) break; + } else { + if ( p->document()->parent() ) + do { + c.gotoNextLetter(); + } while ( c.paragraph() == p ); + else + c.setParagraph( p->next() ); + } } if ( !sel.swapped ) - sel.startCursor.parag()->setSelection( id, sel.startCursor.index(), sel.startCursor.parag()->length() - 1 ); + sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 ); sel.startCursor = start; sel.endCursor = end; - if ( sel.startCursor.parag() == sel.endCursor.parag() ) + if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) sel.swapped = sel.startCursor.index() > sel.endCursor.index(); @@ -2359,104 +2476,47 @@ void QTextDocument::selectAll( int id ) QTextCursor c( this ); - c.setParag( fParag ); + c.setParagraph( fParag ); c.setIndex( 0 ); sel.startCursor = c; - c.setParag( lParag ); + c.setParagraph( lParag ); c.setIndex( lParag->length() - 1 ); sel.endCursor = c; - QTextParag *p = fParag; + selections.insert( id, sel ); + + QTextParagraph *p = fParag; while ( p ) { p->setSelection( id, 0, p->length() - 1 ); - for ( int i = 0; i < (int)p->length(); ++i ) { - if ( p->at( i )->isCustom() && p->at( i )->customItem()->isNested() ) { - QTextTable *t = (QTextTable*)p->at( i )->customItem(); - QPtrList<QTextTableCell> tableCells = t->tableCells(); - for ( QTextTableCell *c = tableCells.first(); c; c = tableCells.next() ) - c->richText()->selectAll( id ); - } - } p = p->next(); } - selections.insert( id, sel ); + for ( QTextDocument *d = childList.first(); d; d = childList.next() ) + d->selectAll( id ); } bool QTextDocument::removeSelection( int id ) { - QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); - if ( it == selections.end() ) + if ( !selections.contains( id ) ) return FALSE; - QTextDocumentSelection &sel = *it; - - if ( sel.startCursor == sel.endCursor ) { - selections.remove( id ); - return TRUE; - } - - if ( !mightHaveCustomItems ) { - QTextCursor start = sel.startCursor; - QTextCursor end = sel.endCursor; - if ( sel.swapped ) { - start = sel.endCursor; - end = sel.startCursor; - } + QTextDocumentSelection &sel = selections[ id ]; - for ( QTextParag *p = start.parag(); p; p = p->next() ) { + QTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor; + QTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor; + QTextParagraph* p = 0; + while ( start != end ) { + if ( p != start.paragraph() ) { + p = start.paragraph(); p->removeSelection( id ); - if ( p == end.parag() ) - break; } - - selections.remove( id ); - return TRUE; + start.gotoNextLetter(); } - - QTextCursor c( this ); - QTextCursor tmp = sel.startCursor; - if ( sel.swapped ) - tmp = sel.endCursor; - tmp.restoreState(); - c.setParag( tmp.parag() ); - QTextCursor old; - bool hadStart = FALSE; - bool hadEnd = FALSE; - QTextParag *lastParag = 0; - bool leftSelection = FALSE; - bool inSelection = FALSE; - sel.swapped = FALSE; - for ( ;; ) { - if ( c.parag() == sel.startCursor.parag() ) - hadStart = TRUE; - if ( c.parag() == sel.endCursor.parag() ) - hadEnd = TRUE; - - if ( inSelection && - ( c == sel.endCursor && hadStart || c == sel.startCursor && hadEnd ) ) - leftSelection = TRUE; - else if ( !leftSelection && !inSelection && ( c.parag() == sel.startCursor.parag() || c.parag() == sel.endCursor.parag() ) ) - inSelection = TRUE; - - bool noSelectionAnymore = leftSelection && !inSelection && !c.parag()->hasSelection( id ) && c.atParagEnd(); - - if ( lastParag != c.parag() ) - c.parag()->removeSelection( id ); - - old = c; - lastParag = c.parag(); - c.gotoNextLetter(); - if ( old == c || noSelectionAnymore ) - break; - } - selections.remove( id ); return TRUE; } -QString QTextDocument::selectedText( int id, bool withCustom ) const +QString QTextDocument::selectedText( int id, bool asRichText ) const { - // ######## TODO: look at textFormat() and return rich text or plain text (like the text() method!) QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id ); if ( it == selections.end() ) @@ -2482,5 +2542,5 @@ QString QTextDocument::selectedText( int id, bool withCustom ) const you always got the entire table. - ### Fix this properly for 3.0.4. + ### Fix this properly when refactoring */ while ( c2.nestedDepth() > c1.nestedDepth() ) @@ -2489,11 +2549,11 @@ QString QTextDocument::selectedText( int id, bool withCustom ) const c1.oneUp(); while ( c1.nestedDepth() && c2.nestedDepth() && - c1.parag()->document() != c2.parag()->document() ) { + c1.paragraph()->document() != c2.paragraph()->document() ) { c1.oneUp(); c2.oneUp(); } - // do not trust sel_swapped with tables. Fix this properly for 3.0.4 as well - if ( c1.parag()->paragId() > c2.parag()->paragId() || - (c1.parag() == c2.parag() && c1.index() > c2.index() ) ) { + // do not trust sel_swapped with tables. Fix this properly when refactoring as well + if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() || + (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) { QTextCursor tmp = c1; c2 = c1; @@ -2503,12 +2563,24 @@ QString QTextDocument::selectedText( int id, bool withCustom ) const // end selection 3.0.3 improvement + if ( asRichText && !parent() ) { + richTextExportStart = &c1; + richTextExportEnd = &c2; + + QString sel = richText(); + int from = sel.find( "<selstart/>" ); + int to = sel.findRev( "<selend/>" ); + if ( from >= 0 && from <= to ) + sel = sel.mid( from, to - from ); + richTextExportStart = richTextExportEnd = 0; + return sel; + } - if ( c1.parag() == c2.parag() ) { QString s; - QTextParag *p = c1.parag(); + if ( c1.paragraph() == c2.paragraph() ) { + QTextParagraph *p = c1.paragraph(); int end = c2.index(); if ( p->at( QMAX( 0, end - 1 ) )->isCustom() ) ++end; - if ( !withCustom || !p->mightHaveCustomItems ) { + if ( !p->mightHaveCustomItems ) { s += p->string()->toString().mid( c1.index(), end - c1.index() ); } else { @@ -2528,17 +2600,14 @@ QString QTextDocument::selectedText( int id, bool withCustom ) const } } - return s; - } - - QString s; - QTextParag *p = c1.parag(); + } else { + QTextParagraph *p = c1.paragraph(); int start = c1.index(); while ( p ) { - int end = p == c2.parag() ? c2.index() : p->length() - 1; - if ( p == c2.parag() && p->at( QMAX( 0, end - 1 ) )->isCustom() ) + int end = p == c2.paragraph() ? c2.index() : p->length() - 1; + if ( p == c2.paragraph() && p->at( QMAX( 0, end - 1 ) )->isCustom() ) ++end; - if ( !withCustom || !p->mightHaveCustomItems ) { + if ( !p->mightHaveCustomItems ) { s += p->string()->toString().mid( start, end - start ); - if ( p != c2.parag() ) + if ( p != c2.paragraph() ) s += "\n"; } else { @@ -2559,8 +2628,17 @@ QString QTextDocument::selectedText( int id, bool withCustom ) const } start = 0; - if ( p == c2.parag() ) + if ( p == c2.paragraph() ) break; p = p->next(); } + } + // ### workaround for plain text export until we get proper + // mime types: turn unicode line seperators into the more + // widely understood \n. Makes copy and pasting code snipplets + // from within Assistent possible + QChar* uc = (QChar*) s.unicode(); + for ( uint ii = 0; ii < s.length(); ii++ ) + if ( uc[(int)ii] == QChar_linesep ) + uc[(int)ii] = QChar('\n'); return s; } @@ -2584,26 +2662,16 @@ void QTextDocument::setFormat( int id, QTextFormat *f, int flags ) c1.restoreState(); - if ( c1.parag() == c2.parag() ) { - c1.parag()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags ); + if ( c1.paragraph() == c2.paragraph() ) { + c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags ); return; } - c1.parag()->setFormat( c1.index(), c1.parag()->length() - c1.index(), f, TRUE, flags ); - QTextParag *p = c1.parag()->next(); - while ( p && p != c2.parag() ) { + c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags ); + QTextParagraph *p = c1.paragraph()->next(); + while ( p && p != c2.paragraph() ) { p->setFormat( 0, p->length(), f, TRUE, flags ); p = p->next(); } - c2.parag()->setFormat( 0, c2.index(), f, TRUE, flags ); -} - -void QTextDocument::copySelectedText( int id ) -{ -#ifndef QT_NO_CLIPBOARD - if ( !hasSelection( id ) ) - return; - - QApplication::clipboard()->setText( selectedText( id ) ); -#endif + c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags ); } @@ -2633,15 +2701,15 @@ void QTextDocument::removeSelectedText( int id, QTextCursor *cursor ) removeSelection( id ); - if ( c1.parag() == c2.parag() ) { - c1.parag()->remove( c1.index(), c2.index() - c1.index() ); + if ( c1.paragraph() == c2.paragraph() ) { + c1.paragraph()->remove( c1.index(), c2.index() - c1.index() ); return; } - if ( c1.parag() == fParag && c1.index() == 0 && - c2.parag() == lParag && c2.index() == lParag->length() - 1 ) + if ( c1.paragraph() == fParag && c1.index() == 0 && + c2.paragraph() == lParag && c2.index() == lParag->length() - 1 ) cursor->setValid( FALSE ); bool didGoLeft = FALSE; - if ( c1.index() == 0 && c1.parag() != fParag ) { + if ( c1.index() == 0 && c1.paragraph() != fParag ) { cursor->gotoPreviousLetter(); if ( cursor->isValid() ) @@ -2649,9 +2717,9 @@ void QTextDocument::removeSelectedText( int id, QTextCursor *cursor ) } - c1.parag()->remove( c1.index(), c1.parag()->length() - 1 - c1.index() ); - QTextParag *p = c1.parag()->next(); + c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() ); + QTextParagraph *p = c1.paragraph()->next(); int dy = 0; - QTextParag *tmp; - while ( p && p != c2.parag() ) { + QTextParagraph *tmp; + while ( p && p != c2.paragraph() ) { tmp = p->next(); dy -= p->rect().height(); @@ -2659,5 +2727,5 @@ void QTextDocument::removeSelectedText( int id, QTextCursor *cursor ) p = tmp; } - c2.parag()->remove( 0, c2.index() ); + c2.paragraph()->remove( 0, c2.index() ); while ( p ) { p->move( dy ); @@ -2667,5 +2735,5 @@ void QTextDocument::removeSelectedText( int id, QTextCursor *cursor ) } - c1.parag()->join( c2.parag() ); + c1.paragraph()->join( c2.paragraph() ); if ( didGoLeft ) @@ -2680,12 +2748,12 @@ void QTextDocument::indentSelection( int id ) QTextDocumentSelection sel = *it; - QTextParag *startParag = sel.startCursor.parag(); - QTextParag *endParag = sel.endCursor.parag(); - if ( sel.endCursor.parag()->paragId() < sel.startCursor.parag()->paragId() ) { - endParag = sel.startCursor.parag(); - startParag = sel.endCursor.parag(); + QTextParagraph *startParag = sel.startCursor.paragraph(); + QTextParagraph *endParag = sel.endCursor.paragraph(); + if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { + endParag = sel.startCursor.paragraph(); + startParag = sel.endCursor.paragraph(); } - QTextParag *p = startParag; + QTextParagraph *p = startParag; while ( p && p != endParag ) { p->indent(); @@ -2709,69 +2777,59 @@ QTextCursor *QTextDocument::redo( QTextCursor *c ) } -bool QTextDocument::find( const QString &expr, bool cs, bool wo, bool forward, - int *parag, int *index, QTextCursor *cursor ) +bool QTextDocument::find( QTextCursor& cursor, const QString &e, bool cs, bool wo, bool forward ) { - QTextParag *p = forward ? fParag : lParag; - if ( parag ) - p = paragAt( *parag ); - else if ( cursor ) - p = cursor->parag(); - bool first = TRUE; - - while ( p ) { - QString s = p->string()->toString(); - s.remove( s.length() - 1, 1 ); // get rid of trailing space - int start = forward ? 0 : s.length() - 1; - if ( first && index ) - start = *index; - else if ( first ) - start = cursor->index(); - if ( !forward && first ) { - start -= expr.length() + 1; - if ( start < 0 ) { - first = FALSE; - p = p->prev(); - continue; + removeSelection( Standard ); + QTextParagraph *p = 0; + QString expr = e; + // if we search for 'word only' than we have to be sure that + // the expression contains no space or punct character at the + // beginning or in the end. Otherwise we would run into a + // endlessloop. + if ( wo ) { + for ( ;; ) { + if ( expr[ 0 ].isSpace() || expr[ 0 ].isPunct() ) + expr = expr.right( expr.length() - 1 ); + else + break; } + for ( ;; ) { + if ( expr.at( expr.length() - 1 ).isSpace() || expr.at( expr.length() - 1 ).isPunct() ) + expr = expr.left( expr.length() - 1 ); + else + break; } - first = FALSE; - + } + for (;;) { + if ( p != cursor.paragraph() ) { + p = cursor.paragraph(); + QString s = cursor.paragraph()->string()->toString(); + int start = cursor.index(); for ( ;; ) { int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs ); - if ( res == -1 ) - break; - - bool ok = TRUE; - if ( wo ) { int end = res + expr.length(); - if ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) && - ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) - ok = TRUE; - else - ok = FALSE; - } - if ( ok ) { - cursor->setParag( p ); - cursor->setIndex( res ); + if ( res == -1 || ( !forward && start < end ) ) + break; + if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) && + ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) { + removeSelection( Standard ); + cursor.setIndex( forward ? end : res ); setSelectionStart( Standard, cursor ); - cursor->setIndex( res + expr.length() ); + cursor.setIndex( forward ? res : end ); setSelectionEnd( Standard, cursor ); - if ( parag ) - *parag = p->paragId(); - if ( index ) - *index = res; return TRUE; } + start = res + (forward ? 1 : -1); + } + } if ( forward ) { - start = res + 1; + if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd () ) + break; + cursor.gotoNextLetter(); } else { - if ( res == 0 ) + if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() ) break; - start = res - 1; - } + cursor.gotoPreviousLetter(); } - p = forward ? p->next() : p->prev(); } - return FALSE; } @@ -2780,11 +2838,6 @@ void QTextDocument::setTextFormat( Qt::TextFormat f ) { txtFormat = f; - if ( txtFormat == Qt::RichText && fParag && fParag == lParag && fParag->length() <= 1 ) { - QPtrVector<QStyleSheetItem> v = fParag->styleSheetItems(); - v.resize( v.size() + 1 ); - v.insert( v.size() - 1, styleSheet()->item( "p" ) ); - fParag->setStyleSheetItems( v ); - } - + if ( fParag == lParag && fParag->length() <= 1 ) + fParag->rtext = ( f == Qt::RichText ); } @@ -2801,15 +2854,15 @@ bool QTextDocument::inSelection( int selId, const QPoint &pos ) const QTextDocumentSelection sel = *it; - QTextParag *startParag = sel.startCursor.parag(); - QTextParag *endParag = sel.endCursor.parag(); - if ( sel.startCursor.parag() == sel.endCursor.parag() && - sel.startCursor.parag()->selectionStart( selId ) == sel.endCursor.parag()->selectionEnd( selId ) ) + QTextParagraph *startParag = sel.startCursor.paragraph(); + QTextParagraph *endParag = sel.endCursor.paragraph(); + if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() && + sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) ) return FALSE; - if ( sel.endCursor.parag()->paragId() < sel.startCursor.parag()->paragId() ) { - endParag = sel.startCursor.parag(); - startParag = sel.endCursor.parag(); + if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { + endParag = sel.startCursor.paragraph(); + startParag = sel.endCursor.paragraph(); } - QTextParag *p = startParag; + QTextParagraph *p = startParag; while ( p ) { if ( p->rect().contains( pos ) ) { @@ -2856,5 +2909,5 @@ void QTextDocument::doLayout( QPainter *p, int w ) cw = w; vw = w; - QTextParag *parag = fParag; + QTextParagraph *parag = fParag; while ( parag ) { parag->invalidate( 0 ); @@ -2869,16 +2922,8 @@ void QTextDocument::doLayout( QPainter *p, int w ) QPixmap *QTextDocument::bufferPixmap( const QSize &s ) { - if ( !buf_pixmap ) { - int w = QABS( s.width() ); - int h = QABS( s.height() ); - buf_pixmap = new QPixmap( w, h ); - } else { - if ( buf_pixmap->width() < s.width() || - buf_pixmap->height() < s.height() ) { - buf_pixmap->resize( QMAX( s.width(), buf_pixmap->width() ), - QMAX( s.height(), buf_pixmap->height() ) ); - } - } - + if ( !buf_pixmap ) + buf_pixmap = new QPixmap( s.expandedTo( QSize(1,1) ) ); + else if ( buf_pixmap->size() != s ) + buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) ); return buf_pixmap; } @@ -2886,5 +2931,5 @@ QPixmap *QTextDocument::bufferPixmap( const QSize &s ) void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper ) { - if ( !firstParag() ) + if ( !firstParagraph() ) return; @@ -2895,19 +2940,8 @@ void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, } - if ( formatCollection()->defaultFormat()->color() != cg.text() ) { - QDict<QTextFormat> formats = formatCollection()->dict(); - QDictIterator<QTextFormat> it( formats ); - while ( it.current() ) { - if ( it.current() == formatCollection()->defaultFormat() ) { - ++it; - continue; - } - it.current()->setColor( cg.text() ); - ++it; - } - formatCollection()->defaultFormat()->setColor( cg.text() ); - } + if ( formatCollection()->defaultFormat()->color() != cg.text() ) + setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() ); - QTextParag *parag = firstParag(); + QTextParagraph *parag = firstParagraph(); while ( parag ) { if ( !parag->isValid() ) @@ -2933,5 +2967,5 @@ void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, } -void QTextDocument::drawParag( QPainter *p, QTextParag *parag, int cx, int cy, int cw, int ch, +void QTextDocument::drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch, QPixmap *&doubleBuffer, const QColorGroup &cg, bool drawCursor, QTextCursor *cursor, bool resetChanged ) @@ -2966,21 +3000,9 @@ void QTextDocument::drawParag( QPainter *p, QTextParag *parag, int cx, int cy, i painter->setBrushOrigin( -ir.x(), -ir.y() ); - if ( useDoubleBuffer || is_printer( painter ) ) { - if ( !parag->backgroundColor() ) - painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), - cg.brush( QColorGroup::Base ) ); - else - painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), - *parag->backgroundColor() ); - } else { - if ( cursor && cursor->parag() == parag ) { - if ( !parag->backgroundColor() ) + if ( useDoubleBuffer || is_printer( painter ) ) + painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) ); + else if ( cursor && cursor->paragraph() == parag ) painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ), - cg.brush( QColorGroup::Base ) ); - else - painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ), - *parag->backgroundColor() ); - } - } + parag->backgroundBrush( cg ) ); painter->translate( -( ir.x() - parag->rect().x() ), @@ -2996,4 +3018,5 @@ void QTextDocument::drawParag( QPainter *p, QTextParag *parag, int cx, int cy, i } + if ( useDoubleBuffer ) { if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) { p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(), @@ -3002,9 +3025,10 @@ void QTextDocument::drawParag( QPainter *p, QTextParag *parag, int cx, int cy, i parag->rect().height(), cg.brush( QColorGroup::Base ) ); } + } parag->document()->nextDoubleBuffered = FALSE; } -QTextParag *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, +QTextParagraph *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, bool onlyChanged, bool drawCursor, QTextCursor *cursor, bool resetChanged ) { @@ -3017,9 +3041,7 @@ QTextParag *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, co withoutDoubleBuffer = FALSE; - if ( !firstParag() ) + if ( !firstParagraph() ) return 0; - if ( drawCursor && cursor ) - tmpCursor = cursor; if ( cx < 0 && cy < 0 ) { cx = 0; @@ -3029,10 +3051,11 @@ QTextParag *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, co } - QTextParag *lastFormatted = 0; - QTextParag *parag = firstParag(); + QTextParagraph *lastFormatted = 0; + QTextParagraph *parag = firstParagraph(); QPixmap *doubleBuffer = 0; QPainter painter; + bool fullWidthSelection = FALSE; while ( parag ) { lastFormatted = parag; @@ -3040,31 +3063,23 @@ QTextParag *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, co parag->format(); - if ( !parag->rect().intersects( QRect( cx, cy, cw, ch ) ) ) { - QRect pr( parag->rect() ); + QRect pr = parag->rect(); + if ( fullWidthSelection ) pr.setWidth( parag->document()->width() ); - if ( pr.intersects( QRect( cx, cy, cw, ch ) ) ) - p->fillRect( pr.intersect( QRect( cx, cy, cw, ch ) ), cg.brush( QColorGroup::Base ) ); - if ( parag->rect().y() > cy + ch ) { - tmpCursor = 0; + if ( pr.y() > cy + ch ) goto floating; - } + if ( !pr.intersects( QRect( cx, cy, cw, ch ) ) || ( onlyChanged && !parag->hasChanged() ) ) { parag = parag->next(); continue; } - if ( !parag->hasChanged() && onlyChanged ) { - parag = parag->next(); - continue; - } - - drawParag( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged ); + drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged ); parag = parag->next(); } - parag = lastParag(); + parag = lastParagraph(); floating: if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) { - if ( !parag->document()->parent() ) { // !useDoubleBuffer + if ( !parag->document()->parent() ) { p->fillRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(), parag->document()->height() - ( parag->rect().y() + parag->rect().height() ), @@ -3073,6 +3088,4 @@ QTextParag *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, co if ( !flow()->isEmpty() ) { QRect cr( cx, cy, cw, ch ); -// cr = cr.intersect( QRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(), -// parag->document()->height() - ( parag->rect().y() + parag->rect().height() ) ) ); flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE ); } @@ -3084,20 +3097,33 @@ QTextParag *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, co } - tmpCursor = 0; return lastFormatted; } -void QTextDocument::setDefaultFont( const QFont &f ) +/* + #### this function only sets the default font size in the format collection + */ +void QTextDocument::setDefaultFormat( const QFont &font, const QColor &color ) { - int s = f.pointSize(); - bool usePixels = FALSE; - if ( s == -1 ) { - s = f.pixelSize(); - usePixels = TRUE; + bool reformat = font != fCollection->defaultFormat()->font(); + for ( QTextDocument *d = childList.first(); d; d = childList.next() ) + d->setDefaultFormat( font, color ); + fCollection->updateDefaultFormat( font, color, sheet_ ); + + if ( !reformat ) + return; + tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; + + // invalidate paragraphs and custom items + QTextParagraph *p = fParag; + while ( p ) { + p->invalidate( 0 ); + for ( int i = 0; i < p->length() - 1; ++i ) + if ( p->at( i )->isCustom() ) + p->at( i )->customItem()->invalidate(); + p = p->next(); } - updateFontSizes( s, usePixels ); } -void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParag *p ) +void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParagraph *p ) { if ( i && i->placement() != QTextCustomItem::PlaceInline ) { @@ -3109,5 +3135,5 @@ void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParag *p ) } -void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParag *p ) +void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p ) { flow_->unregisterFloatingItem( i ); @@ -3144,5 +3170,5 @@ bool QTextDocument::focusNextPrevChild( bool next ) if ( next ) { - QTextParag *p = focusIndicator.parag; + QTextParagraph *p = focusIndicator.parag; int index = focusIndicator.start + focusIndicator.len; while ( p ) { @@ -3203,5 +3229,5 @@ bool QTextDocument::focusNextPrevChild( bool next ) } } else { - QTextParag *p = focusIndicator.parag; + QTextParagraph *p = focusIndicator.parag; int index = focusIndicator.start - 1; if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 ) @@ -3283,5 +3309,5 @@ int QTextDocument::length() const { int l = 0; - QTextParag *p = fParag; + QTextParagraph *p = fParag; while ( p ) { l += p->length() - 1; // don't count trailing space @@ -3386,11 +3412,16 @@ QTextString::QTextString( const QTextString &s ) void QTextString::insert( int index, const QString &s, QTextFormat *f ) { + insert( index, s.unicode(), s.length(), f ); +} + +void QTextString::insert( int index, const QChar *unicode, int len, QTextFormat *f ) +{ int os = data.size(); - data.resize( data.size() + s.length() ); + data.resize( data.size() + len ); if ( index < os ) { - memmove( data.data() + index + s.length(), data.data() + index, + memmove( data.data() + index + len, data.data() + index, sizeof( QTextStringChar ) * ( os - index ) ); } - for ( int i = 0; i < (int)s.length(); ++i ) { + for ( int i = 0; i < len; ++i ) { data[ (int)index + i ].x = 0; data[ (int)index + i ].lineStart = 0; @@ -3399,5 +3430,5 @@ void QTextString::insert( int index, const QString &s, QTextFormat *f ) data[ (int)index + i ].rightToLeft = 0; data[ (int)index + i ].startOfRun = 0; - data[ (int)index + i ].c = s[ i ]; + data[ (int)index + i ].c = unicode[i]; data[ (int)index + i ].setFormat( f ); } @@ -3410,5 +3441,5 @@ QTextString::~QTextString() } -void QTextString::insert( int index, QTextStringChar *c ) +void QTextString::insert( int index, QTextStringChar *c, bool doAddRefFormat ) { int os = data.size(); @@ -3424,4 +3455,6 @@ void QTextString::insert( int index, QTextStringChar *c ) data[ (int)index ].d.format = 0; data[ (int)index ].type = QTextStringChar::Regular; + if ( doAddRefFormat && c->format() ) + c->format()->addRef(); data[ (int)index ].setFormat( c->format() ); bidiDirty = TRUE; @@ -3546,32 +3579,27 @@ void QTextDocument::setStyleSheet( QStyleSheet *s ) return; sheet_ = s; - fCollection->setStyleSheet( s ); - updateStyles(); + list_tm = list_bm = par_tm = par_bm = 12; + list_lm = 40; + li_tm = li_bm = 0; + QStyleSheetItem* item = s->item( "ol" ); + if ( item ) { + list_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); + list_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); + list_lm = QMAX(0,item->margin( QStyleSheetItem::MarginLeft )); } - -void QTextDocument::updateStyles() -{ - invalidate(); - if ( par ) - underlLinks = par->underlLinks; - fCollection->updateStyles(); - for ( QTextDocument *d = childList.first(); d; d = childList.next() ) - d->updateStyles(); + if ( (item = s->item( "li" ) ) ) { + li_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); + li_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); + } + if ( (item = s->item( "p" ) ) ) { + par_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); + par_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); } - -void QTextDocument::updateFontSizes( int base, bool usePixels ) -{ - for ( QTextDocument *d = childList.first(); d; d = childList.next() ) - d->updateFontSizes( base, usePixels ); - invalidate(); - fCollection->updateFontSizes( base, usePixels ); } -void QTextDocument::updateFontAttributes( const QFont &f, const QFont &old ) -{ +void QTextDocument::setUnderlineLinks( bool b ) { + underlLinks = b; for ( QTextDocument *d = childList.first(); d; d = childList.next() ) - d->updateFontAttributes( f, old ); - invalidate(); - fCollection->updateFontAttributes( f, old ); + d->setUnderlineLinks( b ); } @@ -3652,5 +3680,5 @@ int QTextString::width( int idx ) const int w = 0; QTextStringChar *c = &at( idx ); - if ( c->c.unicode() == 0xad ) + if ( c->c.unicode() == 0xad || c->c.unicode() == 0x2028 ) return 0; if( c->isCustom() ) { @@ -3700,48 +3728,26 @@ QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const } -QTextStringChar *QTextStringChar::clone() const -{ - QTextStringChar *chr = new QTextStringChar; - chr->c = c; - chr->x = 0; - chr->lineStart = 0; - chr->rightToLeft = 0; - chr->d.format = 0; - chr->type = QTextStringChar::Regular; - chr->setFormat( format() ); - if ( chr->format() ) - chr->format()->addRef(); - return chr; -} - // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -QTextParag::QTextParag( QTextDocument *d, QTextParag *pr, QTextParag *nx, bool updateIds ) - : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ), align( 0 ),mSelections( 0 ), - mStyleSheetItemsVec( 0 ), mFloatingItems( 0 ), listS( QStyleSheetItem::ListDisc ), - numSubParag( -1 ), tm( -1 ), bm( -1 ), lm( -1 ), rm( -1 ), flm( -1 ), - tArray(0), tabStopWidth(0), eData( 0 ) -{ - listS = QStyleSheetItem::ListDisc; - if ( ! (hasdoc = docOrPseudo != 0 ) ) - docOrPseudo = new QTextParagPseudoDocument; +QTextParagraph::QTextParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds ) + : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ), + changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE), + lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE), + mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE), + align( 0 ),mSelections( 0 ), + mFloatingItems( 0 ), lstyle( QStyleSheetItem::ListDisc ), + utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ), + tArray(0), tabStopWidth(0), eData( 0 ), ldepth( 0 ) +{ + lstyle = QStyleSheetItem::ListDisc; + if ( !hasdoc ) + docOrPseudo = new QTextParagraphPseudoDocument; bgcol = 0; - breakable = TRUE; - isBr = FALSE; - movedDown = FALSE; - mightHaveCustomItems = FALSE; - visible = TRUE; list_val = -1; - newLinesAllowed = FALSE; - lastInFrame = FALSE; - defFormat = formatCollection()->defaultFormat(); + QTextFormat* defFormat = formatCollection()->defaultFormat(); if ( !hasdoc ) { tabStopWidth = defFormat->width( 'x' ) * 8; pseudoDocument()->commandHistory = new QTextCommandHistory( 100 ); } -#if defined(PARSER_DEBUG) - qDebug( debug_indent + "new QTextParag" ); -#endif - fullWidth = TRUE; if ( p ) @@ -3752,12 +3758,9 @@ QTextParag::QTextParag( QTextDocument *d, QTextParag *pr, QTextParag *nx, bool u if ( !p && hasdoc ) - document()->setFirstParag( this ); + document()->setFirstParagraph( this ); if ( !n && hasdoc ) - document()->setLastParag( this ); + document()->setLastParagraph( this ); - changed = FALSE; - firstFormat = TRUE; state = -1; - needPreProcess = FALSE; if ( p ) @@ -3766,13 +3769,11 @@ QTextParag::QTextParag( QTextDocument *d, QTextParag *pr, QTextParag *nx, bool u id = 0; if ( n && updateIds ) { - QTextParag *s = n; + QTextParagraph *s = n; while ( s ) { s->id = s->p->id + 1; - s->numSubParag = -1; - s->lm = s->rm = s->tm = s->bm = -1, s->flm = -1; + s->invalidateStyleCache(); s = s->n; } } - firstPProcess = TRUE; str = new QTextString(); @@ -3780,5 +3781,5 @@ QTextParag::QTextParag( QTextDocument *d, QTextParag *pr, QTextParag *nx, bool u } -QTextParag::~QTextParag() +QTextParagraph::~QTextParagraph() { delete str; @@ -3797,5 +3798,5 @@ QTextParag::~QTextParag() delete [] tArray; delete eData; - QMap<int, QTextParagLineStart*>::Iterator it = lineStarts.begin(); + QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin(); for ( ; it != lineStarts.end(); ++it ) delete *it; @@ -3804,6 +3805,4 @@ QTextParag::~QTextParag() if ( mFloatingItems ) delete mFloatingItems; - if ( mStyleSheetItemsVec ) - delete mStyleSheetItemsVec; if ( p ) p->setNext( n ); @@ -3812,19 +3811,19 @@ QTextParag::~QTextParag() } -void QTextParag::setNext( QTextParag *s ) +void QTextParagraph::setNext( QTextParagraph *s ) { n = s; if ( !n && hasdoc ) - document()->setLastParag( this ); + document()->setLastParagraph( this ); } -void QTextParag::setPrev( QTextParag *s ) +void QTextParagraph::setPrev( QTextParagraph *s ) { p = s; if ( !p && hasdoc ) - document()->setFirstParag( this ); + document()->setFirstParagraph( this ); } -void QTextParag::invalidate( int chr ) +void QTextParagraph::invalidate( int chr ) { if ( invalid < 0 ) @@ -3836,19 +3835,31 @@ void QTextParag::invalidate( int chr ) i->ypos = -1; } - lm = rm = bm = tm = flm = -1; + invalidateStyleCache(); } -void QTextParag::insert( int index, const QString &s ) +void QTextParagraph::invalidateStyleCache() +{ + if ( list_val < 0 ) + list_val = -1; +} + + +void QTextParagraph::insert( int index, const QString &s ) +{ + insert( index, s.unicode(), s.length() ); +} + +void QTextParagraph::insert( int index, const QChar *unicode, int len ) { if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() ) - str->insert( index, s, + str->insert( index, unicode, len, document()->preProcessor()->format( QTextPreProcessor::Standard ) ); else - str->insert( index, s, formatCollection()->defaultFormat() ); + str->insert( index, unicode, len, formatCollection()->defaultFormat() ); invalidate( index ); needPreProcess = TRUE; } -void QTextParag::truncate( int index ) +void QTextParagraph::truncate( int index ) { str->truncate( index ); @@ -3857,5 +3868,5 @@ void QTextParag::truncate( int index ) } -void QTextParag::remove( int index, int len ) +void QTextParagraph::remove( int index, int len ) { if ( index + len - str->length() > 0 ) @@ -3872,5 +3883,5 @@ void QTextParag::remove( int index, int len ) } -void QTextParag::join( QTextParag *s ) +void QTextParagraph::join( QTextParagraph *s ) { int oh = r.height() + s->r.height(); @@ -3879,5 +3890,5 @@ void QTextParag::join( QTextParag *s ) n->p = this; else if ( hasdoc ) - document()->setLastParag( this ); + document()->setLastParagraph( this ); int start = str->length(); @@ -3897,4 +3908,8 @@ void QTextParag::join( QTextParag *s ) str->at( i + start ).setCustomItem( item ); s->str->at( i ).loseCustomItem(); + if ( hasdoc ) { + document()->unregisterCustomItem( item, s ); + document()->registerCustomItem( item, this ); + } } if ( s->str->at( i ).isAnchor() ) { @@ -3915,5 +3930,6 @@ void QTextParag::join( QTextParag *s ) needPreProcess = TRUE; if ( n ) { - QTextParag *s = n; + QTextParagraph *s = n; + s->invalidate( 0 ); while ( s ) { s->id = s->p->id + 1; @@ -3921,4 +3937,5 @@ void QTextParag::join( QTextParag *s ) s->needPreProcess = TRUE; s->changed = TRUE; + s->invalidateStyleCache(); s = s->n; } @@ -3928,5 +3945,5 @@ void QTextParag::join( QTextParag *s ) } -void QTextParag::move( int &dy ) +void QTextParagraph::move( int &dy ) { if ( dy == 0 ) @@ -3952,5 +3969,5 @@ void QTextParag::move( int &dy ) } -void QTextParag::format( int start, bool doMove ) +void QTextParagraph::format( int start, bool doMove ) { if ( !str || str->length() == 0 || !formatter() ) @@ -3967,5 +3984,4 @@ void QTextParag::format( int start, bool doMove ) r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) ); - r.setWidth( documentWidth() ); if ( p ) p->lastInFrame = FALSE; @@ -3976,4 +3992,5 @@ void QTextParag::format( int start, bool doMove ) formatAgain: + r.setWidth( documentWidth() ); if ( hasdoc && mFloatingItems ) { for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) { @@ -3984,5 +4001,5 @@ void QTextParag::format( int start, bool doMove ) } } - QMap<int, QTextParagLineStart*> oldLineStarts = lineStarts; + QMap<int, QTextLineStart*> oldLineStarts = lineStarts; lineStarts.clear(); int y = formatter()->format( document(), this, start, oldLineStarts ); @@ -3992,5 +4009,5 @@ void QTextParag::format( int start, bool doMove ) - QMap<int, QTextParagLineStart*>::Iterator it = oldLineStarts.begin(); + QMap<int, QTextLineStart*>::Iterator it = oldLineStarts.begin(); for ( ; it != oldLineStarts.end(); ++it ) @@ -4003,5 +4020,5 @@ void QTextParag::format( int start, bool doMove ) // as this results in a bigger double buffer than needed but ok for // now. - if ( lineStarts.count() == 1 ) { //&& ( !doc || document()->flow()->isEmpty() ) ) { + if ( lineStarts.count() == 1 ) { if ( !string()->isBidi() ) { c = &str->at( str->length() - 1 ); @@ -4012,5 +4029,5 @@ void QTextParag::format( int start, bool doMove ) } - if ( newLinesAllowed ) { + if ( !hasdoc ) { // qt_format_text bounding rect handling it = lineStarts.begin(); int usedw = 0; @@ -4055,5 +4072,5 @@ void QTextParag::format( int start, bool doMove ) if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) { int dy = ( r.y() + r.height() ) - n->r.y(); - QTextParag *s = n; + QTextParagraph *s = n; bool makeInvalid = p && p->lastInFrame; while ( s && dy ) { @@ -4075,10 +4092,10 @@ void QTextParag::format( int start, bool doMove ) } -int QTextParag::lineHeightOfChar( int i, int *bl, int *y ) const +int QTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const { if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.end(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end(); --it; for ( ;; ) { @@ -4095,15 +4112,15 @@ int QTextParag::lineHeightOfChar( int i, int *bl, int *y ) const } - qWarning( "QTextParag::lineHeightOfChar: couldn't find lh for %d", i ); + qWarning( "QTextParagraph::lineHeightOfChar: couldn't find lh for %d", i ); return 15; } -QTextStringChar *QTextParag::lineStartOfChar( int i, int *index, int *line ) const +QTextStringChar *QTextParagraph::lineStartOfChar( int i, int *index, int *line ) const { if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); int l = (int)lineStarts.count() - 1; - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.end(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end(); --it; for ( ;; ) { @@ -4121,23 +4138,23 @@ QTextStringChar *QTextParag::lineStartOfChar( int i, int *index, int *line ) con } - qWarning( "QTextParag::lineStartOfChar: couldn't find %d", i ); + qWarning( "QTextParagraph::lineStartOfChar: couldn't find %d", i ); return 0; } -int QTextParag::lines() const +int QTextParagraph::lines() const { if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); return (int)lineStarts.count(); } -QTextStringChar *QTextParag::lineStartOfLine( int line, int *index ) const +QTextStringChar *QTextParagraph::lineStartOfLine( int line, int *index ) const { if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); if ( line >= 0 && line < (int)lineStarts.count() ) { - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); while ( line-- > 0 ) ++it; @@ -4148,22 +4165,22 @@ QTextStringChar *QTextParag::lineStartOfLine( int line, int *index ) const } - qWarning( "QTextParag::lineStartOfLine: couldn't find %d", line ); + qWarning( "QTextParagraph::lineStartOfLine: couldn't find %d", line ); return 0; } -int QTextParag::leftGap() const +int QTextParagraph::leftGap() const { if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); int line = 0; int x = str->at(0).x; /* set x to x of first char */ if ( str->isBidi() ) { - for ( int i = 1; i < str->length(); ++i ) + for ( int i = 1; i < str->length()-1; ++i ) x = QMIN(x, str->at(i).x); return x; } - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); while (line < (int)lineStarts.count()) { int i = it.key(); /* char index */ @@ -4175,5 +4192,5 @@ int QTextParag::leftGap() const } -void QTextParag::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags ) +void QTextParagraph::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags ) { if ( !f ) @@ -4213,7 +4230,7 @@ void QTextParag::setFormat( int index, int len, QTextFormat *f, bool useCollecti } -void QTextParag::indent( int *oldIndent, int *newIndent ) +void QTextParagraph::indent( int *oldIndent, int *newIndent ) { - if ( !hasdoc || !document()->indent() || style() && style()->displayMode() != QStyleSheetItem::DisplayBlock ) { + if ( !hasdoc || !document()->indent() || isListItem() ) { if ( oldIndent ) *oldIndent = 0; @@ -4227,239 +4244,165 @@ void QTextParag::indent( int *oldIndent, int *newIndent ) } -void QTextParag::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections, +void QTextParagraph::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections, int clipx, int clipy, int clipw, int cliph ) { if ( !visible ) return; - QTextStringChar *chr = at( 0 ); - int i = 0; - int h = 0; - int baseLine = 0, lastBaseLine = 0; - QTextStringChar *formatChar = 0; - int lastY = -1; - int startX = 0; - int bw = 0; - int cy = 0; - int curx = -1, cury = 0, curh = 0; - bool lastDirection = chr->rightToLeft; - const int full_sel_width = (hasdoc ? document()->width() : r.width()); -#if 0 // seems we don't need that anymore - int tw = 0; -#endif + QTextStringChar *chr = 0; + int i, y, h, baseLine, xstart, xend; + i = y =h = baseLine = 0; + QRect cursorRect; + drawSelections &= ( mSelections != 0 ); + // macintosh full-width selection style + bool fullWidthStyle = FALSE; + int fullSelectionWidth = 0; + if ( drawSelections && fullWidthStyle ) + fullSelectionWidth = (hasdoc ? document()->width() : r.width()); QString qstr = str->toString(); - // ### workaround so that \n are not drawn, actually this should be - // fixed in QFont somewhere (under Windows you get ugly boxes + // ### workaround so that \n are not drawn, actually this should + // be fixed in QFont somewhere (under Windows you get ugly boxes // otherwise) QChar* uc = (QChar*) qstr.unicode(); - for ( uint ii = 0; ii < qstr.length(); ii++ ) { - if ( uc[(int)ii]== '\n' ) + for ( uint ii = 0; ii < qstr.length(); ii++ ) + if ( uc[(int)ii]== '\n' || uc[(int)ii] == QChar_linesep || uc[(int)ii] == '\t' ) uc[(int)ii] = 0x20; - } - - - const int nSels = hasdoc ? document()->numSelections() : 1; - QMemArray<int> selectionStarts( nSels ); - QMemArray<int> selectionEnds( nSels ); - if ( drawSelections ) { - bool hasASelection = FALSE; - for ( i = 0; i < nSels; ++i ) { - if ( !hasSelection( i ) ) { - selectionStarts[ i ] = -1; - selectionEnds[ i ] = -1; - } else { - hasASelection = TRUE; - selectionStarts[ i ] = selectionStart( i ); - int end = selectionEnd( i ); - if ( end == length() - 1 && n && n->hasSelection( i ) ) - end++; - selectionEnds[ i ] = end; - } - } - if ( !hasASelection ) - drawSelections = FALSE; - } int line = -1; - int cw; - bool didListLabel = FALSE; int paintStart = 0; - int paintEnd = -1; - int lasth = 0; + int selection = -1; for ( i = 0; i < length(); i++ ) { chr = at( i ); -#if 0 // seems we don't need that anymore - if ( !str->isBidi() && is_printer( &painter ) ) { // ### fix our broken ps-printer - if ( !chr->lineStart ) - chr->x = QMAX( chr->x, tw ); - else - tw = 0; + + // we flush at end of document + bool flush = i== length()-1; + bool selectionStateChanged = FALSE; + if ( !flush ) { + QTextStringChar *nextchr = at( i+1 ); + // we flush at end of line + flush |= nextchr->lineStart; + // we flush on format changes + flush |= ( nextchr->format() != chr->format() ); + // we flush on anchor changes + flush |= ( nextchr->isAnchor() != chr->isAnchor() ); + // we flush on start of run + flush |= nextchr->startOfRun; + // we flush on bidi changes + flush |= ( nextchr->rightToLeft != chr->rightToLeft ); + // we flush on tab + flush |= ( chr->c == '\t' ); + // we flush on soft hypens + flush |= ( chr->c.unicode() == 0xad ); + // we flush on custom items + flush |= chr->isCustom(); + // we flush before custom items + flush |= nextchr->isCustom(); + // when painting justified, we flush on spaces + if ((alignment() & Qt3::AlignJustify) == Qt3::AlignJustify ) + flush |= QTextFormatter::isBreakable( str, i ); + // we flush when the string is getting too long + flush |= ( i - paintStart >= 256 ); + // we flush when the selection state changes + if ( drawSelections ) { + for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin(); + it != mSelections->end(); ++it ) + selectionStateChanged |=( (*it).start == i || (*it).start == i+1 || (*it).end == i+1 ); + flush |= selectionStateChanged; + } } -#endif - cw = string()->width( i ); - if ( chr->c == '\t' && i < length() - 1 ) - cw = at( i + 1 )->x - chr->x + 1; - if ( chr->c.unicode() == 0xad && i < length() - 1 ) - cw = 0; // init a new line if ( chr->lineStart ) { -#if 0 // seems we don't need that anymore - tw = 0; -#endif + if (fullWidthStyle && drawSelections && selection >= 0) + painter.fillRect( xend, y, fullSelectionWidth - xend, h, + (selection == QTextDocument::Standard || !hasdoc) ? + cg.color( QColorGroup::Highlight ) : + document()->selectionColor( selection ) ); ++line; - lineInfo( line, cy, h, baseLine ); - lasth = h; - if ( clipy != -1 && cy > clipy - r.y() + cliph ) // outside clip area, leave + paintStart = i; + lineInfo( line, y, h, baseLine ); + if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave break; - if ( lastBaseLine == 0 ) - lastBaseLine = baseLine; } - // draw bullet list items - if ( !didListLabel && line == 0 && style() && style()->displayMode() == QStyleSheetItem::DisplayListItem ) { - didListLabel = TRUE; - drawLabel( &painter, chr->x, cy, 0, 0, baseLine, cg ); + // if this is the first line and we are a list item, draw the the bullet label + if ( line == 0 && isListItem() ) + drawLabel( &painter, chr->x, y, 0, 0, baseLine, cg ); } // check for cursor mark - if ( cursor && this == cursor->parag() && i == cursor->index() ) { - curx = cursor->x(); - QTextStringChar *c = chr; - if ( i > 0 ) - --c; - curh = c->format()->height(); - cury = cy + baseLine - c->format()->ascent(); - } - - // first time - start again... - if ( !formatChar || lastY == -1 ) { - formatChar = chr; - lastY = cy; - startX = chr->x; - if ( !chr->isCustom() && chr->c != '\n' ) - paintEnd = i; - bw = cw; - if ( !chr->isCustom() ) - continue; + if ( cursor && this == cursor->paragraph() && i == cursor->index() ) { + QTextStringChar *c = i == 0 ? chr : chr - 1; + cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(), + 1, c->format()->height() ); } - // check if selection state changed - bool selectionChange = FALSE; + // check if we are in a selection and store which one it is + selection = -1; if ( drawSelections ) { - for ( int j = 0; j < nSels; ++j ) { - selectionChange = selectionStarts[ j ] == i || selectionEnds[ j ] == i; - if ( selectionChange ) + for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin(); + it != mSelections->end(); ++it ) + if ( (*it).start <= i && i < (*it).end + ( (*it).end == length()-1 && n && n->hasSelection(it.key()) ) ? 1:0 + // exclude the standard selection from printing + && (it.key() != QTextDocument::Standard || !is_printer( &painter) ) ) { + selection = it.key(); break; } } - //if something (format, etc.) changed, draw what we have so far - if ( ( ( ( alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify && at(paintEnd)->c.isSpace() ) || - lastDirection != (bool)chr->rightToLeft || - chr->startOfRun || - lastY != cy || chr->format() != formatChar->format() || chr->isAnchor() != formatChar->isAnchor() || - ( paintEnd != -1 && at( paintEnd )->c =='\t' ) || chr->c == '\t' || - ( paintEnd != -1 && at( paintEnd )->c.unicode() == 0xad ) || chr->c.unicode() == 0xad || - selectionChange || chr->isCustom() ) ) { - if ( paintStart <= paintEnd ) { - // ### temporary hack until I get the new placement/shaping stuff working - int x = startX; - if ( ( alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify && paintEnd != -1 && - paintEnd > 1 && at( paintEnd )->c.isSpace() ) { - int add = str->at(paintEnd).x - str->at(paintEnd-1).x - str->width(paintEnd-1); - bw += ( lastDirection ? 0 : add ); - } - drawParagString( painter, qstr, paintStart, paintEnd - paintStart + 1, x, lastY, - lastBaseLine, bw, lasth, drawSelections, - formatChar, i, selectionStarts, selectionEnds, cg, lastDirection ); - } -#if 0 // seems we don't need that anymore - if ( !str->isBidi() && is_printer( &painter ) ) { // ### fix our broken ps-printer - if ( !chr->lineStart ) { - // ### the next line doesn't look 100% correct for arabic - tw = startX + painter.fontMetrics().width( qstr.mid(paintStart, paintEnd - paintStart +1) ); - chr->x = QMAX( chr->x, tw ); + if ( flush ) { // something changed, draw what we have so far + if ( chr->rightToLeft ) { + xstart = chr->x; + xend = at( paintStart )->x + str->width( paintStart ); } else { - tw = 0; - } + xstart = at( paintStart )->x; + if ( !selectionStateChanged && i < length() - 1 && !str->at( i + 1 ).lineStart ) + xend = str->at( i + 1 ).x; + else + xend = chr->x + str->width( i ); } -#endif - if ( !chr->isCustom() ) { - if ( chr->c != '\n' ) { - paintStart = i; - paintEnd = i; - } else { - paintStart = i+1; - paintEnd = -1; + + if ( (clipx == -1 || clipw == -1) || (xend >= clipx && xstart <= clipx + clipw) ) { + if ( !chr->isCustom() ) + drawString( painter, qstr, paintStart, i - paintStart + 1, xstart, y, + baseLine, xend-xstart, h, selection, + chr, cg, chr->rightToLeft ); + else if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline ) + chr->customItem()->draw( &painter, chr->x, y, + clipx == -1 ? clipx : (clipx - r.x()), + clipy == -1 ? clipy : (clipy - r.y()), + clipw, cliph, cg, selection >= 0 ); } - formatChar = chr; - lastY = cy; - startX = chr->x; - bw = cw; - } else { - if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline ) { - chr->customItem()->draw( &painter, chr->x, cy, clipx - r.x(), clipy - r.y(), clipw, cliph, cg, - nSels && selectionStarts[ 0 ] <= i && selectionEnds[ 0 ] >= i ); - paintStart = i+1; - paintEnd = -1; - formatChar = chr; - lastY = cy; - startX = chr->x + string()->width( i ); - bw = 0; - } else { - chr->customItem()->resize( chr->customItem()->width ); paintStart = i+1; - paintEnd = -1; - formatChar = chr; - lastY = cy; - startX = chr->x + string()->width( i ); - bw = 0; - } - } - } else { - if ( chr->c != '\n' ) { - if( chr->rightToLeft ) { - startX = chr->x; } - paintEnd = i; - } - bw += cw; - } - lastBaseLine = baseLine; - lasth = h; - lastDirection = chr->rightToLeft; + } - // if we are through the parag, but still have some stuff left to draw, draw it now - if ( paintStart <= paintEnd ) { - bool selectionChange = FALSE; - if ( drawSelections ) { - for ( int j = 0; j < nSels; ++j ) { - selectionChange = selectionStarts[ j ] == i || selectionEnds[ j ] == i; - if ( selectionChange ) + if (fullWidthStyle && drawSelections && selection >= 0 && next() && next()->mSelections) + for ( QMap<int, QTextParagraphSelection>::ConstIterator it = next()->mSelections->begin(); + it != next()->mSelections->end(); ++it ) + if (((*it).start) == 0) { + painter.fillRect( xend, y, fullSelectionWidth - xend, h, + (selection == QTextDocument::Standard || !hasdoc) ? + cg.color( QColorGroup::Highlight ) : + document()->selectionColor( selection ) ); break; } - } - int x = startX; - drawParagString( painter, qstr, paintStart, paintEnd-paintStart+1, x, lastY, - lastBaseLine, bw, h, drawSelections, - formatChar, i, selectionStarts, selectionEnds, cg, lastDirection ); - } - // if we should draw a cursor, draw it now - if ( curx != -1 && cursor ) { - painter.fillRect( QRect( curx, cury, 1, curh - lineSpacing() ), cg.color( QColorGroup::Text ) ); + // time to draw the cursor + const int cursor_extent = 4; + if ( !cursorRect.isNull() && cursor && + ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) { + painter.fillRect( cursorRect, cg.color( QColorGroup::Text ) ); painter.save(); if ( string()->isBidi() ) { - const int d = 4; if ( at( cursor->index() )->rightToLeft ) { painter.setPen( Qt::black ); - painter.drawLine( curx, cury, curx - d / 2, cury + d / 2 ); - painter.drawLine( curx, cury + d, curx - d / 2, cury + d / 2 ); + painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); + painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); } else { painter.setPen( Qt::black ); - painter.drawLine( curx, cury, curx + d / 2, cury + d / 2 ); - painter.drawLine( curx, cury + d, curx + d / 2, cury + d / 2 ); + painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); + painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); } } @@ -4470,9 +4413,10 @@ void QTextParag::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *c //#define BIDI_DEBUG -void QTextParag::drawParagString( QPainter &painter, const QString &s, int start, int len, int startX, - int lastY, int baseLine, int bw, int h, bool drawSelections, - QTextStringChar *formatChar, int i, const QMemArray<int> &selectionStarts, - const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft ) +void QTextParagraph::drawString( QPainter &painter, const QString &s, int start, int len, int xstart, + int y, int baseLine, int w, int h, int selection, + QTextStringChar *formatChar, const QColorGroup& cg, + bool rightToLeft ) { + int i = start + len - 1; bool plainText = hasdoc ? document()->textFormat() == Qt::PlainText : FALSE; QTextFormat* format = formatChar->format(); @@ -4500,27 +4444,20 @@ void QTextParag::drawParagString( QPainter &painter, const QString &s, int start } - if ( drawSelections ) { - const int nSels = hasdoc ? document()->numSelections() : 1; - const int startSel = is_printer( 0 ) ? 1 : 0; - for ( int j = startSel; j < nSels; ++j ) { - if ( i > selectionStarts[ j ] && i <= selectionEnds[ j ] ) { - if ( !hasdoc || document()->invertSelectionText( j ) ) - painter.setPen( QPen( cg.color( QColorGroup::HighlightedText ) ) ); - if ( j == QTextDocument::Standard ) - painter.fillRect( startX, lastY, bw, h, cg.color( QColorGroup::Highlight ) ); - else - painter.fillRect( startX, lastY, bw, h, hasdoc ? document()->selectionColor( j ) : cg.color( QColorGroup::Highlight ) ); - } - } + if ( selection >= 0 ) { + if ( !hasdoc || document()->invertSelectionText( selection ) ) + painter.setPen( cg.color( QColorGroup::HighlightedText ) ); + painter.fillRect( xstart, y, w, h, + (selection == QTextDocument::Standard || !hasdoc) ? + cg.color( QColorGroup::Highlight ) : document()->selectionColor( selection ) ); } if ( str[ start ] != '\t' && str[ start ].unicode() != 0xad ) { if ( format->vAlign() == QTextFormat::AlignNormal ) { - painter.drawText( startX, lastY + baseLine, str.mid( start ), len ); + painter.drawText( xstart, y + baseLine, str.mid( start ), len ); #ifdef BIDI_DEBUG painter.save(); painter.setPen ( Qt::red ); - painter.drawLine( startX, lastY, startX, lastY + baseLine ); - painter.drawLine( startX, lastY + baseLine/2, startX + 10, lastY + baseLine/2 ); + painter.drawLine( xstart, y, xstart, y + baseLine ); + painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 ); int w = 0; int i = 0; @@ -4528,6 +4465,6 @@ void QTextParag::drawParagString( QPainter &painter, const QString &s, int start w += painter.fontMetrics().charWidth( str, start + i++ ); painter.setPen ( Qt::blue ); - painter.drawLine( startX + w - 1, lastY, startX + w - 1, lastY + baseLine ); - painter.drawLine( startX + w - 1, lastY + baseLine/2, startX + w - 1 - 10, lastY + baseLine/2 ); + painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine ); + painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 ); painter.restore(); #endif @@ -4539,5 +4476,5 @@ void QTextParag::drawParagString( QPainter &painter, const QString &s, int start f.setPointSize( ( f.pointSize() * 2 ) / 3 ); painter.setFont( f ); - painter.drawText( startX, lastY + baseLine - ( painter.fontMetrics().height() / 2 ), + painter.drawText( xstart, y + baseLine - ( painter.fontMetrics().height() / 2 ), str.mid( start ), len ); } else if ( format->vAlign() == QTextFormat::AlignSubScript ) { @@ -4548,14 +4485,14 @@ void QTextParag::drawParagString( QPainter &painter, const QString &s, int start f.setPointSize( ( f.pointSize() * 2 ) / 3 ); painter.setFont( f ); - painter.drawText( startX, lastY + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len ); + painter.drawText( xstart, y + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len ); } } if ( i + 1 < length() && at( i + 1 )->lineStart && at( i )->c.unicode() == 0xad ) { - painter.drawText( startX + bw, lastY + baseLine, "\xad" ); + painter.drawText( xstart + w, y + baseLine, "\xad" ); } if ( format->isMisspelled() ) { painter.save(); painter.setPen( QPen( Qt::red, 1, Qt::DotLine ) ); - painter.drawLine( startX, lastY + baseLine + 1, startX + bw, lastY + baseLine + 1 ); + painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 ); painter.restore(); } @@ -4569,30 +4506,20 @@ void QTextParag::drawParagString( QPainter &painter, const QString &s, int start document()->focusIndicator.start <= i && document()->focusIndicator.start + document()->focusIndicator.len >= i + len ) ) { - painter.drawWinFocusRect( QRect( startX, lastY, bw, h ) ); + painter.drawWinFocusRect( QRect( xstart, y, w, h ) ); } } -void QTextParag::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ) +void QTextParagraph::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ) { - if ( !style() ) - return; QRect r ( x, y, w, h ); QStyleSheetItem::ListStyle s = listStyle(); p->save(); - p->setPen( defFormat->color() ); - - QFont font2( defFormat->font() ); - if ( length() > 0 ) { QTextFormat *format = at( 0 )->format(); if ( format ) { - if ( format->fontSizesInPixels() ) - font2.setPixelSize( at( 0 )->format()->font().pixelSize() ); - else - font2.setPointSize( at( 0 )->format()->font().pointSize() ); - } + p->setPen( format->color() ); + p->setFont( format->font() ); } - p->setFont( font2 ); QFontMetrics fm( p->fontMetrics() ); int size = fm.lineSpacing() / 3; @@ -4603,5 +4530,20 @@ void QTextParag::drawLabel( QPainter* p, int x, int y, int w, int h, int base, c case QStyleSheetItem::ListUpperAlpha: { - int n = numberOfSubParagraph(); + if ( list_val == -1 ) { // uninitialised list value, calcluate the right one + int depth = listDepth(); + list_val--; + // ### evil, square and expensive. This needs to be done when formatting, not when painting + QTextParagraph* s = prev(); + int depth_s; + while ( s && (depth_s = s->listDepth()) >= depth ) { + if ( depth_s == depth && s->isListItem() ) + list_val--; + s = s->prev(); + } + } + + int n = list_val; + if ( n < -1 ) + n = -n - 1; QString l; switch ( s ) { @@ -4628,5 +4570,5 @@ void QTextParag::drawLabel( QPainter* p, int x, int y, int w, int h, int base, c { QRect er( r.right() - size * 2, r.top() + fm.height() / 2 - size / 2, size, size ); - p->fillRect( er , cg.brush( QColorGroup::Foreground ) ); + p->fillRect( er , cg.brush( QColorGroup::Text ) ); } break; @@ -4640,5 +4582,5 @@ void QTextParag::drawLabel( QPainter* p, int x, int y, int w, int h, int base, c default: { - p->setBrush( cg.brush( QColorGroup::Foreground )); + p->setBrush( cg.brush( QColorGroup::Text )); QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size); p->drawEllipse( er ); @@ -4651,132 +4593,38 @@ void QTextParag::drawLabel( QPainter* p, int x, int y, int w, int h, int base, c } -void QTextParag::setStyleSheetItems( const QPtrVector<QStyleSheetItem> &vec ) -{ - styleSheetItemsVec() = vec; - invalidate( 0 ); - lm = rm = tm = bm = flm = -1; - numSubParag = -1; -} - -void QTextParag::setList( bool b, int listStyle ) +void QTextParagraph::readStyleInformation( QDataStream& stream ) { - if ( !hasdoc ) - return; - - if ( !style() ) { - styleSheetItemsVec().resize( 2 ); - mStyleSheetItemsVec->insert( 0, document()->styleSheet()->item( "html" ) ); - mStyleSheetItemsVec->insert( 1, document()->styleSheet()->item( "p" ) ); - } - - if ( b ) { - if ( style()->displayMode() != QStyleSheetItem::DisplayListItem || this->listStyle() != listStyle ) { - styleSheetItemsVec().remove( styleSheetItemsVec().size() - 1 ); - QStyleSheetItem *item = (*mStyleSheetItemsVec)[ mStyleSheetItemsVec->size() - 1 ]; - if ( item ) - mStyleSheetItemsVec->remove( mStyleSheetItemsVec->size() - 1 ); - mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 1, - listStyle == QStyleSheetItem::ListDisc || listStyle == QStyleSheetItem::ListCircle - || listStyle == QStyleSheetItem::ListSquare ? - document()->styleSheet()->item( "ul" ) : document()->styleSheet()->item( "ol" ) ); - mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 1, document()->styleSheet()->item( "li" ) ); - setListStyle( (QStyleSheetItem::ListStyle)listStyle ); - } else { - return; - } - } else { - if ( style()->displayMode() != QStyleSheetItem::DisplayBlock ) { - styleSheetItemsVec().remove( styleSheetItemsVec().size() - 1 ); - if ( mStyleSheetItemsVec->size() >= 2 ) { - mStyleSheetItemsVec->remove( mStyleSheetItemsVec->size() - 2 ); - mStyleSheetItemsVec->resize( mStyleSheetItemsVec->size() - 2 ); - } else { - mStyleSheetItemsVec->resize( mStyleSheetItemsVec->size() - 1 ); - } - } else { - return; - } - } - invalidate( 0 ); - lm = rm = tm = bm = flm = -1; - numSubParag = -1; - if ( next() ) { - QTextParag *s = next(); + int int_align, int_lstyle; + uchar uchar_litem, uchar_rtext, uchar_dir; + stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm + >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir; + align = int_align; lstyle = (QStyleSheetItem::ListStyle) int_lstyle; + litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (QChar::Direction)uchar_dir ); + QTextParagraph* s = prev() ? prev() : this; while ( s ) { - s->numSubParag = -1; - s->lm = s->rm = s->tm = s->bm = flm = -1; - s->numSubParag = -1; s->invalidate( 0 ); s = s->next(); } } -} -void QTextParag::incDepth() +void QTextParagraph::writeStyleInformation( QDataStream& stream ) const { - if ( !style() || !hasdoc ) - return; - if ( style()->displayMode() != QStyleSheetItem::DisplayListItem ) - return; - styleSheetItemsVec().resize( styleSheetItemsVec().size() + 1 ); - mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 1, (*mStyleSheetItemsVec)[ mStyleSheetItemsVec->size() - 2 ] ); - mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 2, - listStyle() == QStyleSheetItem::ListDisc || listStyle() == QStyleSheetItem::ListCircle || - listStyle() == QStyleSheetItem::ListSquare ? - document()->styleSheet()->item( "ul" ) : document()->styleSheet()->item( "ol" ) ); - invalidate( 0 ); - lm = -1; - flm = -1; + stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction(); } -void QTextParag::decDepth() -{ - if ( !style() || !hasdoc ) - return; - if ( style()->displayMode() != QStyleSheetItem::DisplayListItem ) - return; - int numLists = 0; - QStyleSheetItem *lastList = 0; - int lastIndex = 0; - int i; - if ( mStyleSheetItemsVec ) { - for ( i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) { - QStyleSheetItem *item = (*mStyleSheetItemsVec)[ i ]; - if ( item->name() == "ol" || item->name() == "ul" ) { - lastList = item; - lastIndex = i; - numLists++; - } - } - } - if ( !lastList ) - return; - styleSheetItemsVec().remove( lastIndex ); - for ( i = lastIndex; i < (int)mStyleSheetItemsVec->size() - 1; ++i ) - mStyleSheetItemsVec->insert( i, (*mStyleSheetItemsVec)[ i + 1 ] ); - mStyleSheetItemsVec->resize( mStyleSheetItemsVec->size() - 1 ); - if ( numLists == 1 ) - setList( FALSE, -1 ); - invalidate( 0 ); - lm = -1; - flm = -1; -} -int QTextParag::listDepth() const -{ - int numLists = 0; - int i; - if ( mStyleSheetItemsVec ) { - for ( i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) { - QStyleSheetItem *item = (*mStyleSheetItemsVec)[ i ]; - if ( item->name() == "ol" || item->name() == "ul" ) - numLists++; - } +void QTextParagraph::setListDepth( int depth ) { + if ( !hasdoc || depth == ldepth ) + return; + ldepth = depth; + QTextParagraph* s = prev() ? prev() : this; + while ( s ) { + s->invalidate( 0 ); + s = s->next(); } - return numLists - 1; } -int *QTextParag::tabArray() const +int *QTextParagraph::tabArray() const { int *ta = tArray; @@ -4786,5 +4634,5 @@ int *QTextParag::tabArray() const } -int QTextParag::nextTab( int, int x ) +int QTextParagraph::nextTab( int, int x ) { int *ta = tArray; @@ -4812,5 +4660,5 @@ int QTextParag::nextTab( int, int x ) } -void QTextParag::adjustToPainter( QPainter *p ) +void QTextParagraph::adjustToPainter( QPainter *p ) { for ( int i = 0; i < length(); ++i ) { @@ -4820,5 +4668,5 @@ void QTextParag::adjustToPainter( QPainter *p ) } -QTextFormatCollection *QTextParag::formatCollection() const +QTextFormatCollection *QTextParagraph::formatCollection() const { if ( hasdoc ) @@ -4832,12 +4680,17 @@ QTextFormatCollection *QTextParag::formatCollection() const } -QString QTextParag::richText() const +QString QTextParagraph::richText() const { QString s; QTextStringChar *formatChar = 0; QString spaces; - bool lastCharWasSpace = FALSE; - int firstcol = 0; - for ( int i = 0; i < length()-1; ++i ) { + bool doStart = richTextExportStart && richTextExportStart->paragraph() == this; + bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this; + int i; + for ( i = 0; i < length()-1; ++i ) { + if ( doStart && i && richTextExportStart->index() == i ) + s += "<selstart/>"; + if ( doEnd && richTextExportEnd->index() == i ) + s += "<selend/>"; QTextStringChar *c = &str->at( i ); if ( c->isAnchor() && !c->anchorName().isEmpty() ) { @@ -4851,65 +4704,32 @@ QString QTextParag::richText() const } if ( !formatChar ) { - s += c->format()->makeFormatChangeTags( 0, QString::null, c->anchorHref() ); + s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), + 0, QString::null, c->anchorHref() ); formatChar = c; } else if ( ( formatChar->format()->key() != c->format()->key() ) || - (formatChar->isAnchor() != c->isAnchor() && - (!c->anchorHref().isEmpty() || !formatChar->anchorHref().isEmpty() ) ) ) {// lisp was here - - if ( !spaces.isEmpty() ) { - if ( spaces[0] == '\t' || lastCharWasSpace ) - s += "<wsp>" + spaces + "</wsp>"; - else if ( spaces.length() > 1 ) - s += "<wsp>" + spaces.mid(1) + "</wsp> "; - else - s += spaces; - lastCharWasSpace = TRUE; - spaces = QString::null; - } - s += c->format()->makeFormatChangeTags( formatChar->format() , formatChar->anchorHref(), c->anchorHref() ); + (c->anchorHref() != formatChar->anchorHref() ) ) { + s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), + formatChar->format() , formatChar->anchorHref(), c->anchorHref() ); formatChar = c; } - - if ( c->c == ' ' || c->c == '\t' ) { - spaces += c->c; - continue; - } else if ( !spaces.isEmpty() ) { - if ( spaces[0] == '\t' || lastCharWasSpace ) - s += "<wsp>" + spaces + "</wsp>"; - else if ( spaces.length() > 1 ) - s += "<wsp>" + spaces.mid(1) + "</wsp> "; - else - s += spaces; - spaces = QString::null; - if ( s.length() - firstcol > 60 ) { - s += '\n'; - firstcol = s.length(); - } - } - - lastCharWasSpace = FALSE; - if ( c->c == '<' ) { + if ( c->c == '<' ) s += "<"; - } else if ( c->c == '>' ) { + else if ( c->c == '>' ) s += ">"; - } else if ( c->isCustom() ) { + else if ( c->isCustom() ) s += c->customItem()->richText(); - } else { - s += c->c; - } - } - if ( !spaces.isEmpty() ) { - if ( spaces.length() > 1 || spaces[0] == '\t' || lastCharWasSpace ) - s += "<wsp>" + spaces + "</wsp>"; + else if ( c->c == '\n' || c->c == QChar_linesep ) + s += "<br />"; // space on purpose for compatibility with Netscape, Lynx & Co. else - s += spaces; + s += c->c; } - + if ( doEnd && richTextExportEnd->index() == i ) + s += "<selend/>"; if ( formatChar ) - s += formatChar->format()->makeFormatEndTags( formatChar->anchorHref() ); + s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() ); return s; } -void QTextParag::addCommand( QTextCommand *cmd ) +void QTextParagraph::addCommand( QTextCommand *cmd ) { if ( !hasdoc ) @@ -4919,5 +4739,5 @@ void QTextParag::addCommand( QTextCommand *cmd ) } -QTextCursor *QTextParag::undo( QTextCursor *c ) +QTextCursor *QTextParagraph::undo( QTextCursor *c ) { if ( !hasdoc ) @@ -4926,5 +4746,5 @@ QTextCursor *QTextParag::undo( QTextCursor *c ) } -QTextCursor *QTextParag::redo( QTextCursor *c ) +QTextCursor *QTextParagraph::redo( QTextCursor *c ) { if ( !hasdoc ) @@ -4933,175 +4753,75 @@ QTextCursor *QTextParag::redo( QTextCursor *c ) } -int QTextParag::topMargin() const +int QTextParagraph::topMargin() const { - if ( !p && ( !hasdoc || !document()->addMargins() ) ) - return 0; - if ( tm != -1 ) - return tm; - QStyleSheetItem *item = style(); - if ( !item ) { - ( (QTextParag*)this )->tm = 0; - return 0; - } - int m = 0; - if ( item->margin( QStyleSheetItem::MarginTop ) != QStyleSheetItem::Undefined ) - m = item->margin( QStyleSheetItem::MarginTop ); - if ( mStyleSheetItemsVec ) { - QStyleSheetItem *it = 0; - QStyleSheetItem *p = prev() ? prev()->style() : 0; - for ( int i = (int)mStyleSheetItemsVec->size() - 2 ; i >= 0; --i ) { - it = (*mStyleSheetItemsVec)[ i ]; - if ( it != p ) - break; - int mar = it->margin( QStyleSheetItem::MarginTop ); - m += (mar != QStyleSheetItem::Undefined) ? mar : 0; - if ( it->displayMode() != QStyleSheetItem::DisplayInline ) - break; - } + if ( rtext ) { + m = isListItem() ? (document()->li_tm/QMAX(1,listDepth())) : document()->par_tm; + if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) ) + m = QMAX( m, document()->list_tm ); } - m = scale( m, QTextFormat::painter() ); - - ( (QTextParag*)this )->tm = m; - return tm; + m += utm; + return scale( m, QTextFormat::painter() ); } -int QTextParag::bottomMargin() const +int QTextParagraph::bottomMargin() const { - if ( bm != -1 ) - return bm; - QStyleSheetItem *item = style(); - if ( !item || !next() ) { - ( (QTextParag*)this )->bm = 0; - return 0; - } - int m = 0; - if ( item->margin( QStyleSheetItem::MarginBottom ) != QStyleSheetItem::Undefined ) - m = item->margin( QStyleSheetItem::MarginBottom ); - if ( mStyleSheetItemsVec ) { - QStyleSheetItem *it = 0; - QStyleSheetItem *n = next() ? next()->style() : 0; - for ( int i =(int)mStyleSheetItemsVec->size() - 2 ; i >= 0; --i ) { - it = (*mStyleSheetItemsVec)[ i ]; - if ( it != n ) - break; - int mar = it->margin( QStyleSheetItem::MarginBottom ); - m += mar != QStyleSheetItem::Undefined ? mar : 0; - if ( it->displayMode() != QStyleSheetItem::DisplayInline ) - break; + if ( rtext ) { + m = isListItem() ? (document()->li_bm/QMAX(1,listDepth())) : document()->par_bm; + if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) ) + m = QMAX( m, document()->list_bm ); } - } - m = scale ( m, QTextFormat::painter() ); - - ( (QTextParag*)this )->bm = m; - return bm; + m += ubm; + return scale( m, QTextFormat::painter() ); } -int QTextParag::leftMargin() const +int QTextParagraph::leftMargin() const { - if ( lm != -1 ) - return lm; - QStyleSheetItem *item = style(); - if ( !item ) { - ( (QTextParag*)this )->lm = 0; - return 0; - } - int m = 0; - if ( mStyleSheetItemsVec ) { - for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) { - item = (*mStyleSheetItemsVec)[ i ]; - int mar = item->margin( QStyleSheetItem::MarginLeft ); - m += mar != QStyleSheetItem::Undefined ? mar : 0; - if ( item->name() == "ol" || item->name() == "ul" ) { - QPainter* oldPainter = QTextFormat::painter(); - QTextFormat::setPainter( 0 ); - m += defFormat->width( '1' ) + - defFormat->width( '2' ) + - defFormat->width( '3' ) + - defFormat->width( '.' ); - QTextFormat::setPainter( oldPainter ); - } - } + int m = ulm; + if ( listDepth() ) + m += listDepth() * document()->list_lm; + return scale( m, QTextFormat::painter() ); } - m = scale ( m, QTextFormat::painter() ); - - ( (QTextParag*)this )->lm = m; - return lm; -} - -int QTextParag::firstLineMargin() const +int QTextParagraph::firstLineMargin() const { - if ( flm != -1 ) - return lm; - QStyleSheetItem *item = style(); - if ( !item ) { - ( (QTextParag*)this )->flm = 0; - return 0; + int m = uflm; + return scale( m, QTextFormat::painter() ); } - int m = 0; - if ( mStyleSheetItemsVec ) { - for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) { - item = (*mStyleSheetItemsVec)[ i ]; - int mar = item->margin( QStyleSheetItem::MarginFirstLine ); - m += mar != QStyleSheetItem::Undefined ? mar : 0; - } - } - - m = scale( m, QTextFormat::painter() ); - ( (QTextParag*)this )->flm = m; - return flm; -} - -int QTextParag::rightMargin() const +int QTextParagraph::rightMargin() const { - if ( rm != -1 ) - return rm; - QStyleSheetItem *item = style(); - if ( !item ) { - ( (QTextParag*)this )->rm = 0; - return 0; - } - int m = 0; - if ( mStyleSheetItemsVec ) { - for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) { - item = (*mStyleSheetItemsVec)[ i ]; - int mar = item->margin( QStyleSheetItem::MarginRight ); - m += mar != QStyleSheetItem::Undefined ? mar : 0; - } - } - m = scale( m, QTextFormat::painter() ); - - ( (QTextParag*)this )->rm = m; - return rm; + int m = urm; + return scale( m, QTextFormat::painter() ); } -int QTextParag::lineSpacing() const +int QTextParagraph::lineSpacing() const { - QStyleSheetItem *item = style(); - if ( !item ) - return 0; - - int ls = item->lineSpacing(); - if ( ls == QStyleSheetItem::Undefined ) - return 0; - ls = scale( ls, QTextFormat::painter() ); - - return ls; + int l = ulinespacing; + l = scale( l, QTextFormat::painter() ); + return l; } -void QTextParag::copyParagData( QTextParag *parag ) +void QTextParagraph::copyParagData( QTextParagraph *parag ) { - setStyleSheetItems( parag->styleSheetItems() ); - setListStyle( parag->listStyle() ); - setAlignment( parag->alignment() ); + rtext = parag->rtext; + lstyle = parag->lstyle; + ldepth = parag->ldepth; + litem = parag->litem; + align = parag->align; + utm = parag->utm; + ubm = parag->ubm; + urm = parag->urm; + ulm = parag->ulm; + uflm = parag->uflm; + ulinespacing = parag->ulinespacing; QColor *c = parag->backgroundColor(); if ( c ) setBackgroundColor( *c ); + str->setDirection( parag->str->direction() ); } -void QTextParag::show() +void QTextParagraph::show() { if ( visible || !hasdoc ) @@ -5110,5 +4830,5 @@ void QTextParag::show() } -void QTextParag::hide() +void QTextParagraph::hide() { if ( !visible || !hasdoc ) @@ -5117,5 +4837,5 @@ void QTextParag::hide() } -void QTextParag::setDirection( QChar::Direction d ) +void QTextParagraph::setDirection( QChar::Direction d ) { if ( str && str->direction() != d ) { @@ -5125,15 +4845,15 @@ void QTextParag::setDirection( QChar::Direction d ) } -QChar::Direction QTextParag::direction() const +QChar::Direction QTextParagraph::direction() const { return (str ? str->direction() : QChar::DirON ); } -void QTextParag::setChanged( bool b, bool recursive ) +void QTextParagraph::setChanged( bool b, bool recursive ) { changed = b; if ( recursive ) { - if ( document() && document()->parentParag() ) - document()->parentParag()->setChanged( b, recursive ); + if ( document() && document()->parentParagraph() ) + document()->parentParagraph()->setChanged( b, recursive ); } } @@ -5153,7 +4873,5 @@ QTextFormatter::QTextFormatter() } -/* only used for bidi or complex text reordering - */ -QTextParagLineStart *QTextFormatter::formatLine( QTextParag *parag, QTextString *string, QTextParagLineStart *line, +QTextLineStart *QTextFormatter::formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) { @@ -5162,5 +4880,4 @@ QTextParagLineStart *QTextFormatter::formatLine( QTextParag *parag, QTextString return bidiReorderLine( parag, string, line, startChar, lastChar, align, space ); #endif - space = QMAX( space, 0 ); // #### with nested tables this gets negative because of a bug I didn't find yet, so workaround for now. This also means non-left aligned nested tables do not work at the moment int start = (startChar - &string->at(0)); int last = (lastChar - &string->at(0) ); @@ -5173,5 +4890,11 @@ QTextParagLineStart *QTextFormatter::formatLine( QTextParag *parag, QTextString } else if ( align & Qt3::AlignJustify ) { int numSpaces = 0; - for ( int j = start; j < last; ++j ) { + // End at "last-1", the last space ends up with a width of 0 + for ( int j = last-1; j >= start; --j ) { + // Start at last tab, if any. + if ( string->at( j ).c == '\t' ) { + start = j+1; + break; + } if( isBreakable( string, j ) ) { numSpaces++; @@ -5195,5 +4918,5 @@ QTextParagLineStart *QTextFormatter::formatLine( QTextParag *parag, QTextString line->w = 0; - return new QTextParagLineStart(); + return new QTextLineStart(); } @@ -5205,10 +4928,9 @@ QTextParagLineStart *QTextFormatter::formatLine( QTextParag *parag, QTextString // collects one line of the paragraph and transforms it to visual order -QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QTextString *text, QTextParagLineStart *line, +QTextLineStart *QTextFormatter::bidiReorderLine( QTextParagraph * /*parag*/, QTextString *text, QTextLineStart *line, QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) { int start = (startChar - &text->at(0)); int last = (lastChar - &text->at(0) ); - //qDebug("doing BiDi reordering from %d to %d!", start, last); QBidiControl *control = new QBidiControl( line->context(), line->status ); @@ -5244,5 +4966,11 @@ QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QT x += space; else if ( align & Qt3::AlignJustify ) { - for ( int j = start; j < last; ++j ) { + // End at "last-1", the last space ends up with a width of 0 + for ( int j = last-1; j >= start; --j ) { + // Start at last tab, if any. + if ( text->at( j ).c == '\t' ) { + start = j+1; + break; + } if( isBreakable( text, j ) ) { numSpaces++; @@ -5306,5 +5034,4 @@ QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QT ww = c->format()->width( ' ' ); } - //qDebug("setting char %d at pos %d", pos, x); if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww; x += ww; @@ -5317,5 +5044,5 @@ QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QT line->w = xmax + 10; - QTextParagLineStart *ls = new QTextParagLineStart( control->context, control->status ); + QTextLineStart *ls = new QTextLineStart( control->context, control->status ); delete control; delete runs; @@ -5324,8 +5051,10 @@ QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QT #endif -bool QTextFormatter::isBreakable( QTextString *string, int pos ) const +bool QTextFormatter::isBreakable( QTextString *string, int pos ) { const QChar &c = string->at( pos ).c; char ch = c.latin1(); + if ( c == QChar_linesep ) + return TRUE; if ( c.isSpace() && ch != '\n' && c.unicode() != 0x00a0U ) return TRUE; @@ -5375,5 +5104,5 @@ bool QTextFormatter::isBreakable( QTextString *string, int pos ) const } -void QTextFormatter::insertLineStart( QTextParag *parag, int index, QTextParagLineStart *ls ) +void QTextFormatter::insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls ) { if ( index > 0 ) { // we can assume that only first line starts are insrted multiple times @@ -5381,5 +5110,5 @@ void QTextFormatter::insertLineStart( QTextParag *parag, int index, QTextParagLi return; } - QMap<int, QTextParagLineStart*>::Iterator it; + QMap<int, QTextLineStart*>::Iterator it; if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) { parag->lineStartList().insert( index, ls ); @@ -5395,12 +5124,12 @@ void QTextFormatter::insertLineStart( QTextParag *parag, int index, QTextParagLi the shift of the paragraphs bottom line. */ -int QTextFormatter::formatVertically( QTextDocument* doc, QTextParag* parag ) +int QTextFormatter::formatVertically( QTextDocument* doc, QTextParagraph* parag ) { int oldHeight = parag->rect().height(); - QMap<int, QTextParagLineStart*>& lineStarts = parag->lineStartList(); - QMap<int, QTextParagLineStart*>::Iterator it = lineStarts.begin(); - int h = doc->addMargins() ? parag->topMargin() : 0; + QMap<int, QTextLineStart*>& lineStarts = parag->lineStartList(); + QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin(); + int h = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0; for ( ; it != lineStarts.end() ; ++it ) { - QTextParagLineStart * ls = it.data(); + QTextLineStart * ls = it.data(); ls->y = h; QTextStringChar *c = ¶g->string()->at(it.key()); @@ -5421,8 +5150,8 @@ int QTextFormatter::formatVertically( QTextDocument* doc, QTextParag* parag ) } int m = parag->bottomMargin(); - if ( parag->next() && doc && !doc->addMargins() ) - m = QMAX( m, parag->next()->topMargin() ); - if ( parag->next() && parag->next()->isLineBreak() ) + if ( !parag->next() ) m = 0; + else + m = QMAX(m, parag->next()->topMargin() ) / 2; h += m; parag->setHeight( h ); @@ -5436,13 +5165,15 @@ QTextFormatterBreakInWords::QTextFormatterBreakInWords() } -int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag, - int start, const QMap<int, QTextParagLineStart*> & ) +#define SPACE(s) doc?(s>0?s:0):s + +int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParagraph *parag, + int start, const QMap<int, QTextLineStart*> & ) { QTextStringChar *c = 0; QTextStringChar *firstChar = 0; - int left = doc ? parag->leftMargin() + doc->leftMargin() : 4; + int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; int x = left + ( doc ? parag->firstLineMargin() : 0 ); int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 ); - int y = doc && doc->addMargins() ? parag->topMargin() : 0; + int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; int h = y; int len = parag->length(); @@ -5461,5 +5192,5 @@ int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag, int i = start; - QTextParagLineStart *lineStart = new QTextParagLineStart( y, y, 0 ); + QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); insertLineStart( parag, 0, lineStart ); @@ -5502,5 +5233,5 @@ int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag, y += h; h = c->height(); - lineStart = new QTextParagLineStart( y, h, h ); + lineStart = new QTextLineStart( y, h, h ); insertLineStart( parag, i, lineStart ); c->lineStart = 1; @@ -5512,11 +5243,10 @@ int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag, if ( wrapEnabled && ( wrapAtColumn() == -1 && x + ww > w || - wrapAtColumn() != -1 && col >= wrapAtColumn() ) || - parag->isNewLinesAllowed() && lastChr == '\n' ) { + wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) { x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw; y += h; h = c->height(); - lineStart = formatLine( parag, parag->string(), lineStart, firstChar, c-1 ); + lineStart = formatLine( parag, parag->string(), lineStart, firstChar, SPACE(c-1) ); lineStart->y = y; insertLineStart( parag, i, lineStart ); @@ -5540,10 +5270,12 @@ int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag, int m = parag->bottomMargin(); - if ( parag->next() && doc && !doc->addMargins() ) - m = QMAX( m, parag->next()->topMargin() ); - parag->setFullWidth( fullWidth ); - if ( parag->next() && parag->next()->isLineBreak() ) + if ( !parag->next() ) m = 0; + else + m = QMAX(m, parag->next()->topMargin() ) / 2; + parag->setFullWidth( fullWidth ); y += h + m; + if ( doc ) + minw += doc->rightMargin(); if ( !wrapEnabled ) minw = QMAX(minw, wused); @@ -5567,6 +5299,6 @@ QTextFormatterBreakWords::QTextFormatterBreakWords() }}while(FALSE) -int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, - int start, const QMap<int, QTextParagLineStart*> & ) +int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParagraph *parag, + int start, const QMap<int, QTextLineStart*> & ) { QTextStringChar *c = 0; @@ -5575,5 +5307,5 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; int x = left + ( doc ? parag->firstLineMargin() : 0 ); - int y = doc && doc->addMargins() ? parag->topMargin() : 0; + int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; int h = y; int len = parag->length(); @@ -5591,5 +5323,5 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, int wused = 0; int tminw = marg; - int linespace = doc ? parag->lineSpacing() : 0; + int linespacing = doc ? parag->lineSpacing() : 0; bool wrapEnabled = isWrapEnabled( parag ); @@ -5599,5 +5331,5 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, int i = start; - QTextParagLineStart *lineStart = new QTextParagLineStart( y, y, 0 ); + QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); insertLineStart( parag, 0, lineStart ); int lastBreak = -1; @@ -5655,5 +5387,5 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - QTextParagLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, w - x ); + QTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); ci->resize( w - x); if ( ci->width < w - x ) { @@ -5667,6 +5399,6 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, curLeft = x; if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) { - y += QMAX( h, tmph ); - tmph = c->height() + linespace; + y += QMAX( h, QMAX( tmph, linespacing ) ); + tmph = c->height(); h = tmph; lineStart = lineStart2; @@ -5676,5 +5408,5 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, firstChar = c; } else { - tmph = c->height() + linespace; + tmph = c->height(); h = tmph; delete lineStart2; @@ -5687,5 +5419,5 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, minw = QMAX( minw, tminw ); - int tw = ci->minimumWidth(); + int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 ); if ( tw < QWIDGETSIZE_MAX ) tminw = tw; @@ -5700,13 +5432,28 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, } - if ( wrapEnabled && ( !c->c.isSpace() || lastBreak == -2 ) - && ( lastBreak != -1 || allowBreakInWords() ) && - ( wrapAtColumn() == -1 && x + ww > w && lastBreak != -1 || - wrapAtColumn() == -1 && x + ww > w - 4 && lastBreak == -1 && allowBreakInWords() || - wrapAtColumn() != -1 && col >= wrapAtColumn() ) || - parag->isNewLinesAllowed() && lastChr == '\n' && firstChar < c ) { + bool lastWasOwnLineCustomItem = lastBreak == -2; + bool hadBreakableChar = lastBreak != -1; + bool lastWasHardBreak = lastChr == QChar_linesep; + + // we break if + // 1. the last character was a hard break (QChar_linesep) or + // 2. the last charater was a own-line custom item (eg. table or ruler) or + // 3. wrapping was enabled, it was not a space and following + // condition is true: We either had a breakable character + // previously or we ar allowed to break in words and - either + // we break at w pixels and the current char would exceed that + // or - we break at a column and the current character would + // exceed that. + if ( lastWasHardBreak || lastWasOwnLineCustomItem || + ( wrapEnabled && + ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) && + ( (wrapAtColumn() == -1 && x + ww > w) || + (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) ) + ) + ) { if ( wrapAtColumn() != -1 ) minw = QMAX( minw, x + ww ); - if ( lastBreak < 0 ) { + // if a break was forced (no breakable char, hard break or own line custom item), break immediately.... + if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) { if ( lineStart ) { lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); @@ -5715,8 +5462,8 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, DO_FLOW( lineStart ); } - lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, w - x ); + lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - if ( parag->isNewLinesAllowed() && c->c == '\t' ) { + if ( !doc && c->c == '\t' ) { // qt_format_text tab handling int nx = parag->nextTab( i, x - left ) + left; if ( nx < x ) @@ -5726,6 +5473,6 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, } curLeft = x; - y += h; - tmph = c->height() + linespace; + y += QMAX( h, linespacing ); + tmph = c->height(); h = 0; lineStart->y = y; @@ -5738,11 +5485,11 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, lastBreak = -1; col = 0; - } else { + } else { // ... otherwise if we had a breakable char, break there DO_FLOW( lineStart ); i = lastBreak; - lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ), align, w - string->at( i ).x ); + lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i ).x) ); x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); - if ( parag->isNewLinesAllowed() && c->c == '\t' ) { + if ( !doc && c->c == '\t' ) { // qt_format_text tab handling int nx = parag->nextTab( i, x - left ) + left; if ( nx < x ) @@ -5752,6 +5499,6 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, } curLeft = x; - y += h; - tmph = c->height() + linespace; + y += QMAX( h, linespacing ); + tmph = c->height(); h = tmph; lineStart->y = y; @@ -5767,8 +5514,8 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, continue; } - } else if ( lineStart && ( isBreakable( string, i ) || parag->isNewLinesAllowed() && c->c == '\n' ) ) { + } else if ( lineStart && isBreakable( string, i ) ) { if ( len <= 2 || i < len - 1 ) { tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); - tmph = QMAX( tmph, c->height() + linespace ); + tmph = QMAX( tmph, c->height() ); } minw = QMAX( minw, tminw ); @@ -5781,5 +5528,5 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, } else { tminw += ww; - int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height() + linespace - c->ascent() ); + int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height()- c->ascent() ); tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); tmph = tmpBaseLine + belowBaseLine; @@ -5791,6 +5538,8 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, } - // ### hack. The last char in the paragraph is always invisible, and somehow sometimes has a wrong format. It changes between - // layouting and printing. This corrects some layouting errors in BiDi mode due to this. + // ### hack. The last char in the paragraph is always invisible, + // ### and somehow sometimes has a wrong format. It changes + // ### between // layouting and printing. This corrects some + // ### layouting errors in BiDi mode due to this. if ( len > 1 && !c->isAnchor() ) { c->format()->removeRef(); @@ -5804,24 +5553,34 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, lineStart->h = h; // last line in a paragraph is not justified - if ( align == Qt3::AlignJustify ) + if ( align == Qt3::AlignJustify || lastChr == QChar_linesep ) align = Qt3::AlignAuto; DO_FLOW( lineStart ); - lineStart = formatLine( parag, string, lineStart, firstChar, c, align, w - x ); + lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) ); delete lineStart; } minw = QMAX( minw, tminw ); + if ( doc ) + minw += doc->rightMargin(); int m = parag->bottomMargin(); - if ( parag->next() && doc && !doc->addMargins() ) - m = QMAX( m, parag->next()->topMargin() ); - parag->setFullWidth( fullWidth ); - if ( parag->next() && parag->next()->isLineBreak() ) + if ( !parag->next() ) m = 0; - y += h + m; + else + m = QMAX(m, parag->next()->topMargin() ) / 2; + parag->setFullWidth( fullWidth ); + y += QMAX( h, linespacing ) + m; wused += rm; if ( !wrapEnabled || wrapAtColumn() != -1 ) minw = QMAX(minw, wused); + + // This is the case where we are breaking wherever we darn well please + // in cases like that, the minw should not be the length of the entire + // word, because we necessarily want to show the word on the whole line. + // example: word wrap in iconview + if ( allowBreakInWords() && minw > wused ) + minw = wused; + thisminw = minw; thiswused = wused; @@ -5838,5 +5597,5 @@ QTextIndent::QTextIndent() QTextFormatCollection::QTextFormatCollection() - : cKey( 307 ), sheet( 0 ) + : cKey( 307 ) { defFormat = new QTextFormat( QApplication::font(), @@ -5856,7 +5615,4 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *f ) { if ( f->parent() == this || f == defFormat ) { -#ifdef DEBUG_COLLECTION - qDebug( "need '%s', best case!", f->key().latin1() ); -#endif lastFormat = f; lastFormat->addRef(); @@ -5865,7 +5621,4 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *f ) if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) { -#ifdef DEBUG_COLLECTION - qDebug( "need '%s', good case!", f->key().latin1() ); -#endif lastFormat->addRef(); return lastFormat; @@ -5874,7 +5627,4 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *f ) QTextFormat *fm = cKey.find( f->key() ); if ( fm ) { -#ifdef DEBUG_COLLECTION - qDebug( "need '%s', normal case!", f->key().latin1() ); -#endif lastFormat = fm; lastFormat->addRef(); @@ -5885,7 +5635,4 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *f ) return defFormat; -#ifdef DEBUG_COLLECTION - qDebug( "need '%s', worst case!", f->key().latin1() ); -#endif lastFormat = createFormat( *f ); lastFormat->collection = this; @@ -5897,7 +5644,4 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, in { if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) { -#ifdef DEBUG_COLLECTION - qDebug( "mix of '%s' and '%s, best case!", of->key().latin1(), nf->key().latin1() ); -#endif cres->addRef(); return cres; @@ -5914,4 +5658,6 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, in if ( flags & QTextFormat::Underline ) cres->fn.setUnderline( nf->fn.underline() ); + if ( flags & QTextFormat::StrikeOut ) + cres->fn.setStrikeOut( nf->fn.strikeOut() ); if ( flags & QTextFormat::Family ) cres->fn.setFamily( nf->fn.family() ); @@ -5932,13 +5678,7 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, in QTextFormat *fm = cKey.find( cres->key() ); if ( !fm ) { -#ifdef DEBUG_COLLECTION - qDebug( "mix of '%s' and '%s, worst case!", of->key().latin1(), nf->key().latin1() ); -#endif cres->collection = this; cKey.insert( cres->key(), cres ); } else { -#ifdef DEBUG_COLLECTION - qDebug( "mix of '%s' and '%s, good case!", of->key().latin1(), nf->key().latin1() ); -#endif delete cres; cres = fm; @@ -5952,7 +5692,4 @@ QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c ) { if ( cachedFormat && cfont == f && ccol == c ) { -#ifdef DEBUG_COLLECTION - qDebug( "format of font and col '%s' - best case", cachedFormat->key().latin1() ); -#endif cachedFormat->addRef(); return cachedFormat; @@ -5965,7 +5702,4 @@ QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c ) if ( cachedFormat ) { -#ifdef DEBUG_COLLECTION - qDebug( "format of font and col '%s' - good case", cachedFormat->key().latin1() ); -#endif cachedFormat->addRef(); return cachedFormat; @@ -5980,7 +5714,4 @@ QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c ) if ( cachedFormat->key() != key ) qWarning("ASSERT: keys for format not identical: '%s '%s'", cachedFormat->key().latin1(), key.latin1() ); -#ifdef DEBUG_COLLECTION - qDebug( "format of font and col '%s' - worst case", cachedFormat->key().latin1() ); -#endif return cachedFormat; } @@ -5997,87 +5728,46 @@ void QTextFormatCollection::remove( QTextFormat *f ) } -void QTextFormatCollection::debug() -{ -#ifdef DEBUG_COLLECTION - qDebug( "------------ QTextFormatCollection: debug --------------- BEGIN" ); - QDictIterator<QTextFormat> it( cKey ); - for ( ; it.current(); ++it ) { - qDebug( "format '%s' (%p): refcount: %d", it.current()->key().latin1(), - it.current(), it.current()->ref ); - } - qDebug( "------------ QTextFormatCollection: debug --------------- END" ); -#endif -} - -void QTextFormatCollection::updateStyles() -{ - QDictIterator<QTextFormat> it( cKey ); - QTextFormat *f; - while ( ( f = it.current() ) ) { - ++it; - f->updateStyle(); - } - updateKeys(); -} +#define UPDATE( up, lo, rest ) \ + if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \ + fm->fn.set##up##rest( font.lo##rest() ) -void QTextFormatCollection::updateFontSizes( int base, bool usePixels ) -{ - QDictIterator<QTextFormat> it( cKey ); - QTextFormat *f; - while ( ( f = it.current() ) ) { - ++it; - f->stdSize = base; - f->usePixelSizes = usePixels; - if ( usePixels ) - f->fn.setPixelSize( f->stdSize ); - else - f->fn.setPointSize( f->stdSize ); - styleSheet()->scaleFont( f->fn, f->logicalFontSize ); - f->update(); - } - f = defFormat; - f->stdSize = base; - f->usePixelSizes = usePixels; - if ( usePixels ) - f->fn.setPixelSize( f->stdSize ); - else - f->fn.setPointSize( f->stdSize ); - styleSheet()->scaleFont( f->fn, f->logicalFontSize ); - f->update(); - updateKeys(); -} - -void QTextFormatCollection::updateFontAttributes( const QFont &f, const QFont &old ) +void QTextFormatCollection::updateDefaultFormat( const QFont &font, const QColor &color, QStyleSheet *sheet ) { QDictIterator<QTextFormat> it( cKey ); QTextFormat *fm; + bool usePixels = font.pointSize() == -1; + bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() : + font.pointSize() != defFormat->fn.pointSize(); + int base = usePixels ? font.pixelSize() : font.pointSize(); while ( ( fm = it.current() ) ) { ++it; - if ( fm->fn.family() == old.family() && - fm->fn.weight() == old.weight() && - fm->fn.italic() == old.italic() && - fm->fn.underline() == old.underline() ) { - fm->fn.setFamily( f.family() ); - fm->fn.setWeight( f.weight() ); - fm->fn.setItalic( f.italic() ); - fm->fn.setUnderline( f.underline() ); - fm->update(); - } + UPDATE( F, f, amily ); + UPDATE( W, w, eight ); + UPDATE( B, b, old ); + UPDATE( I, i, talic ); + UPDATE( U, u, nderline ); + if ( changeSize ) { + fm->stdSize = base; + fm->usePixelSizes = usePixels; + if ( usePixels ) + fm->fn.setPixelSize( fm->stdSize ); + else + fm->fn.setPointSize( fm->stdSize ); + sheet->scaleFont( fm->fn, fm->logicalFontSize ); } - fm = defFormat; - if ( fm->fn.family() == old.family() && - fm->fn.weight() == old.weight() && - fm->fn.italic() == old.italic() && - fm->fn.underline() == old.underline() ) { - fm->fn.setFamily( f.family() ); - fm->fn.setWeight( f.weight() ); - fm->fn.setItalic( f.italic() ); - fm->fn.setUnderline( f.underline() ); + if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col ) + fm->col = color; fm->update(); } + + defFormat->fn = font; + defFormat->col = color; + defFormat->update(); + defFormat->stdSize = base; + defFormat->usePixelSizes = usePixels; + updateKeys(); } - // the keys in cKey have changed, rebuild the hashtable void QTextFormatCollection::updateKeys() @@ -6097,4 +5787,5 @@ void QTextFormatCollection::updateKeys() cKey.insert( (*f)->key(), *f ); cKey.setAutoDelete( TRUE ); + delete [] formats; } @@ -6143,4 +5834,12 @@ void QTextFormat::setUnderline( bool b ) } +void QTextFormat::setStrikeOut( bool b ) +{ + if ( b == fn.strikeOut() ) + return; + fn.setStrikeOut( b ); + update(); +} + void QTextFormat::setFamily( const QString &f ) { @@ -6176,72 +5875,41 @@ void QTextFormat::setColor( const QColor &c ) } -static int makeLogicFontSize( int s ) -{ - int defSize = QApplication::font().pointSize(); - if ( s < defSize - 4 ) - return 1; - if ( s < defSize ) - return 2; - if ( s < defSize + 4 ) - return 3; - if ( s < defSize + 8 ) - return 4; - if ( s < defSize + 12 ) - return 5; - if (s < defSize + 16 ) - return 6; - return 7; -} - -static QTextFormat *defaultFormat = 0; - -QString QTextFormat::makeFormatChangeTags( QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const +QString QTextFormat::makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f, + const QString& oldAnchorHref, const QString& anchorHref ) const { - if ( !defaultFormat ) // #### wrong, use the document's default format instead - defaultFormat = new QTextFormat( QApplication::font(), - QApplication::palette().color( QPalette::Active, QColorGroup::Text ) ); - QString tag; - if ( f ) { - if ( f->font() != defaultFormat->font() ) { - if ( f->font().family() != defaultFormat->font().family() - || f->font().pointSize() != defaultFormat->font().pointSize() - || f->color().rgb() != defaultFormat->color().rgb() ) - tag += "</font>"; - if ( f->font().underline() && f->font().underline() != defaultFormat->font().underline() ) - tag += "</u>"; - if ( f->font().italic() && f->font().italic() != defaultFormat->font().italic() ) - tag += "</i>"; - if ( f->font().bold() && f->font().bold() != defaultFormat->font().bold() ) - tag += "</b>"; - } - if ( !oldAnchorHref.isEmpty() ) - tag += "</a>"; - } + if ( f ) + tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref ); if ( !anchorHref.isEmpty() ) tag += "<a href=\"" + anchorHref + "\">"; - if ( font() != defaultFormat->font() ) { - if ( font().bold() && font().bold() != defaultFormat->font().bold() ) - tag += "<b>"; - if ( font().italic() && font().italic() != defaultFormat->font().italic() ) - tag += "<i>"; - if ( font().underline() && font().underline() != defaultFormat->font().underline() ) - tag += "<u>"; - } if ( font() != defaultFormat->font() + || vAlign() != defaultFormat->vAlign() || color().rgb() != defaultFormat->color().rgb() ) { - QString f; + QString s; if ( font().family() != defaultFormat->font().family() ) - f +=" face=\"" + fn.family() + "\""; - if ( font().pointSize() != defaultFormat->font().pointSize() ) { - f +=" size=\"" + QString::number( makeLogicFontSize( fn.pointSize() ) ) + "\""; - f +=" style=\"font-size:" + QString::number( fn.pointSize() ) + "pt\""; + s += QString(!!s?";":"") + "font-family:" + fn.family(); + if ( font().italic() && font().italic() != defaultFormat->font().italic() ) + s += QString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal"); + if ( font().pointSize() != defaultFormat->font().pointSize() ) + s += QString(!!s?";":"") + "font-size:" + QString::number( fn.pointSize() ) + "pt"; + if ( font().weight() != defaultFormat->font().weight() ) + s += QString(!!s?";":"") + "font-weight:" + QString::number( fn.weight() * 8 ); + if ( font().underline() != defaultFormat->font().underline() ) + s += QString(!!s?";":"") + "text-decoration:" + ( font().underline() ? "underline" : "none"); + if ( vAlign() != defaultFormat->vAlign() ) { + s += QString(!!s?";":"") + "vertical-align:"; + if ( vAlign() == QTextFormat::AlignSuperScript ) + s += "super"; + else if ( vAlign() == QTextFormat::AlignSubScript ) + s += "sub"; + else + s += "normal"; } if ( color().rgb() != defaultFormat->color().rgb() ) - f +=" color=\"" + col.name() + "\""; - if ( !f.isEmpty() ) - tag += "<font" + f + ">"; + s += QString(!!s?";":"") + "color:" + col.name(); + if ( !s.isEmpty() ) + tag += "<span style=\"" + s + "\">"; } @@ -6249,23 +5917,16 @@ QString QTextFormat::makeFormatChangeTags( QTextFormat *f, const QString& oldAnc } -QString QTextFormat::makeFormatEndTags( const QString& anchorHref ) const +QString QTextFormat::makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const { - if ( !defaultFormat ) - defaultFormat = new QTextFormat( QApplication::font(), - QApplication::palette().color( QPalette::Active, QColorGroup::Text ) ); - QString tag; - if ( font() != defaultFormat->font() ) { if ( font().family() != defaultFormat->font().family() || font().pointSize() != defaultFormat->font().pointSize() + || font().weight() != defaultFormat->font().weight() + || font().italic() != defaultFormat->font().italic() + || font().underline() != defaultFormat->font().underline() + || font().strikeOut() != defaultFormat->font().strikeOut() + || vAlign() != defaultFormat->vAlign() || color().rgb() != defaultFormat->color().rgb() ) - tag += "</font>"; - if ( font().underline() && font().underline() != defaultFormat->font().underline() ) - tag += "</u>"; - if ( font().italic() && font().italic() != defaultFormat->font().italic() ) - tag += "</i>"; - if ( font().bold() && font().bold() != defaultFormat->font().bold() ) - tag += "</b>"; - } + tag += "</span>"; if ( !anchorHref.isEmpty() ) tag += "</a>"; @@ -6273,48 +5934,10 @@ QString QTextFormat::makeFormatEndTags( const QString& anchorHref ) const } -QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr ) const +QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const { QTextFormat format(*this); - if ( style ) { - format.style = style->name(); - if ( style->name() == "font") { - if ( attr.contains("color") ) { - QString s = attr["color"]; - if ( !s.isEmpty() ) { - format.col.setNamedColor( s ); - format.linkColor = FALSE; - } - } - if ( attr.contains("size") ) { - QString a = attr["size"]; - int n = a.toInt(); - if ( a[0] == '+' || a[0] == '-' ) - n += format.logicalFontSize; - format.logicalFontSize = n; - if ( format.usePixelSizes ) - format.fn.setPixelSize( format.stdSize ); - else - format.fn.setPointSize( format.stdSize ); - style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); - } - if ( attr.contains("style" ) ) { - QString a = attr["style"]; - if ( a.startsWith( "font-size:" ) ) { - QString s = a.mid( a.find( ':' ) + 1 ); - int n = s.left( s.length() - 2 ).toInt(); - format.logicalFontSize = 0; - if ( format.usePixelSizes ) - format.fn.setPixelSize( n ); - else - format.fn.setPointSize( n ); - } - } - if ( attr.contains("face") ) { - QString a = attr["face"]; - if ( a.contains(',') ) - a = a.left( a.find(',') ); - format.fn.setFamily( a ); - } - } else { + if (!style ) + return format; + if ( !style->isAnchor() && style->color().isValid() ) { // the style is not an anchor and defines a color. @@ -6362,4 +5985,71 @@ QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMa if ( style->definesFontUnderline() ) format.fn.setUnderline( style->fontUnderline() ); + if ( style->definesFontStrikeOut() ) + format.fn.setStrikeOut( style->fontStrikeOut() ); + + + if ( style->name() == "font") { + if ( attr.contains("color") ) { + QString s = attr["color"]; + if ( !s.isEmpty() ) { + format.col.setNamedColor( s ); + format.linkColor = FALSE; + } + } + if ( attr.contains("face") ) { + QString a = attr["face"]; + QString family = QTextDocument::section( a, ",", 0, 0 ); + if ( !!family ) + format.fn.setFamily( family ); + } + if ( attr.contains("size") ) { + QString a = attr["size"]; + int n = a.toInt(); + if ( a[0] == '+' || a[0] == '-' ) + n += format.logicalFontSize; + format.logicalFontSize = n; + if ( format.usePixelSizes ) + format.fn.setPixelSize( format.stdSize ); + else + format.fn.setPointSize( format.stdSize ); + style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); + } + } + if ( attr.contains("style" ) ) { + QString a = attr["style"]; + for ( int s = 0; s < a.contains(';')+1; s++ ) { + QString style = QTextDocument::section( a, ";", s, s ); + if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) { + format.logicalFontSize = 0; + format.setPointSize( int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toInt() ) ); + } if ( style.startsWith("font-style:" ) ) { + QString s = style.mid( 11 ).stripWhiteSpace(); + if ( s == "normal" ) + format.fn.setItalic( FALSE ); + else if ( s == "italic" || s == "oblique" ) + format.fn.setItalic( TRUE ); + } else if ( style.startsWith("font-weight:" ) ) { + QString s = style.mid( 12 ); + bool ok = TRUE; + int n = s.toInt( &ok ); + if ( ok ) + format.fn.setWeight( n/8 ); + } else if ( style.startsWith("font-family:" ) ) { + format.fn.setFamily( QTextDocument::section(style.mid(12),",",0,0).stripWhiteSpace() ); + } else if ( style.startsWith("text-decoration:" ) ) { + QString s = style.mid( 16 ).stripWhiteSpace(); + format.fn.setUnderline( s == "underline" ); + } else if ( style.startsWith("vertical-align:" ) ) { + QString s = style.mid( 15 ).stripWhiteSpace(); + if ( s == "sub" ) + format.setVAlign( QTextFormat::AlignSubScript ); + else if ( s == "super" ) + format.setVAlign( QTextFormat::AlignSuperScript ); + else + format.setVAlign( QTextFormat::AlignNormal ); + } else if ( style.startsWith("color:" ) ) { + format.col.setNamedColor( style.mid(6) ); + format.linkColor = FALSE; + } } } @@ -6382,8 +6072,4 @@ QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, co : QTextCustomItem( p ) { -#if defined(PARSER_DEBUG) - qDebug( debug_indent + "new QTextImage (pappi: %p)", p ); -#endif - width = height = 0; if ( attr.contains("width") ) @@ -6398,8 +6084,4 @@ QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, co imageName = attr["source"]; -#if defined(PARSER_DEBUG) - qDebug( debug_indent + " .." + imageName ); -#endif - if ( !imageName.isEmpty() ) { imgId = QString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory ); @@ -6488,4 +6170,5 @@ QTextImage::~QTextImage() } } + delete reg; } @@ -6646,5 +6329,5 @@ static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, - const QChar* doc, int length, int& pos, QTextParag *curpar ) + const QChar* doc, int length, int& pos, QTextParagraph *curpar ) { @@ -6666,7 +6349,4 @@ QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, tagname = parseCloseTag( doc, length, pos ); if ( tagname == "table" ) { -#if defined(PARSER_DEBUG) - debug_indent.remove( debug_indent.length() - 3, 2 ); -#endif return table; } @@ -6725,8 +6405,8 @@ QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, } QTextTableCell* cell = new QTextTableCell( table, row, col, - attr2, s, fmt.makeTextFormat( s, attr2 ), + attr2, s, fmt.makeTextFormat( s, attr2, scaleFontsFactor ), contxt, *factory_, sheet_, QString( doc, length).mid( pos, end - pos ) ); - cell->richText()->parParag = curpar; + cell->richText()->parentPar = curpar; if ( cell->colspan() > 1 || cell->rowspan() > 1 ) multicells.append( cell ); @@ -6741,7 +6421,4 @@ QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, } } -#if defined(PARSER_DEBUG) - debug_indent.remove( debug_indent.length() - 3, 2 ); -#endif return table; } @@ -7132,17 +6809,8 @@ QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleShe if ( c.isSpace() && c != QChar::nbsp ) { if ( wsm == QStyleSheetItem::WhiteSpacePre ) { - if ( c == ' ' ) - return QChar::nbsp; - else - return c; - } else if ( wsm == QStyleSheetItem_WhiteSpaceNoCompression ) { - return c; - } else if ( wsm == QStyleSheetItem_WhiteSpaceNormalWithNewlines ) { if ( c == '\n' ) + return QChar_linesep; + else return c; - while ( pos< length && - doc[pos].isSpace() && doc[pos] != QChar::nbsp && doc[pos] != '\n' ) - pos++; - return ' '; } else { // non-pre mode: collapse whitespace except nbsp while ( pos< length && @@ -7356,9 +7024,4 @@ QTextTable::QTextTable( QTextDocument *p, const QMap<QString, QString> & attr ) { cells.setAutoDelete( FALSE ); -#if defined(PARSER_DEBUG) - debug_indent += "\t"; - qDebug( debug_indent + "new QTextTable (%p)", this ); - debug_indent += "\t"; -#endif cellspacing = 2; if ( attr.contains("cellspacing") ) @@ -7444,5 +7107,5 @@ QString QTextTable::richText() const it = cell->attributes.begin(); for ( ; it != cell->attributes.end(); ++it ) - s += it.key() + "=" + *it + " "; + s += " " + it.key() + "=" + *it; s += ">"; s += cell->richText()->richText(); @@ -7577,10 +7240,4 @@ void QTextTable::draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, } -#if defined(DEBUG_TABLE_RENDERING) - p->save(); - p->setPen( Qt::red ); - p->drawRect( x, y, width, height ); - p->restore(); -#endif } @@ -7644,5 +7301,5 @@ void QTextTable::addCell( QTextTableCell* cell ) } -bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, bool atEnd ) +bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd ) { currCell.remove( c ); @@ -7653,5 +7310,5 @@ bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, } -bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, const QPoint &pos ) +bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, const QPoint &pos ) { currCell.remove( c ); @@ -7693,5 +7350,5 @@ bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *¶ return FALSE; doc = cell->richText(); - parag = doc->firstParag(); + parag = doc->firstParagraph(); idx = 0; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -7700,5 +7357,5 @@ bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *¶ } -bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ) { int cc = -1; @@ -7726,5 +7383,5 @@ bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, return FALSE; doc = cell->richText(); - parag = doc->firstParag(); + parag = doc->firstParagraph(); idx = 0; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -7733,5 +7390,5 @@ bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, } -bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ) { int cc = -1; @@ -7759,5 +7416,5 @@ bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, return FALSE; doc = cell->richText(); - parag = doc->firstParag(); + parag = doc->lastParagraph(); idx = parag->length() - 1; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -7766,5 +7423,5 @@ bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, } -bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ) { if ( currCell.find( c ) == currCell.end() ) @@ -7797,5 +7454,5 @@ bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, if ( !cell ) return FALSE; - parag = doc->firstParag(); + parag = doc->firstParagraph(); idx = 0; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -7804,5 +7461,5 @@ bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, } -bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ) { if ( currCell.find( c ) == currCell.end() ) @@ -7835,5 +7492,5 @@ bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, in if ( !cell ) return FALSE; - parag = doc->lastParag(); + parag = doc->lastParagraph(); idx = parag->length() - 1; ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); @@ -7850,8 +7507,4 @@ QTextTableCell::QTextTableCell( QTextTable* table, const QString& doc) { -#if defined(PARSER_DEBUG) - qDebug( debug_indent + "new QTextTableCell1 (pappi: %p)", table ); - qDebug( debug_indent + doc ); -#endif cached_width = -1; cached_sizehint = -1; @@ -7889,5 +7542,6 @@ QTextTableCell::QTextTableCell( QTextTable* table, richtext->setMimeSourceFactory( &factory ); richtext->setStyleSheet( sheet ); - richtext->setDefaultFont( table->parent->formatCollection()->defaultFormat()->font() ); + richtext->setDefaultFormat( table->parent->formatCollection()->defaultFormat()->font(), + table->parent->formatCollection()->defaultFormat()->color() ); richtext->setRichText( doc, context ); rowspan_ = 1; @@ -7925,32 +7579,4 @@ QTextTableCell::QTextTableCell( QTextTable* table, } -QTextTableCell::QTextTableCell( QTextTable* table, int row, int column ) -{ -#if defined(PARSER_DEBUG) - qDebug( debug_indent + "new QTextTableCell2( pappi: %p", table ); -#endif - maxw = QWIDGETSIZE_MAX; - minw = 0; - cached_width = -1; - cached_sizehint = -1; - - parent = table; - row_ = row; - col_ = column; - stretch_ = 0; - richtext = new QTextDocument( table->parent ); - richtext->setTableCell( this ); - richtext->setFormatter( table->parent->formatter() ); - richtext->setUseFormatCollection( table->parent->useFormatCollection() ); - richtext->setDefaultFont( table->parent->formatCollection()->defaultFormat()->font() ); - richtext->setRichText( "<html></html>", QString::null ); - rowspan_ = 1; - colspan_ = 1; - background = 0; - hasFixedWidth = FALSE; - parent->addCell( this ); -} - - QTextTableCell::~QTextTableCell() { @@ -8028,5 +7654,5 @@ int QTextTableCell::heightForWidth( int w ) const void QTextTableCell::adjustToPainter( QPainter* p ) { - QTextParag *parag = richtext->firstParag(); + QTextParagraph *parag = richtext->firstParagraph(); while ( parag ) { parag->adjustToPainter( p ); @@ -8072,14 +7698,147 @@ void QTextTableCell::draw( QPainter* p, int x, int y, int cx, int cy, int cw, in QRegion r; - QTextCursor *c = 0; - if ( richtext->parent()->tmpCursor ) - c = richtext->parent()->tmpCursor; if ( cx >= 0 && cy >= 0 ) richtext->draw( p, cx - ( x + horizontalAlignmentOffset() + geom.x() ), cy - ( y + geom.y() + verticalAlignmentOffset() ), - cw, ch, g, FALSE, (c != 0), c ); + cw, ch, g, FALSE, FALSE, 0 ); else - richtext->draw( p, -1, -1, -1, -1, g, FALSE, (c != 0), c ); + richtext->draw( p, -1, -1, -1, -1, g, FALSE, FALSE, 0 ); p->restore(); } + +QString QTextDocument::section( QString str, const QString &sep, int start, int end ) +{ + const QChar *uc = str.unicode(); + if ( !uc ) + return QString(); + QString _sep = sep; + const QChar *uc_sep = _sep.unicode(); + if(!uc_sep) + return QString(); + bool match = FALSE, last_match = TRUE; + + //find start + int n = str.length(), sep_len = _sep.length(); + const QChar *begin = start < 0 ? uc + n : uc; + while(start) { + match = FALSE; + int c = 0; + for(const QChar *tmp = start < 0 ? begin - sep_len : begin; + c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { + if( *tmp != *(uc_sep + c) ) + break; + if(c == sep_len - 1) { + match = TRUE; + break; + } + } + last_match = match; + + if(start < 0) { + if(match) { + begin -= sep_len; + if(!++start) + break; + } else { + if(start == -1 && begin == uc) + break; + begin--; + } + } else { + if(match) { + if(!--start) + break; + begin += sep_len; + } else { + if(start == 1 && begin == uc + n) + break; + begin++; + } + } + if(begin > uc + n || begin < uc) + return QString(); + } + if(match) + begin+=sep_len; + if(begin > uc + n || begin < uc) + return QString(); + + //now find last + match = FALSE; + const QChar *last = end < 0 ? uc + n : uc; + if(end == -1) { + int c = 0; + for(const QChar *tmp = end < 0 ? last - sep_len : last; + c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { + if( *tmp != *(uc_sep + c) ) + break; + if(c == sep_len - 1) { + match = TRUE; + break; + } + } + } else { + end++; + last_match = TRUE; + while(end) { + match = FALSE; + int c = 0; + for(const QChar *tmp = end < 0 ? last - sep_len : last; + c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) { + if( *tmp != *(uc_sep + c) ) + break; + if(c == sep_len - 1) { + match = TRUE; + break; + } + } + last_match = match; + + if(end < 0) { + if(match) { + if(!++end) + break; + last -= sep_len; + } else { + last--; + } + } else { + if(match) { + last += sep_len; + if(!--end) + break; + } else { + last++; + } + } + if(last >= uc + n) { + last = uc + n; + break; + } else if(last < uc) { + return QString(); + } + } + } + if(match) + last -= sep_len; + if(last < uc || last > uc + n || begin >= last) + return QString(); + + //done + return QString(begin, last - begin); +} + +bool QTextDocument::endsWith( QString str, const QString &s) +{ + if ( str.isNull() ) + return s.isNull(); + int pos = str.length() - s.length(); + if ( pos < 0 ) + return FALSE; + for ( uint i = 0; i < s.length(); i++ ) { + if ( str.unicode()[pos+i] != s[(int)i] ) + return FALSE; + } + return TRUE; +} diff --git a/noncore/apps/opie-write/qrichtext_p.cpp b/noncore/apps/opie-write/qrichtext_p.cpp index fb20730..6783e0b 100644 --- a/noncore/apps/opie-write/qrichtext_p.cpp +++ b/noncore/apps/opie-write/qrichtext_p.cpp @@ -57,28 +57,27 @@ int QTextCustomItem::minimumWidth() const { return 0; } QString QTextCustomItem::richText() const { return QString::null; } -bool QTextCustomItem::enter( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, bool atEnd ) +bool QTextCustomItem::enter( QTextCursor *, QTextDocument*&, QTextParagraph *&, int &, int &, int &, bool ) { - doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; Q_UNUSED( atEnd ) return TRUE; - + return TRUE; } -bool QTextCustomItem::enterAt( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, const QPoint & ) +bool QTextCustomItem::enterAt( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int &, const QPoint & ) { - doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; + return TRUE; } -bool QTextCustomItem::next( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextCustomItem::next( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & ) { - doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; + return TRUE; } -bool QTextCustomItem::prev( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextCustomItem::prev( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & ) { - doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; + return TRUE; } -bool QTextCustomItem::down( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextCustomItem::down( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & ) { - doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; + return TRUE; } -bool QTextCustomItem::up( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ) +bool QTextCustomItem::up( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & ) { - doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; + return TRUE; } @@ -90,6 +89,6 @@ void QTextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; } void QTextTable::invalidate() { cachewidth = -1; } -QTextParagData::~QTextParagData() {} -void QTextParagData::join( QTextParagData * ) {} +QTextParagraphData::~QTextParagraphData() {} +void QTextParagraphData::join( QTextParagraphData * ) {} QTextFormatter::~QTextFormatter() {} @@ -101,13 +100,14 @@ void QTextFormatter::setWrapAtColumn( int c ) { wrapColumn = c; } int QTextCursor::x() const { - QTextStringChar *c = string->at( idx ); + QTextStringChar *c = para->at( idx ); int curx = c->x; if ( !c->rightToLeft && c->c.isSpace() && idx > 0 && - ( string->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) - curx = string->at( idx - 1 )->x + string->string()->width( idx - 1 ); + !c->lineStart && + ( para->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) + curx = para->at( idx - 1 )->x + para->string()->width( idx - 1 ); if ( c->rightToLeft ) - curx += string->string()->width( idx ); + curx += para->string()->width( idx ); return curx; } @@ -116,6 +116,33 @@ int QTextCursor::y() const { int dummy, line; - string->lineStartOfChar( idx, &dummy, &line ); - return string->lineY( line ); + para->lineStartOfChar( idx, &dummy, &line ); + return para->lineY( line ); +} + +int QTextCursor::globalX() const { return totalOffsetX() + para->rect().x() + x(); } +int QTextCursor::globalY() const { return totalOffsetY() + para->rect().y() + y(); } + +QTextDocument *QTextCursor::document() const +{ + return para ? para->document() : 0; +} + +void QTextCursor::gotoPosition( QTextParagraph* p, int index ) +{ + if ( para && p != para ) { + while ( para->document() != p->document() && !indices.isEmpty() ) + pop(); + Q_ASSERT( indices.isEmpty() || para->document() == p->document() ); + } + para = p; + if ( index < 0 || index >= para->length() ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QTextCursor::gotoParagraph Index: %d out of range", index ); +#endif + index = index < 0 ? 0 : para->length() - 1; + } + + tmpIndex = -1; + idx = index; } @@ -128,16 +155,16 @@ bool QTextDocument::hasSelection( int id, bool visible ) const } -void QTextDocument::setSelectionStart( int id, QTextCursor *cursor ) +void QTextDocument::setSelectionStart( int id, const QTextCursor &cursor ) { QTextDocumentSelection sel; - sel.startCursor = *cursor; - sel.endCursor = *cursor; + sel.startCursor = cursor; + sel.endCursor = cursor; sel.swapped = FALSE; selections[ id ] = sel; } -QTextParag *QTextDocument::paragAt( int i ) const +QTextParagraph *QTextDocument::paragAt( int i ) const { - QTextParag* p = curParag; + QTextParagraph* p = curParag; if ( !p || p->paragId() > i ) p = fParag; @@ -154,6 +181,5 @@ QTextFormat::~QTextFormat() QTextFormat::QTextFormat() - : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() ), - different( NoFlags ) + : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() ) { ref = 0; @@ -171,6 +197,5 @@ QTextFormat::QTextFormat() QTextFormat::QTextFormat( const QStyleSheetItem *style ) - : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() ), - different( NoFlags ) + : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() ) { ref = 0; @@ -182,5 +207,4 @@ QTextFormat::QTextFormat( const QStyleSheetItem *style ) } - this->style = style->name(); missp = FALSE; ha = AlignNormal; @@ -191,4 +215,5 @@ QTextFormat::QTextFormat( const QStyleSheetItem *style ) style->fontItalic() ); fn.setUnderline( style->fontUnderline() ); + fn.setStrikeOut( style->fontStrikeOut() ); col = style->color(); fm = QFontMetrics( fn ); @@ -203,10 +228,9 @@ QTextFormat::QTextFormat( const QStyleSheetItem *style ) generateKey(); addRef(); - updateStyleFlags(); } QTextFormat::QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent ) : fn( f ), col( c ), fm( QFontMetrics( f ) ), linkColor( TRUE ), - logicalFontSize( 3 ), stdSize( f.pointSize() ), different( NoFlags ) + logicalFontSize( 3 ), stdSize( f.pointSize() ) { ref = 0; @@ -227,5 +251,4 @@ QTextFormat::QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection generateKey(); addRef(); - updateStyleFlags(); } @@ -250,6 +273,4 @@ QTextFormat::QTextFormat( const QTextFormat &f ) k = f.k; linkColor = f.linkColor; - style = f.style; - different = f.different; addRef(); } @@ -275,6 +296,4 @@ QTextFormat& QTextFormat::operator=( const QTextFormat &f ) k = f.k; linkColor = f.linkColor; - style = f.style; - different = f.different; addRef(); return *this; @@ -291,5 +310,4 @@ void QTextFormat::update() memset( widths, 0, 256 ); generateKey(); - updateStyleFlags(); } @@ -373,50 +391,4 @@ QString QTextFormat::getKey( const QFont &fn, const QColor &col, bool misspelled } -void QTextFormat::updateStyle() -{ - if ( !collection || !collection->styleSheet() ) - return; - QStyleSheetItem *item = collection->styleSheet()->item( style ); - if ( !item ) - return; - if ( !( different & Color ) && item->color().isValid() ) - col = item->color(); - if ( !( different & Size ) && item->fontSize() != -1 ) - fn.setPointSize( item->fontSize() ); - if ( !( different & Family ) && !item->fontFamily().isEmpty() ) - fn.setFamily( item->fontFamily() ); - if ( !( different & Bold ) && item->fontWeight() != -1 ) - fn.setWeight( item->fontWeight() ); - if ( !( different & Italic ) && item->definesFontItalic() ) - fn.setItalic( item->fontItalic() ); - if ( !( different & Underline ) && item->definesFontUnderline() ) - fn.setUnderline( item->fontUnderline() ); - generateKey(); - update(); - -} - -void QTextFormat::updateStyleFlags() -{ - different = NoFlags; - if ( !collection || !collection->styleSheet() ) - return; - QStyleSheetItem *item = collection->styleSheet()->item( style ); - if ( !item ) - return; - if ( item->color() != col ) - different |= Color; - if ( item->fontSize() != fn.pointSize() ) - different |= Size; - if ( item->fontFamily() != fn.family() ) - different |= Family; - if ( item->fontItalic() != fn.italic() ) - different |= Italic; - if ( item->fontUnderline() != fn.underline() ) - different |= Underline; - if ( item->fontWeight() != fn.weight() ) - different |= Bold; -} - QString QTextString::toString( const QMemArray<QTextStringChar> &data ) { @@ -444,7 +416,7 @@ QString QTextString::toString() const } -void QTextParag::setSelection( int id, int start, int end ) +void QTextParagraph::setSelection( int id, int start, int end ) { - QMap<int, QTextParagSelection>::ConstIterator it = selections().find( id ); + QMap<int, QTextParagraphSelection>::ConstIterator it = selections().find( id ); if ( it != mSelections->end() ) { if ( start == ( *it ).start && end == ( *it ).end ) @@ -452,5 +424,5 @@ void QTextParag::setSelection( int id, int start, int end ) } - QTextParagSelection sel; + QTextParagraphSelection sel; sel.start = start; sel.end = end; @@ -459,5 +431,5 @@ void QTextParag::setSelection( int id, int start, int end ) } -void QTextParag::removeSelection( int id ) +void QTextParagraph::removeSelection( int id ) { if ( !hasSelection( id ) ) @@ -468,9 +440,9 @@ void QTextParag::removeSelection( int id ) } -int QTextParag::selectionStart( int id ) const +int QTextParagraph::selectionStart( int id ) const { if ( !mSelections ) return -1; - QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id ); + QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id ); if ( it == mSelections->end() ) return -1; @@ -478,9 +450,9 @@ int QTextParag::selectionStart( int id ) const } -int QTextParag::selectionEnd( int id ) const +int QTextParagraph::selectionEnd( int id ) const { if ( !mSelections ) return -1; - QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id ); + QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id ); if ( it == mSelections->end() ) return -1; @@ -488,19 +460,14 @@ int QTextParag::selectionEnd( int id ) const } -bool QTextParag::hasSelection( int id ) const +bool QTextParagraph::hasSelection( int id ) const { - if ( !mSelections ) - return FALSE; - QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id ); - if ( it == mSelections->end() ) - return FALSE; - return ( *it ).start != ( *it ).end || length() == 1; + return mSelections ? mSelections->contains( id ) : FALSE; } -bool QTextParag::fullSelected( int id ) const +bool QTextParagraph::fullSelected( int id ) const { if ( !mSelections ) return FALSE; - QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id ); + QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id ); if ( it == mSelections->end() ) return FALSE; @@ -508,15 +475,15 @@ bool QTextParag::fullSelected( int id ) const } -int QTextParag::lineY( int l ) const +int QTextParagraph::lineY( int l ) const { if ( l > (int)lineStarts.count() - 1 ) { - qWarning( "QTextParag::lineY: line %d out of range!", l ); + qWarning( "QTextParagraph::lineY: line %d out of range!", l ); return 0; } if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); while ( l-- > 0 ) ++it; @@ -524,15 +491,15 @@ int QTextParag::lineY( int l ) const } -int QTextParag::lineBaseLine( int l ) const +int QTextParagraph::lineBaseLine( int l ) const { if ( l > (int)lineStarts.count() - 1 ) { - qWarning( "QTextParag::lineBaseLine: line %d out of range!", l ); + qWarning( "QTextParagraph::lineBaseLine: line %d out of range!", l ); return 10; } if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); while ( l-- > 0 ) ++it; @@ -540,15 +507,15 @@ int QTextParag::lineBaseLine( int l ) const } -int QTextParag::lineHeight( int l ) const +int QTextParagraph::lineHeight( int l ) const { if ( l > (int)lineStarts.count() - 1 ) { - qWarning( "QTextParag::lineHeight: line %d out of range!", l ); + qWarning( "QTextParagraph::lineHeight: line %d out of range!", l ); return 15; } if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); while ( l-- > 0 ) ++it; @@ -556,8 +523,8 @@ int QTextParag::lineHeight( int l ) const } -void QTextParag::lineInfo( int l, int &y, int &h, int &bl ) const +void QTextParagraph::lineInfo( int l, int &y, int &h, int &bl ) const { if ( l > (int)lineStarts.count() - 1 ) { - qWarning( "QTextParag::lineInfo: line %d out of range!", l ); + qWarning( "QTextParagraph::lineInfo: line %d out of range!", l ); qDebug( "%d %d", (int)lineStarts.count() - 1, l ); y = 0; @@ -568,7 +535,7 @@ void QTextParag::lineInfo( int l, int &y, int &h, int &bl ) const if ( !isValid() ) - ( (QTextParag*)this )->format(); + ( (QTextParagraph*)this )->format(); - QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); + QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); while ( l-- > 0 ) ++it; @@ -578,78 +545,14 @@ void QTextParag::lineInfo( int l, int &y, int &h, int &bl ) const } -int QTextParag::alignment() const -{ - if ( align != -1 ) - return align; - QStyleSheetItem *item = style(); - if ( !item ) - return Qt3::AlignAuto; - if ( mStyleSheetItemsVec ) { - for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) { - item = (*mStyleSheetItemsVec)[ i ]; - if ( item->alignment() != QStyleSheetItem::Undefined ) - return item->alignment(); - } - } - return Qt3::AlignAuto; -} - -QPtrVector<QStyleSheetItem> QTextParag::styleSheetItems() const -{ - QPtrVector<QStyleSheetItem> vec; - if ( mStyleSheetItemsVec ) { - vec.resize( mStyleSheetItemsVec->size() ); - for ( int i = 0; i < (int)vec.size(); ++i ) - vec.insert( i, (*mStyleSheetItemsVec)[ i ] ); - } - return vec; -} -QStyleSheetItem *QTextParag::style() const +void QTextParagraph::setAlignment( int a ) { - if ( !mStyleSheetItemsVec || mStyleSheetItemsVec->size() == 0 ) - return 0; - return (*mStyleSheetItemsVec)[ mStyleSheetItemsVec->size() - 1 ]; -} - -int QTextParag::numberOfSubParagraph() const -{ - if ( list_val != -1 ) - return list_val; - if ( numSubParag != -1 ) - return numSubParag; - int n = 0; - QTextParag *p = (QTextParag*)this; - while ( p && ( styleSheetItemsVec().size() >= p->styleSheetItemsVec().size() && - styleSheetItemsVec()[ (int)p->styleSheetItemsVec().size() - 1 ] == p->style() || - p->styleSheetItemsVec().size() >= styleSheetItemsVec().size() && - p->styleSheetItemsVec()[ (int)styleSheetItemsVec().size() - 1 ] == style() ) ) { - if ( p->style() == style() && listStyle() != p->listStyle() - && p->styleSheetItemsVec().size() == styleSheetItemsVec().size() ) - break; - if ( p->style()->displayMode() == QStyleSheetItem::DisplayListItem - && p->style() != style() || styleSheetItemsVec().size() == p->styleSheetItemsVec().size() ) - ++n; - p = p->prev(); - } - ( (QTextParag*)this )->numSubParag = n; - return n; -} - -void QTextParag::setFormat( QTextFormat *fm ) -{ - bool doUpdate = FALSE; - if (defFormat && (defFormat != formatCollection()->defaultFormat())) - doUpdate = TRUE; - defFormat = formatCollection()->format( fm ); - if ( !doUpdate ) + if ( a == (int)align ) return; - for ( int i = 0; i < length(); ++i ) { - if ( at( i )->format()->styleName() == defFormat->styleName() ) - at( i )->format()->updateStyle(); - } + align = a; + invalidate( 0 ); } -QTextFormatter *QTextParag::formatter() const +QTextFormatter *QTextParagraph::formatter() const { if ( hasdoc ) @@ -657,8 +560,8 @@ QTextFormatter *QTextParag::formatter() const if ( pseudoDocument()->pFormatter ) return pseudoDocument()->pFormatter; - return ( ( (QTextParag*)this )->pseudoDocument()->pFormatter = new QTextFormatterBreakWords ); + return ( ( (QTextParagraph*)this )->pseudoDocument()->pFormatter = new QTextFormatterBreakWords ); } -void QTextParag::setTabArray( int *a ) +void QTextParagraph::setTabArray( int *a ) { delete [] tArray; @@ -666,5 +569,5 @@ void QTextParag::setTabArray( int *a ) } -void QTextParag::setTabStops( int tw ) +void QTextParagraph::setTabStops( int tw ) { if ( hasdoc ) @@ -674,22 +577,16 @@ void QTextParag::setTabStops( int tw ) } -QMap<int, QTextParagSelection> &QTextParag::selections() const +QMap<int, QTextParagraphSelection> &QTextParagraph::selections() const { if ( !mSelections ) - ((QTextParag *)this)->mSelections = new QMap<int, QTextParagSelection>; + ((QTextParagraph *)this)->mSelections = new QMap<int, QTextParagraphSelection>; return *mSelections; } -QPtrVector<QStyleSheetItem> &QTextParag::styleSheetItemsVec() const -{ - if ( !mStyleSheetItemsVec ) - ((QTextParag *)this)->mStyleSheetItemsVec = new QPtrVector<QStyleSheetItem>; - return *mStyleSheetItemsVec; -} -QPtrList<QTextCustomItem> &QTextParag::floatingItems() const +QPtrList<QTextCustomItem> &QTextParagraph::floatingItems() const { if ( !mFloatingItems ) - ((QTextParag *)this)->mFloatingItems = new QPtrList<QTextCustomItem>; + ((QTextParagraph *)this)->mFloatingItems = new QPtrList<QTextCustomItem>; return *mFloatingItems; } @@ -703,4 +600,4 @@ QTextStringChar::~QTextStringChar() } -QTextParagPseudoDocument::QTextParagPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0){} -QTextParagPseudoDocument::~QTextParagPseudoDocument(){ delete pFormatter; delete commandHistory; } +QTextParagraphPseudoDocument::QTextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0){} +QTextParagraphPseudoDocument::~QTextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; } diff --git a/noncore/apps/opie-write/qrichtext_p.h b/noncore/apps/opie-write/qrichtext_p.h index 94ce913..e368edb 100644 --- a/noncore/apps/opie-write/qrichtext_p.h +++ b/noncore/apps/opie-write/qrichtext_p.h @@ -52,5 +52,4 @@ #ifndef QT_H -#include "qt3namespace.h" #include "qstring.h" #include "qlist.h" @@ -79,6 +78,4 @@ #endif // QT_H -//#define DEBUG_COLLECTION - namespace Qt3 { @@ -88,5 +85,5 @@ class QTextPreProcessor; class QTextFormat; class QTextCursor; -class QTextParag; +class QTextParagraph; class QTextFormatter; class QTextIndent; @@ -126,5 +123,4 @@ public: void setFormat( QTextFormat *f ); void setCustomItem( QTextCustomItem *i ); - QTextStringChar *clone() const; struct CustomData { @@ -153,10 +149,10 @@ private: } friend class QComplexText; - friend class QTextParag; + friend class QTextParagraph; }; #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QMemArray<QTextStringChar>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<QTextStringChar>; // MOC_SKIP_END #endif @@ -179,5 +175,6 @@ public: void insert( int index, const QString &s, QTextFormat *f ); - void insert( int index, QTextStringChar *c ); + void insert( int index, const QChar *unicode, int len, QTextFormat *f ); + void insert( int index, QTextStringChar *c, bool doAddRefFormat = FALSE ); void truncate( int index ); void remove( int index, int len ); @@ -196,5 +193,5 @@ public: void operator=( const QString &s ) { clear(); insert( 0, s, 0 ); } - void operator+=( const QString &s ); + void operator+=( const QString &s ) {insert( length(), s, 0 ); } void prepend( const QString &s ) { insert( 0, s, 0 ); } @@ -232,7 +229,7 @@ inline QChar::Direction QTextString::direction() const #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QValueStack<int>; -template class Q_EXPORT QValueStack<QTextParag*>; -template class Q_EXPORT QValueStack<bool>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<int>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<QTextParagraph*>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<bool>; // MOC_SKIP_END #endif @@ -241,6 +238,5 @@ class Q_EXPORT QTextCursor { public: - QTextCursor( QTextDocument *d ); - QTextCursor(); + QTextCursor( QTextDocument *d = 0 ); QTextCursor( const QTextCursor &c ); QTextCursor &operator=( const QTextCursor &c ); @@ -250,11 +246,11 @@ public: bool operator!=( const QTextCursor &c ) const { return !(*this == c); } - QTextDocument *document() const { return doc; } - void setDocument( QTextDocument *d ); - - QTextParag *parag() const; + QTextParagraph *paragraph() const; + void setParagraph( QTextParagraph*p ) { gotoPosition(p, 0 ); } + QTextDocument *document() const; int index() const; - void setParag( QTextParag *s, bool restore = TRUE ); + void setIndex( int index ) { gotoPosition(paragraph(), index ); } + void gotoPosition( QTextParagraph* p, int index = 0); void gotoLeft(); void gotoRight(); @@ -275,7 +271,6 @@ public: void insert( const QString &s, bool checkNewLine, QMemArray<QTextStringChar> *formatting = 0 ); - void splitAndInsertEmptyParag( bool ind = TRUE, bool updateIds = TRUE ); + void splitAndInsertEmptyParagraph( bool ind = TRUE, bool updateIds = TRUE ); bool remove(); - void killLine(); void indent(); @@ -283,21 +278,20 @@ public: bool atParagEnd(); - void setIndex( int i, bool restore = TRUE ); - - void checkIndex(); + int x() const; // x in current paragraph + int y() const; // y in current paragraph - int offsetX() const { return ox; } - int offsetY() const { return oy; } + int globalX() const; + int globalY() const; - QTextParag *topParag() const { return parags.isEmpty() ? string : parags.first(); } - int totalOffsetX() const; - int totalOffsetY() const; + QTextParagraph *topParagraph() const { return paras.isEmpty() ? para : paras.first(); } + int offsetX() const { return ox; } // inner document offset + int offsetY() const { return oy; } // inner document offset + int totalOffsetX() const; // total document offset + int totalOffsetY() const; // total document offset - bool place( const QPoint &pos, QTextParag *s ) { return place( pos, s, FALSE ); } - bool place( const QPoint &pos, QTextParag *s, bool link ); + bool place( const QPoint &pos, QTextParagraph *s ) { return place( pos, s, FALSE ); } + bool place( const QPoint &pos, QTextParagraph *s, bool link ); void restoreState(); - int x() const; - int y() const; int nestedDepth() const { return (int)indices.count(); } //### size_t/int cast @@ -315,14 +309,11 @@ private: void gotoIntoNested( const QPoint &globalPos ); - QTextParag *string; - QTextDocument *doc; + QTextParagraph *para; int idx, tmpIndex; int ox, oy; QValueStack<int> indices; - QValueStack<QTextParag*> parags; + QValueStack<QTextParagraph*> paras; QValueStack<int> xOffsets; QValueStack<int> yOffsets; - QValueStack<bool> nestedStack; - uint nested : 1; uint valid : 1; @@ -334,5 +325,5 @@ class Q_EXPORT QTextCommand { public: - enum Commands { Invalid, Insert, Delete, Format, Alignment, ParagType }; + enum Commands { Invalid, Insert, Delete, Format, Style }; QTextCommand( QTextDocument *d ) : doc( d ), cursor( d ) {} @@ -352,5 +343,5 @@ protected: #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QPtrList<QTextCommand>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCommand>; // MOC_SKIP_END #endif @@ -422,16 +413,16 @@ public: QRect geometry() const { return QRect( xpos, ypos, width, height ); } - virtual bool enter( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); - virtual bool enterAt( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, const QPoint & ); - virtual bool next( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); - virtual bool prev( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); - virtual bool down( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); - virtual bool up( QTextCursor *, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); + virtual bool enter( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); + virtual bool enterAt( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, const QPoint & ); + virtual bool next( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool prev( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool down( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool up( QTextCursor *, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); - void setParagraph( QTextParag *p ) { parag = p; } - QTextParag *paragrapth() const { return parag; } + void setParagraph( QTextParagraph *p ) { parag = p; } + QTextParagraph *paragraph() const { return parag; } QTextDocument *parent; - QTextParag *parag; + QTextParagraph *parag; virtual void pageBreak( int y, QTextFlow* flow ); @@ -440,5 +431,5 @@ public: #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QMap<QString, QString>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QString, QString>; // MOC_SKIP_END #endif @@ -490,5 +481,5 @@ private: #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QPtrList<QTextCustomItem>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCustomItem>; // MOC_SKIP_END #endif @@ -547,5 +538,4 @@ public: const QTextFormat& fmt, const QString& context, QMimeSourceFactory &factory, QStyleSheet *sheet, const QString& doc ); - QTextTableCell( QTextTable* table, int row, int column ); virtual ~QTextTableCell(); @@ -601,6 +591,6 @@ private: #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QPtrList<QTextTableCell>; -template class Q_EXPORT QMap<QTextCursor*, int>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextTableCell>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QTextCursor*, int>; // MOC_SKIP_END #endif @@ -626,10 +616,10 @@ public: virtual void invalidate(); - virtual bool enter( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); - virtual bool enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy, const QPoint &pos ); - virtual bool next( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); - virtual bool prev( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); - virtual bool down( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); - virtual bool up( QTextCursor *c, QTextDocument *&doc, QTextParag *¶g, int &idx, int &ox, int &oy ); + virtual bool enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, bool atEnd = FALSE ); + virtual bool enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy, const QPoint &pos ); + virtual bool next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); + virtual bool up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *¶g, int &idx, int &ox, int &oy ); QString richText() const; @@ -667,5 +657,5 @@ private: class QTextTableCell; -class QTextParag; +class QTextParagraph; struct Q_EXPORT QTextDocumentSelection @@ -677,8 +667,8 @@ struct Q_EXPORT QTextDocumentSelection #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QMap<int, QColor>; -template class Q_EXPORT QMap<int, bool>; -template class Q_EXPORT QMap<int, QTextDocumentSelection>; -template class Q_EXPORT QPtrList<QTextDocument>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QColor>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, bool>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextDocumentSelection>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextDocument>; // MOC_SKIP_END #endif @@ -691,5 +681,5 @@ class Q_EXPORT QTextDocument : public QObject friend class QTextCursor; friend class QTextEdit; - friend class QTextParag; + friend class QTextParagraph; public: @@ -705,5 +695,5 @@ public: QTextDocument *parent() const { return par; } - QTextParag *parentParag() const { return parParag; } + QTextParagraph *parentParagraph() const { return parentPar; } void setText( const QString &text, const QString &context ); @@ -723,5 +713,5 @@ public: void setWidth( int w ); int minimumWidth() const; - bool setMinimumWidth( int needed, int used = -1, QTextParag *parag = 0 ); + bool setMinimumWidth( int needed, int used = -1, QTextParagraph *parag = 0 ); void setY( int y ); @@ -731,8 +721,8 @@ public: void setRightMargin( int rm ); - QTextParag *firstParag() const; - QTextParag *lastParag() const; - void setFirstParag( QTextParag *p ); - void setLastParag( QTextParag *p ); + QTextParagraph *firstParagraph() const; + QTextParagraph *lastParagraph() const; + void setFirstParagraph( QTextParagraph *p ); + void setLastParagraph( QTextParagraph *p ); void invalidate(); @@ -752,6 +742,6 @@ public: void setInvertSelectionText( int id, bool b ); bool hasSelection( int id, bool visible = FALSE ) const; - void setSelectionStart( int id, QTextCursor *cursor ); - bool setSelectionEnd( int id, QTextCursor *cursor ); + void setSelectionStart( int id, const QTextCursor &cursor ); + bool setSelectionEnd( int id, const QTextCursor &cursor ); void selectAll( int id ); bool removeSelection( int id ); @@ -761,15 +751,12 @@ public: void selectionEnd( int id, int ¶gId, int &index ); void setFormat( int id, QTextFormat *f, int flags ); - QTextParag *selectionStart( int id ); - QTextParag *selectionEnd( int id ); int numSelections() const { return nSelections; } void addSelection( int id ); - QString selectedText( int id, bool withCustom = TRUE ) const; - void copySelectedText( int id ); + QString selectedText( int id, bool asRichText = FALSE ) const; void removeSelectedText( int id, QTextCursor *cursor ); void indentSelection( int id ); - QTextParag *paragAt( int i ) const; + QTextParagraph *paragAt( int i ) const; void addCommand( QTextCommand *cmd ); @@ -780,5 +767,5 @@ public: QTextFormatCollection *formatCollection() const; - bool find( const QString &expr, bool cs, bool wo, bool forward, int *parag, int *index, QTextCursor *cursor ); + bool find( QTextCursor &cursor, const QString &expr, bool cs, bool wo, bool forward); void setTextFormat( Qt::TextFormat f ); @@ -792,11 +779,9 @@ public: void setStyleSheet( QStyleSheet *s ); - void updateStyles(); - void updateFontSizes( int base, bool usePixels ); - void updateFontAttributes( const QFont &f, const QFont &old ); + void setDefaultFormat( const QFont &font, const QColor &color ); void setMimeSourceFactory( QMimeSourceFactory *f ) { if ( f ) factory_ = f; } void setContext( const QString &c ) { if ( !c.isEmpty() ) contxt = c; } - void setUnderlineLinks( bool b ) { underlLinks = b; } + void setUnderlineLinks( bool b ); bool underlineLinks() const { return underlLinks; } @@ -806,15 +791,13 @@ public: void doLayout( QPainter *p, int w ); void draw( QPainter *p, const QRect& rect, const QColorGroup &cg, const QBrush *paper = 0 ); - void drawParag( QPainter *p, QTextParag *parag, int cx, int cy, int cw, int ch, + void drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch, QPixmap *&doubleBuffer, const QColorGroup &cg, bool drawCursor, QTextCursor *cursor, bool resetChanged = TRUE ); - QTextParag *draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, + QTextParagraph *draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, bool onlyChanged = FALSE, bool drawCursor = FALSE, QTextCursor *cursor = 0, bool resetChanged = TRUE ); - void setDefaultFont( const QFont &f ); - - void registerCustomItem( QTextCustomItem *i, QTextParag *p ); - void unregisterCustomItem( QTextCustomItem *i, QTextParag *p ); + void registerCustomItem( QTextCustomItem *i, QTextParagraph *p ); + void unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p ); void setFlow( QTextFlow *f ); @@ -832,6 +815,6 @@ public: void setPlainText( const QString &text ); void setRichText( const QString &text, const QString &context ); - QString richText( QTextParag *p = 0 ) const; - QString plainText( QTextParag *p = 0 ) const; + QString richText() const; + QString plainText() const; bool focusNextPrevChild( bool next ); @@ -851,5 +834,5 @@ public: void clear( bool createEmptyParag = FALSE ); - virtual QTextParag *createParag( QTextDocument *d, QTextParag *pr = 0, QTextParag *nx = 0, bool updateIds = TRUE ); + virtual QTextParagraph *createParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE ); void insertChild( QObject *o ) { QObject::insertChild( o ); } void removeChild( QObject *o ) { QObject::removeChild( o ); } @@ -858,7 +841,4 @@ public: QPtrList<QTextDocument> children() const { return childList; } - void setAddMargins( bool b ) { addMargs = b; } - int addMargins() const { return addMargs; } - bool hasFocusParagraph() const; QString focusHref() const; @@ -866,4 +846,7 @@ public: void invalidateOriginalText() { oTextValid = FALSE; oText = ""; } + static QString section( QString str, const QString &sep, int start, int end = 0xffffffff ); + static bool endsWith( QString str, const QString &s); + signals: void minimumWidthChanged( int ); @@ -876,5 +859,5 @@ private: bool hasPrefix(const QChar* doc, int length, int pos, const QString& s); QTextCustomItem* parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, - const QChar* doc, int length, int& pos, QTextParag *curpar ); + const QChar* doc, int length, int& pos, QTextParagraph *curpar ); bool eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp = FALSE ); bool eat(const QChar* doc, int length, int& pos, QChar c); @@ -884,9 +867,10 @@ private: QString parseWord(const QChar* doc, int length, int& pos, bool lower = TRUE); QChar parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm ); - void setRichTextInternal( const QString &text ); + void setRichTextInternal( const QString &text, QTextCursor* cursor = 0 ); + void setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar ); private: struct Q_EXPORT Focus { - QTextParag *parag; + QTextParagraph *parag; int start, len; QString href; @@ -894,5 +878,5 @@ private: int cx, cy, cw, vw; - QTextParag *fParag, *lParag; + QTextParagraph *fParag, *lParag; QTextPreProcessor *pProcessor; QMap<int, QColor> selectionColors; @@ -910,5 +894,4 @@ private: uint underlLinks : 1; uint nextDoubleBuffered : 1; - uint addMargs : 1; uint oTextValid : 1; uint mightHaveCustomItems : 1; @@ -917,7 +900,6 @@ private: QTextFlow *flow_; QTextDocument *par; - QTextParag *parParag; + QTextParagraph *parentPar; QTextTableCell *tc; - QTextCursor *tmpCursor; QBrush *backBrush; QPixmap *buf_pixmap; @@ -927,5 +909,5 @@ private: int leftmargin; int rightmargin; - QTextParag *minwParag, *curParag; + QTextParagraph *minwParag, *curParag; QStyleSheet* sheet_; QMimeSourceFactory* factory_; @@ -938,5 +920,7 @@ private: QPtrList<QTextDocument> childList; QColor linkColor; + double scaleFontsFactor; + short list_tm,list_bm, list_lm, li_tm, li_bm, par_tm, par_bm; }; @@ -948,8 +932,6 @@ class Q_EXPORT QTextDeleteCommand : public QTextCommand public: QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, - const QValueList< QPtrVector<QStyleSheetItem> > &os, - const QValueList<QStyleSheetItem::ListStyle> &ols, - const QMemArray<int> &oas ); - QTextDeleteCommand( QTextParag *p, int idx, const QMemArray<QTextStringChar> &str ); + const QByteArray& oldStyle ); + QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ); virtual ~QTextDeleteCommand(); @@ -960,9 +942,7 @@ public: protected: int id, index; - QTextParag *parag; + QTextParagraph *parag; QMemArray<QTextStringChar> text; - QValueList< QPtrVector<QStyleSheetItem> > oldStyles; - QValueList<QStyleSheetItem::ListStyle> oldListStyles; - QMemArray<int> oldAligns; + QByteArray styleInformation; }; @@ -972,9 +952,7 @@ class Q_EXPORT QTextInsertCommand : public QTextDeleteCommand public: QTextInsertCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, - const QValueList< QPtrVector<QStyleSheetItem> > &os, - const QValueList<QStyleSheetItem::ListStyle> &ols, - const QMemArray<int> &oas ) - : QTextDeleteCommand( d, i, idx, str, os, ols, oas ) {} - QTextInsertCommand( QTextParag *p, int idx, const QMemArray<QTextStringChar> &str ) + const QByteArray& oldStyleInfo ) + : QTextDeleteCommand( d, i, idx, str, oldStyleInfo ) {} + QTextInsertCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ) : QTextDeleteCommand( p, idx, str ) {} virtual ~QTextInsertCommand() {} @@ -1004,57 +982,38 @@ protected: }; -class Q_EXPORT QTextAlignmentCommand : public QTextCommand +class Q_EXPORT QTextStyleCommand : public QTextCommand { public: - QTextAlignmentCommand( QTextDocument *d, int fParag, int lParag, int na, const QMemArray<int> &oa ); - virtual ~QTextAlignmentCommand() {} + QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange ); + virtual ~QTextStyleCommand() {} - Commands type() const { return Alignment; } + Commands type() const { return Style; } QTextCursor *execute( QTextCursor *c ); QTextCursor *unexecute( QTextCursor *c ); -private: - int firstParag, lastParag; - int newAlign; - QMemArray<int> oldAligns; - -}; - -class Q_EXPORT QTextParagTypeCommand : public QTextCommand -{ -public: - QTextParagTypeCommand( QTextDocument *d, int fParag, int lParag, bool l, - QStyleSheetItem::ListStyle s, const QValueList< QPtrVector<QStyleSheetItem> > &os, - const QValueList<QStyleSheetItem::ListStyle> &ols ); - virtual ~QTextParagTypeCommand() {} - - Commands type() const { return ParagType; } - QTextCursor *execute( QTextCursor *c ); - QTextCursor *unexecute( QTextCursor *c ); + static QByteArray readStyleInformation( QTextDocument* d, int fParag, int lParag ); + static void writeStyleInformation( QTextDocument* d, int fParag, const QByteArray& style ); private: int firstParag, lastParag; - bool list; - QStyleSheetItem::ListStyle listStyle; - QValueList< QPtrVector<QStyleSheetItem> > oldStyles; - QValueList<QStyleSheetItem::ListStyle> oldListStyles; - + QByteArray before; + QByteArray after; }; // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -struct Q_EXPORT QTextParagSelection +struct Q_EXPORT QTextParagraphSelection { int start, end; }; -struct Q_EXPORT QTextParagLineStart +struct Q_EXPORT QTextLineStart { - QTextParagLineStart() : y( 0 ), baseLine( 0 ), h( 0 ) + QTextLineStart() : y( 0 ), baseLine( 0 ), h( 0 ) #ifndef QT_NO_COMPLEXTEXT , bidicontext( 0 ) #endif { } - QTextParagLineStart( ushort y_, ushort bl, ushort h_ ) : y( y_ ), baseLine( bl ), h( h_ ), + QTextLineStart( ushort y_, ushort bl, ushort h_ ) : y( y_ ), baseLine( bl ), h( h_ ), w( 0 ) #ifndef QT_NO_COMPLEXTEXT @@ -1063,9 +1022,9 @@ struct Q_EXPORT QTextParagLineStart { } #ifndef QT_NO_COMPLEXTEXT - QTextParagLineStart( QBidiContext *c, QBidiStatus s ) : y(0), baseLine(0), h(0), + QTextLineStart( QBidiContext *c, QBidiStatus s ) : y(0), baseLine(0), h(0), status( s ), bidicontext( c ) { if ( bidicontext ) bidicontext->ref(); } #endif - virtual ~QTextParagLineStart() + virtual ~QTextLineStart() { #ifndef QT_NO_COMPLEXTEXT @@ -1103,22 +1062,22 @@ private: #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QMap<int, QTextParagSelection>; -template class Q_EXPORT QMap<int, QTextParagLineStart*>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextParagraphSelection>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextLineStart*>; // MOC_SKIP_END #endif -class Q_EXPORT QTextParagData +class Q_EXPORT QTextParagraphData { public: - QTextParagData() {} - virtual ~QTextParagData(); - virtual void join( QTextParagData * ); + QTextParagraphData() {} + virtual ~QTextParagraphData(); + virtual void join( QTextParagraphData * ); }; -class Q_EXPORT QTextParagPseudoDocument +class Q_EXPORT QTextParagraphPseudoDocument { public: - QTextParagPseudoDocument(); - ~QTextParagPseudoDocument(); + QTextParagraphPseudoDocument(); + ~QTextParagraphPseudoDocument(); QRect docRect; QTextFormatter *pFormatter; @@ -1129,5 +1088,5 @@ public: //nase -class Q_EXPORT QTextParag +class Q_EXPORT QTextParagraph { friend class QTextDocument; @@ -1135,6 +1094,6 @@ class Q_EXPORT QTextParag public: - QTextParag( QTextDocument *d, QTextParag *pr = 0, QTextParag *nx = 0, bool updateIds = TRUE ); - virtual ~QTextParag(); + QTextParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE ); + virtual ~QTextParagraph(); QTextString *string() const; @@ -1143,19 +1102,19 @@ public: int length() const; // maybe remove later - void setListStyle( QStyleSheetItem::ListStyle ls ); - QStyleSheetItem::ListStyle listStyle() const; + void setListStyle( QStyleSheetItem::ListStyle ls ) { lstyle = ls; changed = TRUE; } + QStyleSheetItem::ListStyle listStyle() const { return lstyle; } + void setListItem( bool li ) { litem = li; changed = TRUE; } + bool isListItem() const { return litem; } void setListValue( int v ) { list_val = v; } - int listValue() const { return list_val; } + int listValue() const { return list_val > 0 ? list_val : -1; } - void setList( bool b, int listStyle ); - void incDepth(); - void decDepth(); - int listDepth() const; + void setListDepth( int depth ); + int listDepth() const { return ldepth; } - void setFormat( QTextFormat *fm ); - QTextFormat *paragFormat() const; +// void setFormat( QTextFormat *fm ); +// QTextFormat *paragFormat() const; QTextDocument *document() const; - QTextParagPseudoDocument *pseudoDocument() const; + QTextParagraphPseudoDocument *pseudoDocument() const; QRect rect() const; @@ -1165,14 +1124,15 @@ public: bool isVisible() const { return visible; } - QTextParag *prev() const; - QTextParag *next() const; - void setPrev( QTextParag *s ); - void setNext( QTextParag *s ); + QTextParagraph *prev() const; + QTextParagraph *next() const; + void setPrev( QTextParagraph *s ); + void setNext( QTextParagraph *s ); void insert( int index, const QString &s ); + void insert( int index, const QChar *unicode, int len ); void append( const QString &s, bool reallyAtEnd = FALSE ); void truncate( int index ); void remove( int index, int len ); - void join( QTextParag *s ); + void join( QTextParagraph *s ); void invalidate( int chr ); @@ -1213,8 +1173,8 @@ public: void indent( int *oldIndent = 0, int *newIndent = 0 ); - void setExtraData( QTextParagData *data ); - QTextParagData *extraData() const; + void setExtraData( QTextParagraphData *data ); + QTextParagraphData *extraData() const; - QMap<int, QTextParagLineStart*> &lineStartList(); + QMap<int, QTextLineStart*> &lineStartList(); void setFormat( int index, int len, QTextFormat *f, bool useCollection = TRUE, int flags = -1 ); @@ -1226,8 +1186,4 @@ public: int clipx = -1, int clipy = -1, int clipw = -1, int cliph = -1 ); - void setStyleSheetItems( const QPtrVector<QStyleSheetItem> &vec ); - QPtrVector<QStyleSheetItem> styleSheetItems() const; - QStyleSheetItem *style() const; - virtual int topMargin() const; virtual int bottomMargin() const; @@ -1237,5 +1193,4 @@ public: virtual int lineSpacing() const; - int numberOfSubParagraph() const; void registerFloatingItem( QTextCustomItem *i ); void unregisterFloatingItem( QTextCustomItem *i ); @@ -1271,5 +1226,5 @@ public: QTextCursor *redo( QTextCursor *c = 0 ); QTextCommandHistory *commands() const; - virtual void copyParagData( QTextParag *parag ); + virtual void copyParagData( QTextParagraph *parag ); void setBreakable( bool b ) { breakable = b; } @@ -1280,6 +1235,4 @@ public: void clearBackgroundColor(); - bool isLineBreak() const { return isBr; } - void setMovedDown( bool b ) { movedDown = b; } bool wasMovedDown() const { return movedDown; } @@ -1288,20 +1241,24 @@ public: QChar::Direction direction() const; + void readStyleInformation( QDataStream& stream ); + void writeStyleInformation( QDataStream& stream ) const; + protected: virtual void drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ); - virtual void drawParagString( QPainter &painter, const QString &str, int start, int len, int startX, - int lastY, int baseLine, int bw, int h, bool drawSelections, - QTextStringChar *formatChar, int i, const QMemArray<int> &selectionStarts, - const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft ); + virtual void drawString( QPainter &painter, const QString &str, int start, int len, int xstart, + int y, int baseLine, int w, int h, int selection, + QTextStringChar *formatChar, const QColorGroup& cg, + bool rightToLeft ); private: - QMap<int, QTextParagSelection> &selections() const; - QPtrVector<QStyleSheetItem> &styleSheetItemsVec() const; + QMap<int, QTextParagraphSelection> &selections() const; QPtrList<QTextCustomItem> &floatingItems() const; + QBrush backgroundBrush( const QColorGroup&cg ) { if ( bgcol ) return *bgcol; return cg.brush( QColorGroup::Base ); } + void invalidateStyleCache(); - QMap<int, QTextParagLineStart*> lineStarts; + QMap<int, QTextLineStart*> lineStarts; int invalid; QRect r; - QTextParag *p, *n; + QTextParagraph *p, *n; void *docOrPseudo; uint changed : 1; @@ -1310,27 +1267,25 @@ private: uint needPreProcess : 1; uint fullWidth : 1; - uint newLinesAllowed : 1; uint lastInFrame : 1; uint visible : 1; uint breakable : 1; - uint isBr : 1; uint movedDown : 1; uint mightHaveCustomItems : 1; uint hasdoc : 1; + uint litem : 1; // whether the paragraph is a list item + uint rtext : 1; // whether the paragraph needs rich text margin int align : 4; int state, id; QTextString *str; - QMap<int, QTextParagSelection> *mSelections; - QPtrVector<QStyleSheetItem> *mStyleSheetItemsVec; + QMap<int, QTextParagraphSelection> *mSelections; QPtrList<QTextCustomItem> *mFloatingItems; - QStyleSheetItem::ListStyle listS; - int numSubParag; - int tm, bm, lm, rm, flm; - QTextFormat *defFormat; + QStyleSheetItem::ListStyle lstyle; + short utm, ubm, ulm, urm, uflm, ulinespacing; int *tArray; - int tabStopWidth; - QTextParagData *eData; - int list_val; + short tabStopWidth; + QTextParagraphData *eData; + short list_val; QColor *bgcol; + ushort ldepth; }; @@ -1344,8 +1299,8 @@ public: virtual ~QTextFormatter(); - virtual int format( QTextDocument *doc, QTextParag *parag, int start, const QMap<int, QTextParagLineStart*> &oldLineStarts ) = 0; - virtual int formatVertically( QTextDocument* doc, QTextParag* parag ); + virtual int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ) = 0; + virtual int formatVertically( QTextDocument* doc, QTextParagraph* parag ); - bool isWrapEnabled( QTextParag *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;} + bool isWrapEnabled( QTextParagraph *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;} int wrapAtColumn() const { return wrapColumn;} virtual void setWrapEnabled( bool b ); @@ -1357,13 +1312,14 @@ public: int widthUsed() const { return thiswused; } + static bool isBreakable( QTextString *string, int pos ); + protected: - virtual QTextParagLineStart *formatLine( QTextParag *parag, QTextString *string, QTextParagLineStart *line, QTextStringChar *start, + virtual QTextLineStart *formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start, QTextStringChar *last, int align = Qt3::AlignAuto, int space = 0 ); #ifndef QT_NO_COMPLEXTEXT - virtual QTextParagLineStart *bidiReorderLine( QTextParag *parag, QTextString *string, QTextParagLineStart *line, QTextStringChar *start, + virtual QTextLineStart *bidiReorderLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start, QTextStringChar *last, int align, int space ); #endif - virtual bool isBreakable( QTextString *string, int pos ) const; - void insertLineStart( QTextParag *parag, int index, QTextParagLineStart *ls ); + void insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls ); int thisminw; @@ -1390,5 +1346,5 @@ public: virtual ~QTextFormatterBreakInWords() {} - int format( QTextDocument *doc, QTextParag *parag, int start, const QMap<int, QTextParagLineStart*> &oldLineStarts ); + int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ); }; @@ -1402,5 +1358,5 @@ public: virtual ~QTextFormatterBreakWords() {} - int format( QTextDocument *doc, QTextParag *parag, int start, const QMap<int, QTextParagLineStart*> &oldLineStarts ); + int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ); }; @@ -1414,5 +1370,5 @@ public: virtual ~QTextIndent() {} - virtual void indent( QTextDocument *doc, QTextParag *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0; + virtual void indent( QTextDocument *doc, QTextParagraph *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0; }; @@ -1430,5 +1386,5 @@ public: virtual ~QTextPreProcessor() {} - virtual void process( QTextDocument *doc, QTextParag *, int, bool = TRUE ) = 0; + virtual void process( QTextDocument *doc, QTextParagraph *, int, bool = TRUE ) = 0; virtual QTextFormat *format( int id ) = 0; @@ -1453,5 +1409,6 @@ public: Misspelled = 64, VAlign = 128, - Font = Bold | Italic | Underline | Family | Size, + StrikeOut= 256, + Font = Bold | Italic | Underline | Family | Size | StrikeOut, Format = Font | Color | Misspelled | VAlign }; @@ -1465,5 +1422,5 @@ public: QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent = 0 ); QTextFormat( const QTextFormat &fm ); - QTextFormat makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr ) const; + QTextFormat makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const; QTextFormat& operator=( const QTextFormat &fm ); QColor color() const; @@ -1484,4 +1441,5 @@ public: void setItalic( bool b ); void setUnderline( bool b ); + void setStrikeOut( bool b ); void setFamily( const QString &f ); void setPointSize( int s ); @@ -1500,15 +1458,10 @@ public: void removeRef(); - QString makeFormatChangeTags( QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const; - QString makeFormatEndTags( const QString& anchorHref ) const; + QString makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const; + QString makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const; static void setPainter( QPainter *p ); static QPainter* painter(); - void updateStyle(); - void updateStyleFlags(); - void setStyle( const QString &s ); - QString styleName() const { return style; } - int changed() const { return different; } bool fontSizesInPixels() { return usePixelSizes; } @@ -1536,6 +1489,4 @@ private: int stdSize; static QPainter *pntr; - QString style; - int different; }; @@ -1545,5 +1496,5 @@ private: #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QDict<QTextFormat>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QTextFormat>; // MOC_SKIP_END #endif @@ -1566,11 +1517,6 @@ public: virtual QTextFormat *createFormat( const QTextFormat &f ) { return new QTextFormat( f ); } virtual QTextFormat *createFormat( const QFont &f, const QColor &c ) { return new QTextFormat( f, c, this ); } - void debug(); - QStyleSheet *styleSheet() const { return sheet; } - void setStyleSheet( QStyleSheet *s ) { sheet = s; } - void updateStyles(); - void updateFontSizes( int base, bool usePixels ); - void updateFontAttributes( const QFont &f, const QFont &old ); + void updateDefaultFormat( const QFont &font, const QColor &c, QStyleSheet *sheet ); QDict<QTextFormat> dict() const { return cKey; } @@ -1586,6 +1532,4 @@ private: QString kof, knf; int cflags; - QStyleSheet *sheet; - }; @@ -1597,22 +1541,17 @@ inline int QTextString::length() const } -inline void QTextString::operator+=( const QString &s ) -{ - insert( length(), s, 0 ); -} - -inline int QTextParag::length() const +inline int QTextParagraph::length() const { return str->length(); } -inline QRect QTextParag::rect() const +inline QRect QTextParagraph::rect() const { return r; } -inline QTextParag *QTextCursor::parag() const +inline QTextParagraph *QTextCursor::paragraph() const { - return string; + return para; } @@ -1622,33 +1561,4 @@ inline int QTextCursor::index() const } -inline void QTextCursor::setIndex( int i, bool restore ) -{ - if ( restore ) - restoreState(); - if ( i < 0 || i >= string->length() ) { -#if defined(QT_CHECK_RANGE) - qWarning( "QTextCursor::setIndex: %d out of range", i ); -#endif - i = i < 0 ? 0 : string->length() - 1; - } - - tmpIndex = -1; - idx = i; -} - -inline void QTextCursor::setParag( QTextParag *s, bool restore ) -{ - if ( restore ) - restoreState(); - idx = 0; - string = s; - tmpIndex = -1; -} - -inline void QTextCursor::checkIndex() -{ - if ( idx >= string->length() ) - idx = string->length() - 1; -} // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -1674,20 +1584,20 @@ inline int QTextDocument::visibleWidth() const } -inline QTextParag *QTextDocument::firstParag() const +inline QTextParagraph *QTextDocument::firstParagraph() const { return fParag; } -inline QTextParag *QTextDocument::lastParag() const +inline QTextParagraph *QTextDocument::lastParagraph() const { return lParag; } -inline void QTextDocument::setFirstParag( QTextParag *p ) +inline void QTextDocument::setFirstParagraph( QTextParagraph *p ) { fParag = p; } -inline void QTextDocument::setLastParag( QTextParag *p ) +inline void QTextDocument::setLastParagraph( QTextParagraph *p ) { lParag = p; @@ -1871,7 +1781,4 @@ inline void QTextFormat::addRef() { ref++; -#ifdef DEBUG_COLLECTION - qDebug( "add ref of '%s' to %d (%p)", k.latin1(), ref, this ); -#endif } @@ -1883,7 +1790,4 @@ inline void QTextFormat::removeRef() if ( this == collection->defFormat ) return; -#ifdef DEBUG_COLLECTION - qDebug( "remove ref of '%s' to %d (%p)", k.latin1(), ref, this ); -#endif if ( ref == 0 ) collection->remove( this ); @@ -1900,9 +1804,4 @@ inline bool QTextFormat::useLinkColor() const } -inline void QTextFormat::setStyle( const QString &s ) -{ - style = s; - updateStyleFlags(); -} // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -1915,20 +1814,20 @@ inline QTextStringChar &QTextString::at( int i ) const // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -inline QTextStringChar *QTextParag::at( int i ) const +inline QTextStringChar *QTextParagraph::at( int i ) const { return &str->at( i ); } -inline bool QTextParag::isValid() const +inline bool QTextParagraph::isValid() const { return invalid == -1; } -inline bool QTextParag::hasChanged() const +inline bool QTextParagraph::hasChanged() const { return changed; } -inline void QTextParag::setBackgroundColor( const QColor & c ) +inline void QTextParagraph::setBackgroundColor( const QColor & c ) { delete bgcol; @@ -1937,10 +1836,10 @@ inline void QTextParag::setBackgroundColor( const QColor & c ) } -inline void QTextParag::clearBackgroundColor() +inline void QTextParagraph::clearBackgroundColor() { delete bgcol; bgcol = 0; setChanged( TRUE ); } -inline void QTextParag::append( const QString &s, bool reallyAtEnd ) +inline void QTextParagraph::append( const QString &s, bool reallyAtEnd ) { if ( reallyAtEnd ) @@ -1950,20 +1849,20 @@ inline void QTextParag::append( const QString &s, bool reallyAtEnd ) } -inline QTextParag *QTextParag::prev() const +inline QTextParagraph *QTextParagraph::prev() const { return p; } -inline QTextParag *QTextParag::next() const +inline QTextParagraph *QTextParagraph::next() const { return n; } -inline bool QTextParag::hasAnySelection() const +inline bool QTextParagraph::hasAnySelection() const { return mSelections ? !selections().isEmpty() : FALSE; } -inline void QTextParag::setEndState( int s ) +inline void QTextParagraph::setEndState( int s ) { if ( s == state ) @@ -1972,15 +1871,15 @@ inline void QTextParag::setEndState( int s ) } -inline int QTextParag::endState() const +inline int QTextParagraph::endState() const { return state; } -inline void QTextParag::setParagId( int i ) +inline void QTextParagraph::setParagId( int i ) { id = i; } -inline int QTextParag::paragId() const +inline int QTextParagraph::paragId() const { if ( id == -1 ) @@ -1989,25 +1888,25 @@ inline int QTextParag::paragId() const } -inline bool QTextParag::firstPreProcess() const +inline bool QTextParagraph::firstPreProcess() const { return firstPProcess; } -inline void QTextParag::setFirstPreProcess( bool b ) +inline void QTextParagraph::setFirstPreProcess( bool b ) { firstPProcess = b; } -inline QMap<int, QTextParagLineStart*> &QTextParag::lineStartList() +inline QMap<int, QTextLineStart*> &QTextParagraph::lineStartList() { return lineStarts; } -inline QTextString *QTextParag::string() const +inline QTextString *QTextParagraph::string() const { return str; } -inline QTextDocument *QTextParag::document() const +inline QTextDocument *QTextParagraph::document() const { if ( hasdoc ) @@ -2016,18 +1915,18 @@ inline QTextDocument *QTextParag::document() const } -inline QTextParagPseudoDocument *QTextParag::pseudoDocument() const +inline QTextParagraphPseudoDocument *QTextParagraph::pseudoDocument() const { if ( hasdoc ) return 0; - return (QTextParagPseudoDocument*) docOrPseudo; + return (QTextParagraphPseudoDocument*) docOrPseudo; } -inline QTextTableCell *QTextParag::tableCell() const +inline QTextTableCell *QTextParagraph::tableCell() const { return hasdoc ? document()->tableCell () : 0; } -inline QTextCommandHistory *QTextParag::commands() const +inline QTextCommandHistory *QTextParagraph::commands() const { return hasdoc ? document()->commands() : pseudoDocument()->commandHistory; @@ -2035,83 +1934,54 @@ inline QTextCommandHistory *QTextParag::commands() const -inline void QTextParag::setAlignment( int a ) -{ - if ( a == (int)align ) - return; - align = a; - invalidate( 0 ); -} - -inline void QTextParag::setListStyle( QStyleSheetItem::ListStyle ls ) -{ - listS = ls; - invalidate( 0 ); -} - -inline QStyleSheetItem::ListStyle QTextParag::listStyle() const -{ - return listS; -} - -inline QTextFormat *QTextParag::paragFormat() const +inline int QTextParagraph::alignment() const { - return defFormat; + return align; } -inline void QTextParag::registerFloatingItem( QTextCustomItem *i ) +inline void QTextParagraph::registerFloatingItem( QTextCustomItem *i ) { floatingItems().append( i ); } -inline void QTextParag::unregisterFloatingItem( QTextCustomItem *i ) +inline void QTextParagraph::unregisterFloatingItem( QTextCustomItem *i ) { floatingItems().removeRef( i ); } -inline QBrush *QTextParag::background() const +inline QBrush *QTextParagraph::background() const { return tableCell() ? tableCell()->backGround() : 0; } -inline int QTextParag::documentWidth() const +inline int QTextParagraph::documentWidth() const { return hasdoc ? document()->width() : pseudoDocument()->docRect.width(); } -inline int QTextParag::documentVisibleWidth() const +inline int QTextParagraph::documentVisibleWidth() const { return hasdoc ? document()->visibleWidth() : pseudoDocument()->docRect.width(); } -inline int QTextParag::documentX() const +inline int QTextParagraph::documentX() const { return hasdoc ? document()->x() : pseudoDocument()->docRect.x(); } -inline int QTextParag::documentY() const +inline int QTextParagraph::documentY() const { return hasdoc ? document()->y() : pseudoDocument()->docRect.y(); } -inline void QTextParag::setExtraData( QTextParagData *data ) +inline void QTextParagraph::setExtraData( QTextParagraphData *data ) { eData = data; } -inline QTextParagData *QTextParag::extraData() const +inline QTextParagraphData *QTextParagraph::extraData() const { return eData; } -inline void QTextParag::setNewLinesAllowed( bool b ) -{ - newLinesAllowed = b; -} - -inline bool QTextParag::isNewLinesAllowed() const -{ - return newLinesAllowed; -} - // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/noncore/apps/opie-write/qstylesheet.cpp b/noncore/apps/opie-write/qstylesheet.cpp index 7ab9ec6..67cd828 100644 --- a/noncore/apps/opie-write/qstylesheet.cpp +++ b/noncore/apps/opie-write/qstylesheet.cpp @@ -55,4 +55,5 @@ public: int fontitalic; int fontunderline; + int fontstrikeout; int fontweight; int fontsize; @@ -80,23 +81,26 @@ public: /*! \class QStyleSheetItem qstylesheet.h - \ingroup text \brief The QStyleSheetItem class provides an encapsulation of a set of text styles. + \ingroup text + A style sheet item consists of a name and a set of attributes that specifiy its font, color, etc. When used in a \link QStyleSheet - style sheet\endlink (see styleSheet()), items define the name() of a - rich text tag and the display property changes associated with it. + style sheet\endlink (see styleSheet()), items define the name() of + a rich text tag and the display property changes associated with + it. The \link QStyleSheetItem::DisplayMode display mode\endlink attribute indicates whether the item is a block, an inline element - or a list element; see setDisplayMode(). The treatment of whitespace - is controlled by the \link QStyleSheetItem::WhiteSpaceMode white - space mode\endlink; see setWhiteSpaceMode(). An item's margins are - set with setMargin(), and line spacing is set with setLineSpacing(). + or a list element; see setDisplayMode(). The treatment of + whitespace is controlled by the \link + QStyleSheetItem::WhiteSpaceMode white space mode\endlink; see + setWhiteSpaceMode(). An item's margins are set with setMargin(), In the case of list items, the list style is set with setListStyle(). An item may be a hypertext link anchor; see setAnchor(). Other attributes are set with setAlignment(), setVerticalAlignment(), setFontFamily(), setFontSize(), - setFontWeight(), setFontItalic(), setFontUnderline() and setColor(). + setFontWeight(), setFontItalic(), setFontUnderline(), + setFontStrikeOut and setColor(). */ @@ -105,7 +109,9 @@ public: */ -/*! \enum QStyleSheetItem::WhiteSpaceMode +/*! + \enum QStyleSheetItem::WhiteSpaceMode - This enum defines the ways in which QStyleSheet can treat whitespace. There are three values at present: + This enum defines the ways in which QStyleSheet can treat + whitespace. \value WhiteSpaceNormal any sequence of whitespace (including @@ -116,10 +122,11 @@ public: \value WhiteSpaceNoWrap multiple spaces are collapsed as with - WhiteSpaceNormal, but no automatic line-breaks occur. To break lines manually, - use the \c{<br>} tag. + WhiteSpaceNormal, but no automatic line-breaks occur. To break + lines manually, use the \c{<br>} tag. */ -/*! \enum QStyleSheetItem::Margin +/*! + \enum QStyleSheetItem::Margin \value MarginLeft left margin @@ -130,13 +137,15 @@ public: \value MarginVertical top and bottom margins \value MarginHorizontal left and right margins - \value MarginFirstLine margin (indentation) of the first line of a paragarph (in addition to the MarginLeft of the paragraph) + \value MarginFirstLine margin (indentation) of the first line of + a paragarph (in addition to the MarginLeft of the paragraph) */ /*! - Constructs a new style named \a name for the stylesheet \a parent. + Constructs a new style called \a name for the stylesheet \a + parent. - All properties in QStyleSheetItem are initially in the "do not change" state, - except \link QStyleSheetItem::DisplayMode display mode\endlink, which defaults - to \c DisplayInline. + All properties in QStyleSheetItem are initially in the "do not + change" state, except \link QStyleSheetItem::DisplayMode display + mode\endlink, which defaults to \c DisplayInline. */ QStyleSheetItem::QStyleSheetItem( QStyleSheet* parent, const QString& name ) @@ -151,6 +160,6 @@ QStyleSheetItem::QStyleSheetItem( QStyleSheet* parent, const QString& name ) /*! - Copy constructor. Constructs a copy of \a other that is - not bound to any style sheet. + Copy constructor. Constructs a copy of \a other that is not bound + to any style sheet. */ QStyleSheetItem::QStyleSheetItem( const QStyleSheetItem & other ) @@ -162,6 +171,6 @@ QStyleSheetItem::QStyleSheetItem( const QStyleSheetItem & other ) /*! - Destroys the style. Note that QStyleSheetItem objects become owned - by QStyleSheet when they are created. + Destroys the style. Note that QStyleSheetItem objects become + owned by QStyleSheet when they are created. */ QStyleSheetItem::~QStyleSheetItem() @@ -182,4 +191,5 @@ QStyleSheet* QStyleSheetItem::styleSheet() /*! \overload + Returns the style sheet this item is in. */ @@ -199,4 +209,5 @@ void QStyleSheetItem::init() d->fontitalic = Undefined; d->fontunderline = Undefined; + d->fontstrikeout = Undefined; d->fontweight = Undefined; d->fontsize = Undefined; @@ -213,6 +224,6 @@ void QStyleSheetItem::init() d->margin[3] = Undefined; d->margin[4] = Undefined; - d->list = QStyleSheetItem::ListDisc; - d->whitespacemode = QStyleSheetItem::WhiteSpaceNormal; + d->list = (ListStyle) Undefined; + d->whitespacemode = (WhiteSpaceMode) Undefined; d->selfnest = TRUE; d->lineSpacing = Undefined; @@ -228,6 +239,6 @@ QString QStyleSheetItem::name() const /*! - Returns the \link QStyleSheetItem::DisplayMode display mode\endlink - of the style. + Returns the \link QStyleSheetItem::DisplayMode display + mode\endlink of the style. \sa setDisplayMode() @@ -238,16 +249,17 @@ QStyleSheetItem::DisplayMode QStyleSheetItem::displayMode() const } -/*! \enum QStyleSheetItem::DisplayMode +/*! + \enum QStyleSheetItem::DisplayMode - This enum type defines the way adjacent elements are displayed. The possible values are: + This enum type defines the way adjacent elements are displayed. \value DisplayBlock elements are displayed as a rectangular block (e.g. \c{<p>...</p>}). - \value DisplayInline elements are displayed in a horizontally flowing - sequence (e.g. \c{<em>...</em>}). + \value DisplayInline elements are displayed in a horizontally + flowing sequence (e.g. \c{<em>...</em>}). - \value DisplayListItem elements are displayed in a vertical sequence - (e.g. \c{<li>...</li>}). + \value DisplayListItem elements are displayed in a vertical + sequence (e.g. \c{<li>...</li>}). \value DisplayNone elements are not displayed at all. @@ -266,6 +278,7 @@ void QStyleSheetItem::setDisplayMode(DisplayMode m) /*! - Returns the alignment of this style. Possible values are AlignAuto, AlignLeft, - AlignRight, AlignCenter and AlignJustify. + Returns the alignment of this style. Possible values are \c + AlignAuto, \c AlignLeft, \c AlignRight, \c AlignCenter or \c + AlignJustify. \sa setAlignment(), Qt::AlignmentFlags @@ -277,8 +290,8 @@ int QStyleSheetItem::alignment() const /*! - Sets the alignment to \a f. This only makes sense for styles with a - \link QStyleSheetItem::DisplayMode display mode\endlink of - DisplayBlock. Possible values are AlignAuto, AlignLeft, AlignRight, - AlignCenter and AlignJustify. + Sets the alignment to \a f. This only makes sense for styles with + a \link QStyleSheetItem::DisplayMode display mode\endlink of + DisplayBlock. Possible values are \c AlignAuto, \c AlignLeft, + \c AlignRight, \c AlignCenter or \c AlignJustify. \sa alignment(), displayMode(), Qt::AlignmentFlags @@ -292,7 +305,7 @@ void QStyleSheetItem::setAlignment( int f ) /*! Returns the vertical alignment of the style. Possible values are - VAlignBaseline, VAlignSub and VAlignSuper. + \c VAlignBaseline, \c VAlignSub or \c VAlignSuper. - psa setVerticalAlignment() + \sa setVerticalAlignment() */ QStyleSheetItem::VerticalAlignment QStyleSheetItem::verticalAlignment() const @@ -301,12 +314,13 @@ QStyleSheetItem::VerticalAlignment QStyleSheetItem::verticalAlignment() const } -/*! \enum QStyleSheetItem::VerticalAlignment +/*! + \enum QStyleSheetItem::VerticalAlignment - This enum type defines the way elements are aligned vertically. This - is supported for text elements only. The possible values are: + This enum type defines the way elements are aligned vertically. + This is only supported for text elements. \value VAlignBaseline align the baseline of the element (or the - bottom, if the element doesn't have a baseline) with the baseline of - the parent + bottom, if the element doesn't have a baseline) with the + baseline of the parent \value VAlignSub subscript the element @@ -319,5 +333,5 @@ QStyleSheetItem::VerticalAlignment QStyleSheetItem::verticalAlignment() const /*! Sets the vertical alignment to \a valign. Possible values are - VAlignBaseline, VAlignSub and VAlignSuper. + \c VAlignBaseline, \c VAlignSub or \c VAlignSuper. The vertical alignment property is not inherited. @@ -332,5 +346,6 @@ void QStyleSheetItem::setVerticalAlignment( VerticalAlignment valign ) /*! - Returns TRUE if the style sets an italic font; otherwise returns FALSE. + Returns TRUE if the style sets an italic font; otherwise returns + FALSE. \sa setFontItalic(), definesFontItalic() @@ -353,6 +368,7 @@ void QStyleSheetItem::setFontItalic(bool italic) /*! - Returns whether the style defines a font shape. A style - does not define any shape until setFontItalic() is called. + Returns TRUE if the style defines a font shape; otherwise returns + FALSE. A style does not define any shape until setFontItalic() is + called. \sa setFontItalic(), fontItalic() @@ -364,5 +380,6 @@ bool QStyleSheetItem::definesFontItalic() const /*! - Returns TRUE if the style sets an underlined font; otherwise returns FALSE. + Returns TRUE if the style sets an underlined font; otherwise + returns FALSE. \sa setFontUnderline(), definesFontUnderline() @@ -374,6 +391,6 @@ bool QStyleSheetItem::fontUnderline() const /*! - If \a underline is TRUE sets underline for the style; otherwise sets - no underline. + If \a underline is TRUE, sets underline for the style; otherwise + sets no underline. \sa fontUnderline(), definesFontUnderline() @@ -385,9 +402,10 @@ void QStyleSheetItem::setFontUnderline(bool underline) /*! - Returns whether the style defines a setting for the underline - property of the font. A style does not define this until - setFontUnderline() is called. + Returns TRUE if the style defines a setting for the underline + property of the font; otherwise returns FALSE. A style does not + define this until setFontUnderline() is called. - \sa setFontUnderline(), fontUnderline() */ + \sa setFontUnderline(), fontUnderline() +*/ bool QStyleSheetItem::definesFontUnderline() const { @@ -397,6 +415,41 @@ bool QStyleSheetItem::definesFontUnderline() const /*! + Returns TRUE if the style sets a strike out font; otherwise + returns FALSE. + + \sa setFontStrikeOut(), definesFontStrikeOut() +*/ +bool QStyleSheetItem::fontStrikeOut() const +{ + return d->fontstrikeout > 0; +} + +/*! + If \a strikeOut is TRUE, sets strike out for the style; otherwise + sets no strike out. + + \sa fontStrikeOut(), definesFontStrikeOut() +*/ +void QStyleSheetItem::setFontStrikeOut(bool strikeOut) +{ + d->fontstrikeout = strikeOut?1:0; +} + +/*! + Returns TRUE if the style defines a setting for the strikeOut + property of the font; otherwise returns FALSE. A style does not + define this until setFontStrikeOut() is called. + + \sa setFontStrikeOut(), fontStrikeOut() +*/ +bool QStyleSheetItem::definesFontStrikeOut() const +{ + return d->fontstrikeout != Undefined; +} + + +/*! Returns the font weight setting of the style. This is either a - valid QFont::Weight or the value QStyleSheetItem::Undefined. + valid \c QFont::Weight or the value \c QStyleSheetItem::Undefined. \sa setFontWeight(), QFont @@ -408,6 +461,6 @@ int QStyleSheetItem::fontWeight() const /*! - Sets the font weight setting of the style to \a w. Valid values are - those defined by QFont::Weight. + Sets the font weight setting of the style to \a w. Valid values + are those defined by \c QFont::Weight. \sa QFont, fontWeight() @@ -419,6 +472,6 @@ void QStyleSheetItem::setFontWeight(int w) /*! - Returns the logical font size setting of the style. This is either a valid - size between 1 and 7 or QStyleSheetItem::Undefined. + Returns the logical font size setting of the style. This is either + a valid size between 1 and 7 or \c QStyleSheetItem::Undefined. \sa setLogicalFontSize(), setLogicalFontSizeStep(), QFont::pointSize(), QFont::setPointSize() @@ -431,6 +484,6 @@ int QStyleSheetItem::logicalFontSize() const /*! - Sets the logical font size setting of the style to \a s. - Valid logical sizes are 1 to 7. + Sets the logical font size setting of the style to \a s. Valid + logical sizes are 1 to 7. \sa logicalFontSize(), QFont::pointSize(), QFont::setPointSize() @@ -444,6 +497,6 @@ void QStyleSheetItem::setLogicalFontSize(int s) Returns the logical font size step of this style. - The default is 0. Tags such as \c big define \c +1; \c small defines - \c -1. + The default is 0. Tags such as \c big define \c +1; \c small + defines \c -1. \sa setLogicalFontSizeStep() @@ -478,5 +531,5 @@ void QStyleSheetItem::setFontSize(int s) /*! Returns the font size setting of the style. This is either a valid - point size or QStyleSheetItem::Undefined. + point size or \c QStyleSheetItem::Undefined. \sa setFontSize(), QFont::pointSize(), QFont::setPointSize() @@ -489,6 +542,6 @@ int QStyleSheetItem::fontSize() const /*! - Returns the font family setting of the style. This is either a valid - font family or QString::null if no family has been set. + Returns the font family setting of the style. This is either a + valid font family or QString::null if no family has been set. \sa setFontFamily(), QFont::family(), QFont::setFamily() @@ -539,6 +592,6 @@ void QStyleSheetItem::setNumberOfColumns(int ncols) /*! - Returns the text color of this style or an invalid color - if no color has been set. + Returns the text color of this style or an invalid color if no + color has been set. \sa setColor() QColor::isValid() @@ -570,7 +623,7 @@ bool QStyleSheetItem::isAnchor() const /*! - If \a anc is TRUE sets this style to be an anchor (hypertext link); - otherwise sets it to not be an anchor. Elements in this style have - connections to other documents or anchors. + If \a anc is TRUE, sets this style to be an anchor (hypertext + link); otherwise sets it to not be an anchor. Elements in this + style link to other documents or anchors. \sa isAnchor() @@ -594,4 +647,5 @@ QStyleSheetItem::WhiteSpaceMode QStyleSheetItem::whiteSpaceMode() const /*! Sets the whitespace mode to \a m. + \sa WhiteSpaceMode */ @@ -605,6 +659,6 @@ void QStyleSheetItem::setWhiteSpaceMode(WhiteSpaceMode m) Returns the width of margin \a m in pixels. - The margin, \a m, can be \c MarginLeft, \c MarginRight, - \c MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c + The margin, \a m, can be \c MarginLeft, \c MarginRight, \c + MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c MarginHorizontal. @@ -620,6 +674,6 @@ int QStyleSheetItem::margin(Margin m) const Sets the width of margin \a m to \a v pixels. - The margin, \a m, can be \c MarginLeft, \c MarginRight, - \c MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c + The margin, \a m, can be \c MarginLeft, \c MarginRight, \c + MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c MarginHorizontal. The value \a v must be >= 0. @@ -656,8 +710,9 @@ QStyleSheetItem::ListStyle QStyleSheetItem::listStyle() const } -/*! \enum QStyleSheetItem::ListStyle +/*! + \enum QStyleSheetItem::ListStyle This enum type defines how the items in a list are prefixed when - displayed. The currently defined values are: + displayed. \value ListDisc a filled circle (i.e. a bullet) @@ -668,9 +723,10 @@ QStyleSheetItem::ListStyle QStyleSheetItem::listStyle() const \value ListUpperAlpha an uppercase letter: \e A, \e B, \e C, ... */ + /*! Sets the list style of the style to \a s. - This is used by nested elements that have a display mode of - \c DisplayListItem. + This is used by nested elements that have a display mode of \c + DisplayListItem. \sa listStyle() DisplayMode ListStyle @@ -682,6 +738,7 @@ void QStyleSheetItem::setListStyle(ListStyle s) -/*! Returns a space-separated list of names of styles that may - contain elements of this style. If nothing has been set, contexts() +/*! + Returns a space-separated list of names of styles that may contain + elements of this style. If nothing has been set, contexts() returns an empty string, which indicates that this style can be nested everywhere. @@ -707,6 +764,6 @@ void QStyleSheetItem::setContexts( const QString& c) /*! - Returns TRUE if this style can be nested into an element - of style \a s; otherwise returns FALSE. + Returns TRUE if this style can be nested into an element of style + \a s; otherwise returns FALSE. \sa contexts(), setContexts() @@ -734,7 +791,7 @@ bool QStyleSheetItem::selfNesting() const Sets the self-nesting property for this style to \a nesting. - In order to support "dirty" HTML, paragraphs \c{<p>} and list items - \c{<li>} are not self-nesting. This means that starting a new - paragraph or list item automatically closes the previous one. + In order to support "dirty" HTML, paragraphs \c{<p>} and list + items \c{<li>} are not self-nesting. This means that starting a + new paragraph or list item automatically closes the previous one. \sa selfNesting() @@ -745,5 +802,13 @@ void QStyleSheetItem::setSelfNesting( bool nesting ) } -/*! Sets the linespacing to be \a ls pixels */ +/* + Sets the linespacing to be at least \a ls pixels. + + For compatibility with previous Qt releases, small values get + treated differently: If \a ls is smaller than the default font + line spacing in pixels at parse time, the resulting line spacing + is the sum of the default line spacing plus \a ls. We recommend + not relying on this behavior. +*/ void QStyleSheetItem::setLineSpacing( int ls ) @@ -752,5 +817,9 @@ void QStyleSheetItem::setLineSpacing( int ls ) } -/*! Returns the linespacing */ +/*! + \obsolete + + Returns the linespacing +*/ int QStyleSheetItem::lineSpacing() const @@ -788,200 +857,198 @@ int QStyleSheetItem::lineSpacing() const sorted by structuring bindings, anchors, character style bindings (i.e. inline styles), special elements such as horizontal lines or - images, and other tags. In addition, rich text supports simple HTML - tables. + images, and other tags. In addition, rich text supports simple + HTML tables. The structuring tags are + \table + \header \i Structuring tags \i Notes + \row \i \c{<qt>}...\c{</qt>} + \i A Qt rich text document. It understands the following + attributes: \list - \i \c{<qt>}...\c{</qt>} - - A Qt rich text document. It understands the following attributes: - \list - \i title - - The caption of the document. This attribute is easily accessible with - QTextView::documentTitle(). - \i type - - The type of the document. The default type is \c page . It - indicates that the document is displayed in a page of its - own. Another style is \c detail, which can be used to - explain certain expressions in more detail in a few - sentences. The QTextBrowser will then keep the current page - and display the new document in a small popup similar to - QWhatsThis. Note that links will not work in documents with - \c{<qt type="detail">...</qt>}. - \i bgcolor - - The background color, for example \c bgcolor="yellow" or \c - bgcolor="#0000FF". - \i background - - The background pixmap, for example \c - background="granit.xpm". The pixmap name will be resolved by - a QMimeSourceFactory(). - \i text - - The default text color, for example \c text="red". - \i link - - The link color, for example \c link="green". - \endlist - \i \c{<h1>...</h1>} - - A top-level heading. - \i \c{<h2>...</h2>} - - A sublevel heading. - \i \c{<h3>...</h3>} - - A sub-sublevel heading. - \i \c{<p>...</p>} - - A left-aligned paragraph. Adjust the alignment with - the \c align attribute. Possible values are - \c left, \c right and \c center. - \i \c{<center>...</center>} - - A centered paragraph. - \i \c{<blockquote>...</blockquote>} - - An indented paragraph that is useful for quotes. - \i \c{<ul>...</ul>} - - An unordered list. You can also pass a type argument to - define the bullet style. The default is \c type=disc; other - types are \c circle and \c square. - \i \c{<ol>...</ol>} - - An ordered list. You can also pass a type argument to define - the enumeration label style. The default is \c type="1"; other - types are \c "a" and \c "A". - \i <tt><li></tt>...<tt></li></tt> - - A list item. This tag can be used only within the context of - \c ol or \c ul. - \i \c{<pre>...</pre>} - - For larger chunks of code. Whitespaces in the contents are preserved. - For small bits of code use the inline-style \c code. + \i \c title -- The caption of the document. This attribute is + easily accessible with QTextView::documentTitle(). + \i \c type -- The type of the document. The default type is \c + page. It indicates that the document is displayed in a + page of its own. Another style is \c detail, which can be + used to explain certain expressions in more detail in a + few sentences. For \c detail, QTextBrowser will then keep + the current page and display the new document in a small + popup similar to QWhatsThis. Note that links will not work + in documents with \c{<qt type="detail">...</qt>}. + \i \c bgcolor -- The background color, for example \c + bgcolor="yellow" or \c bgcolor="#0000FF". + \i \c background -- The background pixmap, for example \c + background="granite.xpm". The pixmap name will be resolved + by a QMimeSourceFactory(). + \i \c text -- The default text color, for example \c text="red". + \i \c link -- The link color, for example \c link="green". \endlist + \row \i \c{<h1>...</h1>} + \i A top-level heading. + \row \i \c{<h2>...</h2>} + \i A sublevel heading. + \row \i \c{<h3>...</h3>} + \i A sub-sublevel heading. + \row \i \c{<p>...</p>} + \i A left-aligned paragraph. Adjust the alignment with the \c + align attribute. Possible values are \c left, \c right and + \c center. + \row \i \c{<center>...}<br>\c{</center>} + \i A centered paragraph. + \row \i \c{<blockquote>...}<br>\c{</blockquote>} + \i An indented paragraph that is useful for quotes. + \row \i \c{<ul>...</ul>} + \i An unordered list. You can also pass a type argument to + define the bullet style. The default is \c type=disc; + other types are \c circle and \c square. + \row \i \c{<ol>...</ol>} + \i An ordered list. You can also pass a type argument to + define the enumeration label style. The default is \c + type="1"; other types are \c "a" and \c "A". + \row \i \c{<li>...</li>} + \i A list item. This tag can be used only within the context + of \c{<ol>} or \c{<ul>}. + \row \i \c{<pre>...</pre>} + \i For larger chunks of code. Whitespaces in the contents are + preserved. For small bits of code use the inline-style \c + code. + \endtable Anchors and links are done with a single tag: + \table + \header \i Anchor tags \i Notes + \row \i \c{<a>...</a>} + \i An anchor or link. \list - \i \c{<a>...</a>} - - An anchor or link. The reference target is defined in the \c - href attribute of the tag as in \c{<a - href="target.qml">...</a>}. You can also specify an - additional anchor within the specified target document, for - example \c{<a href="target.qml#123">...</a>}. If \c a is - meant to be an anchor, the reference source is given in the - \c name attribute. + \i A link is created by using an \c href + attribute, for example + <br>\c{<a href="target.qml">Link Text</a>}. Links to + targets within a document are achieved in the same way + as for HTML, e.g. + <br>\c{<a href="target.qml#subtitle">Link Text</a>}. + \i A target is created by using a \c name + attribute, for example + <br>\c{<a name="subtitle"><h2>Sub Title</h2></a>}. \endlist + \endtable The default character style bindings are + \table + \header \i Style tags \i Notes + \row \i \c{<em>...</em>} + \i Emphasized. By default this is the same as \c{<i>...</i>} + (italic). + \row \i \c{<strong>...</strong>} + \i Strong. By default this is the same as \c{<b>...</b>} + (bold). + \row \i \c{<i>...</i>} + \i Italic font style. + \row \i \c{<b>...</b>} + \i Bold font style. + \row \i \c{<u>...</u>} + \i Underlined font style. + \row \i \c{<s>...</s>} + \i Strike out font style. + \row \i \c{<big>...</big>} + \i A larger font size. + \row \i \c{<small>...</small>} + \i A smaller font size. + \row \i \c{<code>...</code>} + \i Indicates code. By default this is the same as + \c{<tt>...</tt>} (typewriter). For larger junks of code + use the block-tag \c{<}\c{pre>}. + \row \i \c{<tt>...</tt>} + \i Typewriter font style. + \row \i \c{<font>...</font>} + \i Customizes the font size, family and text color. The tag + understands the following attributes: \list - \i \c{<em>...</em>} - - Emphasized. By default this is the same as - \c{<i>...</i>} (italic). - \i \c{<strong>...</strong>} - - Strong. By default this is the same as - \c{<b>...</b>} (bold). - \i \c{<i>...</i>} - - Italic font style. - \i \c{<b>...</b>} - - Bold font style. - \i \c{<u>...</u>} - - Underlined font style. - \i \c{<big>...</big>} - - A larger font size. - \i \c{<small>...</small>} - - A smaller font size. - \i \c{<code>...</code>} - - Indicates code. By default this is the same as - \c{<tt>...</tt>} (typewriter). For - larger junks of code use the block-tag \c pre. - \i \c{<tt>...</tt>} - - Typewriter font style. - \i \c{<font>...</font>} - - Customizes the font size, family and text color. The tag understands - the following attributes: - \list - \i color - - The text color, for example \c color="red" or \c color="#FF0000". - \i size - - The logical size of the font. Logical sizes 1 to 7 are supported. - The value may either be absolute (for example, - \c size=3) or relative (\c size=-2). In the latter case the sizes - are simply added. - \i face - - The family of the font, for example \c face=times. - \endlist + \i \c color -- The text color, for example \c color="red" or + \c color="#FF0000". + \i \c size -- The logical size of the font. Logical sizes 1 + to 7 are supported. The value may either be absolute + (for example, \c size=3) or relative (\c size=-2). In + the latter case the sizes are simply added. + \i \c face -- The family of the font, for example \c face=times. \endlist + \endtable Special elements are: - \list - \i \c{<img>} - - An image. The image name for the mime source - factory is given in the source attribute, for example - \c{<img src="qt.xpm">} - The image tag also understands the attributes \c width and \c - height that determine the size of the image. If the pixmap - does not fit the specified size it will be scaled - automatically (by using QImage::smoothScale()). - + \table + \header \i Special tags \i Notes + \row \i \c{<img>} + \i An image. The image name for the mime source factory is + given in the source attribute, for example + \c{<img src="qt.xpm">} The image tag also understands the + attributes \c width and \c height that determine the size + of the image. If the pixmap does not fit the specified + size it will be scaled automatically (by using + QImage::smoothScale()). + <br> The \c align attribute determines where the image is placed. By default, an image is placed inline just like a normal character. Specify \c left or \c right to place the image at the respective side. - \i \c{<hr>} - - A horizonal line. - \i \c{<br>} - - A line break. - \endlist - - Another tag not in any of the above cathegories is + \row \i \c{<hr>} + \i A horizonal line. + \row \i \c{<br>} + \i A line break. + \row \i \c{<nobr>...</nobr>} + \i No break. Prevents word wrap. + \endtable + + In addition, rich text supports simple HTML tables. A table + consists of one or more rows each of which contains one or more + cells. Cells are either data cells or header cells, depending on + their content. Cells which span rows and columns are supported. + + \table + \header \i Table tags \i Notes + \row \i \c{<table>...</table>} + \i A table. Tables support the following attributes: \list - \i \c{<nobr>...</nobr>} - - No break. Prevents word wrap. + \i \c bgcolor -- The background color. + \i \c width -- The table width. This is either an absolute + pixel width or a relative percentage of the table's + width, for example \c width=80%. + \i \c border -- The width of the table border. The default is + 0 (= no border). + \i \c cellspacing -- Additional space around the table cells. + The default is 2. + \i \c cellpadding -- Additional space around the contents of + table cells. The default is 1. \endlist - - In addition, rich text supports simple HTML tables. A table consists - of one or more rows each of which contains one or more cells. Cells - are either data cells or header cells, depending on their - content. Cells which span rows and columns are supported. - - \list - \i \c{<table>...</table>} - - A table. Tables support the following attributes: + \row \i \c{<tr>...</tr>} + \i A table row. This is only valid within a \c table. Rows + support the following attribute: \list - \i bgcolor - - The background color. - \i width - - The table width. This is either an absolute pixel width or a relative - percentage of the table's width, for example \c width=80%. - \i border - - The width of the table border. The default is 0 (= no border). - \i cellspacing - - Additional space around the table cells. The default is 2. - \i cellpadding - - Additional space around the contents of table cells. The default is 1. + \i \c bgcolor -- The background color. \endlist - \i \c{<tr>...</tr>} - - A table row. This is only valid within a \c table. Rows support - the following attribute: + \row \i \c{<th>...</th>} + \i A table header cell. Similar to \c td, but defaults to + center alignment and a bold font. + \row \i \c{<td>...</td>} + \i A table data cell. This is only valid within a \c tr. + Cells support the following attributes: \list - \i bgcolor - - The background color. - \endlist - \i \c{<th>...</th>} - - A table header cell. Similar to \c td, but defaults to center alignment - and a bold font. - \i \c{<td>...</td>} - - A table data cell. This is only valid within a \c tr. Cells - support the following attributes: - \list - \i bgcolor - - The background color. - \i width - - The cell width. This is either an absolute pixel width or a relative - percentage of table's width, for example \c width=50%. - \i colspan - - Specifies how many columns this cell spans. The default is 1. - \i rowspan - - Specifies how many rows this cell spans. The default is 1. - \i align - - Alignment; possible values are \c left, \c right, and \c center. The - default is left. - \endlist + \i \c bgcolor -- The background color. + \i \c width -- The cell width. This is either an absolute + pixel width or a relative percentage of table's width, + for example \c width=50%. + \i \c colspan -- Specifies how many columns this cell spans. + The default is 1. + \i \c rowspan -- Specifies how many rows this cell spans. The + default is 1. + \i \c align -- Alignment; possible values are \c left, \c + right, and \c center. The default is left. \endlist + \endtable */ /*! - Creates a style sheet with parent \a parent and name \a name. Like - any QObject it will be deleted when its parent is - destroyed (if the child still exists). + Creates a style sheet called \a name, with parent \a parent. Like + any QObject it will be deleted when its parent is destroyed (if + the child still exists). By default the style sheet has the tag definitions defined above. @@ -1019,5 +1086,4 @@ void QStyleSheet::init() style = new QStyleSheetItem( this, QString::fromLatin1("qt") ); style->setDisplayMode( QStyleSheetItem::DisplayBlock ); - //style->setMargin( QStyleSheetItem::MarginAll, 4 ); style = new QStyleSheetItem( this, QString::fromLatin1("a") ); @@ -1048,6 +1114,6 @@ void QStyleSheet::init() style->setLogicalFontSize(6); style->setDisplayMode(QStyleSheetItem::DisplayBlock); - style-> setMargin(QStyleSheetItem::MarginTop, 12); - style-> setMargin(QStyleSheetItem::MarginBottom, 6); + style-> setMargin(QStyleSheetItem::MarginTop, 18); + style-> setMargin(QStyleSheetItem::MarginBottom, 12); style = new QStyleSheetItem( this, QString::fromLatin1("h2") ); @@ -1055,6 +1121,6 @@ void QStyleSheet::init() style->setLogicalFontSize(5); style->setDisplayMode(QStyleSheetItem::DisplayBlock); - style-> setMargin(QStyleSheetItem::MarginTop, 10); - style-> setMargin(QStyleSheetItem::MarginBottom, 5); + style-> setMargin(QStyleSheetItem::MarginTop, 16); + style-> setMargin(QStyleSheetItem::MarginBottom, 12); style = new QStyleSheetItem( this, QString::fromLatin1("h3") ); @@ -1062,6 +1128,6 @@ void QStyleSheet::init() style->setLogicalFontSize(4); style->setDisplayMode(QStyleSheetItem::DisplayBlock); - style-> setMargin(QStyleSheetItem::MarginTop, 8); - style-> setMargin(QStyleSheetItem::MarginBottom, 4); + style-> setMargin(QStyleSheetItem::MarginTop, 14); + style-> setMargin(QStyleSheetItem::MarginBottom, 12); style = new QStyleSheetItem( this, QString::fromLatin1("h4") ); @@ -1069,6 +1135,5 @@ void QStyleSheet::init() style->setLogicalFontSize(3); style->setDisplayMode(QStyleSheetItem::DisplayBlock); - style-> setMargin(QStyleSheetItem::MarginTop, 8); - style-> setMargin(QStyleSheetItem::MarginBottom, 4); + style-> setMargin(QStyleSheetItem::MarginVertical, 12); style = new QStyleSheetItem( this, QString::fromLatin1("h5") ); @@ -1076,10 +1141,10 @@ void QStyleSheet::init() style->setLogicalFontSize(2); style->setDisplayMode(QStyleSheetItem::DisplayBlock); - style-> setMargin(QStyleSheetItem::MarginTop, 8); + style-> setMargin(QStyleSheetItem::MarginTop, 12); style-> setMargin(QStyleSheetItem::MarginBottom, 4); style = new QStyleSheetItem( this, QString::fromLatin1("p") ); style->setDisplayMode(QStyleSheetItem::DisplayBlock); - style-> setMargin(QStyleSheetItem::MarginVertical, 8); + style-> setMargin(QStyleSheetItem::MarginVertical, 12); style->setSelfNesting( FALSE ); @@ -1098,16 +1163,17 @@ void QStyleSheet::init() style = new QStyleSheetItem( this, QString::fromLatin1("ul") ); style->setDisplayMode(QStyleSheetItem::DisplayBlock); - style-> setMargin(QStyleSheetItem::MarginVertical, 4); + style->setListStyle( QStyleSheetItem::ListDisc ); + style-> setMargin(QStyleSheetItem::MarginVertical, 12); + style->setMargin( QStyleSheetItem::MarginLeft, 40 ); style = new QStyleSheetItem( this, QString::fromLatin1("ol") ); style->setDisplayMode(QStyleSheetItem::DisplayBlock); style->setListStyle( QStyleSheetItem::ListDecimal ); - style-> setMargin(QStyleSheetItem::MarginVertical, 4); + style-> setMargin(QStyleSheetItem::MarginVertical, 12); + style->setMargin( QStyleSheetItem::MarginLeft, 40 ); style = new QStyleSheetItem( this, QString::fromLatin1("li") ); style->setDisplayMode(QStyleSheetItem::DisplayListItem); style->setSelfNesting( FALSE ); - style->setContexts(QString::fromLatin1("ol ul")); - style-> setMargin(QStyleSheetItem::MarginVertical, 4); style = new QStyleSheetItem( this, QString::fromLatin1("code") ); @@ -1120,4 +1186,5 @@ void QStyleSheet::init() new QStyleSheetItem(this, QString::fromLatin1("br")); new QStyleSheetItem(this, QString::fromLatin1("hr")); + style = new QStyleSheetItem(this, QString::fromLatin1("sub")); style->setVerticalAlignment( QStyleSheetItem::VAlignSub ); @@ -1136,7 +1203,11 @@ void QStyleSheet::init() style = new QStyleSheetItem( this, QString::fromLatin1("head") ); style->setDisplayMode(QStyleSheetItem::DisplayNone); + style = new QStyleSheetItem( this, QString::fromLatin1("body") ); + style->setDisplayMode(QStyleSheetItem::DisplayBlock); style = new QStyleSheetItem( this, QString::fromLatin1("div") ); style->setDisplayMode(QStyleSheetItem::DisplayBlock) ; + style = new QStyleSheetItem( this, QString::fromLatin1("span") ); style = new QStyleSheetItem( this, QString::fromLatin1("dl") ); + style-> setMargin(QStyleSheetItem::MarginVertical, 8); style->setDisplayMode(QStyleSheetItem::DisplayBlock); style = new QStyleSheetItem( this, QString::fromLatin1("dt") ); @@ -1149,8 +1220,13 @@ void QStyleSheet::init() style = new QStyleSheetItem( this, QString::fromLatin1("u") ); style->setFontUnderline( TRUE); + style = new QStyleSheetItem( this, QString::fromLatin1("s") ); + style->setFontStrikeOut( TRUE); style = new QStyleSheetItem( this, QString::fromLatin1("nobr") ); style->setWhiteSpaceMode( QStyleSheetItem::WhiteSpaceNoWrap ); - style = new QStyleSheetItem( this, QString::fromLatin1("wsp") ); // qt extension for QTextEdit - style->setWhiteSpaceMode( (QStyleSheetItem::WhiteSpaceMode) 3 ); // WhiteSpaceModeNoCompression + + // compatibily with some minor 3.0.x Qt versions that had an + // undocumented <wsp> tag. ### Remove 3.1 + style = new QStyleSheetItem( this, QString::fromLatin1("wsp") ); + style->setWhiteSpaceMode( QStyleSheetItem::WhiteSpacePre ); // tables @@ -1174,10 +1250,10 @@ static QSingleCleanupHandler<QStyleSheet> qt_cleanup_stylesheet; /*! - Returns the application-wide default style sheet. This style sheet is - used by rich text rendering classes such as QSimpleRichText, + Returns the application-wide default style sheet. This style sheet + is used by rich text rendering classes such as QSimpleRichText, QWhatsThis and QMessageBox to define the rendering style and - available tags within rich text documents. It serves also as initial - style sheet for the more complex render widgets QTextEdit and - QTextBrowser. + available tags within rich text documents. It also serves as the + initial style sheet for the more complex render widgets, QTextEdit + and QTextBrowser. \sa setDefaultSheet() @@ -1193,7 +1269,7 @@ QStyleSheet* QStyleSheet::defaultSheet() /*! - Sets the application-wide default style sheet to \a sheet, deleting - any style sheet previously set. The ownership is transferred to - QStyleSheet. + Sets the application-wide default style sheet to \a sheet, + deleting any style sheet previously set. The ownership is + transferred to QStyleSheet. \sa defaultSheet() @@ -1223,5 +1299,5 @@ void QStyleSheet::insert( QStyleSheetItem* style ) /*! - Returns the style with name \a name or 0 if there is no such style. + Returns the style called \a name or 0 if there is no such style. */ QStyleSheetItem* QStyleSheet::item( const QString& name) @@ -1234,5 +1310,7 @@ QStyleSheetItem* QStyleSheet::item( const QString& name) /*! \overload - Returns the style with name \a name or 0 if there is no such style (const version) + + Returns the style called \a name or 0 if there is no such style + (const version) */ const QStyleSheetItem* QStyleSheet::item( const QString& name) const @@ -1246,19 +1324,20 @@ const QStyleSheetItem* QStyleSheet::item( const QString& name) const /*! \preliminary + Generates an internal object for the tag called \a name, given the - attributes \a attr, and using additional information provided - by the mime source factory \a factory. + attributes \a attr, and using additional information provided by + the mime source factory \a factory. - \a context is the optional context of the document, i.e. the path to - look for relative links. This becomes important if the text contains - relative references, for example within image tags. QSimpleRichText - always uses the default mime source factory (see - \l{QMimeSourceFactory::defaultFactory()}) to resolve these references. - The context will then be used to calculate the absolute path. See - QMimeSourceFactory::makeAbsolute() for details. + \a context is the optional context of the document, i.e. the path + to look for relative links. This becomes important if the text + contains relative references, for example within image tags. + QSimpleRichText always uses the default mime source factory (see + \l{QMimeSourceFactory::defaultFactory()}) to resolve these + references. The context will then be used to calculate the + absolute path. See QMimeSourceFactory::makeAbsolute() for details. \a emptyTag and \a doc are for internal use only. - This function should not (yet) be used in application code. + This function should not be used in application code. */ QTextCustomItem* QStyleSheet::tag( const QString& name, @@ -1268,14 +1347,11 @@ QTextCustomItem* QStyleSheet::tag( const QString& name, bool /*emptyTag */, QTextDocument *doc ) const { - static QString s_img = QString::fromLatin1("img"); - static QString s_hr = QString::fromLatin1("hr"); - const QStyleSheetItem* style = item( name ); // first some known tags if ( !style ) return 0; - if ( style->name() == s_img ) + if ( style->name() == "img" ) return new QTextImage( doc, attr, context, (QMimeSourceFactory&)factory ); - if ( style->name() == s_hr ) + if ( style->name() == "hr" ) return new QTextHorizontalLine( doc, attr, context, (QMimeSourceFactory&)factory ); return 0; @@ -1283,7 +1359,6 @@ QTextCustomItem* QStyleSheet::tag( const QString& name, -/*! - Auxiliary function. Converts the plain text string \a plain to a - rich text formatted paragraph while preserving its look. +/*! Auxiliary function. Converts the plain text string \a plain to a + rich text formatted paragraph while preserving most of its look. \a mode defines the whitespace mode. Possible values are \c @@ -1301,13 +1376,23 @@ QString QStyleSheet::convertFromPlainText( const QString& plain, QStyleSheetItem for ( int i = 0; i < int(plain.length()); ++i ) { if ( plain[i] == '\n' ){ - if ( col == 1 ) - rich += "<p></p>"; - else - rich += "<br>"; - col = 0; + int c = 1; + while ( i+1 < int(plain.length()) && plain[i+1] == '\n' ) { + i++; + c++; + } + if ( c == 1) + rich += "<br>\n"; + else { + rich += "</p>\n"; + while ( --c > 1 ) + rich += "<br>\n"; + rich += "<p>"; } - else if ( mode == QStyleSheetItem::WhiteSpacePre && plain[i] == '\t' ){ + col = 0; + } else { + if ( mode == QStyleSheetItem::WhiteSpacePre && plain[i] == '\t' ){ rich += 0x00a0U; - while ( col % 4 ) { + ++col; + while ( col % 8 ) { rich += 0x00a0U; ++col; @@ -1326,4 +1411,6 @@ QString QStyleSheet::convertFromPlainText( const QString& plain, QStyleSheetItem ++col; } + } + if ( col != 0 ) rich += "</p>"; return rich; @@ -1359,16 +1446,17 @@ QString QStyleSheet::escape( const QString& plain) This enum is used in widgets that can display both plain text and rich text, e.g. QLabel. It is used for deciding whether a text - string should be interpreted as one or the other. This is - normally done by passing one of the enum values to a setTextFormat() + string should be interpreted as one or the other. This is normally + done by passing one of the enum values to a setTextFormat() function. - \value PlainText The text string is interpreted as a plain text string. + \value PlainText The text string is interpreted as a plain text + string. - \value RichText The text string is interpreted as a rich text string - using the current QStyleSheet::defaultSheet(). + \value RichText The text string is interpreted as a rich text + string using the current QStyleSheet::defaultSheet(). - \value AutoText The text string is interpreted as for \c RichText if - QStyleSheet::mightBeRichText() returns TRUE, otherwise as for \c - PlainText. + \value AutoText The text string is interpreted as for \c RichText + if QStyleSheet::mightBeRichText() returns TRUE, otherwise as + \c PlainText. */ @@ -1377,8 +1465,8 @@ QString QStyleSheet::escape( const QString& plain) otherwise returns FALSE. - Note: The function uses a fast and therefore simple heuristic. It + This function uses a fast and therefore simple heuristic. It mainly checks whether there is something that looks like a tag - before the first line break. Although the result may be correct for - most common cases, there is no guarantee. + before the first line break. Although the result may be correct + for common cases, there is no guarantee. */ bool QStyleSheet::mightBeRichText( const QString& text) @@ -1414,13 +1502,14 @@ bool QStyleSheet::mightBeRichText( const QString& text) -/*! \fn void QStyleSheet::error( const QString& msg) const +/*! + \fn void QStyleSheet::error( const QString& msg) const This virtual function is called when an error occurs when - processing rich text. Reimplement it if you need to catch - error messages. + processing rich text. Reimplement it if you need to catch error + messages. Errors might occur if some rich text strings contain tags that are - not understood by the stylesheet, if some tags are nested incorrectly, or - if tags are not closed properly. + not understood by the stylesheet, if some tags are nested + incorrectly, or if tags are not closed properly. \a msg is the error message. @@ -1435,11 +1524,10 @@ void QStyleSheet::error( const QString& ) const corresponding to the logical font size \a logicalSize. - When calling this function, \a font has a point size corresponding to - the logical font size 3. + When calling this function, \a font has a point size corresponding + to the logical font size 3. Logical font sizes range from 1 to 7, with 1 being the smallest. - \sa QStyleSheetItem::logicalFontSize(), - QStyleSheetItem::logicalFontSizeStep(), QFont::setPointSize() + \sa QStyleSheetItem::logicalFontSize(), QStyleSheetItem::logicalFontSizeStep(), QFont::setPointSize() */ void QStyleSheet::scaleFont( QFont& font, int logicalSize ) const diff --git a/noncore/apps/opie-write/qstylesheet.h b/noncore/apps/opie-write/qstylesheet.h index bb209fa..cb786f5 100644 --- a/noncore/apps/opie-write/qstylesheet.h +++ b/noncore/apps/opie-write/qstylesheet.h @@ -121,4 +121,8 @@ public: bool definesFontUnderline() const; + bool fontStrikeOut() const; + void setFontStrikeOut( bool ); + bool definesFontStrikeOut() const; + bool isAnchor() const; void setAnchor(bool anc); @@ -172,8 +176,8 @@ private: #if defined(Q_TEMPLATEDLL) // MOC_SKIP_BEGIN -template class Q_EXPORT QDict<QStyleSheetItem>; -template class Q_EXPORT QValueList< QPtrVector<QStyleSheetItem> >; -template class Q_EXPORT QPtrVector<QStyleSheetItem>; -template class Q_EXPORT QValueList<QStyleSheetItem::ListStyle>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QStyleSheetItem>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueList< QPtrVector<QStyleSheetItem> >; +Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrVector<QStyleSheetItem>; +Q_TEMPLATE_EXTERN template class Q_EXPORT QValueList<QStyleSheetItem::ListStyle>; // MOC_SKIP_END #endif diff --git a/noncore/apps/opie-write/qt3namespace.h b/noncore/apps/opie-write/qt3namespace.h index 81c5020..557131a 100644 --- a/noncore/apps/opie-write/qt3namespace.h +++ b/noncore/apps/opie-write/qt3namespace.h @@ -3,4 +3,5 @@ #include <qnamespace.h> +#include <qstring.h> #define Q_ASSERT ASSERT diff --git a/noncore/apps/opie-write/qtextedit.cpp b/noncore/apps/opie-write/qtextedit.cpp index 9c5ea79..82401c6 100644 --- a/noncore/apps/opie-write/qtextedit.cpp +++ b/noncore/apps/opie-write/qtextedit.cpp @@ -67,4 +67,6 @@ using namespace Qt3; +static bool qt_enable_richtext_copy = FALSE; + struct QUndoRedoInfoPrivate { @@ -78,9 +80,14 @@ class QTextEditPrivate public: QTextEditPrivate() - :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) {} + :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) + { + for ( int i=0; i<7; i++ ) + id[i] = 0; + } int id[ 7 ]; int preeditStart; int preeditLength; bool ensureCursorVisibleInShowEvent; + QString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized }; @@ -91,5 +98,5 @@ static bool block_set_alignment = FALSE; /*! \class QTextEdit qtextedit.h - \brief The QTextEdit widget provides a sophisticated single-page rich text editor. + \brief The QTextEdit widget provides a powerful single-page rich text editor. \ingroup basic @@ -97,16 +104,72 @@ static bool block_set_alignment = FALSE; \mainclass - QTextEdit is an advanced WYSIWYG editor supporting rich text - formatting. It is optimized to handle large documents and to - respond quickly to user input. + \tableofcontents + + \section1 Introduction and Concepts + + QTextEdit is an advanced WYSIWYG viewer/editor supporting rich + text formatting using HTML-style tags. It is optimized to handle + large documents and to respond quickly to user input. + + QTextEdit has three modes of operation: + \table + \header \i Mode \i Command \i Notes + \row \i Plain Text Editor \i setTextFormat(PlainText) + \i Set text with setText(); text() returns plain text. Text + attributes (e.g. colors) can be set, but plain text is always + returned.<sup>1.</sup> + \row \i Rich Text Editor \i setTextFormat(RichText) + \i Set text with setText(); text() returns rich text. Rich + text editing is fairly limited. You can't set margins or + insert images for example (although you can read and + correctly display files that have margins set and that + include images). This mode is mostly useful for editing small + amounts of rich text. <sup>2.</sup> + \row \i Text Viewer<sup>3.</sup> \i setReadOnly(TRUE) + \i Set text with setText() or append() (which has no undo + history so is faster and uses less memory); text() returns + plain or rich text depending on the textFormat(). This mode + can correctly display a large subset of HTML tags. + \endtable + + <sup>1.</sup><small>We do \e not recommend using QTextEdit to + create syntax highlighting editors because the current API is + insufficient for this purpose. We hope to release a more complete + API that will support syntax highlighting in a later + release.</small> + + <sup>2.</sup><small>A more complete API that supports setting + margins, images, etc., is planned for a later Qt release.</small> + + <sup>3.</sup><small>Qt 3.1 will provide a Log Viewer mode which is + optimised for the fast and memory efficient display of large + amounts of read only text.</small> + + We recommend that you always call setTextFormat() to set the mode + you want to use. If you use \c AutoText then setText() and + append() will try to determine whether the text they are given is + plain text or rich text. If you use \c RichText then setText() and + append() will assume that the text they are given is rich text. + insert() simply inserts the text it is given. QTextEdit works on paragraphs and characters. A paragraph is a formatted string which is word-wrapped to fit into the width of - the widget. A document consists of zero or more paragraphs, - indexed from 0. Characters are indexed on a per-paragraph basis, - also indexed from 0. The words in the paragraph are aligned in - accordance with the paragraph's alignment(). Paragraphs are - separated by hard line breaks. Each character within a paragraph - has its own attributes, for example, font and color. + the widget. By default when reading plain text, two newlines + signify a paragraph. A document consists of zero or more + paragraphs, indexed from 0. Characters are indexed on a + per-paragraph basis, also indexed from 0. The words in the + paragraph are aligned in accordance with the paragraph's + alignment(). Paragraphs are separated by hard line breaks. Each + character within a paragraph has its own attributes, for example, + font and color. + + The text edit documentation uses the following concepts: + \list + \i \e{current format} -- + this is the format at the current cursor position, \e and it + is the format of the selected text if any. + \i \e{current paragraph} -- the paragraph which contains the + cursor. + \endlist QTextEdit can display images (using QMimeSourceFactory), lists and @@ -115,5 +178,6 @@ static bool block_set_alignment = FALSE; plain text and HTML files (a subset of HTML 3.2 and 4). The rendering style and the set of valid tags are defined by a - styleSheet(). Change the style sheet with \l{setStyleSheet()}; see + styleSheet(). Custom tags can be created and placed in a custom + style sheet. Change the style sheet with \l{setStyleSheet()}; see QStyleSheet for details. The images identified by image tags are displayed if they can be interpreted using the text edit's @@ -135,62 +199,27 @@ static bool block_set_alignment = FALSE; text. - The text edit documentation uses the following concepts: - \list - \i <i>current format</i> -- - this is the format at the current cursor position, \e and it - is the format of the selected text if any. - \i <i>current paragraph</i> -- the paragraph which contains the - cursor. - \endlist + Note that we do not intend to add a full-featured web browser + widget to Qt (because that would easily double Qt's size and only + a few applications would benefit from it). The rich + text support in Qt is designed to provide a fast, portable and + efficient way to add reasonable online help facilities to + applications, and to provide a basis for rich text editors. + \section1 Using QTextEdit as a Display Widget + + QTextEdit can display a large HTML subset, including tables and + images. The text is set or replaced using setText() which deletes any existing text and replaces it with the text passed in the - setText() call. Text can be inserted with insert(), paste() and - pasteSubType(). Text can also be cut(). The entire text is deleted - with clear() and the selected text is deleted with - removeSelectedText(). Selected (marked) text can also be deleted - with del() (which will delete the character to the right of the - cursor if no text is selected). - - The current format's attributes are set with setItalic(), - setBold(), setUnderline(), setFamily() (font family), - setPointSize(), setColor() and setCurrentFont(). The current - paragraph's style is set with setParagType() and its alignment is - set with setAlignment(). - - Use setSelection() to select text. The setSelectionAttributes() - function is used to indicate how selected text should be - displayed. Use hasSelectedText() to find out if any text is - selected. The currently selected text's position is available - using getSelection() and the selected text itself is returned by - selectedText(). The selection can be copied to the clipboard with - copy(), or cut to the clipboard with cut(). It can be deleted with - removeSelectedText(). The entire text can be selected (or - unselected) using selectAll(). QTextEdit supports multiple - selections. Most of the selection functions operate on the default - selection, selection 0. If the user presses a non-selecting key, - e.g. a cursor key without also holding down Shift, all selections - are cleared. - - Set and get the position of the cursor with setCursorPosition() - and getCursorPosition() respectively. When the cursor is moved, - the signals currentFontChanged(), currentColorChanged() and - currentAlignmentChanged() are emitted to reflect the font, color - and alignment at the new cursor position. - - If the text changes, the textChanged() signal is emitted, and if - the user inserts a new line by pressing Return or Enter, - returnPressed() is emitted. The isModified() function will return - TRUE if the text has been modified. - - QTextEdit provides command-based undo and redo. To set the depth - of the command history use setUndoDepth() which defaults to 100 - steps. To undo or redo the last operation call undo() or redo(). - The signals undoAvailable() and redoAvailable() indicate whether - the undo and redo operations can be executed. - - The indent() function is used to reindent a paragraph. It is - useful for code editors, for example in <em>Qt Designer</em>'s - code editor \e{Ctrl+I} invokes the indent() function. + setText() call. If you call setText() with legacy HTML (with + setTextFormat(RichText) in force), and then call text(), the text + that is returned may have different markup, but will render the + same. Text can be inserted with insert(), paste(), pasteSubType() + and append(). Text that is appended does not go into the undo + history; this makes append() faster and consumes less memory. Text + can also be cut(). The entire text is deleted with clear() and the + selected text is deleted with removeSelectedText(). Selected + (marked) text can also be deleted with del() (which will delete + the character to the right of the cursor if no text is selected). Loading and saving text is achieved using setText() and text(), @@ -244,4 +273,83 @@ static bool block_set_alignment = FALSE; used to find and select a given string within the text. + A read-only QTextEdit provides the same functionality as the + (obsolete) QTextView. (QTextView is still supplied for + compatibility with old code.) + + \section2 Read-only key bindings + + When QTextEdit is used read-only the key-bindings are limited to + navigation, and text may only be selected with the mouse: + \table + \header \i Keypresses \i Action + \row \i \e{UpArrow} \i Move one line up + \row \i \e{DownArrow} \i Move one line down + \row \i \e{LeftArrow} \i Move one character left + \row \i \e{RightArrow} \i Move one character right + \row \i \e{PageUp} \i Move one (viewport) page up + \row \i \e{PageDown} \i Move one (viewport) page down + \row \i \e{Home} \i Move to the beginning of the text + \row \i \e{End} \i Move to the end of the text + \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel) + \row \i \e{Ctrl+Wheel} \i Zoom the text + \endtable + + The text edit may be able to provide some meta-information. For + example, the documentTitle() function will return the text from + within HTML \c{<title>} tags. + + The text displayed in a text edit has a \e context. The context is + a path which the text edit's QMimeSourceFactory uses to resolve + the locations of files and images. It is passed to the + mimeSourceFactory() when quering data. (See QTextEdit() and + \l{context()}.) + + \section1 Using QTextEdit as an Editor + + All the information about using QTextEdit as a display widget also + applies here. + + The current format's attributes are set with setItalic(), + setBold(), setUnderline(), setFamily() (font family), + setPointSize(), setColor() and setCurrentFont(). The current + paragraph's alignment is set with setAlignment(). + + Use setSelection() to select text. The setSelectionAttributes() + function is used to indicate how selected text should be + displayed. Use hasSelectedText() to find out if any text is + selected. The currently selected text's position is available + using getSelection() and the selected text itself is returned by + selectedText(). The selection can be copied to the clipboard with + copy(), or cut to the clipboard with cut(). It can be deleted with + removeSelectedText(). The entire text can be selected (or + unselected) using selectAll(). QTextEdit supports multiple + selections. Most of the selection functions operate on the default + selection, selection 0. If the user presses a non-selecting key, + e.g. a cursor key without also holding down Shift, all selections + are cleared. + + Set and get the position of the cursor with setCursorPosition() + and getCursorPosition() respectively. When the cursor is moved, + the signals currentFontChanged(), currentColorChanged() and + currentAlignmentChanged() are emitted to reflect the font, color + and alignment at the new cursor position. + + If the text changes, the textChanged() signal is emitted, and if + the user inserts a new line by pressing Return or Enter, + returnPressed() is emitted. The isModified() function will return + TRUE if the text has been modified. + + QTextEdit provides command-based undo and redo. To set the depth + of the command history use setUndoDepth() which defaults to 100 + steps. To undo or redo the last operation call undo() or redo(). + The signals undoAvailable() and redoAvailable() indicate whether + the undo and redo operations can be executed. + + The indent() function is used to reindent a paragraph. It is + useful for code editors, for example in <em>Qt Designer</em>'s + code editor \e{Ctrl+I} invokes the indent() function. + + \section2 Editing key bindings + The list of key-bindings which are implemented for editing: \table @@ -296,41 +404,4 @@ static bool block_set_alignment = FALSE; the right of the cursor, using setOverwriteMode(). - QTextEdit can also be used as read-only text viewer. Call - setReadOnly( TRUE ) to disable editing. A read-only QTextEdit - provides the same functionality as the (obsolete) QTextView. - (QTextView is still supplied for compatibility with old code.) - - When QTextEdit is used read-only the key-bindings are limited to - navigation, and text may only be selected with the mouse: - \table - \header \i Keypresses \i Action - \row \i \e{UpArrow} \i Move one line up - \row \i \e{DownArrow} \i Move one line down - \row \i \e{LeftArrow} \i Move one character left - \row \i \e{RightArrow} \i Move one character right - \row \i \e{PageUp} \i Move one (viewport) page up - \row \i \e{PageDown} \i Move one (viewport) page down - \row \i \e{Home} \i Move to the beginning of the text - \row \i \e{End} \i Move to the end of the text - \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel) - \row \i \e{Ctrl+Wheel} \i Zoom the text - \endtable - - The text edit may be able to provide some meta-information. For - example, the documentTitle() function will return the text from - within HTML \c{<title>} tags. - - The text displayed in a text edit has a \e context. The context is - a path which the text edit's QMimeSourceFactory uses to resolve - the locations of files and images. It is passed to the - mimeSourceFactory() when quering data. (See QTextEdit() and - \l{context()}.) - - Note that we do not intend to add a full-featured web browser - widget to Qt (because that would easily double Qt's size and only - a few applications would benefit from it). The rich - text support in Qt is designed to provide a fast, portable and - efficient way to add reasonable online help facilities to - applications, and to provide a basis for rich text editors. */ @@ -641,4 +712,6 @@ void QTextEdit::init() doc->setFormatter( new QTextFormatterBreakWords ); + doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() ); + doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( QColorGroup::Text ) ); currentFormat = doc->formatCollection()->defaultFormat(); currentAlignment = Qt3::AlignAuto; @@ -646,6 +719,6 @@ void QTextEdit::init() viewport()->setBackgroundMode( PaletteBase ); viewport()->setAcceptDrops( TRUE ); - resizeContents( 0, doc->lastParag() ? - ( doc->lastParag()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); + resizeContents( 0, doc->lastParagraph() ? + ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); setKeyCompression( TRUE ); @@ -659,5 +732,5 @@ void QTextEdit::init() connect( formatTimer, SIGNAL( timeout() ), this, SLOT( formatMore() ) ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); scrollTimer = new QTimer( this ); @@ -714,8 +787,8 @@ void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); - if ( lastFormatted == doc->lastParag() ) + if ( lastFormatted == doc->lastParagraph() ) resizeContents( contentsWidth(), doc->height() ); - if ( contentsHeight() < visibleHeight() && ( !doc->lastParag() || doc->lastParag()->isValid() ) && drawAll ) + if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll ) p->fillRect( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) ); @@ -814,9 +887,15 @@ bool QTextEdit::event( QEvent *e ) } - if ( e->type() == QEvent::Show && d->ensureCursorVisibleInShowEvent ) { + if ( e->type() == QEvent::Show ) { + if ( d->ensureCursorVisibleInShowEvent ) { sync(); ensureCursorVisible(); d->ensureCursorVisibleInShowEvent = FALSE; } + if ( !d->scrollToAnchor.isEmpty() ) { + scrollToAnchor( d->scrollToAnchor ); + d->scrollToAnchor = QString::null; + } + } return QWidget::event( e ); } @@ -846,5 +925,5 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) if ( selChanged ) { - cursor->parag()->document()->nextDoubleBuffered = TRUE; + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; repaintChanged(); } @@ -859,5 +938,5 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) // correct semantics and movement for BiDi and non BiDi text. CursorAction a; - if ( cursor->parag()->string()->isRightToLeft() == (e->key() == Key_Right) ) + if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) ) a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; else @@ -887,4 +966,8 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) if ( doc->hasSelection( QTextDocument::Standard, FALSE ) ) removeSelectedText(); + if ( textFormat() == Qt::RichText && ( e->state() & ControlButton ) ) { + // Ctrl-Enter inserts a line break in rich text mode + insert( QString( QChar( 0x2028) ), TRUE, FALSE, TRUE ); + } else { #ifndef QT_NO_CURSOR viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); @@ -893,4 +976,5 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) doKeyboardAction( ActionReturn ); emit returnPressed(); + } break; case Key_Delete: @@ -912,4 +996,8 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) if ( e->state() & ShiftButton ) paste(); +#if defined (Q_WS_WIN) + else if ( e->state() & ControlButton ) + copy(); +#endif break; case Key_Backspace: @@ -919,8 +1007,4 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) } - if ( !cursor->parag()->prev() && - cursor->atParagStart() ) - break; - doKeyboardAction( ActionBackspace ); clearUndoRedoInfo = FALSE; @@ -944,9 +1028,12 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) clearUndoRedoInfo = FALSE; if ( e->key() == Key_Tab ) { - if ( textFormat() == Qt::RichText && - cursor->index() == 0 && cursor->parag()->style() && - cursor->parag()->style()->displayMode() == - QStyleSheetItem::DisplayListItem ) { - cursor->parag()->incDepth(); + if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 ); + clearUndoRedo(); drawCursor( FALSE ); repaintChanged(); @@ -955,17 +1042,24 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) } } - if ( textFormat() == Qt::RichText && ( !cursor->parag()->style() || - cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayBlock ) && - cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { + + if ( textFormat() == Qt::RichText && !cursor->paragraph()->isListItem() ) { + if ( cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); - cursor->parag()->incDepth(); + clearUndoRedo(); drawCursor( FALSE ); repaintChanged(); drawCursor( TRUE ); - } else { + break; + } + } if ( overWrite && !cursor->atParagEnd() ) cursor->remove(); QString t = e->text(); - QTextParag *p = cursor->parag(); + QTextParagraph *p = cursor->paragraph(); if ( p && p->string() && p->string()->isRightToLeft() ) { QChar *c = (QChar *)t.unicode(); @@ -978,5 +1072,4 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) } insert( t, TRUE, FALSE, TRUE ); - } break; } else if ( e->state() & ControlButton ) { @@ -1020,5 +1113,5 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) break; } - if ( !cursor->parag()->prev() && + if ( !cursor->paragraph()->prev() && cursor->atParagStart() ) break; @@ -1037,4 +1130,7 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) break; case Key_Z: + if(e->state() & ShiftButton) + redo(); + else undo(); break; @@ -1064,5 +1160,5 @@ void QTextEdit::keyPressEvent( QKeyEvent *e ) emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); if ( clearUndoRedoInfo ) clearUndoRedo(); @@ -1085,106 +1181,89 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) return; - lastFormatted = cursor->parag(); + lastFormatted = cursor->paragraph(); drawCursor( FALSE ); bool doUpdateCurrentFormat = TRUE; switch ( action ) { - case ActionDelete: { + case ActionDelete: + if ( !cursor->atParagEnd() ) { checkUndoRedoInfo( UndoRedoInfo::Delete ); if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); + undoRedoInfo.id = cursor->paragraph()->paragId(); undoRedoInfo.index = cursor->index(); undoRedoInfo.d->text = QString::null; } - undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; - if ( cursor->parag()->at( cursor->index() )->format() ) { - cursor->parag()->at( cursor->index() )->format()->addRef(); - undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); - } - QTextParag *old = cursor->parag(); - if ( cursor->remove() ) { - if ( old != cursor->parag() && lastFormatted == old ) - lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; - undoRedoInfo.d->text += "\n"; + undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( cursor->index() ), TRUE ); + cursor->remove(); + } else { + clearUndoRedo(); + doc->setSelectionStart( QTextDocument::Temp, *cursor ); + cursor->gotoNextLetter(); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + removeSelectedText( QTextDocument::Temp ); } - } break; + break; case ActionBackspace: - if ( textFormat() == Qt::RichText && - cursor->parag()->style() && - cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayListItem && - cursor->index() == 0 ) { - cursor->parag()->decDepth(); - lastFormatted = cursor->parag(); + if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() && cursor->index() == 0 ) { + clearUndoRedo(); + undoRedoInfo.type = UndoRedoInfo::Style; + undoRedoInfo.id = cursor->paragraph()->paragId(); + undoRedoInfo.eid = undoRedoInfo.id; + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + int ldepth = cursor->paragraph()->listDepth(); + ldepth = QMAX( ldepth-1, 0 ); + cursor->paragraph()->setListDepth( ldepth ); + if ( ldepth == 0 ) + cursor->paragraph()->setListItem( FALSE ); + clearUndoRedo(); + lastFormatted = cursor->paragraph(); repaintChanged(); drawCursor( TRUE ); return; } + if ( !cursor->atParagStart() ) { checkUndoRedoInfo( UndoRedoInfo::Delete ); if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); + undoRedoInfo.id = cursor->paragraph()->paragId(); undoRedoInfo.index = cursor->index(); undoRedoInfo.d->text = QString::null; } cursor->gotoPreviousLetter(); - undoRedoInfo.d->text.prepend( QString( cursor->parag()->at( cursor->index() )->c ) ); - if ( cursor->parag()->at( cursor->index() )->format() ) { - cursor->parag()->at( cursor->index() )->format()->addRef(); - undoRedoInfo.d->text.at( 0 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); - } - undoRedoInfo.index = cursor->index(); - if ( cursor->remove() ) { - undoRedoInfo.d->text.remove( 0, 1 ); - undoRedoInfo.d->text.prepend( "\n" ); + undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index() ), TRUE ); undoRedoInfo.index = cursor->index(); - undoRedoInfo.id = cursor->parag()->paragId(); + cursor->remove(); + lastFormatted = cursor->paragraph(); + } else if ( cursor->paragraph()->prev() ){ + clearUndoRedo(); + doc->setSelectionStart( QTextDocument::Temp, *cursor ); + cursor->gotoPreviousLetter(); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + removeSelectedText( QTextDocument::Temp ); } - lastFormatted = cursor->parag(); break; - case ActionReturn: { + case ActionReturn: checkUndoRedoInfo( UndoRedoInfo::Return ); if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); + undoRedoInfo.id = cursor->paragraph()->paragId(); undoRedoInfo.index = cursor->index(); undoRedoInfo.d->text = QString::null; } undoRedoInfo.d->text += "\n"; - cursor->splitAndInsertEmptyParag(); - if ( cursor->parag()->prev() ) { - lastFormatted = cursor->parag()->prev(); + cursor->splitAndInsertEmptyParagraph(); + if ( cursor->paragraph()->prev() ) { + lastFormatted = cursor->paragraph()->prev(); lastFormatted->invalidate( 0 ); } doUpdateCurrentFormat = FALSE; - } break; + break; case ActionKill: - checkUndoRedoInfo( UndoRedoInfo::Delete ); - if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.index = cursor->index(); - undoRedoInfo.d->text = QString::null; - } - if ( cursor->atParagEnd() ) { - undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; - if ( cursor->parag()->at( cursor->index() )->format() ) { - cursor->parag()->at( cursor->index() )->format()->addRef(); - undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); - } - QTextParag *old = cursor->parag(); - if ( cursor->remove() ) { - if ( old != cursor->parag() && lastFormatted == old ) - lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; - undoRedoInfo.d->text += "\n"; - } - } else { - int oldLen = undoRedoInfo.d->text.length(); - undoRedoInfo.d->text += cursor->parag()->string()->toString().mid( cursor->index() ); - for ( int i = cursor->index(); i < cursor->parag()->length(); ++i ) { - if ( cursor->parag()->at( i )->format() ) { - cursor->parag()->at( i )->format()->addRef(); - undoRedoInfo.d->text.at( oldLen + i - cursor->index() ).setFormat( cursor->parag()->at( i )->format() ); - } - } - undoRedoInfo.d->text.remove( undoRedoInfo.d->text.length() - 1, 1 ); - cursor->killLine(); - } + clearUndoRedo(); + doc->setSelectionStart( QTextDocument::Temp, *cursor ); + if ( cursor->atParagEnd() ) + cursor->gotoNextLetter(); + else + cursor->setIndex( cursor->paragraph()->length() - 1 ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + removeSelectedText( QTextDocument::Temp ); break; } @@ -1194,14 +1273,5 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) ensureCursorVisible(); drawCursor( TRUE ); - - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } - + updateMicroFocusHint(); if ( doUpdateCurrentFormat ) updateCurrentFormat(); @@ -1210,60 +1280,36 @@ void QTextEdit::doKeyboardAction( KeyboardAction action ) } -void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles ) +void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles ) { + QDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly ); c2.restoreState(); c1.restoreState(); - if ( c1.parag() == c2.parag() ) { - for ( int i = c1.index(); i < c2.index(); ++i ) { - if ( c1.parag()->at( i )->format() ) { - c1.parag()->at( i )->format()->addRef(); - text.at( oldLen + i - c1.index() ).setFormat( c1.parag()->at( i )->format() ); - } - } + int lastIndex = text.length(); + if ( c1.paragraph() == c2.paragraph() ) { + for ( int i = c1.index(); i < c2.index(); ++i ) + text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE ); if ( fillStyles ) { - undoRedoInfo.oldAligns[ 0 ] = c1.parag()->alignment(); - undoRedoInfo.oldStyles << c1.parag()->styleSheetItems(); - undoRedoInfo.oldListStyles << c1.parag()->listStyle(); + styleStream << (int) 1; + c1.paragraph()->writeStyleInformation( styleStream ); } } else { - int lastIndex = oldLen; int i; - for ( i = c1.index(); i < c1.parag()->length(); ++i ) { - if ( c1.parag()->at( i )->format() ) { - c1.parag()->at( i )->format()->addRef(); - text.at( lastIndex ).setFormat( c1.parag()->at( i )->format() ); - lastIndex++; - } - } - QTextParag *p = c1.parag()->next(); - while ( p && p != c2.parag() ) { - for ( int i = 0; i < p->length(); ++i ) { - if ( p->at( i )->format() ) { - p->at( i )->format()->addRef(); - text.at( i + lastIndex ).setFormat( p->at( i )->format() ); - } - } - lastIndex += p->length(); + for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i ) + text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE ); + int num = 2; // start and end, being different + text += "\n"; lastIndex++; + QTextParagraph *p = c1.paragraph()->next(); + while ( p && p != c2.paragraph() ) { + for ( i = 0; i < p->length()-1; ++i ) + text.insert( lastIndex++ , p->at( i ), TRUE ); + text += "\n"; num++; lastIndex++; p = p->next(); } - for ( i = 0; i < c2.index(); ++i ) { - if ( c2.parag()->at( i )->format() ) { - c2.parag()->at( i )->format()->addRef(); - text.at( i + lastIndex ).setFormat( c2.parag()->at( i )->format() ); - } - } + for ( i = 0; i < c2.index(); ++i ) + text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE ); if ( fillStyles ) { - QTextParag *p = c1.parag(); - i = 0; - while ( p ) { - if ( i < (int)undoRedoInfo.oldAligns.size() ) - undoRedoInfo.oldAligns[ i ] = p->alignment(); - undoRedoInfo.oldStyles << p->styleSheetItems(); - undoRedoInfo.oldListStyles << p->listStyle(); - if ( p == c2.parag() ) - break; - p = p->next(); - ++i; - } + styleStream << num; + for ( QTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() ) + p->writeStyleInformation( styleStream ); } } @@ -1295,7 +1341,9 @@ void QTextEdit::removeSelectedText( int selNum ) QTextCursor c1 = doc->selectionStartCursor( selNum ); + c1.restoreState(); QTextCursor c2 = doc->selectionEndCursor( selNum ); + c2.restoreState(); - // ### no support for editing tables yet + // ### no support for editing tables yet, plus security for broken selections if ( c1.nestedDepth() || c2.nestedDepth() ) return; @@ -1313,12 +1361,11 @@ void QTextEdit::removeSelectedText( int selNum ) undoRedoInfo.d->text = QString::null; } - int oldLen = undoRedoInfo.d->text.length(); - undoRedoInfo.d->text = doc->selectedText( selNum, FALSE ); - undoRedoInfo.oldAligns.resize( undoRedoInfo.oldAligns.size() + QMAX( 0, c2.parag()->paragId() - c1.parag()->paragId() + 1 ) ); - readFormats( c1, c2, oldLen, undoRedoInfo.d->text, TRUE ); + readFormats( c1, c2, undoRedoInfo.d->text, TRUE ); + + doc->removeSelectedText( selNum, cursor ); if ( cursor->isValid() ) { ensureCursorVisible(); - lastFormatted = cursor->parag(); + lastFormatted = cursor->paragraph(); formatMore(); repaintChanged(); @@ -1335,16 +1382,8 @@ void QTextEdit::removeSelectedText( int selNum ) viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); #endif - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); } else { - cursor->setDocument( doc ); - cursor->setParag( doc->firstParag() ); - cursor->setIndex( 0 ); + delete cursor; + cursor = new QTextCursor( doc ); drawCursor( TRUE ); viewport()->repaint( TRUE ); @@ -1366,8 +1405,8 @@ void QTextEdit::moveCursor( CursorAction action, bool select ) if ( select ) { if ( !doc->hasSelection( QTextDocument::Standard ) ) - doc->setSelectionStart( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, *cursor ); moveCursor( action ); - if ( doc->setSelectionEnd( QTextDocument::Standard, cursor ) ) { - cursor->parag()->document()->nextDoubleBuffered = TRUE; + if ( doc->setSelectionEnd( QTextDocument::Standard, *cursor ) ) { + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; repaintChanged(); } else { @@ -1384,5 +1423,5 @@ void QTextEdit::moveCursor( CursorAction action, bool select ) drawCursor( TRUE ); } else { - cursor->parag()->document()->nextDoubleBuffered = TRUE; + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; repaintChanged(); ensureCursorVisible(); @@ -1400,12 +1439,5 @@ void QTextEdit::moveCursor( CursorAction action, bool select ) drawCursor( TRUE ); updateCurrentFormat(); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); } @@ -1450,17 +1482,9 @@ void QTextEdit::moveCursor( CursorAction action ) break; case MoveEnd: - ensureFormatted( doc->lastParag() ); + ensureFormatted( doc->lastParagraph() ); cursor->gotoEnd(); break; } - - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); updateCurrentFormat(); } @@ -1471,4 +1495,6 @@ void QTextEdit::resizeEvent( QResizeEvent *e ) { QScrollView::resizeEvent( e ); + if ( doc->visibleWidth() == 0 ) + doResize(); } @@ -1478,9 +1504,12 @@ void QTextEdit::viewportResizeEvent( QResizeEvent *e ) { QScrollView::viewportResizeEvent( e ); - if ( e->oldSize().width() != e->size().width() ) + if ( e->oldSize().width() != e->size().width() ) { + bool stayAtBottom = e->oldSize().height() != e->size().height() && + contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height(); doResize(); + if ( stayAtBottom ) + scrollToBottom(); + } } - -static bool blockEnsureCursorVisible = FALSE; /*! @@ -1493,18 +1522,16 @@ static bool blockEnsureCursorVisible = FALSE; void QTextEdit::ensureCursorVisible() { - if ( blockEnsureCursorVisible ) - return; if ( !isVisible() ) { d->ensureCursorVisibleInShowEvent = TRUE; return; } - lastFormatted = cursor->parag(); + lastFormatted = cursor->paragraph(); formatMore(); - QTextStringChar *chr = cursor->parag()->at( cursor->index() ); - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - int x = cursor->parag()->rect().x() + chr->x + cursor->offsetX(); + QTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); + int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX(); int y = 0; int dummy; - cursor->parag()->lineHeightOfChar( cursor->index(), &dummy, &y ); - y += cursor->parag()->rect().y() + cursor->offsetY(); + cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); + y += cursor->paragraph()->rect().y() + cursor->offsetY(); int w = 1; ensureVisible( x, y + h / 2, w, h / 2 + 2 ); @@ -1518,6 +1545,6 @@ void QTextEdit::drawCursor( bool visible ) if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() || - !cursor->parag() || - !cursor->parag()->isValid() || + !cursor->paragraph() || + !cursor->paragraph()->isValid() || !selectedText().isEmpty() || ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || @@ -1526,19 +1553,19 @@ void QTextEdit::drawCursor( bool visible ) QPainter p( viewport() ); - QRect r( cursor->topParag()->rect() ); - cursor->parag()->setChanged( TRUE ); + QRect r( cursor->topParagraph()->rect() ); + cursor->paragraph()->setChanged( TRUE ); p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); QPixmap *pix = 0; QColorGroup cg( colorGroup() ); - if ( cursor->parag()->background() ) - cg.setBrush( QColorGroup::Base, *cursor->parag()->background() ); + if ( cursor->paragraph()->background() ) + cg.setBrush( QColorGroup::Base, *cursor->paragraph()->background() ); else if ( doc->paper() ) cg.setBrush( QColorGroup::Base, *doc->paper() ); p.setBrushOrigin( -contentsX(), -contentsY() ); - cursor->parag()->document()->nextDoubleBuffered = TRUE; + cursor->paragraph()->document()->nextDoubleBuffered = TRUE; if ( !cursor->nestedDepth() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); + int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); int dist = 5; - if ( ( cursor->parag()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) + if ( ( cursor->paragraph()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) dist = 50; int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; @@ -1546,8 +1573,8 @@ void QTextEdit::drawCursor( bool visible ) p.setClipRect( QRect( x - contentsX(), r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); - doc->drawParag( &p, cursor->parag(), x, + doc->drawParagraph( &p, cursor->paragraph(), x, r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); } else { - doc->drawParag( &p, cursor->parag(), r.x() - cursor->totalOffsetX(), + doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(), r.y() - cursor->totalOffsetY(), r.width(), r.height(), pix, cg, visible, cursor ); @@ -1603,7 +1630,7 @@ void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) QTextCursor c = *cursor; placeCursor( e->pos(), &c, TRUE ); - if ( c.parag() && c.parag()->at( c.index() ) && - c.parag()->at( c.index() )->isAnchor() ) { - pressedLink = c.parag()->at( c.index() )->anchorHref(); + if ( c.paragraph() && c.paragraph()->at( c.index() ) && + c.paragraph()->at( c.index() )->isAnchor() ) { + pressedLink = c.paragraph()->at( c.index() )->anchorHref(); } } @@ -1623,14 +1650,14 @@ void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) if ( !( e->state() & ShiftButton ) ) { redraw = doc->removeSelection( QTextDocument::Standard ); - doc->setSelectionStart( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, *cursor ); } else { - redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; + redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; } } else { if ( isReadOnly() || !( e->state() & ShiftButton ) ) { - doc->setSelectionStart( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, *cursor ); } else { - doc->setSelectionStart( QTextDocument::Standard, &c ); - redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; + doc->setSelectionStart( QTextDocument::Standard, c ); + redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; } } @@ -1715,5 +1742,5 @@ void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e ) } emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); if ( oldCursor != *cursor ) updateCurrentFormat(); @@ -1745,11 +1772,11 @@ void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * ) QTextCursor c1 = *cursor; QTextCursor c2 = *cursor; - if ( cursor->index() > 0 && !cursor->parag()->at( cursor->index()-1 )->c.isSpace() ) + if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() ) c1.gotoPreviousWord(); - if ( !cursor->parag()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) + if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) c2.gotoNextWord(); - doc->setSelectionStart( QTextDocument::Standard, &c1 ); - doc->setSelectionEnd( QTextDocument::Standard, &c2 ); + doc->setSelectionStart( QTextDocument::Standard, c1 ); + doc->setSelectionEnd( QTextDocument::Standard, c2 ); *cursor = c2; @@ -1807,7 +1834,40 @@ void QTextEdit::contentsDropEvent( QDropEvent *e ) bool intern = FALSE; if ( QTextDrag::decode( e, text ) ) { - if ( ( e->source() == this || - e->source() == viewport() ) && - e->action() == QDropEvent::Move ) { + bool hasSel = doc->hasSelection( QTextDocument::Standard ); + bool internalDrag = e->source() == this || e->source() == viewport(); + int dropId, dropIndex; + QTextCursor insertCursor = *cursor; + dropId = cursor->paragraph()->paragId(); + dropIndex = cursor->index(); + if ( hasSel && internalDrag ) { + QTextCursor c1, c2; + int selStartId, selStartIndex; + int selEndId, selEndIndex; + c1 = doc->selectionStartCursor( QTextDocument::Standard ); + c1.restoreState(); + c2 = doc->selectionEndCursor( QTextDocument::Standard ); + c2.restoreState(); + selStartId = c1.paragraph()->paragId(); + selStartIndex = c1.index(); + selEndId = c2.paragraph()->paragId(); + selEndIndex = c2.index(); + if ( ( ( dropId > selStartId ) || + ( dropId == selStartId && dropIndex > selStartIndex ) ) && + ( ( dropId < selEndId ) || + ( dropId == selEndId && dropIndex <= selEndIndex ) ) ) + insertCursor = c1; + if ( dropId == selEndId && dropIndex > selEndIndex ) { + insertCursor = c1; + if ( selStartId == selEndId ) { + insertCursor.setIndex( dropIndex - + ( selEndIndex - selStartIndex ) ); + } else { + insertCursor.setIndex( dropIndex - selEndIndex + + selStartIndex ); + } + } + } + + if ( internalDrag && e->action() == QDropEvent::Move ) { removeSelectedText(); intern = TRUE; @@ -1819,5 +1879,6 @@ void QTextEdit::contentsDropEvent( QDropEvent *e ) } drawCursor( FALSE ); - placeCursor( e->pos(), cursor ); + cursor->setParagraph( insertCursor.paragraph() ); + cursor->setIndex( insertCursor.index() ); drawCursor( TRUE ); if ( !cursor->nestedDepth() ) { @@ -1860,11 +1921,11 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) cr.gotoNextWord(); - int diff = QABS( oldCursor.parag()->at( oldCursor.index() )->x - mousePos.x() ); - int ldiff = QABS( cl.parag()->at( cl.index() )->x - mousePos.x() ); - int rdiff = QABS( cr.parag()->at( cr.index() )->x - mousePos.x() ); + int diff = QABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() ); + int ldiff = QABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() ); + int rdiff = QABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() ); - if ( cursor->parag()->lineStartOfChar( cursor->index() ) != - oldCursor.parag()->lineStartOfChar( oldCursor.index() ) ) + if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) != + oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) ) diff = 0xFFFFFF; @@ -1881,5 +1942,5 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) bool redraw = FALSE; if ( doc->hasSelection( QTextDocument::Standard ) ) { - redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; + redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; } @@ -1891,7 +1952,7 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) } - if ( currentFormat && currentFormat->key() != cursor->parag()->at( cursor->index() )->format()->key() ) { + if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) { currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( cursor->parag()->at( cursor->index() )->format() ); + currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() ); if ( currentFormat->isMisspelled() ) { currentFormat->removeRef(); @@ -1903,6 +1964,6 @@ void QTextEdit::handleMouseMove( const QPoint& pos ) } - if ( currentAlignment != cursor->parag()->alignment() ) { - currentAlignment = cursor->parag()->alignment(); + if ( currentAlignment != cursor->paragraph()->alignment() ) { + currentAlignment = cursor->paragraph()->alignment(); block_set_alignment = TRUE; emit currentAlignmentChanged( currentAlignment ); @@ -1926,16 +1987,28 @@ void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link ) c->restoreState(); - QTextParag *s = doc->firstParag(); + QTextParagraph *s = doc->firstParagraph(); c->place( pos, s, link ); + updateMicroFocusHint(); +} + + +void QTextEdit::updateMicroFocusHint() +{ + QTextCursor c( *cursor ); + if ( d->preeditStart != -1 ) + c.setIndex( d->preeditStart ); + if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); + int h = c.paragraph()->lineHeightOfChar( cursor->index() ); if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); + QFont f = c.paragraph()->at( c.index() )->format()->font(); + setMicroFocusHint( c.x() - contentsX() + frameWidth(), + c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); } } } + + void QTextEdit::formatMore() { @@ -1945,5 +2018,5 @@ void QTextEdit::formatMore() int bottom = contentsHeight(); int lastBottom = -1; - int to = !sender() ? 2 : 20; + int to = 20; bool firstVisible = FALSE; QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); @@ -1962,8 +2035,12 @@ void QTextEdit::formatMore() } - if ( bottom > contentsHeight() ) + if ( bottom > contentsHeight() ) { resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) ); - else if ( lastBottom != -1 && lastBottom < contentsHeight() ) + } else if ( lastBottom != -1 && lastBottom < contentsHeight() ) { resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); + if ( contentsHeight() < visibleHeight() ) + updateContents( 0, contentsHeight(), visibleWidth(), + visibleHeight() - contentsHeight() ); + } if ( lastFormatted ) @@ -1981,5 +2058,5 @@ void QTextEdit::doResize() doc->setWidth( visibleWidth() ); doc->invalidate(); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; formatMore(); @@ -2002,14 +2079,5 @@ bool QTextEdit::eventFilter( QObject *o, QEvent *e ) blinkTimer->start( QApplication::cursorFlashTime() / 2 ); drawCursor( TRUE ); - - if ( !readonly ) { - // make sure the micro focus hint is updated... - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - - contentsY() + frameWidth(), 0, - cursor->parag()->lineHeightOfChar( cursor->index() ), - TRUE ); - } + updateMicroFocusHint(); } else if ( e->type() == QEvent::FocusOut ) { blinkTimer->stop(); @@ -2021,12 +2089,12 @@ bool QTextEdit::eventFilter( QObject *o, QEvent *e ) } -/*! - Inserts \a text at the current cursor position. If \a indent is TRUE, - the paragraph is re-indented. If \a checkNewLine is TRUE, newline - characters in \a text result in hard line breaks (i.e. new - paragraphs). If \a checkNewLine is FALSE the behaviour of the editor - is undefined if the \a text contains newlines. If \a removeSelected is - TRUE, any selected text (in selection 0) is removed before the text is - inserted. +/*! Inserts \a text at the current cursor position. If \a indent is + TRUE, the paragraph is re-indented. If \a checkNewLine is TRUE, + newline characters in \a text result in hard line breaks (i.e. new + paragraphs). If \a checkNewLine is FALSE and there are newlines in + \a text, the behavior is undefined. If \a checkNewLine is FALSE the + behaviour of the editor is undefined if the \a text contains + newlines. If \a removeSelected is TRUE, any selected text (in + selection 0) is removed before the text is inserted. \sa paste() pasteSubType() @@ -2047,5 +2115,5 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo checkUndoRedoInfo( UndoRedoInfo::Insert ); if ( !undoRedoInfo.valid() ) { - undoRedoInfo.id = cursor->parag()->paragId(); + undoRedoInfo.id = cursor->paragraph()->paragId(); undoRedoInfo.index = cursor->index(); undoRedoInfo.d->text = QString::null; @@ -2054,11 +2122,11 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo } - lastFormatted = checkNewLine && cursor->parag()->prev() ? - cursor->parag()->prev() : cursor->parag(); + lastFormatted = checkNewLine && cursor->paragraph()->prev() ? + cursor->paragraph()->prev() : cursor->paragraph(); QTextCursor oldCursor = *cursor; cursor->insert( txt, checkNewLine ); if ( doc->useFormatCollection() ) { - doc->setSelectionStart( QTextDocument::Temp, &oldCursor ); - doc->setSelectionEnd( QTextDocument::Temp, cursor ); + doc->setSelectionStart( QTextDocument::Temp, oldCursor ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); doc->removeSelection( QTextDocument::Temp ); @@ -2076,7 +2144,7 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo if ( !doc->preProcessor() ) { for ( int i = 0; i < (int)txt.length(); ++i ) { - if ( txt[ i ] != '\n' && c2.parag()->at( c2.index() )->format() ) { - c2.parag()->at( c2.index() )->format()->addRef(); - undoRedoInfo.d->text.setFormat( oldLen + i, c2.parag()->at( c2.index() )->format(), TRUE ); + if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) { + c2.paragraph()->at( c2.index() )->format()->addRef(); + undoRedoInfo.d->text.setFormat( oldLen + i, c2.paragraph()->at( c2.index() )->format(), TRUE ); } c2.gotoNextLetter(); @@ -2085,19 +2153,12 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo } - setModified(); - emit textChanged(); if ( !removeSelected ) { - doc->setSelectionStart( QTextDocument::Standard, &oldCursor ); - doc->setSelectionEnd( QTextDocument::Standard, cursor ); + doc->setSelectionStart( QTextDocument::Standard, oldCursor ); + doc->setSelectionEnd( QTextDocument::Standard, *cursor ); repaintChanged(); } - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); + setModified(); + emit textChanged(); } @@ -2106,9 +2167,10 @@ void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, boo void QTextEdit::insertAt( const QString &text, int para, int index ) { - QTextParag *p = doc->paragAt( para ); + removeSelection( QTextDocument::Standard ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return; QTextCursor tmp = *cursor; - cursor->setParag( p ); + cursor->setParagraph( p ); cursor->setIndex( index ); insert( text, FALSE, TRUE, FALSE ); @@ -2123,11 +2185,11 @@ void QTextEdit::insertAt( const QString &text, int para, int index ) void QTextEdit::insertParagraph( const QString &text, int para ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( p ) { QTextCursor tmp( doc ); - tmp.setParag( p ); + tmp.setParagraph( p ); tmp.setIndex( 0 ); tmp.insert( text, TRUE ); - tmp.splitAndInsertEmptyParag(); + tmp.splitAndInsertEmptyParagraph(); repaintChanged(); } else { @@ -2140,5 +2202,5 @@ void QTextEdit::insertParagraph( const QString &text, int para ) void QTextEdit::removeParagraph( int para ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return; @@ -2146,5 +2208,5 @@ void QTextEdit::removeParagraph( int para ) doc->removeSelection( i ); - if ( p == doc->firstParag() && p == doc->lastParag() ) { + if ( p == doc->firstParagraph() && p == doc->lastParagraph() ) { p->remove( 0, p->length() - 1 ); repaintChanged(); @@ -2152,14 +2214,14 @@ void QTextEdit::removeParagraph( int para ) } drawCursor( FALSE ); - bool resetCursor = cursor->parag() == p; + bool resetCursor = cursor->paragraph() == p; if ( p->prev() ) p->prev()->setNext( p->next() ); else - doc->setFirstParag( p->next() ); + doc->setFirstParagraph( p->next() ); if ( p->next() ) p->next()->setPrev( p->prev() ); else - doc->setLastParag( p->prev() ); - QTextParag *start = p->next(); + doc->setLastParagraph( p->prev() ); + QTextParagraph *start = p->next(); int h = p->rect().height(); delete p; @@ -2175,5 +2237,5 @@ void QTextEdit::removeParagraph( int para ) if ( resetCursor ) { - cursor->setParag( doc->firstParag() ); + cursor->setParagraph( doc->firstParagraph() ); cursor->setIndex( 0 ); } @@ -2218,14 +2280,7 @@ void QTextEdit::undo() repaintChanged(); drawCursor( TRUE ); + updateMicroFocusHint(); setModified(); emit textChanged(); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } } @@ -2263,14 +2318,7 @@ void QTextEdit::redo() ensureCursorVisible(); drawCursor( TRUE ); + updateMicroFocusHint(); setModified(); emit textChanged(); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } } @@ -2290,12 +2338,5 @@ void QTextEdit::paste() return; pasteSubType( "plain" ); - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); #endif } @@ -2338,16 +2379,11 @@ void QTextEdit::cut() return; - if ( doc->hasSelection( QTextDocument::Standard ) ) { - doc->copySelectedText( QTextDocument::Standard ); + QString t; + if ( doc->hasSelection( QTextDocument::Standard ) && + !( t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ) ).isEmpty() ) { + QApplication::clipboard()->setText( t ); removeSelectedText(); } - if ( hasFocus() || viewport()->hasFocus() ) { - int h = cursor->parag()->lineHeightOfChar( cursor->index() ); - if ( !readonly ) { - QFont f = cursor->parag()->at( cursor->index() )->format()->font(); - setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), - cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); - } - } + updateMicroFocusHint(); } @@ -2359,6 +2395,8 @@ void QTextEdit::cut() void QTextEdit::copy() { - if ( !doc->selectedText( QTextDocument::Standard ).isEmpty() ) - doc->copySelectedText( QTextDocument::Standard ); + QString t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ); + if ( doc->hasSelection( QTextDocument::Standard ) && + !t.isEmpty() && t.simplifyWhiteSpace() != "<selstart/>" ) + QApplication::clipboard()->setText( t ); } @@ -2413,15 +2451,15 @@ void QTextEdit::setFormat( QTextFormat *f, int flags ) if ( doc->hasSelection( QTextDocument::Standard ) ) { drawCursor( FALSE ); - QString str = doc->selectedText( QTextDocument::Standard ); QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard ); + c1.restoreState(); QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard ); + c2.restoreState(); clearUndoRedo(); undoRedoInfo.type = UndoRedoInfo::Format; - undoRedoInfo.id = c1.parag()->paragId(); + undoRedoInfo.id = c1.paragraph()->paragId(); undoRedoInfo.index = c1.index(); - undoRedoInfo.eid = c2.parag()->paragId(); + undoRedoInfo.eid = c2.paragraph()->paragId(); undoRedoInfo.eindex = c2.index(); - undoRedoInfo.d->text = str; - readFormats( c1, c2, 0, undoRedoInfo.d->text ); + readFormats( c1, c2, undoRedoInfo.d->text ); undoRedoInfo.format = f; undoRedoInfo.flags = flags; @@ -2444,10 +2482,10 @@ void QTextEdit::setFormat( QTextFormat *f, int flags ) emit currentColorChanged( currentFormat->color() ); emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); - if ( cursor->index() == cursor->parag()->length() - 1 ) { + if ( cursor->index() == cursor->paragraph()->length() - 1 ) { currentFormat->addRef(); - cursor->parag()->string()->setFormat( cursor->index(), currentFormat, TRUE ); - if ( cursor->parag()->length() == 1 ) { - cursor->parag()->invalidate( 0 ); - cursor->parag()->format(); + cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE ); + if ( cursor->paragraph()->length() == 1 ) { + cursor->paragraph()->invalidate( 0 ); + cursor->paragraph()->format(); repaintChanged(); } @@ -2468,5 +2506,10 @@ void QTextEdit::setPalette( const QPalette &p ) } -/*! +/*! \internal + + \warning In Qt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in Qt 4.0 this + function will go away. + Sets the paragraph style of the current paragraph to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the @@ -2482,47 +2525,35 @@ void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem:: drawCursor( FALSE ); - if ( !doc->hasSelection( QTextDocument::Standard ) ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::ParagType; - QValueList< QPtrVector<QStyleSheetItem> > oldStyles; - undoRedoInfo.oldStyles.clear(); - undoRedoInfo.oldStyles << cursor->parag()->styleSheetItems(); - undoRedoInfo.oldListStyles.clear(); - undoRedoInfo.oldListStyles << cursor->parag()->listStyle(); - undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; - undoRedoInfo.listStyle = listStyle; - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.eid = cursor->parag()->paragId(); - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; - clearUndoRedo(); - cursor->parag()->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); - repaintChanged(); - } else { - QTextParag *start = doc->selectionStart( QTextDocument::Standard ); - QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); - lastFormatted = start; + QTextParagraph *start = cursor->paragraph(); + QTextParagraph *end = start; + if ( doc->hasSelection( QTextDocument::Standard ) ) { + start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph(); + end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph(); + if ( end->paragId() < start->paragId() ) + return; // do not trust our selections + } + clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::ParagType; + undoRedoInfo.type = UndoRedoInfo::Style; undoRedoInfo.id = start->paragId(); undoRedoInfo.eid = end->paragId(); - undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; - undoRedoInfo.listStyle = listStyle; - undoRedoInfo.oldStyles.clear(); - undoRedoInfo.oldListStyles.clear(); - while ( start ) { - undoRedoInfo.oldStyles << start->styleSheetItems(); - undoRedoInfo.oldListStyles << start->listStyle(); - start->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); - if ( start == end ) - break; + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + + while ( start != end->next() ) { + start->setListStyle( listStyle ); + if ( dm == QStyleSheetItem::DisplayListItem ) { + start->setListItem( TRUE ); + if( start->listDepth() == 0 ) + start->setListDepth( 1 ); + } else if ( start->isListItem() ) { + start->setListItem( FALSE ); + start->setListDepth( QMAX( start->listDepth()-1, 0 ) ); + } start = start->next(); } - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; + clearUndoRedo(); repaintChanged(); formatMore(); - } drawCursor( TRUE ); setModified(); @@ -2535,5 +2566,4 @@ void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem:: Qt::AlignCenter (which centers horizontally). - \sa setParagType() */ @@ -2544,48 +2574,27 @@ void QTextEdit::setAlignment( int a ) drawCursor( FALSE ); - if ( !doc->hasSelection( QTextDocument::Standard ) ) { - if ( cursor->parag()->alignment() != a ) { - clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Alignment; - QMemArray<int> oa( 1 ); - oa[ 0 ] = cursor->parag()->alignment(); - undoRedoInfo.oldAligns = oa; - undoRedoInfo.newAlign = a; - undoRedoInfo.id = cursor->parag()->paragId(); - undoRedoInfo.eid = cursor->parag()->paragId(); - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; - clearUndoRedo(); - cursor->parag()->setAlignment( a ); - repaintChanged(); + QTextParagraph *start = cursor->paragraph(); + QTextParagraph *end = start; + if ( doc->hasSelection( QTextDocument::Standard ) ) { + start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph(); + end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph(); + if ( end->paragId() < start->paragId() ) + return; // do not trust our selections } - } else { - QTextParag *start = doc->selectionStart( QTextDocument::Standard ); - QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); - lastFormatted = start; - int len = end->paragId() - start->paragId() + 1; + clearUndoRedo(); - undoRedoInfo.type = UndoRedoInfo::Alignment; + undoRedoInfo.type = UndoRedoInfo::Style; undoRedoInfo.id = start->paragId(); undoRedoInfo.eid = end->paragId(); - QMemArray<int> oa( QMAX( 0, len ) ); - int i = 0; - while ( start ) { - if ( i < (int)oa.size() ) - oa[ i ] = start->alignment(); + undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); + + while ( start != end->next() ) { start->setAlignment( a ); - if ( start == end ) - break; start = start->next(); - ++i; } - undoRedoInfo.oldAligns = oa; - undoRedoInfo.newAlign = a; - undoRedoInfo.d->text = " "; - undoRedoInfo.index = 1; + clearUndoRedo(); repaintChanged(); formatMore(); - } drawCursor( TRUE ); if ( currentAlignment != a ) { @@ -2603,8 +2612,8 @@ void QTextEdit::updateCurrentFormat() --i; if ( doc->useFormatCollection() && - ( !currentFormat || currentFormat->key() != cursor->parag()->at( i )->format()->key() ) ) { + ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) { if ( currentFormat ) currentFormat->removeRef(); - currentFormat = doc->formatCollection()->format( cursor->parag()->at( i )->format() ); + currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() ); if ( currentFormat->isMisspelled() ) { currentFormat->removeRef(); @@ -2616,6 +2625,6 @@ void QTextEdit::updateCurrentFormat() } - if ( currentAlignment != cursor->parag()->alignment() ) { - currentAlignment = cursor->parag()->alignment(); + if ( currentAlignment != cursor->paragraph()->alignment() ) { + currentAlignment = cursor->paragraph()->alignment(); block_set_alignment = TRUE; emit currentAlignmentChanged( currentAlignment ); @@ -2779,5 +2788,6 @@ QString QTextEdit::text( int para ) const void QTextEdit::setText( const QString &text, const QString &context ) { - if ( !isModified() && this->context() == context && this->text() == text ) + if ( !isModified() && isReadOnly() && + this->context() == context && this->text() == text ) return; @@ -2800,8 +2810,7 @@ void QTextEdit::setText( const QString &text, const QString &context ) } - cursor->setDocument( doc ); - lastFormatted = doc->firstParag(); - cursor->setParag( doc->firstParag() ); - cursor->setIndex( 0 ); + lastFormatted = doc->firstParagraph(); + delete cursor; + cursor = new QTextCursor( doc ); updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); @@ -2811,4 +2820,5 @@ void QTextEdit::setText( const QString &text, const QString &context ) formatMore(); updateCurrentFormat(); + d->scrollToAnchor = QString::null; } @@ -2848,7 +2858,7 @@ void QTextEdit::setText( const QString &text, const QString &context ) If \a para and \a index are both null the search begins from the - start of the text. If \a para and \a index are both not null, the - search begins from the \e *\a index character position in the \e - *\a para paragraph. + current cursor position. If \a para and \a index are both not + null, the search begins from the \e *\a index character position + in the \e *\a para paragraph. If \a cs is TRUE the search is case sensitive, otherwise it is @@ -2874,12 +2884,32 @@ bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward, { drawCursor( FALSE ); - doc->removeSelection( QTextDocument::Standard ); #ifndef QT_NO_CURSOR viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); #endif - bool found = doc->find( expr, cs, wo, forward, para, index, cursor ); + QTextCursor findcur = *cursor; + if ( para && index ) { + if ( doc->paragAt( *para ) ) + findcur.gotoPosition( doc->paragAt(*para), *index ); + else + findcur.gotoEnd(); + } else if ( doc->hasSelection( QTextDocument::Standard ) ){ + // maks sure we do not find the same selection again + if ( forward ) + findcur.gotoNextLetter(); + else + findcur.gotoPreviousLetter(); + } + removeSelection( QTextDocument::Standard ); + bool found = doc->find( findcur, expr, cs, wo, forward ); + if ( found ) { + if ( para ) + *para = findcur.paragraph()->paragId(); + if ( index ) + *index = findcur.index(); + *cursor = findcur; + repaintChanged(); ensureCursorVisible(); + } drawCursor( TRUE ); - repaintChanged(); return found; } @@ -2903,5 +2933,5 @@ void QTextEdit::blinkCursor() void QTextEdit::setCursorPosition( int para, int index ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return; @@ -2911,10 +2941,11 @@ void QTextEdit::setCursorPosition( int para, int index ) drawCursor( FALSE ); - cursor->setParag( p ); + cursor->setParagraph( p ); cursor->setIndex( index ); ensureCursorVisible(); drawCursor( TRUE ); + updateCurrentFormat(); emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); } @@ -2931,5 +2962,5 @@ void QTextEdit::getCursorPosition( int *para, int *index ) const if ( !para || !index ) return; - *para = cursor->parag()->paragId(); + *para = cursor->paragraph()->paragId(); *index = cursor->index(); } @@ -2959,8 +2990,8 @@ void QTextEdit::setSelection( int paraFrom, int indexFrom, if ( selNum > doc->numSelections() - 1 ) doc->addSelection( selNum ); - QTextParag *p1 = doc->paragAt( paraFrom ); + QTextParagraph *p1 = doc->paragAt( paraFrom ); if ( !p1 ) return; - QTextParag *p2 = doc->paragAt( paraTo ); + QTextParagraph *p2 = doc->paragAt( paraTo ); if ( !p2 ) return; @@ -2974,10 +3005,10 @@ void QTextEdit::setSelection( int paraFrom, int indexFrom, QTextCursor c = *cursor; QTextCursor oldCursor = *cursor; - c.setParag( p1 ); + c.setParagraph( p1 ); c.setIndex( indexFrom ); - cursor->setParag( p2 ); + cursor->setParagraph( p2 ); cursor->setIndex( indexTo ); - doc->setSelectionStart( selNum, &c ); - doc->setSelectionEnd( selNum, cursor ); + doc->setSelectionStart( selNum, c ); + doc->setSelectionEnd( selNum, *cursor ); repaintChanged(); ensureCursorVisible(); @@ -3057,5 +3088,5 @@ Qt::TextFormat QTextEdit::textFormat() const int QTextEdit::paragraphs() const { - return doc->lastParag()->paragId() + 1; + return doc->lastParagraph()->paragId() + 1; } @@ -3067,5 +3098,5 @@ int QTextEdit::paragraphs() const int QTextEdit::linesOfParagraph( int para ) const { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return -1; @@ -3080,5 +3111,5 @@ int QTextEdit::linesOfParagraph( int para ) const int QTextEdit::paragraphLength( int para ) const { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return -1; @@ -3096,5 +3127,5 @@ int QTextEdit::paragraphLength( int para ) const int QTextEdit::lines() const { - QTextParag *p = doc->firstParag(); + QTextParagraph *p = doc->firstParagraph(); int l = 0; while ( p ) { @@ -3116,5 +3147,5 @@ int QTextEdit::lines() const int QTextEdit::lineOfChar( int para, int index ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return -1; @@ -3249,5 +3280,5 @@ void QTextEdit::startDrag() mousePressed = FALSE; inDoubleClick = FALSE; - QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard ), viewport() ); + QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ), viewport() ); if ( isReadOnly() ) { drag->dragCopy(); @@ -3286,20 +3317,18 @@ void QTextEdit::UndoRedoInfo::clear() if ( valid() ) { if ( type == Insert || type == Return ) - doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); + doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) ); else if ( type == Format ) doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); - else if ( type == Alignment ) - doc->addCommand( new QTextAlignmentCommand( doc, id, eid, newAlign, oldAligns ) ); - else if ( type == ParagType ) - doc->addCommand( new QTextParagTypeCommand( doc, id, eid, list, listStyle, oldStyles, oldListStyles ) ); - else if ( type != Invalid ) - doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); + else if ( type == Style ) + doc->addCommand( new QTextStyleCommand( doc, id, eid, styleInformation ) ); + else if ( type != Invalid ) { + doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) ); + } } + type = Invalid; d->text = QString::null; id = -1; index = -1; - oldStyles.clear(); - oldListStyles.clear(); - oldAligns.resize( 0 ); + styleInformation = QByteArray(); } @@ -3341,5 +3370,5 @@ QTextEdit::UndoRedoInfo::~UndoRedoInfo() bool QTextEdit::UndoRedoInfo::valid() const { - return d->text.length() > 0 && id >= 0 && index >= 0; + return id >= 0 && type != Invalid; } @@ -3410,8 +3439,5 @@ QBrush QTextEdit::paper() const void QTextEdit::setLinkUnderline( bool b ) { - if ( b == doc->underlineLinks() ) - return; doc->setUnderlineLinks( b ); - updateStyles(); } @@ -3466,8 +3492,7 @@ void QTextEdit::append( const QString &text ) { // flush and clear the undo/redo stack if necessary - if ( isReadOnly() && undoRedoInfo.valid() ) { undoRedoInfo.clear(); doc->commands()->clear(); - } + doc->removeSelection( QTextDocument::Standard ); TextFormat f = doc->textFormat(); @@ -3478,33 +3503,35 @@ void QTextEdit::append( const QString &text ) f = PlainText; } - if ( f == PlainText ) { + + drawCursor( FALSE ); QTextCursor oldc( *cursor ); - ensureFormatted( doc->lastParag() ); - bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight() - - ( horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0 ); - if ( !scrollToEnd ) - blockEnsureCursorVisible = TRUE; + ensureFormatted( doc->lastParagraph() ); + bool atBottom = contentsY() >= contentsHeight() - visibleHeight(); cursor->gotoEnd(); if ( cursor->index() > 0 ) - cursor->splitAndInsertEmptyParag(); + cursor->splitAndInsertEmptyParagraph(); QTextCursor oldCursor2 = *cursor; + + if ( f == Qt::PlainText ) { cursor->insert( text, TRUE ); - if ( doc->useFormatCollection() && currentFormat != cursor->parag()->at( cursor->index() )->format() ) { - doc->setSelectionStart( QTextDocument::Temp, &oldCursor2 ); - doc->setSelectionEnd( QTextDocument::Temp, cursor ); + if ( doc->useFormatCollection() && + currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) { + doc->setSelectionStart( QTextDocument::Temp, oldCursor2 ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); doc->removeSelection( QTextDocument::Temp ); } + } else { + if ( cursor->paragraph()->prev() ) + cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change + doc->setRichTextInternal( text ); + } formatMore(); repaintChanged(); - ensureCursorVisible(); - drawCursor( TRUE ); + if ( atBottom ) + scrollToBottom(); *cursor = oldc; - if ( !scrollToEnd ) - blockEnsureCursorVisible = FALSE; - } else if ( f == RichText ) { - doc->setRichTextInternal( text ); - repaintChanged(); - } + if ( !isReadOnly() ) + cursorVisible = TRUE; setModified(); emit textChanged(); @@ -3618,5 +3645,5 @@ QString QTextEdit::documentTitle() const } -void QTextEdit::makeParagVisible( QTextParag *p ) +void QTextEdit::makeParagVisible( QTextParagraph *p ) { setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); @@ -3631,21 +3658,27 @@ void QTextEdit::makeParagVisible( QTextParag *p ) void QTextEdit::scrollToAnchor( const QString& name ) { + if ( !isVisible() ) { + d->scrollToAnchor = name; + return; + } if ( name.isEmpty() ) return; sync(); QTextCursor cursor( doc ); - QTextParag* last = doc->lastParag(); - do { - QTextStringChar* c = cursor.parag()->at( cursor.index() ); + QTextParagraph* last = doc->lastParagraph(); + for (;;) { + QTextStringChar* c = cursor.paragraph()->at( cursor.index() ); if( c->isAnchor() ) { QString a = c->anchorName(); if ( a == name || (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) { - setContentsPos( contentsX(), QMIN( cursor.parag()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); - return; + setContentsPos( contentsX(), QMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); + break; } } + if ( cursor.paragraph() == last && cursor.atParagEnd() ) + break; cursor.gotoNextLetter(); - } while( cursor.parag() != last || !cursor.atParagEnd() ); + } } @@ -3659,5 +3692,5 @@ QString QTextEdit::anchorAt( const QPoint& pos ) QTextCursor c( doc ); placeCursor( pos, &c ); - return c.parag()->at( c.index() )->anchorHref(); + return c.paragraph()->at( c.index() )->anchorHref(); } @@ -3667,13 +3700,11 @@ void QTextEdit::documentWidthChanged( int w ) } -/*! - Updates all the rendering styles used to display the text. You will - probably want to call this function after calling setStyleSheet(). +/*! \internal + + This function does nothing */ void QTextEdit::updateStyles() { - doc->updateStyles(); - updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); } @@ -3683,6 +3714,8 @@ void QTextEdit::setDocument( QTextDocument *dc ) return; doc = dc; - cursor->setDocument( doc ); + delete cursor; + cursor = new QTextCursor( doc ); clearUndoRedo(); + undoRedoInfo.doc = doc; lastFormatted = 0; } @@ -3704,5 +3737,50 @@ void QTextEdit::pasteSubType( const QCString& subtype ) QCString st = subtype; QString t = QApplication::clipboard()->text(st); + if ( doc->hasSelection( QTextDocument::Standard ) ) + removeSelectedText(); if ( !t.isEmpty() ) { + if ( t.startsWith( "<selstart/>" ) ) { + t.remove( 0, 11 ); + QTextCursor oldC = *cursor; + lastFormatted = cursor->paragraph(); + if ( lastFormatted->prev() ) + lastFormatted = lastFormatted->prev(); + doc->setRichTextInternal( t, cursor ); + + if ( undoEnabled && !isReadOnly() ) { + doc->setSelectionStart( QTextDocument::Temp, oldC ); + doc->setSelectionEnd( QTextDocument::Temp, *cursor ); + + checkUndoRedoInfo( UndoRedoInfo::Insert ); + if ( !undoRedoInfo.valid() ) { + undoRedoInfo.id = oldC.paragraph()->paragId(); + undoRedoInfo.index = oldC.index(); + undoRedoInfo.d->text = QString::null; + } + int oldLen = undoRedoInfo.d->text.length(); + if ( !doc->preProcessor() ) { + QString txt = doc->selectedText( QTextDocument::Temp ); + undoRedoInfo.d->text += txt; + for ( int i = 0; i < (int)txt.length(); ++i ) { + if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) { + oldC.paragraph()->at( oldC.index() )->format()->addRef(); + undoRedoInfo.d->text. + setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE ); + } + oldC.gotoNextLetter(); + } + } + undoRedoInfo.clear(); + removeSelection( QTextDocument::Temp ); + } + + formatMore(); + setModified(); + emit textChanged(); + repaintChanged(); + ensureCursorVisible(); + return; + } + #if defined(Q_OS_WIN32) // Need to convert CRLF to LF @@ -3839,5 +3917,5 @@ void QTextEdit::setWordWrap( WordWrap mode ) doc->invalidate(); updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; formatMore(); @@ -3900,5 +3978,5 @@ void QTextEdit::setWrapColumnOrWidth( int value ) doc->invalidate(); updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; formatMore(); @@ -3953,5 +4031,5 @@ void QTextEdit::setWrapPolicy( WrapPolicy policy ) doc->invalidate(); updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; formatMore(); @@ -3980,12 +4058,11 @@ void QTextEdit::clear() cursor->restoreState(); doc->clear( TRUE ); - cursor->setDocument( doc ); - cursor->setParag( doc->firstParag() ); - cursor->setIndex( 0 ); + delete cursor; + cursor = new QTextCursor( doc ); lastFormatted = 0; updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); emit cursorPositionChanged( cursor ); - emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); + emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); } @@ -4026,5 +4103,5 @@ void QTextEdit::setTabStopWidth( int ts ) document()->setTabStops( ts ); doc->invalidate(); - lastFormatted = doc->firstParag(); + lastFormatted = doc->firstParagraph(); interval = 0; formatMore(); @@ -4047,5 +4124,11 @@ void QTextEdit::clearUndoRedo() } -/*! This function gets the format of the character at position \a +/*! \internal + + \warning In Qt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in Qt 4.0 this + function will go away. + + This function gets the format of the character at position \a index in paragraph \a para. Sets \a font to the character's font, \a color to the character's color and \a verticalAlignment to the @@ -4060,5 +4143,5 @@ bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, Vert if ( !font || !color ) return FALSE; - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return FALSE; @@ -4071,5 +4154,11 @@ bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, Vert } -/*! This function gets the format of the paragraph \a para. Sets \a +/*! \internal + + \warning In Qt 3.1 we will provide a cleaer API for the + functionality which is provided by this function and in Qt 4.0 this + function will go away. + + This function gets the format of the paragraph \a para. Sets \a font to the paragraphs's font, \a color to the paragraph's color, \a verticalAlignment to the paragraph's vertical alignment, \a @@ -4091,12 +4180,12 @@ bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color, if ( !font || !color || !alignment || !displayMode || !listStyle ) return FALSE; - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return FALSE; - *font = p->paragFormat()->font(); - *color = p->paragFormat()->color(); - *verticalAlignment = (VerticalAlignment)p->paragFormat()->vAlign(); + *font = p->at(0)->format()->font(); + *color = p->at(0)->format()->color(); + *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign(); *alignment = p->alignment(); - *displayMode = p->style() ? p->style()->displayMode() : QStyleSheetItem::DisplayBlock; + *displayMode = p->isListItem() ? QStyleSheetItem::DisplayListItem : QStyleSheetItem::DisplayBlock; *listStyle = p->listStyle(); *listDepth = p->listDepth(); @@ -4156,8 +4245,12 @@ QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) /*! \overload + \obsolete This function is called to create a right mouse button popup menu. If you want to create a custom popup menu, reimplement this function and return the created popup menu. Ownership of the popup menu is transferred to the caller. + + This function is only called if createPopupMenu( const QPoint & ) + returns 0. */ @@ -4174,19 +4267,6 @@ void QTextEdit::setFont( const QFont &f ) QScrollView::setFont( f ); doc->setMinimumWidth( -1 ); - - // ### that is a bit hacky - static short diff = 1; - diff *= -1; - doc->setWidth( visibleWidth() + diff ); - - int s = f.pointSize(); - bool usePixels = FALSE; - if ( s == -1 ) { - s = f.pixelSize(); - usePixels = TRUE; - } - doc->updateFontSizes( s, usePixels ); - doc->updateFontAttributes( f, old ); - lastFormatted = doc->firstParag(); + doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() ); + lastFormatted = doc->firstParagraph(); formatMore(); repaintChanged(); @@ -4274,8 +4354,7 @@ void QTextEdit::zoomTo( int size ) void QTextEdit::sync() { - QTextParag *p = lastFormatted; - while ( p ) { - p->format(); - p = p->next(); + while ( lastFormatted ) { + lastFormatted->format(); + lastFormatted = lastFormatted->next(); } resizeContents( contentsWidth(), doc->height() ); @@ -4361,5 +4440,5 @@ QRect QTextEdit::paragraphRect( int para ) const QTextEdit *that = (QTextEdit *)this; that->sync(); - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return QRect( -1, -1, -1, -1 ); @@ -4375,7 +4454,7 @@ int QTextEdit::paragraphAt( const QPoint &pos ) const { QTextCursor c( doc ); - c.place( pos, doc->firstParag() ); - if ( c.parag() ) - return c.parag()->paragId(); + c.place( pos, doc->firstParagraph() ); + if ( c.paragraph() ) + return c.paragraph()->paragId(); return -1; } @@ -4391,8 +4470,8 @@ int QTextEdit::charAt( const QPoint &pos, int *para ) const { QTextCursor c( doc ); - c.place( pos, doc->firstParag() ); - if ( c.parag() ) { + c.place( pos, doc->firstParagraph() ); + if ( c.paragraph() ) { if ( para ) - *para = c.parag()->paragId(); + *para = c.paragraph()->paragId(); return c.index(); } @@ -4404,5 +4483,5 @@ int QTextEdit::charAt( const QPoint &pos, int *para ) const void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return; @@ -4417,5 +4496,5 @@ void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) void QTextEdit::clearParagraphBackground( int para ) { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return; @@ -4431,5 +4510,5 @@ void QTextEdit::clearParagraphBackground( int para ) QColor QTextEdit::paragraphBackgroundColor( int para ) const { - QTextParag *p = doc->paragAt( para ); + QTextParagraph *p = doc->paragAt( para ); if ( !p ) return QColor(); @@ -4470,5 +4549,5 @@ bool QTextEdit::isRedoAvailable() const } -void QTextEdit::ensureFormatted( QTextParag *p ) +void QTextEdit::ensureFormatted( QTextParagraph *p ) { while ( !p->isValid() ) { @@ -4487,9 +4566,9 @@ void QTextEdit::updateCursor( const QPoint & pos ) #ifndef QT_NO_NETWORKPROTOCOL - if ( c.parag() && c.parag()->at( c.index() ) && - c.parag()->at( c.index() )->isAnchor() && - !c.parag()->at( c.index() )->anchorHref().isEmpty() ) { - if ( c.index() < c.parag()->length() - 1 ) - onLink = c.parag()->at( c.index() )->anchorHref(); + if ( c.paragraph() && c.paragraph()->at( c.index() ) && + c.paragraph()->at( c.index() )->isAnchor() && + !c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) { + if ( c.index() < c.paragraph()->length() - 1 ) + onLink = c.paragraph()->at( c.index() )->anchorHref(); else onLink = QString::null; diff --git a/noncore/apps/opie-write/qtextedit.h b/noncore/apps/opie-write/qtextedit.h index b4e5701..64e8f45 100644 --- a/noncore/apps/opie-write/qtextedit.h +++ b/noncore/apps/opie-write/qtextedit.h @@ -62,7 +62,9 @@ class QTextDocument; class QTextCursor; class QTextCommand; -class QTextParag; +class QTextParagraph; class QTextFormat; +class QTextEdit; class QTextBrowser; +class QTextString; class QTextEditPrivate; @@ -197,5 +199,8 @@ public: int alignment() const; int undoDepth() const; + + // do not use, will go away virtual bool getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment ); + // do not use, will go away virtual bool getParagraphFormat( int para, QFont *font, QColor *color, VerticalAlignment *verticalAlignment, int *alignment, @@ -203,4 +208,6 @@ public: QStyleSheetItem::ListStyle *listStyle, int *listDepth ); + + bool isOverwriteMode() const { return overWrite; } QColor paragraphBackgroundColor( int para ) const; @@ -258,5 +265,8 @@ public slots: virtual void setVerticalAlignment( VerticalAlignment a ); virtual void setAlignment( int a ); + + // do not use, will go away virtual void setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle ); + virtual void setCursorPosition( int parag, int index ); virtual void setSelection( int parag_from, int index_from, int parag_to, int index_to, int selNum = 0 ); @@ -347,5 +357,5 @@ private slots: private: struct Q_EXPORT UndoRedoInfo { - enum Type { Invalid, Insert, Delete, Backspace, Return, RemoveSelected, Format, Alignment, ParagType }; + enum Type { Invalid, Insert, Delete, Backspace, Return, RemoveSelected, Format, Style }; UndoRedoInfo( QTextDocument *dc ); @@ -363,10 +373,5 @@ private: Type type; QTextDocument *doc; - QMemArray<int> oldAligns; - int newAlign; - bool list; - QStyleSheetItem::ListStyle listStyle; - QValueList< QPtrVector<QStyleSheetItem> > oldStyles; - QValueList<QStyleSheetItem::ListStyle> oldListStyles; + QByteArray styleInformation; }; @@ -380,5 +385,5 @@ private: void updateCurrentFormat(); bool handleReadOnlyKeyEvent( QKeyEvent *e ); - void makeParagVisible( QTextParag *p ); + void makeParagVisible( QTextParagraph *p ); #ifndef QT_NO_MIME QCString pickSpecial(QMimeSource* ms, bool always_ask, const QPoint&); @@ -392,10 +397,11 @@ private: virtual void emitLinkClicked( const QString & ) {} - void readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles = FALSE ); + void readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles = FALSE ); void clearUndoRedo(); void paintDocument( bool drawAll, QPainter *p, int cx = -1, int cy = -1, int cw = -1, int ch = -1 ); void moveCursor( CursorAction action ); - void ensureFormatted( QTextParag *p ); + void ensureFormatted( QTextParagraph *p ); void placeCursor( const QPoint &pos, QTextCursor *c, bool link ); + void updateMicroFocusHint(); private: @@ -403,5 +409,5 @@ private: QTextCursor *cursor; QTimer *formatTimer, *scrollTimer, *changeIntervalTimer, *blinkTimer, *dragStartTimer; - QTextParag *lastFormatted; + QTextParagraph *lastFormatted; int interval; UndoRedoInfo undoRedoInfo; |