summaryrefslogtreecommitdiff
path: root/noncore/apps/opie-write/qrichtext.cpp
authorleseb <leseb>2002-07-15 23:22:50 (UTC)
committer leseb <leseb>2002-07-15 23:22:50 (UTC)
commit72eb74051ed8f1b7696041e241ab99df3af5b08d (patch) (side-by-side diff)
treebf9beee9469bc4384cb8178fbd6565cf161b4708 /noncore/apps/opie-write/qrichtext.cpp
parentdcea0e50a00ed9efb988ded5abf5d39de1bea393 (diff)
downloadopie-72eb74051ed8f1b7696041e241ab99df3af5b08d.zip
opie-72eb74051ed8f1b7696041e241ab99df3af5b08d.tar.gz
opie-72eb74051ed8f1b7696041e241ab99df3af5b08d.tar.bz2
Sync with Qt 3.0.5
Diffstat (limited to 'noncore/apps/opie-write/qrichtext.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-write/qrichtext.cpp4311
1 files changed, 2035 insertions, 2276 deletions
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
@@ -38,20 +38,17 @@
#include "qrichtext_p.h"
#include "qstringlist.h"
#include "qfont.h"
#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"
#include "qpaintdevicemetrics.h"
#include "qpainter.h"
#include "qdrawutil.h"
#include "qcursor.h"
@@ -61,31 +58,25 @@
#include "qcleanuphandler.h"
#include <stdlib.h>
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 )
{
if ( !p || !p->device() )
return FALSE;
return p->device()->devType() == QInternal::Printer;
}
@@ -174,24 +165,22 @@ bool QTextCommandHistory::isRedoAvailable()
return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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 ) {
if ( text[ j ].format() )
text[ j ].format()->addRef();
}
}
-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 )
{
for ( int i = 0; i < (int)text.size(); ++i ) {
if ( text[ i ].format() )
text[ i ].format()->addRef();
}
@@ -205,90 +194,74 @@ QTextDeleteCommand::~QTextDeleteCommand()
}
text.resize( 0 );
}
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();
if ( 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 )
*c = cursor;
} else {
s->remove( index, len );
}
return 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 )
c->gotoNextLetter();
}
- 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;
- p = p->next();
- ++it;
- ++lit;
- ++i;
+ if ( !styleInformation.isEmpty() ) {
+ QDataStream styleStream( styleInformation, IO_ReadOnly );
+ int num;
+ styleStream >> num;
+ QTextParagraph *p = s;
+ while ( num-- && p ) {
+ p->readStyleInformation( styleStream );
+ p = p->next();
+ }
}
-
- 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();
}
return &cursor;
}
@@ -312,38 +285,38 @@ QTextFormatCommand::~QTextFormatCommand()
oldFormats[ j ].format()->removeRef();
}
}
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 );
if ( endIndex == ep->length() )
end.gotoLeft();
*c = end;
return 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;
int idx = startIndex;
int fIndex = 0;
for ( ;; ) {
@@ -370,384 +343,324 @@ QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c )
sp = sp->next();
idx = 0;
}
}
QTextCursor end( doc );
- end.setParag( ep );
+ end.setParagraph( ep );
end.setIndex( endIndex );
if ( endIndex == ep->length() )
end.gotoLeft();
*c = end;
return 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 *QTextParagTypeCommand::execute( QTextCursor *c )
+QTextCursor *QTextStyleCommand::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;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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;
valid = c.valid;
}
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;
valid = c.valid;
return *this;
}
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;
}
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;
}
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<int>::Iterator it2 = indices.begin();
- for ( ; it != parags.end(); ++it, ++it2 ) {
- if ( *it == string )
- continue;
- (*it)->invalidate( 0 );
- if ( (*it)->at( *it2 )->isCustom() )
- (*it)->at( *it2 )->customItem()->invalidate();
- }
+ QValueStack<QTextParagraph*>::Iterator it = paras.begin();
+ QValueStack<int>::Iterator it2 = indices.begin();
+ for ( ; it != paras.end(); ++it, ++it2 ) {
+ if ( *it == para )
+ continue;
+ (*it)->invalidate( 0 );
+ if ( (*it)->at( *it2 )->isCustom() )
+ (*it)->at( *it2 )->customItem()->invalidate();
}
}
void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting )
{
tmpIndex = -1;
bool justInsert = TRUE;
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;
}
+ 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++;
+ }
- idx += s.length();
- }
- 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 ) {
p->setParagId( p->prev()->paragId() + 1 );
p->move( dy );
p->invalidate( 0 );
p->setEndState( -1 );
p = p->next();
}
}
- 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
gotoPreviousLetter();
}
void QTextCursor::gotoPreviousLetter()
{
tmpIndex = -1;
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 );
+ if ( idx == -1 ) {
pop();
- processNesting( Prev );
- if ( idx == -1 ) {
- pop();
- if ( idx > 0 ) {
- idx--;
- } else if ( string->prev() ) {
- string = string->prev();
- idx = string->length() - 1;
- }
+ if ( idx > 0 ) {
+ idx--;
+ } else if ( para->prev() ) {
+ para = para->prev();
+ idx = para->length() - 1;
}
}
}
-
- 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();
}
void QTextCursor::restoreState()
{
while ( !indices.isEmpty() )
pop();
}
-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;
if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() || !s->next() )
break;
s = s->next();
}
if ( !s || !str )
return FALSE;
s = str;
- setParag( s, FALSE );
+ setParagraph( s );
int y = s->rect().y();
int lines = s->lines();
QTextStringChar *chr = 0;
int index = 0;
int i = 0;
int cy = 0;
@@ -755,13 +668,13 @@ bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link )
for ( ; i < lines; ++i ) {
chr = s->lineStartOfLine( i, &index );
cy = s->lineY( i );
ch = s->lineHeight( i );
if ( !chr )
return FALSE;
- if ( pos.y() >= y + cy && pos.y() <= y + cy + ch )
+ if ( pos.y() <= y + cy + ch )
break;
}
int nextLine;
if ( i < lines - 1 )
s->lineStartOfLine( i+1, &nextLine );
else
@@ -795,205 +708,200 @@ bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link )
if ( !link || pos.x() >= x + chr->x )
curpos = i;
}
}
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();
}
return TRUE;
}
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;
}
if ( !ok )
pop();
}
void QTextCursor::gotoRight()
{
- if ( string->string()->isRightToLeft() )
+ if ( para->string()->isRightToLeft() )
gotoPreviousLetter();
else
gotoNextLetter();
}
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 );
return;
}
- 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;
- idx = 0;
- }
- } else {
- if ( nested ) {
+ } else if ( para->next() ) {
+ para = para->next();
+ while ( !para->isVisible() && para->next() )
+ para = para->next();
+ idx = 0;
+ } else if ( nestedDepth() ) {
+ pop();
+ processNesting( Next );
+ if ( idx == -1 ) {
pop();
- processNesting( Next );
- if ( idx == -1 ) {
- pop();
- if ( idx < string->length() - 1 ) {
- idx++;
- } else if ( string->next() ) {
- string = string->next();
- idx = 0;
- }
+ if ( idx < para->length() - 1 ) {
+ idx++;
+ } else if ( para->next() ) {
+ para = para->next();
+ idx = 0;
}
}
}
}
void QTextCursor::gotoUp()
{
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 ( indexOfLineStart == 0 ) {
- if ( !string->prev() ) {
- if ( !nested )
+ if ( !para->prev() ) {
+ if ( !nestedDepth() )
return;
pop();
processNesting( Up );
if ( idx == -1 ) {
pop();
- if ( !string->prev() )
+ if ( !para->prev() )
return;
idx = tmpIndex = 0;
} else {
tmpIndex = -1;
return;
}
}
- 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 )
idx = indexOfLineStart + tmpIndex;
else
idx = oldIndexOfLineStart - 1;
}
}
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();
processNesting( Down );
if ( idx == -1 ) {
pop();
- if ( !string->next() )
+ if ( !para->next() )
return;
idx = tmpIndex = 0;
} else {
tmpIndex = -1;
return;
}
}
- 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;
else
idx = end - 1;
} else {
++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 )
idx = indexOfLineStart + tmpIndex;
else
idx = end - 1;
}
@@ -1001,122 +909,95 @@ void QTextCursor::gotoDown()
void QTextCursor::gotoLineEnd()
{
tmpIndex = -1;
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;
}
}
void QTextCursor::gotoLineStart()
{
tmpIndex = -1;
int indexOfLineStart;
int line;
- QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line );
+ QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
if ( !c )
return;
idx = indexOfLineStart;
}
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
gotoNextWord();
}
void QTextCursor::gotoWordLeft()
{
- if ( string->string()->isRightToLeft() )
+ if ( para->string()->isRightToLeft() )
gotoNextWord();
else
gotoPreviousWord();
}
void QTextCursor::gotoPreviousWord()
{
gotoPreviousLetter();
tmpIndex = -1;
- QTextString *s = string->string();
+ QTextString *s = para->string();
bool allowSame = FALSE;
if ( idx == ((int)s->length()-1) )
return;
for ( int i = idx; i >= 0; --i ) {
if ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) {
@@ -1132,13 +1013,13 @@ void QTextCursor::gotoPreviousWord()
idx = 0;
}
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 ) {
if ( ! (s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';') ) {
if ( !allowSame )
continue;
@@ -1150,18 +1031,18 @@ void QTextCursor::gotoNextWord()
allowSame = TRUE;
}
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;
}
} else {
gotoLineEnd();
}
}
@@ -1170,184 +1051,143 @@ bool QTextCursor::atParagStart()
{
return idx == 0;
}
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;
}
}
invalidateNested();
}
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;
}
return FALSE;
}
-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;
if ( idx >= oi )
idx += ni - oi;
else
idx = ni;
}
-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;
init();
}
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;
init();
}
void QTextDocument::init()
{
-#if defined(PARSER_DEBUG)
- qDebug( debug_indent + "new QTextDocument (%p)", this );
-#endif
oTextValid = TRUE;
mightHaveCustomItems = FALSE;
if ( par )
par->insertChild( this );
pProcessor = 0;
useFC = TRUE;
@@ -1360,42 +1200,41 @@ void QTextDocument::init()
focusIndicator.parag = 0;
minw = 0;
wused = 0;
minwParag = curParag = 0;
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;
backBrush = 0;
buf_pixmap = 0;
nextDoubleBuffered = FALSE;
if ( par )
withoutDoubleBuffer = par->withoutDoubleBuffer;
else
withoutDoubleBuffer = FALSE;
- lParag = fParag = createParag( this, 0, 0 );
- tmpCursor = 0;
+ lParag = fParag = createParagraph( this, 0, 0 );
cx = 0;
cy = 2;
if ( par )
cx = cy = 0;
cw = 600;
vw = 0;
flow_ = new QTextFlow;
flow_->setWidth( cw );
leftmargin = rightmargin = 4;
+ scaleFontsFactor = 1;
+
selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight );
selectionText[ Standard ] = TRUE;
commandHistory = new QTextCommandHistory( 100 );
tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8;
}
@@ -1420,20 +1259,22 @@ QTextDocument::~QTextDocument()
void QTextDocument::clear( bool createEmptyParag )
{
if ( flow_ )
flow_->clear();
while ( fParag ) {
- QTextParag *p = fParag->next();
+ QTextParagraph *p = fParag->next();
delete fParag;
fParag = p;
}
fParag = lParag = 0;
if ( createEmptyParag )
- fParag = lParag = createParag( this );
+ fParag = lParag = createParagraph( this );
selections.clear();
+ oText = QString::null;
+ oTextValid = TRUE;
}
int QTextDocument::widthUsed() const
{
return wused + border_tolerance;
}
@@ -1446,18 +1287,18 @@ int QTextDocument::height() const
int fh = flow_->boundingRect().bottom();
return QMAX( h, fh );
}
-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 ) {
minw = 0;
wused = 0;
p = 0;
}
@@ -1482,24 +1323,24 @@ void QTextDocument::setPlainText( const QString &text )
oTextValid = TRUE;
oText = text;
int lastNl = 0;
int nl = text.find( '\n' );
if ( nl == -1 ) {
- lParag = createParag( this, lParag, 0 );
+ lParag = createParagraph( this, lParag, 0 );
if ( !fParag )
fParag = lParag;
QString s = text;
if ( !s.isEmpty() ) {
if ( s[ (int)s.length() - 1 ] == '\r' )
s.remove( s.length() - 1, 1 );
lParag->append( s );
}
} else {
for (;;) {
- lParag = createParag( this, lParag, 0 );
+ lParag = createParagraph( this, lParag, 0 );
if ( !fParag )
fParag = lParag;
QString s = text.mid( lastNl, nl - lastNl );
if ( !s.isEmpty() ) {
if ( s[ (int)s.length() - 1 ] == '\r' )
s.remove( s.length() - 1, 1 );
@@ -1511,13 +1352,13 @@ void QTextDocument::setPlainText( const QString &text )
nl = text.find( '\n', nl + 1 );
if ( nl == -1 )
nl = 0xffffff;
}
}
if ( !lParag )
- lParag = fParag = createParag( this, 0, 0 );
+ lParag = fParag = createParagraph( this, 0, 0 );
}
struct Q_EXPORT QTextDocumentTag {
QTextDocumentTag(){}
QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f )
:name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) {
@@ -1556,191 +1397,186 @@ struct Q_EXPORT QTextDocumentTag {
#if defined(Q_FULL_TEMPLATE_INSTANTIATION)
bool operator==( const QTextDocumentTag& ) const { return FALSE; }
#endif
};
-#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;
QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() );
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, '<' ) ){
if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) {
// open tag
QMap<QString, QString> attr;
bool emptyTag = FALSE;
QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag);
if ( tagname.isEmpty() )
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
while ( !nstyle->allowedInContext( curtag.style ) ) {
QString msg;
msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)",
tagname.ascii(), curtag.style->name().ascii(), pos);
sheet_->error( msg );
if ( tags.isEmpty() )
break;
curtag = tags.pop();
}
- // 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() )
break;
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
- 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 );
- } else if ( tagname == "hr" ) {
- emptyTag = TRUE;
- custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
- NEWPAR;
- } else if ( tagname == "table" ) {
- QTextFormat format = curtag.format.makeTextFormat( nstyle, attr );
- 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 ) );
+
+ // some well-known tags, some have a nstyle, some not
+ if ( wellKnownTags.find( tagname ) != -1 ) {
+ if ( tagname == "br" ) {
+ 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 = space = TRUE;
+ custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
+ NEWPAR;
+ } else if ( tagname == "table" ) {
+ emptyTag = space = TRUE;
+ QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
+ curpar->setAlignment( curtag.alignment );
+ custom = parseTable( attr, format, doc, length, pos, curpar );
+ } 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() );
}
}
if ( !img.isNull() ) {
QPixmap pm;
pm.convertFromImage( img );
QBrush *b = new QBrush( QColor(), pm );
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();
QDictIterator<QTextFormat> it( formats );
while ( it.current() ) {
if ( it.current() == formatCollection()->defaultFormat() ) {
++it;
@@ -1749,141 +1585,200 @@ void QTextDocument::setRichTextInternal( const QString &text )
it.current()->setColor( c );
++it;
}
formatCollection()->defaultFormat()->setColor( c );
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();
+ }
+ }
+ }
+ 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 );
}
- } else {
+ } // 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
continue;
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 );
curpar->at( index )->setCustomItem( custom );
if ( !curtag.anchorHref.isEmpty() )
curpar->at(index)->setAnchor( QString::null, curtag.anchorHref );
if ( !anchorName.isEmpty() ) {
curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
anchorName = QString::null;
}
registerCustomItem( custom, curpar );
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 {
if ( !tags.isEmpty() )
curtag = tags.top();
else
curtag = initag;
}
- 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() )
anchorName += "#" + attr["name"];
else
anchorName = attr["name"];
curtag.anchorHref = attr["href"];
}
if ( nstyle->alignment() != QStyleSheetItem::Undefined )
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 ) {
+ 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;
+ }
+ }
+ }
+
+
+ /* 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" )
+ curtag.alignment = Qt::AlignCenter;
+ else if ( align == "right" )
+ curtag.alignment = Qt::AlignRight;
+ else if ( align == "justify" )
+ curtag.alignment = Qt3::AlignJustify;
+ }
+ if ( attr.contains( "dir" ) ) {
+ QString dir = attr["dir"];
+ if ( dir == "rtl" )
+ curtag.direction = QChar::DirR;
+ else if ( dir == "ltr" )
+ curtag.direction = QChar::DirL;
+ }
+
NEWPAR;
- }
- if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
- curpar->setListStyle( curtag.liststyle );
- if ( attr.find( "value" ) != attr.end() )
- curpar->setListValue( (*attr.find( "value" )).toInt() );
- }
+ if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
+ if ( attr.contains( "value " ) )
+ curpar->setListValue( attr["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' ) ) {
- QString align = attr["align"];
- if ( align == "center" )
- curtag.alignment = Qt::AlignCenter;
- else if ( align == "right" )
- curtag.alignment = Qt::AlignRight;
- else if ( align == "justify" )
- curtag.alignment = Qt3::AlignJustify;
- }
- if ( attr.contains( "dir" ) &&
- ( curtag.name == "p" ||
- curtag.name == "div" ||
- curtag.name == "li" ||
- curtag.name[ 0 ] == 'h' ) ) {
- QString dir = attr["dir"];
- if ( dir == "rtl" )
- curtag.direction = QChar::DirR;
- else if ( dir == "ltr" )
- curtag.direction = QChar::DirL;
- }
- if ( nstyle->displayMode() != QStyleSheetItem::DisplayInline ) {
- curpar->setAlignment( curtag.alignment );
- curpar->setDirection( (QChar::Direction)curtag.direction );
+ 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
if ( !sheet_->item( tagname ) ) // ignore unknown tags
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
while ( curtag.name != tagname ) {
QString msg;
msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)",
curtag.name.ascii(), tagname.ascii(), pos);
@@ -1898,49 +1793,69 @@ void QTextDocument::setRichTextInternal( const QString &text )
if ( !tags.isEmpty() )
curtag = tags.pop();
else
curtag = initag;
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;
}
}
} else {
// normal contents
QString s;
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 )
continue;
if ( c == '\r' )
continue;
space = c_isSpace;
s += c;
}
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 );
curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already
f->ref += s.length() -1; // that what friends are for...
if ( !curtag.anchorHref.isEmpty() ) {
for ( int i = 0; i < int(s.length()); i++ )
@@ -1948,31 +1863,185 @@ void QTextDocument::setRichTextInternal( const QString &text )
}
if ( !anchorName.isEmpty() ) {
curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
anchorName = QString::null;
}
}
- 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();
+ }
}
void QTextDocument::setText( const QString &text, const QString &context )
{
focusIndicator.parag = 0;
selections.clear();
@@ -1980,178 +2049,237 @@ void QTextDocument::setText( const QString &text, const QString &context )
txtFormat == Qt::RichText )
setRichText( text, context );
else
setPlainText( text );
}
-QString QTextDocument::plainText( QTextParag *p ) const
+QString QTextDocument::plainText() const
{
- if ( !p ) {
- QString buffer;
- QString s;
- QTextParag *p = fParag;
- while ( p ) {
- if ( !p->mightHaveCustomItems ) {
- s = p->string()->toString();
- } else {
- for ( int i = 0; i < p->length() - 1; ++i ) {
- if ( p->at( i )->isCustom() ) {
- if ( p->at( i )->customItem()->isNested() ) {
- s += "\n";
- QTextTable *t = (QTextTable*)p->at( i )->customItem();
- QPtrList<QTextTableCell> cells = t->tableCells();
- for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
- s += c->richText()->plainText() + "\n";
- s += "\n";
- }
- } else {
- s += p->at( i )->c;
+ QString buffer;
+ QString s;
+ QTextParagraph *p = fParag;
+ while ( p ) {
+ if ( !p->mightHaveCustomItems ) {
+ s = p->string()->toString();
+ } else {
+ for ( int i = 0; i < p->length() - 1; ++i ) {
+ if ( p->at( i )->isCustom() ) {
+ if ( p->at( i )->customItem()->isNested() ) {
+ s += "\n";
+ QTextTable *t = (QTextTable*)p->at( i )->customItem();
+ QPtrList<QTextTableCell> cells = t->tableCells();
+ for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
+ s += c->richText()->plainText() + "\n";
+ s += "\n";
}
+ } else {
+ s += p->at( i )->c;
}
}
- s.remove( s.length() - 1, 1 );
- if ( p->next() )
- s += "\n";
- buffer += s;
- p = p->next();
}
- return buffer;
- } else {
- return p->string()->toString();
+ s.remove( s.length() - 1, 1 );
+ if ( p->next() )
+ s += "\n";
+ buffer += s;
+ p = p->next();
}
+ return buffer;
}
-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 )
- return " align=\"center\"";
- if ( a & Qt3::AlignJustify )
- return " align=\"justify\"";
- }
- return "";
+ if ( a & Qt::AlignRight )
+ return " align=\"right\"";
+ if ( a & Qt::AlignHCenter )
+ return " align=\"center\"";
+ if ( a & Qt3::AlignJustify )
+ return " align=\"justify\"";
+ 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() ) + ">";
- }
- } 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() + ">" );
- }
- 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;
- }
- } 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 + ">" );
- }
- 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;
+ if ( v != -1 )
+ return " listvalue=\"" + QString::number( v ) + "\"";
+ return QString::null;
+}
+
+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;
+ }
+}
+
+static inline bool list_is_ordered( int v )
+{
+ return v == QStyleSheetItem::ListDecimal ||
+ v == QStyleSheetItem::ListLowerAlpha ||
+ v == QStyleSheetItem::ListUpperAlpha;
+}
+
+
+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;
+}
+
+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 +="\">";
+ }
+ 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 + ">";
}
- if ( ( p = p->next() ) )
- s += '\n';
- }
- } else {
- s = p->richText();
+ } else {
+ 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;
}
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 );
s = s->next();
}
}
void QTextDocument::selectionStart( int id, int &paragId, int &index )
{
QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
if ( it == selections.end() )
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();
}
QTextCursor QTextDocument::selectionStartCursor( int id)
{
QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
@@ -2177,38 +2305,16 @@ QTextCursor QTextDocument::selectionEndCursor( int id)
void QTextDocument::selectionEnd( int id, int &paragId, int &index )
{
QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
if ( it == selections.end() )
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 )
{
nSelections = QMAX( nSelections, id + 1 );
}
static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCursor &start, QTextCursor &end )
@@ -2217,58 +2323,57 @@ static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCur
QTextCursor c2 = end;
if ( sel.swapped ) {
c1 = end;
c2 = start;
}
- 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 );
if ( it == selections.end() )
return FALSE;
QTextDocumentSelection &sel = *it;
QTextCursor start = sel.startCursor;
- QTextCursor end = *cursor;
+ QTextCursor end = cursor;
if ( start == end ) {
removeSelection( id );
setSelectionStart( id, cursor );
return TRUE;
}
- if ( sel.endCursor.parag() == end.parag() ) {
+ if ( sel.endCursor.paragraph() == end.paragraph() ) {
setSelectionEndHelper( id, sel, start, end );
return TRUE;
}
bool inSelection = FALSE;
QTextCursor c( this );
QTextCursor tmp = sel.startCursor;
if ( sel.swapped )
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;
bool hadStartParag = FALSE;
bool hadEndParag = FALSE;
bool hadOldStart = FALSE;
bool hadOldEnd = FALSE;
@@ -2276,76 +2381,88 @@ bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor )
sel.swapped = FALSE;
for ( ;; ) {
if ( c == start )
hadStart = TRUE;
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 )
hadOldStart = TRUE;
if ( c == sel.endCursor )
hadOldEnd = TRUE;
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;
if ( c == end && hadStartParag ||
c == start && hadEndParag ) {
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() );
}
}
if ( inSelection &&
( c == end && hadStart || c == start && hadEnd ) )
leftSelection = TRUE;
else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) )
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 );
}
}
if ( leftSelection )
inSelection = FALSE;
- old = c;
- c.gotoNextLetter();
- if ( old == c || noSelectionAnymore )
+ if ( noSelectionAnymore )
break;
+ // *ugle*hack optimization
+ QTextParagraph *p = c.paragraph();
+ if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) {
+ c.gotoNextLetter();
+ 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();
setSelectionEndHelper( id, sel, start, end );
return TRUE;
}
@@ -2355,112 +2472,55 @@ void QTextDocument::selectAll( int id )
removeSelection( id );
QTextDocumentSelection sel;
sel.swapped = FALSE;
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;
- }
-
- 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;
+ start.gotoNextLetter();
}
-
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() )
return QString::null;
QTextDocumentSelection sel = *it;
@@ -2478,41 +2538,53 @@ QString QTextDocument::selectedText( int id, bool withCustom ) const
to paragraphs within the same text document.
Meaning if you select text in two table cells, you will get the
entire table. This is still far better than the 3.0.2, where
you always got the entire table.
- ### Fix this properly for 3.0.4.
+ ### Fix this properly when refactoring
*/
while ( c2.nestedDepth() > c1.nestedDepth() )
c2.oneUp();
while ( c1.nestedDepth() > c2.nestedDepth() )
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;
c1 = tmp;
}
// end selection 3.0.3 improvement
+ if ( asRichText && !parent() ) {
+ richTextExportStart = &c1;
+ richTextExportEnd = &c2;
- if ( c1.parag() == c2.parag() ) {
- QString s;
- QTextParag *p = c1.parag();
+ 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;
+ }
+
+ QString s;
+ 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 {
for ( int i = c1.index(); i < end; ++i ) {
if ( p->at( i )->isCustom() ) {
if ( p->at( i )->customItem()->isNested() ) {
s += "\n";
@@ -2524,47 +2596,53 @@ QString QTextDocument::selectedText( int id, bool withCustom ) const
}
} else {
s += p->at( i )->c;
}
}
}
- return s;
- }
-
- QString s;
- QTextParag *p = c1.parag();
- 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() )
- ++end;
- if ( !withCustom || !p->mightHaveCustomItems ) {
- s += p->string()->toString().mid( start, end - start );
- if ( p != c2.parag() )
- s += "\n";
- } else {
- for ( int i = start; i < end; ++i ) {
- if ( p->at( i )->isCustom() ) {
- if ( p->at( i )->customItem()->isNested() ) {
- s += "\n";
- QTextTable *t = (QTextTable*)p->at( i )->customItem();
- QPtrList<QTextTableCell> cells = t->tableCells();
- for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
- s += c->richText()->plainText() + "\n";
- s += "\n";
+ } else {
+ QTextParagraph *p = c1.paragraph();
+ int start = c1.index();
+ while ( p ) {
+ int end = p == c2.paragraph() ? c2.index() : p->length() - 1;
+ if ( p == c2.paragraph() && p->at( QMAX( 0, end - 1 ) )->isCustom() )
+ ++end;
+ if ( !p->mightHaveCustomItems ) {
+ s += p->string()->toString().mid( start, end - start );
+ if ( p != c2.paragraph() )
+ s += "\n";
+ } else {
+ for ( int i = start; i < end; ++i ) {
+ if ( p->at( i )->isCustom() ) {
+ if ( p->at( i )->customItem()->isNested() ) {
+ s += "\n";
+ QTextTable *t = (QTextTable*)p->at( i )->customItem();
+ QPtrList<QTextTableCell> cells = t->tableCells();
+ for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
+ s += c->richText()->plainText() + "\n";
+ s += "\n";
+ }
+ } else {
+ s += p->at( i )->c;
}
- } else {
- s += p->at( i )->c;
}
}
+ start = 0;
+ if ( p == c2.paragraph() )
+ break;
+ p = p->next();
}
- start = 0;
- if ( p == c2.parag() )
- 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;
}
void QTextDocument::setFormat( int id, QTextFormat *f, int flags )
{
QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id );
@@ -2580,34 +2658,24 @@ void QTextDocument::setFormat( int id, QTextFormat *f, int flags )
c1 = sel.endCursor;
}
c2.restoreState();
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 );
}
void QTextDocument::removeSelectedText( int id, QTextCursor *cursor )
{
QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
if ( it == selections.end() )
@@ -2629,67 +2697,67 @@ void QTextDocument::removeSelectedText( int id, QTextCursor *cursor )
c2.restoreState();
c1.restoreState();
*cursor = c1;
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() )
didGoLeft = TRUE;
}
- 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();
delete p;
p = tmp;
}
- c2.parag()->remove( 0, c2.index() );
+ c2.paragraph()->remove( 0, c2.index() );
while ( p ) {
p->move( dy );
p->invalidate( 0 );
p->setEndState( -1 );
p = p->next();
}
- c1.parag()->join( c2.parag() );
+ c1.paragraph()->join( c2.paragraph() );
if ( didGoLeft )
cursor->gotoNextLetter();
}
void QTextDocument::indentSelection( int id )
{
QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
if ( it == selections.end() )
return;
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();
p = p->next();
}
}
@@ -2705,90 +2773,75 @@ QTextCursor *QTextDocument::undo( QTextCursor *c )
QTextCursor *QTextDocument::redo( QTextCursor *c )
{
return commandHistory->redo( 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;
}
- first = FALSE;
-
for ( ;; ) {
- int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs );
- if ( res == -1 )
+ if ( expr.at( expr.length() - 1 ).isSpace() || expr.at( expr.length() - 1 ).isPunct() )
+ expr = expr.left( expr.length() - 1 );
+ else
break;
-
- bool ok = TRUE;
- if ( wo ) {
+ }
+ }
+ 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 );
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 );
- setSelectionStart( Standard, cursor );
- cursor->setIndex( res + expr.length() );
- setSelectionEnd( Standard, cursor );
- if ( parag )
- *parag = p->paragId();
- if ( index )
- *index = res;
- return TRUE;
- }
- if ( forward ) {
- start = res + 1;
- } else {
- if ( res == 0 )
+ if ( res == -1 || ( !forward && start < end ) )
break;
- start = res - 1;
+ 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( forward ? res : end );
+ setSelectionEnd( Standard, cursor );
+ return TRUE;
+ }
+ start = res + (forward ? 1 : -1);
}
}
- p = forward ? p->next() : p->prev();
+ if ( forward ) {
+ if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd () )
+ break;
+ cursor.gotoNextLetter();
+ } else {
+ if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() )
+ break;
+ cursor.gotoPreviousLetter();
+ }
}
-
return FALSE;
}
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 );
}
Qt::TextFormat QTextDocument::textFormat() const
{
return txtFormat;
}
@@ -2797,23 +2850,23 @@ bool QTextDocument::inSelection( int selId, const QPoint &pos ) const
{
QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( selId );
if ( it == selections.end() )
return FALSE;
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 ) ) {
bool inSel = FALSE;
int selStart = p->selectionStart( selId );
int selEnd = p->selectionEnd( selId );
int y = 0;
@@ -2852,66 +2905,47 @@ void QTextDocument::doLayout( QPainter *p, int w )
withoutDoubleBuffer = ( p != 0 );
QPainter * oldPainter = QTextFormat::painter();
QTextFormat::setPainter( p );
flow_->setWidth( w );
cw = w;
vw = w;
- QTextParag *parag = fParag;
+ QTextParagraph *parag = fParag;
while ( parag ) {
parag->invalidate( 0 );
if ( p )
parag->adjustToPainter( p );
parag->format();
parag = parag->next();
}
QTextFormat::setPainter( oldPainter );
}
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;
}
void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper )
{
- if ( !firstParag() )
+ if ( !firstParagraph() )
return;
if ( paper ) {
p->setBrushOrigin( 0, 0 );
p->fillRect( rect, *paper );
}
- 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() )
parag->format();
int y = parag->rect().y();
QRect pr( parag->rect() );
pr.setX( 0 );
@@ -2929,13 +2963,13 @@ void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg,
parag = parag->next();
if ( !flow()->isEmpty() )
flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE );
}
}
-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 )
{
QPainter *painter = 0;
if ( resetChanged )
parag->setChanged( FALSE );
@@ -2962,29 +2996,17 @@ void QTextDocument::drawParag( QPainter *p, QTextParag *parag, int cx, int cy, i
painter = p;
painter->translate( ir.x(), ir.y() );
}
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() )
- 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() );
- }
- }
+ 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() ),
+ parag->backgroundBrush( cg ) );
painter->translate( -( ir.x() - parag->rect().x() ),
-( ir.y() - parag->rect().y() ) );
parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch );
if ( useDoubleBuffer ) {
@@ -2992,126 +3014,130 @@ void QTextDocument::drawParag( QPainter *p, QTextParag *parag, int cx, int cy, i
painter = 0;
p->drawPixmap( ir.topLeft(), *doubleBuffer, QRect( QPoint( 0, 0 ), ir.size() ) );
} else {
painter->translate( -ir.x(), -ir.y() );
}
- if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) {
- p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(),
- ( parag->document()->x() + parag->document()->width() ) -
- ( parag->rect().x() + parag->rect().width() ),
- parag->rect().height(), cg.brush( QColorGroup::Base ) );
+ 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(),
+ ( parag->document()->x() + parag->document()->width() ) -
+ ( parag->rect().x() + parag->rect().width() ),
+ 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 )
{
if ( withoutDoubleBuffer || par && par->withoutDoubleBuffer ) {
withoutDoubleBuffer = TRUE;
QRect r;
draw( p, r, cg );
return 0;
}
withoutDoubleBuffer = FALSE;
- if ( !firstParag() )
+ if ( !firstParagraph() )
return 0;
- if ( drawCursor && cursor )
- tmpCursor = cursor;
if ( cx < 0 && cy < 0 ) {
cx = 0;
cy = 0;
cw = width();
ch = height();
}
- QTextParag *lastFormatted = 0;
- QTextParag *parag = firstParag();
+ QTextParagraph *lastFormatted = 0;
+ QTextParagraph *parag = firstParagraph();
QPixmap *doubleBuffer = 0;
QPainter painter;
+ bool fullWidthSelection = FALSE;
while ( parag ) {
lastFormatted = parag;
if ( !parag->isValid() )
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;
- goto floating;
- }
- parag = parag->next();
- continue;
- }
-
- if ( !parag->hasChanged() && onlyChanged ) {
+ if ( pr.y() > cy + ch )
+ goto floating;
+ if ( !pr.intersects( QRect( cx, cy, cw, ch ) ) || ( onlyChanged && !parag->hasChanged() ) ) {
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() ),
cg.brush( QColorGroup::Base ) );
}
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 );
}
}
if ( buf_pixmap && buf_pixmap->height() > 300 ) {
delete buf_pixmap;
buf_pixmap = 0;
}
- 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 ) {
flow_->registerFloatingItem( i );
p->registerFloatingItem( i );
i->setParagraph( p );
}
p->mightHaveCustomItems = mightHaveCustomItems = TRUE;
}
-void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParag *p )
+void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p )
{
flow_->unregisterFloatingItem( i );
p->unregisterFloatingItem( i );
i->setParagraph( 0 );
}
@@ -3140,13 +3166,13 @@ bool QTextDocument::focusNextPrevChild( bool next )
} else {
focusIndicator.parag->setChanged( TRUE );
}
focusIndicator.href = QString::null;
if ( next ) {
- QTextParag *p = focusIndicator.parag;
+ QTextParagraph *p = focusIndicator.parag;
int index = focusIndicator.start + focusIndicator.len;
while ( p ) {
for ( int i = index; i < p->length(); ++i ) {
if ( p->at( i )->isAnchor() ) {
p->setChanged( TRUE );
focusIndicator.parag = p;
@@ -3199,13 +3225,13 @@ bool QTextDocument::focusNextPrevChild( bool next )
}
}
index = 0;
p = p->next();
}
} else {
- QTextParag *p = focusIndicator.parag;
+ QTextParagraph *p = focusIndicator.parag;
int index = focusIndicator.start - 1;
if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 )
index++;
while ( p ) {
for ( int i = index; i >= 0; --i ) {
if ( p->at( i )->isAnchor() ) {
@@ -3279,13 +3305,13 @@ bool QTextDocument::focusNextPrevChild( bool next )
return FALSE;
}
int QTextDocument::length() const
{
int l = 0;
- QTextParag *p = fParag;
+ QTextParagraph *p = fParag;
while ( p ) {
l += p->length() - 1; // don't count trailing space
p = p->next();
}
return l;
}
@@ -3382,37 +3408,42 @@ QTextString::QTextString( const QTextString &s )
dir = s.dir;
data = s.subString();
}
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;
data[ (int)index + i ].d.format = 0;
data[ (int)index + i ].type = QTextStringChar::Regular;
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 );
}
bidiDirty = TRUE;
}
QTextString::~QTextString()
{
clear();
}
-void QTextString::insert( int index, QTextStringChar *c )
+void QTextString::insert( int index, QTextStringChar *c, bool doAddRefFormat )
{
int os = data.size();
data.resize( data.size() + 1 );
if ( index < os ) {
memmove( data.data() + index + 1, data.data() + index,
sizeof( QTextStringChar ) * ( os - index ) );
@@ -3420,12 +3451,14 @@ void QTextString::insert( int index, QTextStringChar *c )
data[ (int)index ].c = c->c;
data[ (int)index ].x = 0;
data[ (int)index ].lineStart = 0;
data[ (int)index ].rightToLeft = 0;
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;
}
void QTextString::truncate( int index )
{
@@ -3542,52 +3575,47 @@ void QTextString::checkBidi() const
void QTextDocument::setStyleSheet( QStyleSheet *s )
{
if ( !s )
return;
sheet_ = s;
- fCollection->setStyleSheet( s );
- updateStyles();
-}
-
-void QTextDocument::updateStyles()
-{
- invalidate();
- if ( par )
- underlLinks = par->underlLinks;
- fCollection->updateStyles();
- for ( QTextDocument *d = childList.first(); d; d = childList.next() )
- d->updateStyles();
-}
-
-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 );
+ 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 ));
+ }
+ 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::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 );
}
void QTextStringChar::setFormat( QTextFormat *f )
{
if ( type == Regular ) {
- d.format = f;
+ d.format = f;
} else {
- if ( !d.custom ) {
- d.custom = new CustomData;
- d.custom->custom = 0;
- }
- d.custom->format = f;
+ if ( !d.custom ) {
+ d.custom = new CustomData;
+ d.custom->custom = 0;
+ }
+ d.custom->format = f;
}
}
void QTextStringChar::setCustomItem( QTextCustomItem *i )
{
if ( type == Regular ) {
@@ -3648,13 +3676,13 @@ void QTextStringChar::setAnchor( const QString& name, const QString& href )
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() ) {
if( c->customItem()->placement() == QTextCustomItem::PlaceInline )
w = c->customItem()->width;
} else {
int r = c->c.row();
@@ -3696,93 +3724,66 @@ QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const
if ( c->format() )
c->format()->addRef();
}
return a;
}
-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 )
p->n = this;
if ( n )
n->p = this;
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 )
id = p->id + 1;
else
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();
str->insert( 0, " ", formatCollection()->defaultFormat() );
}
-QTextParag::~QTextParag()
+QTextParagraph::~QTextParagraph()
{
delete str;
if ( hasdoc ) {
register QTextDocument *doc = document();
if ( this == doc->minwParag ) {
doc->minwParag = 0;
@@ -3793,73 +3794,83 @@ QTextParag::~QTextParag()
} else {
delete pseudoDocument();
}
if ( tArray )
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;
if ( mSelections )
delete mSelections;
if ( mFloatingItems )
delete mFloatingItems;
- if ( mStyleSheetItemsVec )
- delete mStyleSheetItemsVec;
if ( p )
p->setNext( n );
if ( n )
n->setPrev( p );
}
-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 )
invalid = chr;
else
invalid = QMIN( invalid, chr );
if ( mFloatingItems ) {
for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() )
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 );
insert( length(), " " );
needPreProcess = TRUE;
}
-void QTextParag::remove( int index, int len )
+void QTextParagraph::remove( int index, int len )
{
if ( index + len - str->length() > 0 )
return;
for ( int i = index; i < index + len; ++i ) {
QTextStringChar *c = at( i );
if ( hasdoc && c->isCustom() ) {
@@ -3868,20 +3879,20 @@ void QTextParag::remove( int index, int len )
}
str->remove( index, len );
invalidate( 0 );
needPreProcess = TRUE;
}
-void QTextParag::join( QTextParag *s )
+void QTextParagraph::join( QTextParagraph *s )
{
int oh = r.height() + s->r.height();
n = s->n;
if ( n )
n->p = this;
else if ( hasdoc )
- document()->setLastParag( this );
+ document()->setLastParagraph( this );
int start = str->length();
if ( length() > 0 && at( length() - 1 )->c == ' ' ) {
remove( length() - 1, 1 );
--start;
}
@@ -3893,12 +3904,16 @@ void QTextParag::join( QTextParag *s )
str->setFormat( i + start, s->str->at( i ).format(), TRUE );
}
if ( s->str->at( i ).isCustom() ) {
QTextCustomItem * item = s->str->at( i ).customItem();
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() ) {
str->at( i + start ).setAnchor( s->str->at( i ).anchorName(),
s->str->at( i ).anchorHref() );
}
}
@@ -3911,26 +3926,28 @@ void QTextParag::join( QTextParag *s )
}
delete s;
invalidate( 0 );
r.setHeight( oh );
needPreProcess = TRUE;
if ( n ) {
- QTextParag *s = n;
+ QTextParagraph *s = n;
+ s->invalidate( 0 );
while ( s ) {
s->id = s->p->id + 1;
s->state = -1;
s->needPreProcess = TRUE;
s->changed = TRUE;
+ s->invalidateStyleCache();
s = s->n;
}
}
format();
state = -1;
}
-void QTextParag::move( int &dy )
+void QTextParagraph::move( int &dy )
{
if ( dy == 0 )
return;
changed = TRUE;
r.moveBy( 0, dy );
if ( mFloatingItems ) {
@@ -3948,13 +3965,13 @@ void QTextParag::move( int &dy )
p->setChanged( TRUE );
dy += shift;
}
}
}
-void QTextParag::format( int start, bool doMove )
+void QTextParagraph::format( int start, bool doMove )
{
if ( !str || str->length() == 0 || !formatter() )
return;
if ( hasdoc &&
document()->preProcessor() &&
@@ -3963,58 +3980,58 @@ void QTextParag::format( int start, bool doMove )
needPreProcess = FALSE;
if ( invalid == -1 )
return;
r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) );
- r.setWidth( documentWidth() );
if ( p )
p->lastInFrame = FALSE;
movedDown = FALSE;
bool formattedAgain = FALSE;
formatAgain:
+ r.setWidth( documentWidth() );
if ( hasdoc && mFloatingItems ) {
for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) {
i->ypos = r.y();
if ( i->placement() == QTextCustomItem::PlaceRight ) {
i->xpos = r.x() + r.width() - i->width;
}
}
}
- QMap<int, QTextParagLineStart*> oldLineStarts = lineStarts;
+ QMap<int, QTextLineStart*> oldLineStarts = lineStarts;
lineStarts.clear();
int y = formatter()->format( document(), this, start, oldLineStarts );
r.setWidth( QMAX( r.width(), formatter()->minimumWidth() ) );
- QMap<int, QTextParagLineStart*>::Iterator it = oldLineStarts.begin();
+ QMap<int, QTextLineStart*>::Iterator it = oldLineStarts.begin();
for ( ; it != oldLineStarts.end(); ++it )
delete *it;
QTextStringChar *c = 0;
- // do not do this on mac, as the paragraph
- // with has to be the full document width on mac as the selections
- // always extend completely to the right. This is a bit unefficient,
- // as this results in a bigger double buffer than needed but ok for
- // now.
- if ( lineStarts.count() == 1 ) { //&& ( !doc || document()->flow()->isEmpty() ) ) {
+ // do not do this on mac, as the paragraph
+ // with has to be the full document width on mac as the selections
+ // always extend completely to the right. This is a bit unefficient,
+ // as this results in a bigger double buffer than needed but ok for
+ // now.
+ if ( lineStarts.count() == 1 ) {
if ( !string()->isBidi() ) {
c = &str->at( str->length() - 1 );
r.setWidth( c->x + str->width( str->length() - 1 ) );
} else {
r.setWidth( lineStarts[0]->w );
}
}
- if ( newLinesAllowed ) {
+ if ( !hasdoc ) { // qt_format_text bounding rect handling
it = lineStarts.begin();
int usedw = 0;
for ( ; it != lineStarts.end(); ++it )
usedw = QMAX( usedw, (*it)->w );
if ( r.width() <= 0 ) {
// if the user specifies an invalid rect, this means that the
@@ -4051,13 +4068,13 @@ void QTextParag::format( int start, bool doMove )
goto formatAgain;
}
}
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 ) {
if ( !s->isFullWidth() )
makeInvalid = TRUE;
if ( makeInvalid )
s->invalidate( 0 );
@@ -4071,18 +4088,18 @@ void QTextParag::format( int start, bool doMove )
firstFormat = FALSE;
changed = TRUE;
invalid = -1;
//##### string()->setTextChanged( FALSE );
}
-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 ( ;; ) {
if ( i >= it.key() ) {
if ( bl )
*bl = ( *it )->baseLine;
if ( y )
@@ -4091,23 +4108,23 @@ int QTextParag::lineHeightOfChar( int i, int *bl, int *y ) const
}
if ( it == lineStarts.begin() )
break;
--it;
}
- 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 ( ;; ) {
if ( i >= it.key() ) {
if ( index )
*index = it.key();
if ( line )
@@ -4117,67 +4134,67 @@ QTextStringChar *QTextParag::lineStartOfChar( int i, int *index, int *line ) con
if ( it == lineStarts.begin() )
break;
--it;
--l;
}
- 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;
int i = it.key();
if ( index )
*index = i;
return &str->at( i );
}
- 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 */
x = QMIN(x, str->at(i).x);
++it;
++line;
}
return x;
}
-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 )
return;
if ( index < 0 )
index = 0;
if ( index > str->length() - 1 )
@@ -4209,274 +4226,201 @@ void QTextParag::setFormat( int index, int len, QTextFormat *f, bool useCollecti
QTextFormat *fm = fc->format( of, f, flags );
str->setFormat( i + index, fm, useCollection );
}
}
}
-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;
if ( newIndent )
*newIndent = 0;
if ( oldIndent && newIndent )
*newIndent = *oldIndent;
return;
}
document()->indent()->indent( document(), this, oldIndent, 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 );
- } else {
- tw = 0;
- }
- }
-#endif
- if ( !chr->isCustom() ) {
- if ( chr->c != '\n' ) {
- paintStart = i;
- paintEnd = i;
- } else {
- paintStart = i+1;
- paintEnd = -1;
- }
- formatChar = chr;
- lastY = cy;
- startX = chr->x;
- bw = cw;
+ if ( flush ) { // something changed, draw what we have so far
+ if ( chr->rightToLeft ) {
+ xstart = chr->x;
+ xend = at( paintStart )->x + str->width( paintStart );
} 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;
- }
+ 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 );
}
- } else {
- if ( chr->c != '\n' ) {
- if( chr->rightToLeft ) {
- startX = chr->x;
- }
- paintEnd = i;
+
+ 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 );
}
- bw += cw;
+ paintStart = i+1;
}
- 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 )
- break;
+ 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 );
}
}
painter.restore();
}
}
//#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();
QString str( s );
if ( str[ (int)str.length() - 1 ].unicode() == 0xad )
str.remove( str.length() - 1, 1 );
if ( !plainText || hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() )
@@ -4496,116 +4440,114 @@ void QTextParag::drawParagString( QPainter &painter, const QString &s, int start
QFont fn = format->font();
fn.setUnderline( TRUE );
painter.setFont( fn );
}
}
- 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;
while( i < len )
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
} else if ( format->vAlign() == QTextFormat::AlignSuperScript ) {
QFont f( painter.font() );
if ( format->fontSizesInPixels() )
f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
else
f.setPointSize( ( f.pointSize() * 2 ) / 3 );
painter.setFont( f );
- painter.drawText( startX, lastY + baseLine - ( painter.fontMetrics().height() / 2 ),
- str.mid( start ), len );
+ painter.drawText( xstart, y + baseLine - ( painter.fontMetrics().height() / 2 ),
+ str.mid( start ), len );
} else if ( format->vAlign() == QTextFormat::AlignSubScript ) {
QFont f( painter.font() );
if ( format->fontSizesInPixels() )
f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
else
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();
}
i -= len;
if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() &&
document()->focusIndicator.parag == this &&
( document()->focusIndicator.start >= i &&
document()->focusIndicator.start + document()->focusIndicator.len <= i + len ||
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() );
- }
+ QTextFormat *format = at( 0 )->format();
+ if ( format ) {
+ p->setPen( format->color() );
+ p->setFont( format->font() );
}
- p->setFont( font2 );
QFontMetrics fm( p->fontMetrics() );
int size = fm.lineSpacing() / 3;
switch ( s ) {
case QStyleSheetItem::ListDecimal:
case QStyleSheetItem::ListLowerAlpha:
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 ) {
case QStyleSheetItem::ListLowerAlpha:
if ( n < 27 ) {
l = QChar( ('a' + (char) (n-1)));
break;
@@ -4624,171 +4566,77 @@ void QTextParag::drawLabel( QPainter* p, int x, int y, int w, int h, int base, c
p->drawText( r.right() - fm.width( l ), r.top() + base, l );
}
break;
case QStyleSheetItem::ListSquare:
{
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;
case QStyleSheetItem::ListCircle:
{
QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size);
p->drawEllipse( er );
}
break;
case QStyleSheetItem::ListDisc:
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 );
p->setBrush( Qt::NoBrush );
}
break;
}
p->restore();
}
-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();
- while ( s ) {
- s->numSubParag = -1;
- s->lm = s->rm = s->tm = s->bm = flm = -1;
- s->numSubParag = -1;
- s->invalidate( 0 );
- s = 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->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;
if ( !ta && hasdoc )
ta = document()->tabArray();
return ta;
}
-int QTextParag::nextTab( int, int x )
+int QTextParagraph::nextTab( int, int x )
{
int *ta = tArray;
if ( hasdoc ) {
if ( !ta )
ta = document()->tabArray();
tabStopWidth = document()->tabStopWidth();
@@ -4808,336 +4656,208 @@ int QTextParag::nextTab( int, int x )
else
return x;
return tabStopWidth * ( d + 1 );
}
}
-void QTextParag::adjustToPainter( QPainter *p )
+void QTextParagraph::adjustToPainter( QPainter *p )
{
for ( int i = 0; i < length(); ++i ) {
if ( at( i )->isCustom() )
at( i )->customItem()->adjustToPainter( p );
}
}
-QTextFormatCollection *QTextParag::formatCollection() const
+QTextFormatCollection *QTextParagraph::formatCollection() const
{
if ( hasdoc )
return document()->formatCollection();
if ( !qFormatCollection ) {
qFormatCollection = new QTextFormatCollection;
static QSingleCleanupHandler<QTextFormatCollection> qtfCleanup;
qtfCleanup.set( &qFormatCollection );
}
return qFormatCollection;
}
-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() ) {
if ( c->anchorName().contains( '#' ) ) {
QStringList l = QStringList::split( '#', c->anchorName() );
for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it )
s += "<a name=\"" + *it + "\"></a>";
} else {
s += "<a name=\"" + c->anchorName() + "\"></a>";
}
}
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 += "&lt;";
- } else if ( c->c == '>' ) {
+ else if ( c->c == '>' )
s += "&gt;";
- } 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 )
pseudoDocument()->commandHistory->addCommand( cmd );
else
document()->commands()->addCommand( cmd );
}
-QTextCursor *QTextParag::undo( QTextCursor *c )
+QTextCursor *QTextParagraph::undo( QTextCursor *c )
{
if ( !hasdoc )
return pseudoDocument()->commandHistory->undo( c );
return document()->commands()->undo( c );
}
-QTextCursor *QTextParag::redo( QTextCursor *c )
+QTextCursor *QTextParagraph::redo( QTextCursor *c )
{
if ( !hasdoc )
return pseudoDocument()->commandHistory->redo( c );
return document()->commands()->redo( 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 );
- }
- }
- }
-
- m = scale ( m, QTextFormat::painter() );
-
- ( (QTextParag*)this )->lm = m;
- return lm;
+ int m = ulm;
+ if ( listDepth() )
+ m += listDepth() * document()->list_lm;
+ return scale( m, QTextFormat::painter() );
}
-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 = 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 m = uflm;
+ return scale( m, QTextFormat::painter() );
}
-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 )
return;
visible = TRUE;
}
-void QTextParag::hide()
+void QTextParagraph::hide()
{
if ( !visible || !hasdoc )
return;
visible = FALSE;
}
-void QTextParag::setDirection( QChar::Direction d )
+void QTextParagraph::setDirection( QChar::Direction d )
{
if ( str && str->direction() != d ) {
str->setDirection( d );
invalidate( 0 );
}
}
-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 );
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -5149,33 +4869,36 @@ QTextPreProcessor::QTextPreProcessor()
QTextFormatter::QTextFormatter()
: thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE )
{
}
-/* 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 )
{
#ifndef QT_NO_COMPLEXTEXT
if( string->isBidi() )
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) );
// do alignment Auto == Left in this case
if ( align & Qt::AlignHCenter || align & Qt::AlignRight ) {
if ( align & Qt::AlignHCenter )
space /= 2;
for ( int j = start; j <= last; ++j )
string->at( j ).x += space;
} 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++;
}
}
int toAdd = 0;
for ( int k = start + 1; k <= last; ++k ) {
@@ -5191,28 +4914,27 @@ QTextParagLineStart *QTextFormatter::formatLine( QTextParag *parag, QTextString
if ( last >= 0 && last < string->length() )
line->w = string->at( last ).x + string->width( last );
else
line->w = 0;
- return new QTextParagLineStart();
+ return new QTextLineStart();
}
#ifndef QT_NO_COMPLEXTEXT
#ifdef BIDI_DEBUG
#include <iostream>
#endif
// 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 );
QString str;
str.setUnicode( 0, last - start + 1 );
// fill string with logically ordered chars.
QTextStringChar *ch = startChar;
@@ -5240,13 +4962,19 @@ QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QT
if ( align & Qt::AlignHCenter )
x += space/2;
else if ( align & Qt::AlignRight )
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++;
}
}
}
int toAdd = 0;
@@ -5302,34 +5030,35 @@ QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QT
int ww = 0;
if ( c->c.unicode() >= 32 || c->c == '\t' || c->isCustom() ) {
ww = text->width( pos );
} else {
ww = c->format()->width( ' ' );
}
- //qDebug("setting char %d at pos %d", pos, x);
if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww;
x += ww;
pos++;
}
}
text->at( r->start + start ).startOfRun = TRUE;
r = runs->next();
}
line->w = xmax + 10;
- QTextParagLineStart *ls = new QTextParagLineStart( control->context, control->status );
+ QTextLineStart *ls = new QTextLineStart( control->context, control->status );
delete control;
delete runs;
return ls;
}
#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;
if ( c.unicode() == 0xad ) // soft hyphen
return TRUE;
if ( !ch ) {
// not latin1, need to do more sophisticated checks for other scripts
@@ -5371,19 +5100,19 @@ bool QTextFormatter::isBreakable( QTextString *string, int pos ) const
// in front of a punctuation character.
return TRUE;
}
return FALSE;
}
-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
parag->lineStartList().insert( index, ls );
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 );
} else {
delete *it;
parag->lineStartList().remove( it );
parag->lineStartList().insert( index, ls );
@@ -5391,20 +5120,20 @@ void QTextFormatter::insertLineStart( QTextParag *parag, int index, QTextParagLi
}
/* Standard pagebreak algorithm using QTextFlow::adjustFlow. Returns
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 = &parag->string()->at(it.key());
if ( c && c->customItem() && c->customItem()->ownLine() ) {
int h = c->customItem()->height;
c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() );
int delta = c->customItem()->height - h;
@@ -5417,36 +5146,38 @@ int QTextFormatter::formatVertically( QTextDocument* doc, QTextParag* parag )
if ( shift )
parag->setMovedDown( TRUE );
}
h = ls->y + ls->h;
}
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 );
return h - oldHeight;
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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();
if ( doc )
x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 );
int rm = parag->rightMargin();
int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
@@ -5457,13 +5188,13 @@ int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag,
start = 0; //######### what is the point with start?! (Matthias)
if ( start == 0 )
c = &parag->string()->at( 0 );
int i = start;
- QTextParagLineStart *lineStart = new QTextParagLineStart( y, y, 0 );
+ QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
insertLineStart( parag, 0, lineStart );
QPainter *painter = QTextFormat::painter();
int col = 0;
int ww = 0;
@@ -5498,29 +5229,28 @@ int QTextFormatterBreakInWords::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 );
c->customItem()->resize( w - x );
w = dw;
y += h;
h = c->height();
- lineStart = new QTextParagLineStart( y, h, h );
+ lineStart = new QTextLineStart( y, h, h );
insertLineStart( parag, i, lineStart );
c->lineStart = 1;
firstChar = c;
x = 0xffffff;
continue;
}
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 );
lineStart->baseLine = c->ascent();
lineStart->h = c->height();
c->lineStart = 1;
firstChar = c;
@@ -5536,18 +5266,20 @@ int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag,
c->x = x;
x += ww;
wused = QMAX( wused, x );
}
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);
thisminw = minw;
thiswused = wused;
return y;
@@ -5563,21 +5295,21 @@ QTextFormatterBreakWords::QTextFormatterBreakWords()
int yflow = lineStart->y + parag->rect().y();\
int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \
lineStart->y += shift;\
y += shift;\
}}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;
QTextStringChar *firstChar = 0;
QTextString *string = parag->string();
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();
if ( doc )
x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 );
int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 );
@@ -5587,21 +5319,21 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag,
int w = dw - rdiff;
bool fullWidth = TRUE;
int marg = left + rdiff;
int minw = 0;
int wused = 0;
int tminw = marg;
- int linespace = doc ? parag->lineSpacing() : 0;
+ int linespacing = doc ? parag->lineSpacing() : 0;
bool wrapEnabled = isWrapEnabled( parag );
start = 0;
if ( start == 0 )
c = &parag->string()->at( 0 );
int i = start;
- QTextParagLineStart *lineStart = new QTextParagLineStart( y, y, 0 );
+ QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
insertLineStart( parag, 0, lineStart );
int lastBreak = -1;
int tmpBaseLine = 0, tmph = 0;
bool lastWasNonInlineCustom = FALSE;
int align = parag->alignment();
@@ -5651,111 +5383,126 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag,
ww = 0;
QTextCustomItem* ci = c->customItem();
if ( c->isCustom() && ci->ownLine() ) {
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 ) {
if ( align & Qt::AlignHCenter )
x = ( w - ci->width ) / 2;
else if ( align & Qt::AlignRight ) {
x = w - ci->width;
}
}
c->x = x;
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;
lineStart->y = y;
insertLineStart( parag, i, lineStart );
c->lineStart = 1;
firstChar = c;
} else {
- tmph = c->height() + linespace;
+ tmph = c->height();
h = tmph;
delete lineStart2;
}
lineStart->h = h;
lineStart->baseLine = h;
tmpBaseLine = lineStart->baseLine;
lastBreak = -2;
x = 0xffffff;
minw = QMAX( minw, tminw );
- int tw = ci->minimumWidth();
+ int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 );
if ( tw < QWIDGETSIZE_MAX )
tminw = tw;
else
tminw = marg;
wused = QMAX( wused, ci->width );
continue;
} else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) {
int tw = ci->minimumWidth();
if ( tw < QWIDGETSIZE_MAX )
minw = QMAX( minw, tw );
}
- 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 );
h = QMAX( h, tmph );
lineStart->h = h;
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 )
ww = w - x;
else
ww = nx - x;
}
curLeft = x;
- y += h;
- tmph = c->height() + linespace;
+ y += QMAX( h, linespacing );
+ tmph = c->height();
h = 0;
lineStart->y = y;
insertLineStart( parag, i, lineStart );
lineStart->baseLine = c->ascent();
lineStart->h = c->height();
c->lineStart = 1;
firstChar = c;
tmpBaseLine = lineStart->baseLine;
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 )
ww = w - x;
else
ww = nx - x;
}
curLeft = x;
- y += h;
- tmph = c->height() + linespace;
+ y += QMAX( h, linespacing );
+ tmph = c->height();
h = tmph;
lineStart->y = y;
insertLineStart( parag, i + 1, lineStart );
lineStart->baseLine = c->ascent();
lineStart->h = c->height();
c->lineStart = 1;
@@ -5763,69 +5510,81 @@ int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag,
tmpBaseLine = lineStart->baseLine;
lastBreak = -1;
col = 0;
tminw = marg;
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 );
tminw = marg + ww;
lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
h = QMAX( h, tmph );
lineStart->h = h;
if ( i < len - 2 || c->c != ' ' )
lastBreak = i;
} 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;
}
c->x = x;
x += ww;
wused = QMAX( wused, x );
}
- // ### 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();
c->setFormat( string->at( len - 2 ).format() );
c->format()->addRef();
}
if ( lineStart ) {
lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
h = QMAX( h, tmph );
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;
return y;
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -5834,13 +5593,13 @@ QTextIndent::QTextIndent()
{
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
QTextFormatCollection::QTextFormatCollection()
- : cKey( 307 ), sheet( 0 )
+ : cKey( 307 )
{
defFormat = new QTextFormat( QApplication::font(),
QApplication::palette().color( QPalette::Active, QColorGroup::Text ) );
lastFormat = cres = 0;
cflags = -1;
cKey.setAutoDelete( TRUE );
@@ -5852,56 +5611,41 @@ QTextFormatCollection::~QTextFormatCollection()
delete defFormat;
}
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();
return lastFormat;
}
if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) {
-#ifdef DEBUG_COLLECTION
- qDebug( "need '%s', good case!", f->key().latin1() );
-#endif
lastFormat->addRef();
return lastFormat;
}
QTextFormat *fm = cKey.find( f->key() );
if ( fm ) {
-#ifdef DEBUG_COLLECTION
- qDebug( "need '%s', normal case!", f->key().latin1() );
-#endif
lastFormat = fm;
lastFormat->addRef();
return lastFormat;
}
if ( f->key() == defFormat->key() )
return defFormat;
-#ifdef DEBUG_COLLECTION
- qDebug( "need '%s', worst case!", f->key().latin1() );
-#endif
lastFormat = createFormat( *f );
lastFormat->collection = this;
cKey.insert( lastFormat->key(), lastFormat );
return lastFormat;
}
QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, int flags )
{
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;
}
cres = createFormat( *of );
kof = of->key();
@@ -5910,12 +5654,14 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, in
if ( flags & QTextFormat::Bold )
cres->fn.setBold( nf->fn.bold() );
if ( flags & QTextFormat::Italic )
cres->fn.setItalic( nf->fn.italic() );
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() );
if ( flags & QTextFormat::Size ) {
if ( of->usePixelSizes )
cres->fn.setPixelSize( nf->fn.pixelSize() );
else
@@ -5928,63 +5674,48 @@ QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, in
if ( flags & QTextFormat::VAlign )
cres->ha = nf->ha;
cres->update();
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;
cres->addRef();
}
return cres;
}
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;
}
QString key = QTextFormat::getKey( f, c, FALSE, QTextFormat::AlignNormal );
cachedFormat = cKey.find( key );
cfont = f;
ccol = c;
if ( cachedFormat ) {
-#ifdef DEBUG_COLLECTION
- qDebug( "format of font and col '%s' - good case", cachedFormat->key().latin1() );
-#endif
cachedFormat->addRef();
return cachedFormat;
}
if ( key == defFormat->key() )
return defFormat;
cachedFormat = createFormat( f, c );
cachedFormat->collection = this;
cKey.insert( cachedFormat->key(), cachedFormat );
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;
}
void QTextFormatCollection::remove( QTextFormat *f )
{
if ( lastFormat == f )
@@ -5993,112 +5724,72 @@ void QTextFormatCollection::remove( QTextFormat *f )
cres = 0;
if ( cachedFormat == f )
cachedFormat = 0;
cKey.remove( f->key() );
}
-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();
-}
-
-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();
-}
+#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::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();
- }
- }
- 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() );
+ 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 );
+ }
+ 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()
{
if ( cKey.isEmpty() )
return;
cKey.setAutoDelete( FALSE );
- QTextFormat** formats = new QTextFormat*[ cKey.count() + 1];
+ QTextFormat** formats = new QTextFormat*[ cKey.count() + 1 ];
QTextFormat **f = formats;
QDictIterator<QTextFormat> it( cKey );
while ( ( *f = it.current() ) ) {
++it;
++f;
}
cKey.clear();
for ( f = formats; *f; f++ )
cKey.insert( (*f)->key(), *f );
cKey.setAutoDelete( TRUE );
+ delete [] formats;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -6139,12 +5830,20 @@ void QTextFormat::setUnderline( bool b )
if ( b == fn.underline() )
return;
fn.setUnderline( b );
update();
}
+void QTextFormat::setStrikeOut( bool b )
+{
+ if ( b == fn.strikeOut() )
+ return;
+ fn.setStrikeOut( b );
+ update();
+}
+
void QTextFormat::setFamily( const QString &f )
{
if ( f == fn.family() )
return;
fn.setFamily( f );
update();
@@ -6172,198 +5871,189 @@ void QTextFormat::setColor( const QColor &c )
if ( c == col )
return;
col = c;
update();
}
-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 + "\">";
}
return tag;
}
-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()
- || 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>";
- }
+ 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 += "</span>";
if ( !anchorHref.isEmpty() )
tag += "</a>";
return tag;
}
-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->isAnchor() && style->color().isValid() ) {
- // the style is not an anchor and defines a color.
- // It might be used inside an anchor and it should
- // override the link color.
+ if (!style )
+ return format;
+
+ if ( !style->isAnchor() && style->color().isValid() ) {
+ // the style is not an anchor and defines a color.
+ // It might be used inside an anchor and it should
+ // override the link color.
+ format.linkColor = FALSE;
+ }
+ switch ( style->verticalAlignment() ) {
+ case QStyleSheetItem::VAlignBaseline:
+ format.setVAlign( QTextFormat::AlignNormal );
+ break;
+ case QStyleSheetItem::VAlignSuper:
+ format.setVAlign( QTextFormat::AlignSuperScript );
+ break;
+ case QStyleSheetItem::VAlignSub:
+ format.setVAlign( QTextFormat::AlignSubScript );
+ break;
+ }
+
+ if ( style->fontWeight() != QStyleSheetItem::Undefined )
+ format.fn.setWeight( style->fontWeight() );
+ if ( style->fontSize() != QStyleSheetItem::Undefined ) {
+ format.fn.setPointSize( style->fontSize() );
+ } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) {
+ format.logicalFontSize = style->logicalFontSize();
+ if ( format.usePixelSizes )
+ format.fn.setPixelSize( format.stdSize );
+ else
+ format.fn.setPointSize( format.stdSize );
+ style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
+ } else if ( style->logicalFontSizeStep() ) {
+ format.logicalFontSize += style->logicalFontSizeStep();
+ if ( format.usePixelSizes )
+ format.fn.setPixelSize( format.stdSize );
+ else
+ format.fn.setPointSize( format.stdSize );
+ style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
+ }
+ if ( !style->fontFamily().isEmpty() )
+ format.fn.setFamily( style->fontFamily() );
+ if ( style->color().isValid() )
+ format.col = style->color();
+ if ( style->definesFontItalic() )
+ format.fn.setItalic( style->fontItalic() );
+ 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;
}
- switch ( style->verticalAlignment() ) {
- case QStyleSheetItem::VAlignBaseline:
- format.setVAlign( QTextFormat::AlignNormal );
- break;
- case QStyleSheetItem::VAlignSuper:
- format.setVAlign( QTextFormat::AlignSuperScript );
- break;
- case QStyleSheetItem::VAlignSub:
- format.setVAlign( QTextFormat::AlignSubScript );
- break;
- }
-
- if ( style->fontWeight() != QStyleSheetItem::Undefined )
- format.fn.setWeight( style->fontWeight() );
- if ( style->fontSize() != QStyleSheetItem::Undefined ) {
- format.fn.setPointSize( style->fontSize() );
- } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) {
- format.logicalFontSize = style->logicalFontSize();
- if ( format.usePixelSizes )
- format.fn.setPixelSize( format.stdSize );
- else
- format.fn.setPointSize( format.stdSize );
- style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
- } else if ( style->logicalFontSizeStep() ) {
- format.logicalFontSize += style->logicalFontSizeStep();
- if ( format.usePixelSizes )
- format.fn.setPixelSize( format.stdSize );
+ }
+ 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.fn.setPointSize( format.stdSize );
- style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
+ format.setVAlign( QTextFormat::AlignNormal );
+ } else if ( style.startsWith("color:" ) ) {
+ format.col.setNamedColor( style.mid(6) );
+ format.linkColor = FALSE;
}
- if ( !style->fontFamily().isEmpty() )
- format.fn.setFamily( style->fontFamily() );
- if ( style->color().isValid() )
- format.col = style->color();
- if ( style->definesFontItalic() )
- format.fn.setItalic( style->fontItalic() );
- if ( style->definesFontUnderline() )
- format.fn.setUnderline( style->fontUnderline() );
}
}
format.update();
return format;
}
@@ -6378,32 +6068,24 @@ struct QPixmapInt
static QMap<QString, QPixmapInt> *pixmap_map = 0;
QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context,
QMimeSourceFactory &factory )
: QTextCustomItem( p )
{
-#if defined(PARSER_DEBUG)
- qDebug( debug_indent + "new QTextImage (pappi: %p)", p );
-#endif
-
width = height = 0;
if ( attr.contains("width") )
width = attr["width"].toInt();
if ( attr.contains("height") )
height = attr["height"].toInt();
reg = 0;
QString imageName = attr["src"];
if (!imageName)
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 );
if ( !pixmap_map )
pixmap_map = new QMap<QString, QPixmapInt>;
if ( pixmap_map->contains( imgId ) ) {
QPixmapInt& pmi = pixmap_map->operator[](imgId);
@@ -6484,12 +6166,13 @@ QTextImage::~QTextImage()
if ( pixmap_map->isEmpty() ) {
delete pixmap_map;
pixmap_map = 0;
}
}
}
+ delete reg;
}
QString QTextImage::richText() const
{
QString s;
s += "<img ";
@@ -6642,13 +6325,13 @@ static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col
return TRUE;
}
return FALSE;
}
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 )
{
QTextTable* table = new QTextTable( this, attr );
int row = -1;
int col = -1;
@@ -6662,15 +6345,12 @@ QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr,
(void) eatSpace(doc, length, pos);
while ( pos < length) {
if (hasPrefix(doc, length, pos, QChar('<')) ){
if (hasPrefix(doc, length, pos+1, QChar('/'))) {
tagname = parseCloseTag( doc, length, pos );
if ( tagname == "table" ) {
-#if defined(PARSER_DEBUG)
- debug_indent.remove( debug_indent.length() - 3, 2 );
-#endif
return table;
}
} else {
QMap<QString, QString> attr2;
bool emptyTag = FALSE;
tagname = parseOpenTag( doc, length, pos, attr2, emptyTag );
@@ -6721,31 +6401,28 @@ QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr,
end++;
}
}
end++;
}
QTextTableCell* cell = new QTextTableCell( table, row, col,
- attr2, s, fmt.makeTextFormat( s, attr2 ),
- contxt, *factory_, sheet_,
- QString( doc, length).mid( pos, end - pos ) );
- cell->richText()->parParag = curpar;
+ attr2, s, fmt.makeTextFormat( s, attr2, scaleFontsFactor ),
+ contxt, *factory_, sheet_,
+ QString( doc, length).mid( pos, end - pos ) );
+ cell->richText()->parentPar = curpar;
if ( cell->colspan() > 1 || cell->rowspan() > 1 )
multicells.append( cell );
col += cell->colspan()-1;
pos = end;
}
}
}
} else {
++pos;
}
}
-#if defined(PARSER_DEBUG)
- debug_indent.remove( debug_indent.length() - 3, 2 );
-#endif
return table;
}
bool QTextDocument::eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp )
{
int old_pos = pos;
@@ -7128,25 +6805,16 @@ QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleShe
if (c == '<' )
return QChar::null;
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 &&
doc[pos].isSpace() && doc[pos] != QChar::nbsp )
pos++;
if ( wsm == QStyleSheetItem::WhiteSpaceNoWrap )
return QChar::nbsp;
@@ -7352,17 +7020,12 @@ void QTextCustomItem::pageBreak( int /*y*/ , QTextFlow* /*flow*/ )
}
QTextTable::QTextTable( QTextDocument *p, const QMap<QString, QString> & attr )
: QTextCustomItem( p )
{
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") )
cellspacing = attr["cellspacing"].toInt();
cellpadding = 1;
if ( attr.contains("cellpadding") )
cellpadding = attr["cellpadding"].toInt();
@@ -7437,16 +7100,16 @@ QString QTextTable::richText() const
if ( lastRow != -1 )
s += "</tr>\n";
s += "<tr>";
lastRow = cell->row();
needEnd = TRUE;
}
- s += "<td ";
+ s += "<td";
it = cell->attributes.begin();
for ( ; it != cell->attributes.end(); ++it )
- s += it.key() + "=" + *it + " ";
+ s += " " + it.key() + "=" + *it;
s += ">";
s += cell->richText()->richText();
s += "</td>";
}
if ( needEnd )
s += "</tr>\n";
@@ -7573,18 +7236,12 @@ void QTextTable::draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch,
p->fillRect( r.left(), r.bottom()-s, r.width(), s, cg.button() );
}
qDrawShadePanel( p, r, cg, FALSE, border );
}
}
-#if defined(DEBUG_TABLE_RENDERING)
- p->save();
- p->setPen( Qt::red );
- p->drawRect( x, y, width, height );
- p->restore();
-#endif
}
int QTextTable::minimumWidth() const
{
return (layout ? layout->minimumSize().width() : 0) + 2 * outerborder;
}
@@ -7640,22 +7297,22 @@ void QTextTable::addCell( QTextTableCell* cell )
{
cells.append( cell );
layout->addMultiCell( cell, cell->row(), cell->row() + cell->rowspan()-1,
cell->column(), cell->column() + cell->colspan()-1 );
}
-bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, bool atEnd )
+bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, bool atEnd )
{
currCell.remove( c );
if ( !atEnd )
return next( c, doc, parag, idx, ox, oy );
currCell.insert( c, cells.count() );
return prev( c, doc, parag, idx, ox, oy );
}
-bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, const QPoint &pos )
+bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, const QPoint &pos )
{
currCell.remove( c );
int lastCell = -1;
int lastY = -1;
int i;
for ( i = 0; i < (int)cells.count(); ++i ) {
@@ -7689,20 +7346,20 @@ bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *&para
}
QTextTableCell *cell = cells.at( *currCell.find( c ) );
if ( !cell )
return FALSE;
doc = cell->richText();
- parag = doc->firstParag();
+ parag = doc->firstParagraph();
idx = 0;
ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
return TRUE;
}
-bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy )
+bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
{
int cc = -1;
if ( currCell.find( c ) != currCell.end() )
cc = *currCell.find( c );
if ( cc > (int)cells.count() - 1 || cc < 0 )
cc = -1;
@@ -7722,20 +7379,20 @@ bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag,
if ( currCell.find( c ) == currCell.end() )
return FALSE;
QTextTableCell *cell = cells.at( *currCell.find( c ) );
if ( !cell )
return FALSE;
doc = cell->richText();
- parag = doc->firstParag();
+ parag = doc->firstParagraph();
idx = 0;
ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
return TRUE;
}
-bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy )
+bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
{
int cc = -1;
if ( currCell.find( c ) != currCell.end() )
cc = *currCell.find( c );
if ( cc > (int)cells.count() - 1 || cc < 0 )
cc = cells.count();
@@ -7755,20 +7412,20 @@ bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag,
if ( currCell.find( c ) == currCell.end() )
return FALSE;
QTextTableCell *cell = cells.at( *currCell.find( c ) );
if ( !cell )
return FALSE;
doc = cell->richText();
- parag = doc->firstParag();
+ parag = doc->lastParagraph();
idx = parag->length() - 1;
ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
return TRUE;
}
-bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy )
+bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
{
if ( currCell.find( c ) == currCell.end() )
return FALSE;
QTextTableCell *cell = cells.at( *currCell.find( c ) );
if ( cell->row_ == layout->numRows() - 1 ) {
currCell.insert( c, 0 );
@@ -7793,20 +7450,20 @@ bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag,
break;
}
}
doc = cell->richText();
if ( !cell )
return FALSE;
- parag = doc->firstParag();
+ parag = doc->firstParagraph();
idx = 0;
ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
return TRUE;
}
-bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy )
+bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
{
if ( currCell.find( c ) == currCell.end() )
return FALSE;
QTextTableCell *cell = cells.at( *currCell.find( c ) );
if ( cell->row_ == 0 ) {
currCell.insert( c, 0 );
@@ -7831,13 +7488,13 @@ bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, in
break;
}
}
doc = cell->richText();
if ( !cell )
return FALSE;
- parag = doc->lastParag();
+ parag = doc->lastParagraph();
idx = parag->length() - 1;
ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
return TRUE;
}
@@ -7846,16 +7503,12 @@ QTextTableCell::QTextTableCell( QTextTable* table,
const QMap<QString, QString> &attr,
const QStyleSheetItem* /*style*/, // ### use them
const QTextFormat& /*fmt*/, const QString& context,
QMimeSourceFactory &factory, QStyleSheet *sheet,
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;
maxw = QWIDGETSIZE_MAX;
minw = 0;
@@ -7885,13 +7538,14 @@ QTextTableCell::QTextTableCell( QTextTable* table,
align |= Qt::AlignBottom;
}
richtext->setFormatter( table->parent->formatter() );
richtext->setUseFormatCollection( table->parent->useFormatCollection() );
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;
colspan_ = 1;
if ( attr.contains("colspan") )
colspan_ = attr["colspan"].toInt();
if ( attr.contains("rowspan") )
@@ -7921,40 +7575,12 @@ QTextTableCell::QTextTableCell( QTextTable* table,
attributes = attr;
parent->addCell( this );
}
-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()
{
delete background;
background = 0;
delete richtext;
richtext = 0;
@@ -8024,13 +7650,13 @@ int QTextTableCell::heightForWidth( int w ) const
}
return richtext->height() + extra;
}
void QTextTableCell::adjustToPainter( QPainter* p )
{
- QTextParag *parag = richtext->firstParag();
+ QTextParagraph *parag = richtext->firstParagraph();
while ( parag ) {
parag->adjustToPainter( p );
parag = parag->next();
}
}
@@ -8068,18 +7694,151 @@ void QTextTableCell::draw( QPainter* p, int x, int y, int cx, int cy, int cw, in
else if ( richtext->paper() )
p->fillRect( 0, 0, geom.width(), geom.height(), *richtext->paper() );
p->translate( horizontalAlignmentOffset(), verticalAlignmentOffset() );
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;
+}