summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-write/qrichtext.cpp72
1 files changed, 23 insertions, 49 deletions
diff --git a/noncore/apps/opie-write/qrichtext.cpp b/noncore/apps/opie-write/qrichtext.cpp
index 768da44..b457cd6 100644
--- a/noncore/apps/opie-write/qrichtext.cpp
+++ b/noncore/apps/opie-write/qrichtext.cpp
@@ -1,6903 +1,6877 @@
1/**************************************************************************** 1/****************************************************************************
2** $Id$ 2** $Id$
3** 3**
4** Implementation of the internal Qt classes dealing with rich text 4** Implementation of the internal Qt classes dealing with rich text
5** 5**
6** Created : 990101 6** Created : 990101
7** 7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. 8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9** 9**
10** This file is part of the kernel module of the Qt GUI Toolkit. 10** This file is part of the kernel module of the Qt GUI Toolkit.
11** 11**
12** This file may be distributed under the terms of the Q Public License 12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file 13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file. 14** LICENSE.QPL included in the packaging of this file.
15** 15**
16** This file may be distributed and/or modified under the terms of the 16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software 17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the 18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file. 19** packaging of this file.
20** 20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition 21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License 22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software. 23** Agreement provided with the Software.
24** 24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27** 27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for 28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements. 29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information. 30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information. 31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32** 32**
33** Contact info@trolltech.com if any conditions of this licensing are 33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you. 34** not clear to you.
35** 35**
36**********************************************************************/ 36**********************************************************************/
37 37
38#include "qrichtext_p.h" 38#include "qrichtext_p.h"
39 39
40/* OPIE */ 40/* OPIE */
41#include <opie2/odebug.h> 41#include <opie2/odebug.h>
42using namespace Opie::Core; 42using namespace Opie::Core;
43 43
44/* QT */ 44/* QT */
45#include "qdragobject.h" 45#include "qdragobject.h"
46#include "qpaintdevicemetrics.h" 46#include "qpaintdevicemetrics.h"
47#include "qdrawutil.h" 47#include "qdrawutil.h"
48#include "qcleanuphandler.h" 48#include "qcleanuphandler.h"
49 49
50/* STD */ 50/* STD */
51#include <stdlib.h> 51#include <stdlib.h>
52 52
53using namespace Qt3; 53using namespace Qt3;
54 54
55static QTextCursor* richTextExportStart = 0; 55static QTextCursor* richTextExportStart = 0;
56static QTextCursor* richTextExportEnd = 0; 56static QTextCursor* richTextExportEnd = 0;
57 57
58static QTextFormatCollection *qFormatCollection = 0; 58static QTextFormatCollection *qFormatCollection = 0;
59 59
60const int border_tolerance = 2; 60const int border_tolerance = 2;
61 61
62#ifdef Q_WS_WIN 62#ifdef Q_WS_WIN
63#include "qt_windows.h" 63#include "qt_windows.h"
64#endif 64#endif
65 65
66#define QChar_linesep QChar(0x2028U) 66#define QChar_linesep QChar(0x2028U)
67 67
68static inline bool is_printer( QPainter *p ) 68static inline bool is_printer( QPainter *p )
69{ 69{
70 if ( !p || !p->device() ) 70 if ( !p || !p->device() )
71 return FALSE; 71 return FALSE;
72 return p->device()->devType() == QInternal::Printer; 72 return p->device()->devType() == QInternal::Printer;
73} 73}
74 74
75static inline int scale( int value, QPainter *painter ) 75static inline int scale( int value, QPainter *painter )
76{ 76{
77 if ( is_printer( painter ) ) { 77 if ( is_printer( painter ) ) {
78 QPaintDeviceMetrics metrics( painter->device() ); 78 QPaintDeviceMetrics metrics( painter->device() );
79#if defined(Q_WS_X11) 79#if defined(Q_WS_X11)
80 value = value * metrics.logicalDpiY() / QPaintDevice::x11AppDpiY(); 80 value = value * metrics.logicalDpiY() / QPaintDevice::x11AppDpiY();
81#elif defined (Q_WS_WIN) 81#elif defined (Q_WS_WIN)
82 HDC hdc = GetDC( 0 ); 82 HDC hdc = GetDC( 0 );
83 int gdc = GetDeviceCaps( hdc, LOGPIXELSY ); 83 int gdc = GetDeviceCaps( hdc, LOGPIXELSY );
84 if ( gdc ) 84 if ( gdc )
85 value = value * metrics.logicalDpiY() / gdc; 85 value = value * metrics.logicalDpiY() / gdc;
86 ReleaseDC( 0, hdc ); 86 ReleaseDC( 0, hdc );
87#elif defined (Q_WS_MAC) 87#elif defined (Q_WS_MAC)
88 value = value * metrics.logicalDpiY() / 75; // ##### FIXME 88 value = value * metrics.logicalDpiY() / 75; // ##### FIXME
89#elif defined (Q_WS_QWS) 89#elif defined (Q_WS_QWS)
90 value = value * metrics.logicalDpiY() / 75; 90 value = value * metrics.logicalDpiY() / 75;
91#endif 91#endif
92 } 92 }
93 return value; 93 return value;
94} 94}
95 95
96// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 96// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
97 97
98void QTextCommandHistory::addCommand( QTextCommand *cmd ) 98void QTextCommandHistory::addCommand( QTextCommand *cmd )
99{ 99{
100 if ( current < (int)history.count() - 1 ) { 100 if ( current < (int)history.count() - 1 ) {
101 QPtrList<QTextCommand> commands; 101 QPtrList<QTextCommand> commands;
102 commands.setAutoDelete( FALSE ); 102 commands.setAutoDelete( FALSE );
103 103
104 for( int i = 0; i <= current; ++i ) { 104 for( int i = 0; i <= current; ++i ) {
105 commands.insert( i, history.at( 0 ) ); 105 commands.insert( i, history.at( 0 ) );
106 history.take( 0 ); 106 history.take( 0 );
107 } 107 }
108 108
109 commands.append( cmd ); 109 commands.append( cmd );
110 history.clear(); 110 history.clear();
111 history = commands; 111 history = commands;
112 history.setAutoDelete( TRUE ); 112 history.setAutoDelete( TRUE );
113 } else { 113 } else {
114 history.append( cmd ); 114 history.append( cmd );
115 } 115 }
116 116
117 if ( (int)history.count() > steps ) 117 if ( (int)history.count() > steps )
118 history.removeFirst(); 118 history.removeFirst();
119 else 119 else
120 ++current; 120 ++current;
121} 121}
122 122
123QTextCursor *QTextCommandHistory::undo( QTextCursor *c ) 123QTextCursor *QTextCommandHistory::undo( QTextCursor *c )
124{ 124{
125 if ( current > -1 ) { 125 if ( current > -1 ) {
126 QTextCursor *c2 = history.at( current )->unexecute( c ); 126 QTextCursor *c2 = history.at( current )->unexecute( c );
127 --current; 127 --current;
128 return c2; 128 return c2;
129 } 129 }
130 return 0; 130 return 0;
131} 131}
132 132
133QTextCursor *QTextCommandHistory::redo( QTextCursor *c ) 133QTextCursor *QTextCommandHistory::redo( QTextCursor *c )
134{ 134{
135 if ( current > -1 ) { 135 if ( current > -1 ) {
136 if ( current < (int)history.count() - 1 ) { 136 if ( current < (int)history.count() - 1 ) {
137 ++current; 137 ++current;
138 return history.at( current )->execute( c ); 138 return history.at( current )->execute( c );
139 } 139 }
140 } else { 140 } else {
141 if ( history.count() > 0 ) { 141 if ( history.count() > 0 ) {
142 ++current; 142 ++current;
143 return history.at( current )->execute( c ); 143 return history.at( current )->execute( c );
144 } 144 }
145 } 145 }
146 return 0; 146 return 0;
147} 147}
148 148
149bool QTextCommandHistory::isUndoAvailable() 149bool QTextCommandHistory::isUndoAvailable()
150{ 150{
151 return current > -1; 151 return current > -1;
152} 152}
153 153
154bool QTextCommandHistory::isRedoAvailable() 154bool QTextCommandHistory::isRedoAvailable()
155{ 155{
156 return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0; 156 return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0;
157} 157}
158 158
159// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 159// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
160 160
161QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, 161QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str,
162 const QByteArray& oldStyleInfo ) 162 const QByteArray& oldStyleInfo )
163 : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo ) 163 : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo )
164{ 164{
165 for ( int j = 0; j < (int)text.size(); ++j ) { 165 for ( int j = 0; j < (int)text.size(); ++j ) {
166 if ( text[ j ].format() ) 166 if ( text[ j ].format() )
167 text[ j ].format()->addRef(); 167 text[ j ].format()->addRef();
168 } 168 }
169} 169}
170 170
171QTextDeleteCommand::QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str ) 171QTextDeleteCommand::QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str )
172 : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str ) 172 : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str )
173{ 173{
174 for ( int i = 0; i < (int)text.size(); ++i ) { 174 for ( int i = 0; i < (int)text.size(); ++i ) {
175 if ( text[ i ].format() ) 175 if ( text[ i ].format() )
176 text[ i ].format()->addRef(); 176 text[ i ].format()->addRef();
177 } 177 }
178} 178}
179 179
180QTextDeleteCommand::~QTextDeleteCommand() 180QTextDeleteCommand::~QTextDeleteCommand()
181{ 181{
182 for ( int i = 0; i < (int)text.size(); ++i ) { 182 for ( int i = 0; i < (int)text.size(); ++i ) {
183 if ( text[ i ].format() ) 183 if ( text[ i ].format() )
184 text[ i ].format()->removeRef(); 184 text[ i ].format()->removeRef();
185 } 185 }
186 text.resize( 0 ); 186 text.resize( 0 );
187} 187}
188 188
189QTextCursor *QTextDeleteCommand::execute( QTextCursor *c ) 189QTextCursor *QTextDeleteCommand::execute( QTextCursor *c )
190{ 190{
191 QTextParagraph *s = doc ? doc->paragAt( id ) : parag; 191 QTextParagraph *s = doc ? doc->paragAt( id ) : parag;
192 if ( !s && doc ) { 192 if ( !s ) {
193 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl; 193 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl;
194 return 0; 194 return 0;
195 } else if ( !doc ) {
196 owarn << "No valid doc" << oendl;
197 return 0;
198 } 195 }
199 196
200 cursor.setParagraph( s ); 197 cursor.setParagraph( s );
201 cursor.setIndex( index ); 198 cursor.setIndex( index );
202 int len = text.size(); 199 int len = text.size();
203 if ( c ) 200 if ( c )
204 *c = cursor; 201 *c = cursor;
205 if ( doc ) { 202 if ( doc ) {
206 doc->setSelectionStart( QTextDocument::Temp, cursor ); 203 doc->setSelectionStart( QTextDocument::Temp, cursor );
207 for ( int i = 0; i < len; ++i ) 204 for ( int i = 0; i < len; ++i )
208 cursor.gotoNextLetter(); 205 cursor.gotoNextLetter();
209 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 206 doc->setSelectionEnd( QTextDocument::Temp, cursor );
210 doc->removeSelectedText( QTextDocument::Temp, &cursor ); 207 doc->removeSelectedText( QTextDocument::Temp, &cursor );
211 if ( c ) 208 if ( c )
212 *c = cursor; 209 *c = cursor;
213 } else { 210 } else {
214 s->remove( index, len ); 211 s->remove( index, len );
215 } 212 }
216 213
217 return c; 214 return c;
218} 215}
219 216
220QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c ) 217QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c )
221{ 218{
222 QTextParagraph *s = doc ? doc->paragAt( id ) : parag; 219 QTextParagraph *s = doc ? doc->paragAt( id ) : parag;
223 if ( !s && doc ) { 220 if ( !s ) {
224 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl; 221 owarn << "can't locate parag at " << id << ", last parag: " << doc->lastParagraph()->paragId() << "" << oendl;
225 return 0; 222 return 0;
226 } else if ( !doc ) {
227 owarn << "No valid doc" << oendl;
228 return 0;
229 } 223 }
230 224
231 cursor.setParagraph( s ); 225 cursor.setParagraph( s );
232 cursor.setIndex( index ); 226 cursor.setIndex( index );
233 QString str = QTextString::toString( text ); 227 QString str = QTextString::toString( text );
234 cursor.insert( str, TRUE, &text ); 228 cursor.insert( str, TRUE, &text );
235 cursor.setParagraph( s ); 229 cursor.setParagraph( s );
236 cursor.setIndex( index ); 230 cursor.setIndex( index );
237 if ( c ) { 231 if ( c ) {
238 c->setParagraph( s ); 232 c->setParagraph( s );
239 c->setIndex( index ); 233 c->setIndex( index );
240 for ( int i = 0; i < (int)text.size(); ++i ) 234 for ( int i = 0; i < (int)text.size(); ++i )
241 c->gotoNextLetter(); 235 c->gotoNextLetter();
242 } else {
243 owarn << "No valid cursor" << oendl;
244 return 0;
245 } 236 }
246 237
247 if ( !styleInformation.isEmpty() ) { 238 if ( !styleInformation.isEmpty() ) {
248 QDataStream styleStream( styleInformation, IO_ReadOnly ); 239 QDataStream styleStream( styleInformation, IO_ReadOnly );
249 int num; 240 int num;
250 styleStream >> num; 241 styleStream >> num;
251 QTextParagraph *p = s; 242 QTextParagraph *p = s;
252 while ( num-- && p ) { 243 while ( num-- && p ) {
253 p->readStyleInformation( styleStream ); 244 p->readStyleInformation( styleStream );
254 p = p->next(); 245 p = p->next();
255 } 246 }
256 } 247 }
257 s = cursor.paragraph(); 248 s = cursor.paragraph();
258 while ( s ) { 249 while ( s ) {
259 s->format(); 250 s->format();
260 s->setChanged( TRUE ); 251 s->setChanged( TRUE );
261 if ( s == c->paragraph() ) 252 if ( s == c->paragraph() )
262 break; 253 break;
263 s = s->next(); 254 s = s->next();
264 } 255 }
265 256
266 return &cursor; 257 return &cursor;
267} 258}
268 259
269QTextFormatCommand::QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, 260QTextFormatCommand::QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx,
270 const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl ) 261 const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl )
271 : QTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl ) 262 : QTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl )
272{ 263{
273 format = d->formatCollection()->format( f ); 264 format = d->formatCollection()->format( f );
274 for ( int j = 0; j < (int)oldFormats.size(); ++j ) { 265 for ( int j = 0; j < (int)oldFormats.size(); ++j ) {
275 if ( oldFormats[ j ].format() ) 266 if ( oldFormats[ j ].format() )
276 oldFormats[ j ].format()->addRef(); 267 oldFormats[ j ].format()->addRef();
277 } 268 }
278} 269}
279 270
280QTextFormatCommand::~QTextFormatCommand() 271QTextFormatCommand::~QTextFormatCommand()
281{ 272{
282 format->removeRef(); 273 format->removeRef();
283 for ( int j = 0; j < (int)oldFormats.size(); ++j ) { 274 for ( int j = 0; j < (int)oldFormats.size(); ++j ) {
284 if ( oldFormats[ j ].format() ) 275 if ( oldFormats[ j ].format() )
285 oldFormats[ j ].format()->removeRef(); 276 oldFormats[ j ].format()->removeRef();
286 } 277 }
287} 278}
288 279
289QTextCursor *QTextFormatCommand::execute( QTextCursor *c ) 280QTextCursor *QTextFormatCommand::execute( QTextCursor *c )
290{ 281{
291 QTextParagraph *sp = doc->paragAt( startId ); 282 QTextParagraph *sp = doc->paragAt( startId );
292 QTextParagraph *ep = doc->paragAt( endId ); 283 QTextParagraph *ep = doc->paragAt( endId );
293 if ( !sp || !ep ) 284 if ( !sp || !ep )
294 return c; 285 return c;
295 286
296 QTextCursor start( doc ); 287 QTextCursor start( doc );
297 start.setParagraph( sp ); 288 start.setParagraph( sp );
298 start.setIndex( startIndex ); 289 start.setIndex( startIndex );
299 QTextCursor end( doc ); 290 QTextCursor end( doc );
300 end.setParagraph( ep ); 291 end.setParagraph( ep );
301 end.setIndex( endIndex ); 292 end.setIndex( endIndex );
302 293
303 doc->setSelectionStart( QTextDocument::Temp, start ); 294 doc->setSelectionStart( QTextDocument::Temp, start );
304 doc->setSelectionEnd( QTextDocument::Temp, end ); 295 doc->setSelectionEnd( QTextDocument::Temp, end );
305 doc->setFormat( QTextDocument::Temp, format, flags ); 296 doc->setFormat( QTextDocument::Temp, format, flags );
306 doc->removeSelection( QTextDocument::Temp ); 297 doc->removeSelection( QTextDocument::Temp );
307 if ( endIndex == ep->length() ) 298 if ( endIndex == ep->length() )
308 end.gotoLeft(); 299 end.gotoLeft();
309 *c = end; 300 *c = end;
310 return c; 301 return c;
311} 302}
312 303
313QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c ) 304QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c )
314{ 305{
315 QTextParagraph *sp = doc->paragAt( startId ); 306 QTextParagraph *sp = doc->paragAt( startId );
316 QTextParagraph *ep = doc->paragAt( endId ); 307 QTextParagraph *ep = doc->paragAt( endId );
317 if ( !sp || !ep ) 308 if ( !sp || !ep )
318 return 0; 309 return 0;
319 310
320 int idx = startIndex; 311 int idx = startIndex;
321 int fIndex = 0; 312 int fIndex = 0;
322 for ( ;; ) { 313 for ( ;; ) {
323 if ( oldFormats.at( fIndex ).c == '\n' ) { 314 if ( oldFormats.at( fIndex ).c == '\n' ) {
324 if ( idx > 0 ) { 315 if ( idx > 0 ) {
325 if ( idx < sp->length() && fIndex > 0 ) 316 if ( idx < sp->length() && fIndex > 0 )
326 sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() ); 317 sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() );
327 if ( sp == ep ) 318 if ( sp == ep )
328 break; 319 break;
329 sp = sp->next(); 320 sp = sp->next();
330 idx = 0; 321 idx = 0;
331 } 322 }
332 fIndex++; 323 fIndex++;
333 } 324 }
334 if ( oldFormats.at( fIndex ).format() ) 325 if ( oldFormats.at( fIndex ).format() )
335 sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() ); 326 sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() );
336 idx++; 327 idx++;
337 fIndex++; 328 fIndex++;
338 if ( fIndex >= (int)oldFormats.size() ) 329 if ( fIndex >= (int)oldFormats.size() )
339 break; 330 break;
340 if ( idx >= sp->length() ) { 331 if ( idx >= sp->length() ) {
341 if ( sp == ep ) 332 if ( sp == ep )
342 break; 333 break;
343 sp = sp->next(); 334 sp = sp->next();
344 idx = 0; 335 idx = 0;
345 } 336 }
346 } 337 }
347 338
348 QTextCursor end( doc ); 339 QTextCursor end( doc );
349 end.setParagraph( ep ); 340 end.setParagraph( ep );
350 end.setIndex( endIndex ); 341 end.setIndex( endIndex );
351 if ( endIndex == ep->length() ) 342 if ( endIndex == ep->length() )
352 end.gotoLeft(); 343 end.gotoLeft();
353 *c = end; 344 *c = end;
354 return c; 345 return c;
355} 346}
356 347
357QTextStyleCommand::QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange ) 348QTextStyleCommand::QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange )
358 : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange ) 349 : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange )
359{ 350{
360 after = readStyleInformation( d, fParag, lParag ); 351 after = readStyleInformation( d, fParag, lParag );
361} 352}
362 353
363 354
364QByteArray QTextStyleCommand::readStyleInformation( QTextDocument* doc, int fParag, int lParag ) 355QByteArray QTextStyleCommand::readStyleInformation( QTextDocument* doc, int fParag, int lParag )
365{ 356{
366 QByteArray style; 357 QByteArray style;
367 QTextParagraph *p = doc->paragAt( fParag ); 358 QTextParagraph *p = doc->paragAt( fParag );
368 if ( !p ) 359 if ( !p )
369 return style; 360 return style;
370 QDataStream styleStream( style, IO_WriteOnly ); 361 QDataStream styleStream( style, IO_WriteOnly );
371 int num = lParag - fParag + 1; 362 int num = lParag - fParag + 1;
372 styleStream << num; 363 styleStream << num;
373 while ( num -- && p ) { 364 while ( num -- && p ) {
374 p->writeStyleInformation( styleStream ); 365 p->writeStyleInformation( styleStream );
375 p = p->next(); 366 p = p->next();
376 } 367 }
377 return style; 368 return style;
378} 369}
379 370
380void QTextStyleCommand::writeStyleInformation( QTextDocument* doc, int fParag, const QByteArray& style ) 371void QTextStyleCommand::writeStyleInformation( QTextDocument* doc, int fParag, const QByteArray& style )
381{ 372{
382 QTextParagraph *p = doc->paragAt( fParag ); 373 QTextParagraph *p = doc->paragAt( fParag );
383 if ( !p ) 374 if ( !p )
384 return; 375 return;
385 QDataStream styleStream( style, IO_ReadOnly ); 376 QDataStream styleStream( style, IO_ReadOnly );
386 int num; 377 int num;
387 styleStream >> num; 378 styleStream >> num;
388 while ( num-- && p ) { 379 while ( num-- && p ) {
389 p->readStyleInformation( styleStream ); 380 p->readStyleInformation( styleStream );
390 p = p->next(); 381 p = p->next();
391 } 382 }
392} 383}
393 384
394QTextCursor *QTextStyleCommand::execute( QTextCursor *c ) 385QTextCursor *QTextStyleCommand::execute( QTextCursor *c )
395{ 386{
396 writeStyleInformation( doc, firstParag, after ); 387 writeStyleInformation( doc, firstParag, after );
397 return c; 388 return c;
398} 389}
399 390
400QTextCursor *QTextStyleCommand::unexecute( QTextCursor *c ) 391QTextCursor *QTextStyleCommand::unexecute( QTextCursor *c )
401{ 392{
402 writeStyleInformation( doc, firstParag, before ); 393 writeStyleInformation( doc, firstParag, before );
403 return c; 394 return c;
404} 395}
405 396
406// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 397// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
407 398
408QTextCursor::QTextCursor( QTextDocument *d ) 399QTextCursor::QTextCursor( QTextDocument *d )
409 : idx( 0 ), tmpIndex( -1 ), ox( 0 ), oy( 0 ), 400 : idx( 0 ), tmpIndex( -1 ), ox( 0 ), oy( 0 ),
410 valid( TRUE ) 401 valid( TRUE )
411{ 402{
412 para = d ? d->firstParagraph() : 0; 403 para = d ? d->firstParagraph() : 0;
413} 404}
414 405
415QTextCursor::QTextCursor( const QTextCursor &c ) 406QTextCursor::QTextCursor( const QTextCursor &c )
416{ 407{
417 ox = c.ox; 408 ox = c.ox;
418 oy = c.oy; 409 oy = c.oy;
419 idx = c.idx; 410 idx = c.idx;
420 para = c.para; 411 para = c.para;
421 tmpIndex = c.tmpIndex; 412 tmpIndex = c.tmpIndex;
422 indices = c.indices; 413 indices = c.indices;
423 paras = c.paras; 414 paras = c.paras;
424 xOffsets = c.xOffsets; 415 xOffsets = c.xOffsets;
425 yOffsets = c.yOffsets; 416 yOffsets = c.yOffsets;
426 valid = c.valid; 417 valid = c.valid;
427} 418}
428 419
429QTextCursor &QTextCursor::operator=( const QTextCursor &c ) 420QTextCursor &QTextCursor::operator=( const QTextCursor &c )
430{ 421{
431 ox = c.ox; 422 ox = c.ox;
432 oy = c.oy; 423 oy = c.oy;
433 idx = c.idx; 424 idx = c.idx;
434 para = c.para; 425 para = c.para;
435 tmpIndex = c.tmpIndex; 426 tmpIndex = c.tmpIndex;
436 indices = c.indices; 427 indices = c.indices;
437 paras = c.paras; 428 paras = c.paras;
438 xOffsets = c.xOffsets; 429 xOffsets = c.xOffsets;
439 yOffsets = c.yOffsets; 430 yOffsets = c.yOffsets;
440 valid = c.valid; 431 valid = c.valid;
441 432
442 return *this; 433 return *this;
443} 434}
444 435
445bool QTextCursor::operator==( const QTextCursor &c ) const 436bool QTextCursor::operator==( const QTextCursor &c ) const
446{ 437{
447 return para == c.para && idx == c.idx; 438 return para == c.para && idx == c.idx;
448} 439}
449 440
450int QTextCursor::totalOffsetX() const 441int QTextCursor::totalOffsetX() const
451{ 442{
452 int xoff = ox; 443 int xoff = ox;
453 for ( QValueStack<int>::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit ) 444 for ( QValueStack<int>::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit )
454 xoff += *xit; 445 xoff += *xit;
455 return xoff; 446 return xoff;
456} 447}
457 448
458int QTextCursor::totalOffsetY() const 449int QTextCursor::totalOffsetY() const
459{ 450{
460 int yoff = oy; 451 int yoff = oy;
461 for ( QValueStack<int>::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit ) 452 for ( QValueStack<int>::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit )
462 yoff += *yit; 453 yoff += *yit;
463 return yoff; 454 return yoff;
464} 455}
465 456
466void QTextCursor::gotoIntoNested( const QPoint &globalPos ) 457void QTextCursor::gotoIntoNested( const QPoint &globalPos )
467{ 458{
468 if ( !para ) 459 if ( !para )
469 return; 460 return;
470 push(); 461 push();
471 ox = 0; 462 ox = 0;
472 int bl, y; 463 int bl, y;
473 para->lineHeightOfChar( idx, &bl, &y ); 464 para->lineHeightOfChar( idx, &bl, &y );
474 oy = y + para->rect().y(); 465 oy = y + para->rect().y();
475 QPoint p( globalPos.x() - offsetX(), globalPos.y() - offsetY() ); 466 QPoint p( globalPos.x() - offsetX(), globalPos.y() - offsetY() );
476 Q_ASSERT( para->at( idx )->isCustom() ); 467 Q_ASSERT( para->at( idx )->isCustom() );
477 ox = para->at( idx )->x; 468 ox = para->at( idx )->x;
478 469
479 QTextDocument* doc = document(); 470 QTextDocument* doc = document();
480 para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, p ); 471 para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, p );
481} 472}
482 473
483void QTextCursor::invalidateNested() 474void QTextCursor::invalidateNested()
484{ 475{
485 QValueStack<QTextParagraph*>::Iterator it = paras.begin(); 476 QValueStack<QTextParagraph*>::Iterator it = paras.begin();
486 QValueStack<int>::Iterator it2 = indices.begin(); 477 QValueStack<int>::Iterator it2 = indices.begin();
487 for ( ; it != paras.end(); ++it, ++it2 ) { 478 for ( ; it != paras.end(); ++it, ++it2 ) {
488 if ( *it == para ) 479 if ( *it == para )
489 continue; 480 continue;
490 (*it)->invalidate( 0 ); 481 (*it)->invalidate( 0 );
491 if ( (*it)->at( *it2 )->isCustom() ) 482 if ( (*it)->at( *it2 )->isCustom() )
492 (*it)->at( *it2 )->customItem()->invalidate(); 483 (*it)->at( *it2 )->customItem()->invalidate();
493 } 484 }
494} 485}
495 486
496void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting ) 487void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting )
497{ 488{
498 tmpIndex = -1; 489 tmpIndex = -1;
499 bool justInsert = TRUE; 490 bool justInsert = TRUE;
500 QString s( str ); 491 QString s( str );
501#if defined(Q_WS_WIN) 492#if defined(Q_WS_WIN)
502 if ( checkNewLine ) { 493 if ( checkNewLine ) {
503 int i = 0; 494 int i = 0;
504 while ( ( i = s.find( '\r', i ) ) != -1 ) 495 while ( ( i = s.find( '\r', i ) ) != -1 )
505 s.remove( i ,1 ); 496 s.remove( i ,1 );
506 } 497 }
507#endif 498#endif
508 if ( checkNewLine ) 499 if ( checkNewLine )
509 justInsert = s.find( '\n' ) == -1; 500 justInsert = s.find( '\n' ) == -1;
510 if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index 501 if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index
511 para->insert( idx, s.unicode(), s.length() ); 502 para->insert( idx, s.unicode(), s.length() );
512 if ( formatting ) { 503 if ( formatting ) {
513 for ( int i = 0; i < (int)s.length(); ++i ) { 504 for ( int i = 0; i < (int)s.length(); ++i ) {
514 if ( formatting->at( i ).format() ) { 505 if ( formatting->at( i ).format() ) {
515 formatting->at( i ).format()->addRef(); 506 formatting->at( i ).format()->addRef();
516 para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE ); 507 para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE );
517 } 508 }
518 } 509 }
519 } 510 }
520 idx += s.length(); 511 idx += s.length();
521 } else { // we split at new lines 512 } else { // we split at new lines
522 int start = -1; 513 int start = -1;
523 int end; 514 int end;
524 int y = para->rect().y() + para->rect().height(); 515 int y = para->rect().y() + para->rect().height();
525 int lastIndex = 0; 516 int lastIndex = 0;
526 do { 517 do {
527 end = s.find( '\n', start + 1 ); // find line break 518 end = s.find( '\n', start + 1 ); // find line break
528 if ( end == -1 ) // didn't find one, so end of line is end of string 519 if ( end == -1 ) // didn't find one, so end of line is end of string
529 end = s.length(); 520 end = s.length();
530 int len = (start == -1 ? end : end - start - 1); 521 int len = (start == -1 ? end : end - start - 1);
531 if ( len > 0 ) // insert the line 522 if ( len > 0 ) // insert the line
532 para->insert( idx, s.unicode() + start + 1, len ); 523 para->insert( idx, s.unicode() + start + 1, len );
533 else 524 else
534 para->invalidate( 0 ); 525 para->invalidate( 0 );
535 if ( formatting ) { // set formats to the chars of the line 526 if ( formatting ) { // set formats to the chars of the line
536 for ( int i = 0; i < len; ++i ) { 527 for ( int i = 0; i < len; ++i ) {
537 if ( formatting->at( i + lastIndex ).format() ) { 528 if ( formatting->at( i + lastIndex ).format() ) {
538 formatting->at( i + lastIndex ).format()->addRef(); 529 formatting->at( i + lastIndex ).format()->addRef();
539 para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE ); 530 para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE );
540 } 531 }
541 } 532 }
542 lastIndex += len; 533 lastIndex += len;
543 } 534 }
544 start = end; // next start is at the end of this line 535 start = end; // next start is at the end of this line
545 idx += len; // increase the index of the cursor to the end of the inserted text 536 idx += len; // increase the index of the cursor to the end of the inserted text
546 if ( s[end] == '\n' ) { // if at the end was a line break, break the line 537 if ( s[end] == '\n' ) { // if at the end was a line break, break the line
547 splitAndInsertEmptyParagraph( FALSE, TRUE ); 538 splitAndInsertEmptyParagraph( FALSE, TRUE );
548 para->setEndState( -1 ); 539 para->setEndState( -1 );
549 para->prev()->format( -1, FALSE ); 540 para->prev()->format( -1, FALSE );
550 lastIndex++; 541 lastIndex++;
551 } 542 }
552 543
553 } while ( end < (int)s.length() ); 544 } while ( end < (int)s.length() );
554 545
555 para->format( -1, FALSE ); 546 para->format( -1, FALSE );
556 int dy = para->rect().y() + para->rect().height() - y; 547 int dy = para->rect().y() + para->rect().height() - y;
557 QTextParagraph *p = para; 548 QTextParagraph *p = para;
558 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); 549 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 );
559 p = p->next(); 550 p = p->next();
560 while ( p ) { 551 while ( p ) {
561 p->setParagId( p->prev()->paragId() + 1 ); 552 p->setParagId( p->prev()->paragId() + 1 );
562 p->move( dy ); 553 p->move( dy );
563 p->invalidate( 0 ); 554 p->invalidate( 0 );
564 p->setEndState( -1 ); 555 p->setEndState( -1 );
565 p = p->next(); 556 p = p->next();
566 } 557 }
567 } 558 }
568 559
569 int h = para->rect().height(); 560 int h = para->rect().height();
570 para->format( -1, TRUE ); 561 para->format( -1, TRUE );
571 if ( h != para->rect().height() ) 562 if ( h != para->rect().height() )
572 invalidateNested(); 563 invalidateNested();
573 else if ( para->document() && para->document()->parent() ) 564 else if ( para->document() && para->document()->parent() )
574 para->document()->nextDoubleBuffered = TRUE; 565 para->document()->nextDoubleBuffered = TRUE;
575} 566}
576 567
577void QTextCursor::gotoLeft() 568void QTextCursor::gotoLeft()
578{ 569{
579 if ( para->string()->isRightToLeft() ) 570 if ( para->string()->isRightToLeft() )
580 gotoNextLetter(); 571 gotoNextLetter();
581 else 572 else
582 gotoPreviousLetter(); 573 gotoPreviousLetter();
583} 574}
584 575
585void QTextCursor::gotoPreviousLetter() 576void QTextCursor::gotoPreviousLetter()
586{ 577{
587 tmpIndex = -1; 578 tmpIndex = -1;
588 579
589 if ( idx > 0 ) { 580 if ( idx > 0 ) {
590 idx--; 581 idx--;
591 const QTextStringChar *tsc = para->at( idx ); 582 const QTextStringChar *tsc = para->at( idx );
592 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) 583 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() )
593 processNesting( EnterEnd ); 584 processNesting( EnterEnd );
594 } else if ( para->prev() ) { 585 } else if ( para->prev() ) {
595 para = para->prev(); 586 para = para->prev();
596 while ( !para->isVisible() && para->prev() ) 587 while ( !para->isVisible() && para->prev() )
597 para = para->prev(); 588 para = para->prev();
598 idx = para->length() - 1; 589 idx = para->length() - 1;
599 } else if ( nestedDepth() ) { 590 } else if ( nestedDepth() ) {
600 pop(); 591 pop();
601 processNesting( Prev ); 592 processNesting( Prev );
602 if ( idx == -1 ) { 593 if ( idx == -1 ) {
603 pop(); 594 pop();
604 if ( idx > 0 ) { 595 if ( idx > 0 ) {
605 idx--; 596 idx--;
606 } else if ( para->prev() ) { 597 } else if ( para->prev() ) {
607 para = para->prev(); 598 para = para->prev();
608 idx = para->length() - 1; 599 idx = para->length() - 1;
609 } 600 }
610 } 601 }
611 } 602 }
612} 603}
613 604
614void QTextCursor::push() 605void QTextCursor::push()
615{ 606{
616 indices.push( idx ); 607 indices.push( idx );
617 paras.push( para ); 608 paras.push( para );
618 xOffsets.push( ox ); 609 xOffsets.push( ox );
619 yOffsets.push( oy ); 610 yOffsets.push( oy );
620} 611}
621 612
622void QTextCursor::pop() 613void QTextCursor::pop()
623{ 614{
624 if ( indices.isEmpty() ) 615 if ( indices.isEmpty() )
625 return; 616 return;
626 idx = indices.pop(); 617 idx = indices.pop();
627 para = paras.pop(); 618 para = paras.pop();
628 ox = xOffsets.pop(); 619 ox = xOffsets.pop();
629 oy = yOffsets.pop(); 620 oy = yOffsets.pop();
630} 621}
631 622
632void QTextCursor::restoreState() 623void QTextCursor::restoreState()
633{ 624{
634 while ( !indices.isEmpty() ) 625 while ( !indices.isEmpty() )
635 pop(); 626 pop();
636} 627}
637 628
638bool QTextCursor::place( const QPoint &p, QTextParagraph *s, bool link ) 629bool QTextCursor::place( const QPoint &p, QTextParagraph *s, bool link )
639{ 630{
640 QPoint pos( p ); 631 QPoint pos( p );
641 QRect r; 632 QRect r;
642 QTextParagraph *str = s; 633 QTextParagraph *str = s;
643 if ( pos.y() < s->rect().y() ) 634 if ( pos.y() < s->rect().y() )
644 pos.setY( s->rect().y() ); 635 pos.setY( s->rect().y() );
645 while ( s ) { 636 while ( s ) {
646 r = s->rect(); 637 r = s->rect();
647 r.setWidth( document() ? document()->width() : QWIDGETSIZE_MAX ); 638 r.setWidth( document() ? document()->width() : QWIDGETSIZE_MAX );
648 if ( s->isVisible() ) 639 if ( s->isVisible() )
649 str = s; 640 str = s;
650 if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() || !s->next() ) 641 if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() || !s->next() )
651 break; 642 break;
652 s = s->next(); 643 s = s->next();
653 } 644 }
654 645
655 if ( !s || !str ) 646 if ( !s || !str )
656 return FALSE; 647 return FALSE;
657 648
658 s = str; 649 s = str;
659 650
660 setParagraph( s ); 651 setParagraph( s );
661 int y = s->rect().y(); 652 int y = s->rect().y();
662 int lines = s->lines(); 653 int lines = s->lines();
663 QTextStringChar *chr = 0; 654 QTextStringChar *chr = 0;
664 int index = 0; 655 int index = 0;
665 int i = 0; 656 int i = 0;
666 int cy = 0; 657 int cy = 0;
667 int ch = 0; 658 int ch = 0;
668 for ( ; i < lines; ++i ) { 659 for ( ; i < lines; ++i ) {
669 chr = s->lineStartOfLine( i, &index ); 660 chr = s->lineStartOfLine( i, &index );
670 cy = s->lineY( i ); 661 cy = s->lineY( i );
671 ch = s->lineHeight( i ); 662 ch = s->lineHeight( i );
672 if ( !chr ) 663 if ( !chr )
673 return FALSE; 664 return FALSE;
674 if ( pos.y() <= y + cy + ch ) 665 if ( pos.y() <= y + cy + ch )
675 break; 666 break;
676 } 667 }
677 int nextLine; 668 int nextLine;
678 if ( i < lines - 1 ) 669 if ( i < lines - 1 )
679 s->lineStartOfLine( i+1, &nextLine ); 670 s->lineStartOfLine( i+1, &nextLine );
680 else 671 else
681 nextLine = s->length(); 672 nextLine = s->length();
682 i = index; 673 i = index;
683 int x = s->rect().x(); 674 int x = s->rect().x();
684 if ( pos.x() < x ) 675 if ( pos.x() < x )
685 pos.setX( x + 1 ); 676 pos.setX( x + 1 );
686 int cw; 677 int cw;
687 int curpos = s->length()-1; 678 int curpos = s->length()-1;
688 int dist = 10000000; 679 int dist = 10000000;
689 bool inCustom = FALSE; 680 bool inCustom = FALSE;
690 while ( i < nextLine ) { 681 while ( i < nextLine ) {
691 chr = s->at(i); 682 chr = s->at(i);
692 int cpos = x + chr->x; 683 int cpos = x + chr->x;
693 cw = s->string()->width( i ); 684 cw = s->string()->width( i );
694 if ( chr->isCustom() && chr->customItem()->isNested() ) { 685 if ( chr->isCustom() && chr->customItem()->isNested() ) {
695 if ( pos.x() >= cpos && pos.x() <= cpos + cw && 686 if ( pos.x() >= cpos && pos.x() <= cpos + cw &&
696 pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) { 687 pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) {
697 inCustom = TRUE; 688 inCustom = TRUE;
698 curpos = i; 689 curpos = i;
699 break; 690 break;
700 } 691 }
701 } else { 692 } else {
702 if( chr->rightToLeft ) 693 if( chr->rightToLeft )
703 cpos += cw; 694 cpos += cw;
704 int d = cpos - pos.x(); 695 int d = cpos - pos.x();
705 bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft; 696 bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft;
706 if ( QABS( d ) < dist || (dist == d && dm == TRUE ) ) { 697 if ( QABS( d ) < dist || (dist == d && dm == TRUE ) ) {
707 dist = QABS( d ); 698 dist = QABS( d );
708 if ( !link || pos.x() >= x + chr->x ) 699 if ( !link || pos.x() >= x + chr->x )
709 curpos = i; 700 curpos = i;
710 } 701 }
711 } 702 }
712 i++; 703 i++;
713 } 704 }
714 setIndex( curpos ); 705 setIndex( curpos );
715 706
716 if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) { 707 if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) {
717 QTextDocument *oldDoc = para->document(); 708 QTextDocument *oldDoc = para->document();
718 gotoIntoNested( pos ); 709 gotoIntoNested( pos );
719 if ( oldDoc == para->document() ) 710 if ( oldDoc == para->document() )
720 return TRUE; 711 return TRUE;
721 QPoint p( pos.x() - offsetX(), pos.y() - offsetY() ); 712 QPoint p( pos.x() - offsetX(), pos.y() - offsetY() );
722 if ( !place( p, document()->firstParagraph(), link ) ) 713 if ( !place( p, document()->firstParagraph(), link ) )
723 pop(); 714 pop();
724 } 715 }
725 return TRUE; 716 return TRUE;
726} 717}
727 718
728void QTextCursor::processNesting( Operation op ) 719void QTextCursor::processNesting( Operation op )
729{ 720{
730 if ( !para->document() ) 721 if ( !para->document() )
731 return; 722 return;
732 QTextDocument* doc = para->document(); 723 QTextDocument* doc = para->document();
733 push(); 724 push();
734 ox = para->at( idx )->x; 725 ox = para->at( idx )->x;
735 int bl, y; 726 int bl, y;
736 para->lineHeightOfChar( idx, &bl, &y ); 727 para->lineHeightOfChar( idx, &bl, &y );
737 oy = y + para->rect().y(); 728 oy = y + para->rect().y();
738 bool ok = FALSE; 729 bool ok = FALSE;
739 730
740 switch ( op ) { 731 switch ( op ) {
741 case EnterBegin: 732 case EnterBegin:
742 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy ); 733 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy );
743 break; 734 break;
744 case EnterEnd: 735 case EnterEnd:
745 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE ); 736 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE );
746 break; 737 break;
747 case Next: 738 case Next:
748 ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy ); 739 ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy );
749 break; 740 break;
750 case Prev: 741 case Prev:
751 ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy ); 742 ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy );
752 break; 743 break;
753 case Down: 744 case Down:
754 ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy ); 745 ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy );
755 break; 746 break;
756 case Up: 747 case Up:
757 ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy ); 748 ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy );
758 break; 749 break;
759 } 750 }
760 if ( !ok ) 751 if ( !ok )
761 pop(); 752 pop();
762} 753}
763 754
764void QTextCursor::gotoRight() 755void QTextCursor::gotoRight()
765{ 756{
766 if ( para->string()->isRightToLeft() ) 757 if ( para->string()->isRightToLeft() )
767 gotoPreviousLetter(); 758 gotoPreviousLetter();
768 else 759 else
769 gotoNextLetter(); 760 gotoNextLetter();
770} 761}
771 762
772void QTextCursor::gotoNextLetter() 763void QTextCursor::gotoNextLetter()
773{ 764{
774 tmpIndex = -1; 765 tmpIndex = -1;
775 766
776 const QTextStringChar *tsc = para->at( idx ); 767 const QTextStringChar *tsc = para->at( idx );
777 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) { 768 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) {
778 processNesting( EnterBegin ); 769 processNesting( EnterBegin );
779 return; 770 return;
780 } 771 }
781 772
782 if ( idx < para->length() - 1 ) { 773 if ( idx < para->length() - 1 ) {
783 idx++; 774 idx++;
784 } else if ( para->next() ) { 775 } else if ( para->next() ) {
785 para = para->next(); 776 para = para->next();
786 while ( !para->isVisible() && para->next() ) 777 while ( !para->isVisible() && para->next() )
787 para = para->next(); 778 para = para->next();
788 idx = 0; 779 idx = 0;
789 } else if ( nestedDepth() ) { 780 } else if ( nestedDepth() ) {
790 pop(); 781 pop();
791 processNesting( Next ); 782 processNesting( Next );
792 if ( idx == -1 ) { 783 if ( idx == -1 ) {
793 pop(); 784 pop();
794 if ( idx < para->length() - 1 ) { 785 if ( idx < para->length() - 1 ) {
795 idx++; 786 idx++;
796 } else if ( para->next() ) { 787 } else if ( para->next() ) {
797 para = para->next(); 788 para = para->next();
798 idx = 0; 789 idx = 0;
799 } 790 }
800 } 791 }
801 } 792 }
802} 793}
803 794
804void QTextCursor::gotoUp() 795void QTextCursor::gotoUp()
805{ 796{
806 int indexOfLineStart; 797 int indexOfLineStart;
807 int line; 798 int line;
808 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 799 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
809 if ( !c ) 800 if ( !c )
810 return; 801 return;
811 802
812 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); 803 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart );
813 if ( indexOfLineStart == 0 ) { 804 if ( indexOfLineStart == 0 ) {
814 if ( !para->prev() ) { 805 if ( !para->prev() ) {
815 if ( !nestedDepth() ) 806 if ( !nestedDepth() )
816 return; 807 return;
817 pop(); 808 pop();
818 processNesting( Up ); 809 processNesting( Up );
819 if ( idx == -1 ) { 810 if ( idx == -1 ) {
820 pop(); 811 pop();
821 if ( !para->prev() ) 812 if ( !para->prev() )
822 return; 813 return;
823 idx = tmpIndex = 0; 814 idx = tmpIndex = 0;
824 } else { 815 } else {
825 tmpIndex = -1; 816 tmpIndex = -1;
826 return; 817 return;
827 } 818 }
828 } 819 }
829 QTextParagraph *p = para->prev(); 820 QTextParagraph *p = para->prev();
830 while ( p && !p->isVisible() ) 821 while ( p && !p->isVisible() )
831 p = p->prev(); 822 p = p->prev();
832 if ( p ) 823 if ( p )
833 para = p; 824 para = p;
834 int lastLine = para->lines() - 1; 825 int lastLine = para->lines() - 1;
835 if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) ) 826 if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) )
836 return; 827 return;
837 if ( indexOfLineStart + tmpIndex < para->length() ) 828 if ( indexOfLineStart + tmpIndex < para->length() )
838 idx = indexOfLineStart + tmpIndex; 829 idx = indexOfLineStart + tmpIndex;
839 else 830 else
840 idx = para->length() - 1; 831 idx = para->length() - 1;
841 } else { 832 } else {
842 --line; 833 --line;
843 int oldIndexOfLineStart = indexOfLineStart; 834 int oldIndexOfLineStart = indexOfLineStart;
844 if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) 835 if ( !para->lineStartOfLine( line, &indexOfLineStart ) )
845 return; 836 return;
846 if ( indexOfLineStart + tmpIndex < oldIndexOfLineStart ) 837 if ( indexOfLineStart + tmpIndex < oldIndexOfLineStart )
847 idx = indexOfLineStart + tmpIndex; 838 idx = indexOfLineStart + tmpIndex;
848 else 839 else
849 idx = oldIndexOfLineStart - 1; 840 idx = oldIndexOfLineStart - 1;
850 } 841 }
851} 842}
852 843
853void QTextCursor::gotoDown() 844void QTextCursor::gotoDown()
854{ 845{
855 int indexOfLineStart; 846 int indexOfLineStart;
856 int line; 847 int line;
857 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 848 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
858 if ( !c ) 849 if ( !c )
859 return; 850 return;
860 851
861 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); 852 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart );
862 if ( line == para->lines() - 1 ) { 853 if ( line == para->lines() - 1 ) {
863 if ( !para->next() ) { 854 if ( !para->next() ) {
864 if ( !nestedDepth() ) 855 if ( !nestedDepth() )
865 return; 856 return;
866 pop(); 857 pop();
867 processNesting( Down ); 858 processNesting( Down );
868 if ( idx == -1 ) { 859 if ( idx == -1 ) {
869 pop(); 860 pop();
870 if ( !para->next() ) 861 if ( !para->next() )
871 return; 862 return;
872 idx = tmpIndex = 0; 863 idx = tmpIndex = 0;
873 } else { 864 } else {
874 tmpIndex = -1; 865 tmpIndex = -1;
875 return; 866 return;
876 } 867 }
877 } 868 }
878 QTextParagraph *s = para->next(); 869 QTextParagraph *s = para->next();
879 while ( s && !s->isVisible() ) 870 while ( s && !s->isVisible() )
880 s = s->next(); 871 s = s->next();
881 if ( s ) 872 if ( s )
882 para = s; 873 para = s;
883 if ( !para->lineStartOfLine( 0, &indexOfLineStart ) ) 874 if ( !para->lineStartOfLine( 0, &indexOfLineStart ) )
884 return; 875 return;
885 int end; 876 int end;
886 if ( para->lines() == 1 ) 877 if ( para->lines() == 1 )
887 end = para->length(); 878 end = para->length();
888 else 879 else
889 para->lineStartOfLine( 1, &end ); 880 para->lineStartOfLine( 1, &end );
890 if ( indexOfLineStart + tmpIndex < end ) 881 if ( indexOfLineStart + tmpIndex < end )
891 idx = indexOfLineStart + tmpIndex; 882 idx = indexOfLineStart + tmpIndex;
892 else 883 else
893 idx = end - 1; 884 idx = end - 1;
894 } else { 885 } else {
895 ++line; 886 ++line;
896 int end; 887 int end;
897 if ( line == para->lines() - 1 ) 888 if ( line == para->lines() - 1 )
898 end = para->length(); 889 end = para->length();
899 else 890 else
900 para->lineStartOfLine( line + 1, &end ); 891 para->lineStartOfLine( line + 1, &end );
901 if ( !para->lineStartOfLine( line, &indexOfLineStart ) ) 892 if ( !para->lineStartOfLine( line, &indexOfLineStart ) )
902 return; 893 return;
903 if ( indexOfLineStart + tmpIndex < end ) 894 if ( indexOfLineStart + tmpIndex < end )
904 idx = indexOfLineStart + tmpIndex; 895 idx = indexOfLineStart + tmpIndex;
905 else 896 else
906 idx = end - 1; 897 idx = end - 1;
907 } 898 }
908} 899}
909 900
910void QTextCursor::gotoLineEnd() 901void QTextCursor::gotoLineEnd()
911{ 902{
912 tmpIndex = -1; 903 tmpIndex = -1;
913 int indexOfLineStart; 904 int indexOfLineStart;
914 int line; 905 int line;
915 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 906 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
916 if ( !c ) 907 if ( !c )
917 return; 908 return;
918 909
919 if ( line == para->lines() - 1 ) { 910 if ( line == para->lines() - 1 ) {
920 idx = para->length() - 1; 911 idx = para->length() - 1;
921 } else { 912 } else {
922 c = para->lineStartOfLine( ++line, &indexOfLineStart ); 913 c = para->lineStartOfLine( ++line, &indexOfLineStart );
923 indexOfLineStart--; 914 indexOfLineStart--;
924 idx = indexOfLineStart; 915 idx = indexOfLineStart;
925 } 916 }
926} 917}
927 918
928void QTextCursor::gotoLineStart() 919void QTextCursor::gotoLineStart()
929{ 920{
930 tmpIndex = -1; 921 tmpIndex = -1;
931 int indexOfLineStart; 922 int indexOfLineStart;
932 int line; 923 int line;
933 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line ); 924 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
934 if ( !c ) 925 if ( !c )
935 return; 926 return;
936 927
937 idx = indexOfLineStart; 928 idx = indexOfLineStart;
938} 929}
939 930
940void QTextCursor::gotoHome() 931void QTextCursor::gotoHome()
941{ 932{
942 if ( topParagraph()->document() ) 933 if ( topParagraph()->document() )
943 gotoPosition( topParagraph()->document()->firstParagraph() ); 934 gotoPosition( topParagraph()->document()->firstParagraph() );
944 else 935 else
945 gotoLineStart(); 936 gotoLineStart();
946} 937}
947 938
948void QTextCursor::gotoEnd() 939void QTextCursor::gotoEnd()
949{ 940{
950 if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() ) 941 if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() )
951 gotoPosition( topParagraph()->document()->lastParagraph(), 942 gotoPosition( topParagraph()->document()->lastParagraph(),
952 topParagraph()->document()->lastParagraph()->length() - 1); 943 topParagraph()->document()->lastParagraph()->length() - 1);
953 else 944 else
954 gotoLineEnd(); 945 gotoLineEnd();
955} 946}
956 947
957void QTextCursor::gotoPageUp( int visibleHeight ) 948void QTextCursor::gotoPageUp( int visibleHeight )
958{ 949{
959 int targetY = globalY() - visibleHeight; 950 int targetY = globalY() - visibleHeight;
960 QTextParagraph* old; int index; 951 QTextParagraph* old; int index;
961 do { 952 do {
962 old = para; index = idx; 953 old = para; index = idx;
963 gotoUp(); 954 gotoUp();
964 } while ( (old != para || index != idx) && globalY() > targetY ); 955 } while ( (old != para || index != idx) && globalY() > targetY );
965} 956}
966 957
967void QTextCursor::gotoPageDown( int visibleHeight ) 958void QTextCursor::gotoPageDown( int visibleHeight )
968{ 959{
969 int targetY = globalY() + visibleHeight; 960 int targetY = globalY() + visibleHeight;
970 QTextParagraph* old; int index; 961 QTextParagraph* old; int index;
971 do { 962 do {
972 old = para; index = idx; 963 old = para; index = idx;
973 gotoDown(); 964 gotoDown();
974 } while ( (old != para || index != idx) && globalY() < targetY ); 965 } while ( (old != para || index != idx) && globalY() < targetY );
975} 966}
976 967
977void QTextCursor::gotoWordRight() 968void QTextCursor::gotoWordRight()
978{ 969{
979 if ( para->string()->isRightToLeft() ) 970 if ( para->string()->isRightToLeft() )
980 gotoPreviousWord(); 971 gotoPreviousWord();
981 else 972 else
982 gotoNextWord(); 973 gotoNextWord();
983} 974}
984 975
985void QTextCursor::gotoWordLeft() 976void QTextCursor::gotoWordLeft()
986{ 977{
987 if ( para->string()->isRightToLeft() ) 978 if ( para->string()->isRightToLeft() )
988 gotoNextWord(); 979 gotoNextWord();
989 else 980 else
990 gotoPreviousWord(); 981 gotoPreviousWord();
991} 982}
992 983
993void QTextCursor::gotoPreviousWord() 984void QTextCursor::gotoPreviousWord()
994{ 985{
995 gotoPreviousLetter(); 986 gotoPreviousLetter();
996 tmpIndex = -1; 987 tmpIndex = -1;
997 QTextString *s = para->string(); 988 QTextString *s = para->string();
998 bool allowSame = FALSE; 989 bool allowSame = FALSE;
999 if ( idx == ((int)s->length()-1) ) 990 if ( idx == ((int)s->length()-1) )
1000 return; 991 return;
1001 for ( int i = idx; i >= 0; --i ) { 992 for ( int i = idx; i >= 0; --i ) {
1002 if ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 993 if ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1003 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) { 994 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) {
1004 if ( !allowSame ) 995 if ( !allowSame )
1005 continue; 996 continue;
1006 idx = i + 1; 997 idx = i + 1;
1007 return; 998 return;
1008 } 999 }
1009 if ( !allowSame && !( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1000 if ( !allowSame && !( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1010 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) ) 1001 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) )
1011 allowSame = TRUE; 1002 allowSame = TRUE;
1012 } 1003 }
1013 idx = 0; 1004 idx = 0;
1014} 1005}
1015 1006
1016void QTextCursor::gotoNextWord() 1007void QTextCursor::gotoNextWord()
1017{ 1008{
1018 tmpIndex = -1; 1009 tmpIndex = -1;
1019 QTextString *s = para->string(); 1010 QTextString *s = para->string();
1020 bool allowSame = FALSE; 1011 bool allowSame = FALSE;
1021 for ( int i = idx; i < (int)s->length(); ++i ) { 1012 for ( int i = idx; i < (int)s->length(); ++i ) {
1022 if ( ! (s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1013 if ( ! (s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1023 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';') ) { 1014 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';') ) {
1024 if ( !allowSame ) 1015 if ( !allowSame )
1025 continue; 1016 continue;
1026 idx = i; 1017 idx = i;
1027 return; 1018 return;
1028 } 1019 }
1029 if ( !allowSame && ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1020 if ( !allowSame && ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1030 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) ) 1021 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) )
1031 allowSame = TRUE; 1022 allowSame = TRUE;
1032 1023
1033 } 1024 }
1034 1025
1035 if ( idx < ((int)s->length()-1) ) { 1026 if ( idx < ((int)s->length()-1) ) {
1036 gotoLineEnd(); 1027 gotoLineEnd();
1037 } else if ( para->next() ) { 1028 } else if ( para->next() ) {
1038 QTextParagraph *p = para->next(); 1029 QTextParagraph *p = para->next();
1039 while ( p && !p->isVisible() ) 1030 while ( p && !p->isVisible() )
1040 p = p->next(); 1031 p = p->next();
1041 if ( s ) { 1032 if ( s ) {
1042 para = p; 1033 para = p;
1043 idx = 0; 1034 idx = 0;
1044 } 1035 }
1045 } else { 1036 } else {
1046 gotoLineEnd(); 1037 gotoLineEnd();
1047 } 1038 }
1048} 1039}
1049 1040
1050bool QTextCursor::atParagStart() 1041bool QTextCursor::atParagStart()
1051{ 1042{
1052 return idx == 0; 1043 return idx == 0;
1053} 1044}
1054 1045
1055bool QTextCursor::atParagEnd() 1046bool QTextCursor::atParagEnd()
1056{ 1047{
1057 return idx == para->length() - 1; 1048 return idx == para->length() - 1;
1058} 1049}
1059 1050
1060void QTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds ) 1051void QTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds )
1061{ 1052{
1062 if ( !para->document() ) 1053 if ( !para->document() )
1063 return; 1054 return;
1064 tmpIndex = -1; 1055 tmpIndex = -1;
1065 QTextFormat *f = 0; 1056 QTextFormat *f = 0;
1066 if ( para->document()->useFormatCollection() ) { 1057 if ( para->document()->useFormatCollection() ) {
1067 f = para->at( idx )->format(); 1058 f = para->at( idx )->format();
1068 if ( idx == para->length() - 1 && idx > 0 ) 1059 if ( idx == para->length() - 1 && idx > 0 )
1069 f = para->at( idx - 1 )->format(); 1060 f = para->at( idx - 1 )->format();
1070 if ( f->isMisspelled() ) { 1061 if ( f->isMisspelled() ) {
1071 f->removeRef(); 1062 f->removeRef();
1072 f = para->document()->formatCollection()->format( f->font(), f->color() ); 1063 f = para->document()->formatCollection()->format( f->font(), f->color() );
1073 } 1064 }
1074 } 1065 }
1075 1066
1076 if ( atParagEnd() ) { 1067 if ( atParagEnd() ) {
1077 QTextParagraph *n = para->next(); 1068 QTextParagraph *n = para->next();
1078 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); 1069 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds );
1079 if ( f ) 1070 if ( f )
1080 s->setFormat( 0, 1, f, TRUE ); 1071 s->setFormat( 0, 1, f, TRUE );
1081 s->copyParagData( para ); 1072 s->copyParagData( para );
1082 if ( ind ) { 1073 if ( ind ) {
1083 int oi, ni; 1074 int oi, ni;
1084 s->indent( &oi, &ni ); 1075 s->indent( &oi, &ni );
1085 para = s; 1076 para = s;
1086 idx = ni; 1077 idx = ni;
1087 } else { 1078 } else {
1088 para = s; 1079 para = s;
1089 idx = 0; 1080 idx = 0;
1090 } 1081 }
1091 } else if ( atParagStart() ) { 1082 } else if ( atParagStart() ) {
1092 QTextParagraph *p = para->prev(); 1083 QTextParagraph *p = para->prev();
1093 QTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds ); 1084 QTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds );
1094 if ( f ) 1085 if ( f )
1095 s->setFormat( 0, 1, f, TRUE ); 1086 s->setFormat( 0, 1, f, TRUE );
1096 s->copyParagData( para ); 1087 s->copyParagData( para );
1097 if ( ind ) { 1088 if ( ind ) {
1098 s->indent(); 1089 s->indent();
1099 s->format(); 1090 s->format();
1100 indent(); 1091 indent();
1101 para->format(); 1092 para->format();
1102 } 1093 }
1103 } else { 1094 } else {
1104 QString str = para->string()->toString().mid( idx, 0xFFFFFF ); 1095 QString str = para->string()->toString().mid( idx, 0xFFFFFF );
1105 QTextParagraph *n = para->next(); 1096 QTextParagraph *n = para->next();
1106 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds ); 1097 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds );
1107 s->copyParagData( para ); 1098 s->copyParagData( para );
1108 s->remove( 0, 1 ); 1099 s->remove( 0, 1 );
1109 s->append( str, TRUE ); 1100 s->append( str, TRUE );
1110 for ( uint i = 0; i < str.length(); ++i ) { 1101 for ( uint i = 0; i < str.length(); ++i ) {
1111 QTextStringChar* tsc = para->at( idx + i ); 1102 QTextStringChar* tsc = para->at( idx + i );
1112 s->setFormat( i, 1, tsc->format(), TRUE ); 1103 s->setFormat( i, 1, tsc->format(), TRUE );
1113 if ( tsc->isCustom() ) { 1104 if ( tsc->isCustom() ) {
1114 QTextCustomItem * item = tsc->customItem(); 1105 QTextCustomItem * item = tsc->customItem();
1115 s->at( i )->setCustomItem( item ); 1106 s->at( i )->setCustomItem( item );
1116 tsc->loseCustomItem(); 1107 tsc->loseCustomItem();
1117 } 1108 }
1118 if ( tsc->isAnchor() ) 1109 if ( tsc->isAnchor() )
1119 s->at( i )->setAnchor( tsc->anchorName(), 1110 s->at( i )->setAnchor( tsc->anchorName(),
1120 tsc->anchorHref() ); 1111 tsc->anchorHref() );
1121 } 1112 }
1122 para->truncate( idx ); 1113 para->truncate( idx );
1123 if ( ind ) { 1114 if ( ind ) {
1124 int oi, ni; 1115 int oi, ni;
1125 s->indent( &oi, &ni ); 1116 s->indent( &oi, &ni );
1126 para = s; 1117 para = s;
1127 idx = ni; 1118 idx = ni;
1128 } else { 1119 } else {
1129 para = s; 1120 para = s;
1130 idx = 0; 1121 idx = 0;
1131 } 1122 }
1132 } 1123 }
1133 1124
1134 invalidateNested(); 1125 invalidateNested();
1135} 1126}
1136 1127
1137bool QTextCursor::remove() 1128bool QTextCursor::remove()
1138{ 1129{
1139 tmpIndex = -1; 1130 tmpIndex = -1;
1140 if ( !atParagEnd() ) { 1131 if ( !atParagEnd() ) {
1141 para->remove( idx, 1 ); 1132 para->remove( idx, 1 );
1142 int h = para->rect().height(); 1133 int h = para->rect().height();
1143 para->format( -1, TRUE ); 1134 para->format( -1, TRUE );
1144 if ( h != para->rect().height() ) 1135 if ( h != para->rect().height() )
1145 invalidateNested(); 1136 invalidateNested();
1146 else if ( para->document() && para->document()->parent() ) 1137 else if ( para->document() && para->document()->parent() )
1147 para->document()->nextDoubleBuffered = TRUE; 1138 para->document()->nextDoubleBuffered = TRUE;
1148 return FALSE; 1139 return FALSE;
1149 } else if ( para->next() ) { 1140 } else if ( para->next() ) {
1150 para->join( para->next() ); 1141 para->join( para->next() );
1151 invalidateNested(); 1142 invalidateNested();
1152 return TRUE; 1143 return TRUE;
1153 } 1144 }
1154 return FALSE; 1145 return FALSE;
1155} 1146}
1156 1147
1157void QTextCursor::indent() 1148void QTextCursor::indent()
1158{ 1149{
1159 int oi = 0, ni = 0; 1150 int oi = 0, ni = 0;
1160 para->indent( &oi, &ni ); 1151 para->indent( &oi, &ni );
1161 if ( oi == ni ) 1152 if ( oi == ni )
1162 return; 1153 return;
1163 1154
1164 if ( idx >= oi ) 1155 if ( idx >= oi )
1165 idx += ni - oi; 1156 idx += ni - oi;
1166 else 1157 else
1167 idx = ni; 1158 idx = ni;
1168} 1159}
1169 1160
1170// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1161// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1171 1162
1172QTextDocument::QTextDocument( QTextDocument *p ) 1163QTextDocument::QTextDocument( QTextDocument *p )
1173 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) 1164 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 )
1174{ 1165{
1175 fCollection = new QTextFormatCollection; 1166 fCollection = new QTextFormatCollection;
1176 init(); 1167 init();
1177} 1168}
1178 1169
1179QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f ) 1170QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f )
1180 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) 1171 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 )
1181{ 1172{
1182 fCollection = f; 1173 fCollection = f;
1183 init(); 1174 init();
1184} 1175}
1185 1176
1186void QTextDocument::init() 1177void QTextDocument::init()
1187{ 1178{
1188 oTextValid = TRUE; 1179 oTextValid = TRUE;
1189 mightHaveCustomItems = FALSE; 1180 mightHaveCustomItems = FALSE;
1190 if ( par ) 1181 if ( par )
1191 par->insertChild( this ); 1182 par->insertChild( this );
1192 pProcessor = 0; 1183 pProcessor = 0;
1193 useFC = TRUE; 1184 useFC = TRUE;
1194 pFormatter = 0; 1185 pFormatter = 0;
1195 indenter = 0; 1186 indenter = 0;
1196 fParag = 0; 1187 fParag = 0;
1197 txtFormat = Qt::AutoText; 1188 txtFormat = Qt::AutoText;
1198 preferRichText = FALSE; 1189 preferRichText = FALSE;
1199 pages = FALSE; 1190 pages = FALSE;
1200 focusIndicator.parag = 0; 1191 focusIndicator.parag = 0;
1201 minw = 0; 1192 minw = 0;
1202 wused = 0; 1193 wused = 0;
1203 minwParag = curParag = 0; 1194 minwParag = curParag = 0;
1204 align = AlignAuto; 1195 align = AlignAuto;
1205 nSelections = 1; 1196 nSelections = 1;
1206 1197
1207 setStyleSheet( QStyleSheet::defaultSheet() ); 1198 setStyleSheet( QStyleSheet::defaultSheet() );
1208 factory_ = QMimeSourceFactory::defaultFactory(); 1199 factory_ = QMimeSourceFactory::defaultFactory();
1209 contxt = QString::null; 1200 contxt = QString::null;
1210 1201
1211 underlLinks = par ? par->underlLinks : TRUE; 1202 underlLinks = par ? par->underlLinks : TRUE;
1212 backBrush = 0; 1203 backBrush = 0;
1213 buf_pixmap = 0; 1204 buf_pixmap = 0;
1214 nextDoubleBuffered = FALSE; 1205 nextDoubleBuffered = FALSE;
1215 1206
1216 if ( par ) 1207 if ( par )
1217 withoutDoubleBuffer = par->withoutDoubleBuffer; 1208 withoutDoubleBuffer = par->withoutDoubleBuffer;
1218 else 1209 else
1219 withoutDoubleBuffer = FALSE; 1210 withoutDoubleBuffer = FALSE;
1220 1211
1221 lParag = fParag = createParagraph( this, 0, 0 ); 1212 lParag = fParag = createParagraph( this, 0, 0 );
1222 1213
1223 cx = 0; 1214 cx = 0;
1224 cy = 2; 1215 cy = 2;
1225 if ( par ) 1216 if ( par )
1226 cx = cy = 0; 1217 cx = cy = 0;
1227 cw = 600; 1218 cw = 600;
1228 vw = 0; 1219 vw = 0;
1229 flow_ = new QTextFlow; 1220 flow_ = new QTextFlow;
1230 flow_->setWidth( cw ); 1221 flow_->setWidth( cw );
1231 1222
1232 leftmargin = rightmargin = 4; 1223 leftmargin = rightmargin = 4;
1233 scaleFontsFactor = 1; 1224 scaleFontsFactor = 1;
1234 1225
1235 1226
1236 selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight ); 1227 selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight );
1237 selectionText[ Standard ] = TRUE; 1228 selectionText[ Standard ] = TRUE;
1238 commandHistory = new QTextCommandHistory( 100 ); 1229 commandHistory = new QTextCommandHistory( 100 );
1239 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; 1230 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8;
1240} 1231}
1241 1232
1242QTextDocument::~QTextDocument() 1233QTextDocument::~QTextDocument()
1243{ 1234{
1244 if ( par ) 1235 if ( par )
1245 par->removeChild( this ); 1236 par->removeChild( this );
1246 clear(); 1237 clear();
1247 delete commandHistory; 1238 delete commandHistory;
1248 delete flow_; 1239 delete flow_;
1249 if ( !par ) 1240 if ( !par )
1250 delete pFormatter; 1241 delete pFormatter;
1251 delete fCollection; 1242 delete fCollection;
1252 delete pProcessor; 1243 delete pProcessor;
1253 delete buf_pixmap; 1244 delete buf_pixmap;
1254 delete indenter; 1245 delete indenter;
1255 delete backBrush; 1246 delete backBrush;
1256 if ( tArray ) 1247 if ( tArray )
1257 delete [] tArray; 1248 delete [] tArray;
1258} 1249}
1259 1250
1260void QTextDocument::clear( bool createEmptyParag ) 1251void QTextDocument::clear( bool createEmptyParag )
1261{ 1252{
1262 if ( flow_ ) 1253 if ( flow_ )
1263 flow_->clear(); 1254 flow_->clear();
1264 while ( fParag ) { 1255 while ( fParag ) {
1265 QTextParagraph *p = fParag->next(); 1256 QTextParagraph *p = fParag->next();
1266 delete fParag; 1257 delete fParag;
1267 fParag = p; 1258 fParag = p;
1268 } 1259 }
1269 fParag = lParag = 0; 1260 fParag = lParag = 0;
1270 if ( createEmptyParag ) 1261 if ( createEmptyParag )
1271 fParag = lParag = createParagraph( this ); 1262 fParag = lParag = createParagraph( this );
1272 selections.clear(); 1263 selections.clear();
1273 oText = QString::null; 1264 oText = QString::null;
1274 oTextValid = TRUE; 1265 oTextValid = TRUE;
1275} 1266}
1276 1267
1277int QTextDocument::widthUsed() const 1268int QTextDocument::widthUsed() const
1278{ 1269{
1279 return wused + border_tolerance; 1270 return wused + border_tolerance;
1280} 1271}
1281 1272
1282int QTextDocument::height() const 1273int QTextDocument::height() const
1283{ 1274{
1284 int h = 0; 1275 int h = 0;
1285 if ( lParag ) 1276 if ( lParag )
1286 h = lParag->rect().top() + lParag->rect().height() + 1; 1277 h = lParag->rect().top() + lParag->rect().height() + 1;
1287 int fh = flow_->boundingRect().bottom(); 1278 int fh = flow_->boundingRect().bottom();
1288 return QMAX( h, fh ); 1279 return QMAX( h, fh );
1289} 1280}
1290 1281
1291 1282
1292 1283
1293QTextParagraph *QTextDocument::createParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds ) 1284QTextParagraph *QTextDocument::createParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds )
1294{ 1285{
1295 return new QTextParagraph( d, pr, nx, updateIds ); 1286 return new QTextParagraph( d, pr, nx, updateIds );
1296} 1287}
1297 1288
1298bool QTextDocument::setMinimumWidth( int needed, int used, QTextParagraph *p ) 1289bool QTextDocument::setMinimumWidth( int needed, int used, QTextParagraph *p )
1299{ 1290{
1300 if ( needed == -1 ) { 1291 if ( needed == -1 ) {
1301 minw = 0; 1292 minw = 0;
1302 wused = 0; 1293 wused = 0;
1303 p = 0; 1294 p = 0;
1304 } 1295 }
1305 if ( p == minwParag ) { 1296 if ( p == minwParag ) {
1306 minw = needed; 1297 minw = needed;
1307 emit minimumWidthChanged( minw ); 1298 emit minimumWidthChanged( minw );
1308 } else if ( needed > minw ) { 1299 } else if ( needed > minw ) {
1309 minw = needed; 1300 minw = needed;
1310 minwParag = p; 1301 minwParag = p;
1311 emit minimumWidthChanged( minw ); 1302 emit minimumWidthChanged( minw );
1312 } 1303 }
1313 wused = QMAX( wused, used ); 1304 wused = QMAX( wused, used );
1314 wused = QMAX( wused, minw ); 1305 wused = QMAX( wused, minw );
1315 cw = QMAX( minw, cw ); 1306 cw = QMAX( minw, cw );
1316 return TRUE; 1307 return TRUE;
1317} 1308}
1318 1309
1319void QTextDocument::setPlainText( const QString &text ) 1310void QTextDocument::setPlainText( const QString &text )
1320{ 1311{
1321 clear(); 1312 clear();
1322 preferRichText = FALSE; 1313 preferRichText = FALSE;
1323 oTextValid = TRUE; 1314 oTextValid = TRUE;
1324 oText = text; 1315 oText = text;
1325 1316
1326 int lastNl = 0; 1317 int lastNl = 0;
1327 int nl = text.find( '\n' ); 1318 int nl = text.find( '\n' );
1328 if ( nl == -1 ) { 1319 if ( nl == -1 ) {
1329 lParag = createParagraph( this, lParag, 0 ); 1320 lParag = createParagraph( this, lParag, 0 );
1330 if ( !fParag ) 1321 if ( !fParag )
1331 fParag = lParag; 1322 fParag = lParag;
1332 QString s = text; 1323 QString s = text;
1333 if ( !s.isEmpty() ) { 1324 if ( !s.isEmpty() ) {
1334 if ( s[ (int)s.length() - 1 ] == '\r' ) 1325 if ( s[ (int)s.length() - 1 ] == '\r' )
1335 s.remove( s.length() - 1, 1 ); 1326 s.remove( s.length() - 1, 1 );
1336 lParag->append( s ); 1327 lParag->append( s );
1337 } 1328 }
1338 } else { 1329 } else {
1339 for (;;) { 1330 for (;;) {
1340 lParag = createParagraph( this, lParag, 0 ); 1331 lParag = createParagraph( this, lParag, 0 );
1341 if ( !fParag ) 1332 if ( !fParag )
1342 fParag = lParag; 1333 fParag = lParag;
1343 QString s = text.mid( lastNl, nl - lastNl ); 1334 QString s = text.mid( lastNl, nl - lastNl );
1344 if ( !s.isEmpty() ) { 1335 if ( !s.isEmpty() ) {
1345 if ( s[ (int)s.length() - 1 ] == '\r' ) 1336 if ( s[ (int)s.length() - 1 ] == '\r' )
1346 s.remove( s.length() - 1, 1 ); 1337 s.remove( s.length() - 1, 1 );
1347 lParag->append( s ); 1338 lParag->append( s );
1348 } 1339 }
1349 if ( nl == 0xffffff ) 1340 if ( nl == 0xffffff )
1350 break; 1341 break;
1351 lastNl = nl + 1; 1342 lastNl = nl + 1;
1352 nl = text.find( '\n', nl + 1 ); 1343 nl = text.find( '\n', nl + 1 );
1353 if ( nl == -1 ) 1344 if ( nl == -1 )
1354 nl = 0xffffff; 1345 nl = 0xffffff;
1355 } 1346 }
1356 } 1347 }
1357 if ( !lParag ) 1348 if ( !lParag )
1358 lParag = fParag = createParagraph( this, 0, 0 ); 1349 lParag = fParag = createParagraph( this, 0, 0 );
1359} 1350}
1360 1351
1361struct Q_EXPORT QTextDocumentTag { 1352struct Q_EXPORT QTextDocumentTag {
1362 QTextDocumentTag(){} 1353 QTextDocumentTag(){}
1363 QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f ) 1354 QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f )
1364 :name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) { 1355 :name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) {
1365 wsm = QStyleSheetItem::WhiteSpaceNormal; 1356 wsm = QStyleSheetItem::WhiteSpaceNormal;
1366 } 1357 }
1367 QString name; 1358 QString name;
1368 const QStyleSheetItem* style; 1359 const QStyleSheetItem* style;
1369 QString anchorHref; 1360 QString anchorHref;
1370 QStyleSheetItem::WhiteSpaceMode wsm; 1361 QStyleSheetItem::WhiteSpaceMode wsm;
1371 QTextFormat format; 1362 QTextFormat format;
1372 int alignment : 16; 1363 int alignment : 16;
1373 int direction : 5; 1364 int direction : 5;
1374 QStyleSheetItem::ListStyle liststyle; 1365 QStyleSheetItem::ListStyle liststyle;
1375 1366
1376 QTextDocumentTag( const QTextDocumentTag& t ) { 1367 QTextDocumentTag( const QTextDocumentTag& t ) {
1377 name = t.name; 1368 name = t.name;
1378 style = t.style; 1369 style = t.style;
1379 anchorHref = t.anchorHref; 1370 anchorHref = t.anchorHref;
1380 wsm = t.wsm; 1371 wsm = t.wsm;
1381 format = t.format; 1372 format = t.format;
1382 alignment = t.alignment; 1373 alignment = t.alignment;
1383 direction = t.direction; 1374 direction = t.direction;
1384 liststyle = t.liststyle; 1375 liststyle = t.liststyle;
1385 } 1376 }
1386 QTextDocumentTag& operator=(const QTextDocumentTag& t) { 1377 QTextDocumentTag& operator=(const QTextDocumentTag& t) {
1387 name = t.name; 1378 name = t.name;
1388 style = t.style; 1379 style = t.style;
1389 anchorHref = t.anchorHref; 1380 anchorHref = t.anchorHref;
1390 wsm = t.wsm; 1381 wsm = t.wsm;
1391 format = t.format; 1382 format = t.format;
1392 alignment = t.alignment; 1383 alignment = t.alignment;
1393 direction = t.direction; 1384 direction = t.direction;
1394 liststyle = t.liststyle; 1385 liststyle = t.liststyle;
1395 return *this; 1386 return *this;
1396 } 1387 }
1397 1388
1398#if defined(Q_FULL_TEMPLATE_INSTANTIATION) 1389#if defined(Q_FULL_TEMPLATE_INSTANTIATION)
1399 bool operator==( const QTextDocumentTag& ) const { return FALSE; } 1390 bool operator==( const QTextDocumentTag& ) const { return FALSE; }
1400#endif 1391#endif
1401}; 1392};
1402 1393
1403 1394
1404#define NEWPAR do { \ 1395#define NEWPAR do{ if ( !hasNewPar) { \
1405 if ( !hasNewPar) { \ 1396 if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \
1406 if ( !curpar ) { \ 1397 curpar->remove( curpar->length()-2, 1 ); \
1407 owarn << "no current paragraph" << oendl; \ 1398 curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); vec = 0;} \
1408 return; \ 1399 hasNewPar = TRUE; \
1409 } \ 1400 curpar->rtext = TRUE; \
1410 if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \ 1401 curpar->align = curtag.alignment; \
1411 curpar->remove( curpar->length()-2, 1 ); \ 1402 curpar->lstyle = curtag.liststyle; \
1412 curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); \ 1403 curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \
1413 if ( !curpar ) { \ 1404 curpar->str->setDirection( (QChar::Direction)curtag.direction ); \
1414 owarn << "failed in creating a new paragraph" << oendl; \ 1405 space = TRUE; \
1415 return; \ 1406 delete vec; vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \
1416 } \ 1407 int i = 0; \
1417 vec = 0; \ 1408 for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \
1418 } \ 1409 vec->insert( i++, (*it).style ); \
1419 hasNewPar = TRUE; \ 1410 vec->insert( i, curtag.style ); \
1420 curpar->rtext = TRUE; \ 1411 }while(FALSE)
1421 curpar->align = curtag.alignment; \ 1412
1422 curpar->lstyle = curtag.liststyle; \
1423 curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \
1424 curpar->str->setDirection( (QChar::Direction)curtag.direction ); \
1425 space = TRUE; \
1426 delete vec; \
1427 vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \
1428 int i = 0; \
1429 for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \
1430 vec->insert( i++, (*it).style ); \
1431 vec->insert( i, curtag.style ); \
1432 } while ( FALSE )
1433 1413
1434void QTextDocument::setRichText( const QString &text, const QString &context ) 1414void QTextDocument::setRichText( const QString &text, const QString &context )
1435{ 1415{
1436 if ( !context.isEmpty() ) 1416 if ( !context.isEmpty() )
1437 setContext( context ); 1417 setContext( context );
1438 clear(); 1418 clear();
1439 fParag = lParag = createParagraph( this ); 1419 fParag = lParag = createParagraph( this );
1440 oTextValid = TRUE; 1420 oTextValid = TRUE;
1441 oText = text; 1421 oText = text;
1442 setRichTextInternal( text ); 1422 setRichTextInternal( text );
1443 fParag->rtext = TRUE; 1423 fParag->rtext = TRUE;
1444} 1424}
1445 1425
1446void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* cursor ) 1426void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* cursor )
1447{ 1427{
1448 QTextParagraph* curpar = lParag; 1428 QTextParagraph* curpar = lParag;
1449 int pos = 0; 1429 int pos = 0;
1450 QValueStack<QTextDocumentTag> tags; 1430 QValueStack<QTextDocumentTag> tags;
1451 QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() ); 1431 QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() );
1452 QTextDocumentTag curtag = initag; 1432 QTextDocumentTag curtag = initag;
1453 bool space = TRUE; 1433 bool space = TRUE;
1454 bool canMergeLi = FALSE; 1434 bool canMergeLi = FALSE;
1455 1435
1456 bool textEditMode = FALSE; 1436 bool textEditMode = FALSE;
1457 1437
1458 const QChar* doc = text.unicode(); 1438 const QChar* doc = text.unicode();
1459 int length = text.length(); 1439 int length = text.length();
1460 bool hasNewPar = curpar->length() <= 1; 1440 bool hasNewPar = curpar->length() <= 1;
1461 QString anchorName; 1441 QString anchorName;
1462 1442
1463 // style sheet handling for margin and line spacing calculation below 1443 // style sheet handling for margin and line spacing calculation below
1464 QTextParagraph* stylesPar = curpar; 1444 QTextParagraph* stylesPar = curpar;
1465 QPtrVector<QStyleSheetItem>* vec = 0; 1445 QPtrVector<QStyleSheetItem>* vec = 0;
1466 QPtrList< QPtrVector<QStyleSheetItem> > styles; 1446 QPtrList< QPtrVector<QStyleSheetItem> > styles;
1467 styles.setAutoDelete( TRUE ); 1447 styles.setAutoDelete( TRUE );
1468 1448
1469 if ( cursor ) { 1449 if ( cursor ) {
1470 cursor->splitAndInsertEmptyParagraph(); 1450 cursor->splitAndInsertEmptyParagraph();
1471 QTextCursor tmp = *cursor; 1451 QTextCursor tmp = *cursor;
1472 tmp.gotoPreviousLetter(); 1452 tmp.gotoPreviousLetter();
1473 stylesPar = curpar = tmp.paragraph(); 1453 stylesPar = curpar = tmp.paragraph();
1474 hasNewPar = TRUE; 1454 hasNewPar = TRUE;
1475 textEditMode = TRUE; 1455 textEditMode = TRUE;
1476 } else { 1456 } else {
1477 NEWPAR; 1457 NEWPAR;
1478 } 1458 }
1479 1459
1480 // set rtext spacing to FALSE for the initial paragraph. 1460 // set rtext spacing to FALSE for the initial paragraph.
1481 curpar->rtext = FALSE; 1461 curpar->rtext = FALSE;
1482 1462
1483 QString wellKnownTags = "br hr wsp table qt body meta title"; 1463 QString wellKnownTags = "br hr wsp table qt body meta title";
1484 1464
1485 while ( pos < length ) { 1465 while ( pos < length ) {
1486 if ( hasPrefix(doc, length, pos, '<' ) ){ 1466 if ( hasPrefix(doc, length, pos, '<' ) ){
1487 if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) { 1467 if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) {
1488 // open tag 1468 // open tag
1489 QMap<QString, QString> attr; 1469 QMap<QString, QString> attr;
1490 bool emptyTag = FALSE; 1470 bool emptyTag = FALSE;
1491 QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag); 1471 QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag);
1492 if ( tagname.isEmpty() ) 1472 if ( tagname.isEmpty() )
1493 continue; // nothing we could do with this, probably parse error 1473 continue; // nothing we could do with this, probably parse error
1494 1474
1495 const QStyleSheetItem* nstyle = sheet_->item(tagname); 1475 const QStyleSheetItem* nstyle = sheet_->item(tagname);
1496 1476
1497 if ( nstyle ) { 1477 if ( nstyle ) {
1498 // we might have to close some 'forgotten' tags 1478 // we might have to close some 'forgotten' tags
1499 while ( !nstyle->allowedInContext( curtag.style ) ) { 1479 while ( !nstyle->allowedInContext( curtag.style ) ) {
1500 QString msg; 1480 QString msg;
1501 msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)", 1481 msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)",
1502 tagname.ascii(), curtag.style->name().ascii(), pos); 1482 tagname.ascii(), curtag.style->name().ascii(), pos);
1503 sheet_->error( msg ); 1483 sheet_->error( msg );
1504 if ( tags.isEmpty() ) 1484 if ( tags.isEmpty() )
1505 break; 1485 break;
1506 curtag = tags.pop(); 1486 curtag = tags.pop();
1507 } 1487 }
1508 1488
1509 /* special handling for p and li for HTML 1489 /* special handling for p and li for HTML
1510 compatibility. We do not want to embed blocks in 1490 compatibility. We do not want to embed blocks in
1511 p, and we do not want new blocks inside non-empty 1491 p, and we do not want new blocks inside non-empty
1512 lis. Plus we want to merge empty lis sometimes. */ 1492 lis. Plus we want to merge empty lis sometimes. */
1513 if( nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) { 1493 if( nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) {
1514 canMergeLi = TRUE; 1494 canMergeLi = TRUE;
1515 } else if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { 1495 } else if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) {
1516 while ( curtag.style->name() == "p" ) { 1496 while ( curtag.style->name() == "p" ) {
1517 if ( tags.isEmpty() ) 1497 if ( tags.isEmpty() )
1518 break; 1498 break;
1519 curtag = tags.pop(); 1499 curtag = tags.pop();
1520 } 1500 }
1521 1501
1522 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1502 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1523 // we are in a li and a new block comes along 1503 // we are in a li and a new block comes along
1524 if ( nstyle->name() == "ul" || nstyle->name() == "ol" ) 1504 if ( nstyle->name() == "ul" || nstyle->name() == "ol" )
1525 hasNewPar = FALSE; // we want an empty li (like most browsers) 1505 hasNewPar = FALSE; // we want an empty li (like most browsers)
1526 if ( !hasNewPar ) { 1506 if ( !hasNewPar ) {
1527 /* do not add new blocks inside 1507 /* do not add new blocks inside
1528 non-empty lis */ 1508 non-empty lis */
1529 while ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1509 while ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1530 if ( tags.isEmpty() ) 1510 if ( tags.isEmpty() )
1531 break; 1511 break;
1532 curtag = tags.pop(); 1512 curtag = tags.pop();
1533 } 1513 }
1534 } else if ( canMergeLi ) { 1514 } else if ( canMergeLi ) {
1535 /* we have an empty li and a block 1515 /* we have an empty li and a block
1536 comes along, merge them */ 1516 comes along, merge them */
1537 nstyle = curtag.style; 1517 nstyle = curtag.style;
1538 } 1518 }
1539 canMergeLi = FALSE; 1519 canMergeLi = FALSE;
1540 } 1520 }
1541 } 1521 }
1542 } 1522 }
1543 1523
1544 QTextCustomItem* custom = 0; 1524 QTextCustomItem* custom = 0;
1545 1525
1546 // some well-known tags, some have a nstyle, some not 1526 // some well-known tags, some have a nstyle, some not
1547 if ( wellKnownTags.find( tagname ) != -1 ) { 1527 if ( wellKnownTags.find( tagname ) != -1 ) {
1548 if ( tagname == "br" ) { 1528 if ( tagname == "br" ) {
1549 emptyTag = space = TRUE; 1529 emptyTag = space = TRUE;
1550 int index = QMAX( curpar->length(),1) - 1; 1530 int index = QMAX( curpar->length(),1) - 1;
1551 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1531 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1552 curpar->append( QChar_linesep ); 1532 curpar->append( QChar_linesep );
1553 curpar->setFormat( index, 1, &format ); 1533 curpar->setFormat( index, 1, &format );
1554 } else if ( tagname == "hr" ) { 1534 } else if ( tagname == "hr" ) {
1555 emptyTag = space = TRUE; 1535 emptyTag = space = TRUE;
1556 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); 1536 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
1557 NEWPAR; 1537 NEWPAR;
1558 } else if ( tagname == "table" ) { 1538 } else if ( tagname == "table" ) {
1559 emptyTag = space = TRUE; 1539 emptyTag = space = TRUE;
1560 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1540 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1561 curpar->setAlignment( curtag.alignment ); 1541 curpar->setAlignment( curtag.alignment );
1562 custom = parseTable( attr, format, doc, length, pos, curpar ); 1542 custom = parseTable( attr, format, doc, length, pos, curpar );
1563 } else if ( tagname == "qt" || tagname == "body" ) { 1543 } else if ( tagname == "qt" || tagname == "body" ) {
1564 if ( attr.contains( "bgcolor" ) ) { 1544 if ( attr.contains( "bgcolor" ) ) {
1565 QBrush *b = new QBrush( QColor( attr["bgcolor"] ) ); 1545 QBrush *b = new QBrush( QColor( attr["bgcolor"] ) );
1566 setPaper( b ); 1546 setPaper( b );
1567 } 1547 }
1568 if ( attr.contains( "background" ) ) { 1548 if ( attr.contains( "background" ) ) {
1569 QImage img; 1549 QImage img;
1570 QString bg = attr["background"]; 1550 QString bg = attr["background"];
1571 const QMimeSource* m = factory_->data( bg, contxt ); 1551 const QMimeSource* m = factory_->data( bg, contxt );
1572 if ( !m ) { 1552 if ( !m ) {
1573 owarn << "QRichText: no mimesource for " << bg.latin1() << "" << oendl; 1553 owarn << "QRichText: no mimesource for " << bg.latin1() << "" << oendl;
1574 } else { 1554 } else {
1575 if ( !QImageDrag::decode( m, img ) ) { 1555 if ( !QImageDrag::decode( m, img ) ) {
1576 owarn << "QTextImage: cannot decode " << bg.latin1() << "" << oendl; 1556 owarn << "QTextImage: cannot decode " << bg.latin1() << "" << oendl;
1577 } 1557 }
1578 } 1558 }
1579 if ( !img.isNull() ) { 1559 if ( !img.isNull() ) {
1580 QPixmap pm; 1560 QPixmap pm;
1581 pm.convertFromImage( img ); 1561 pm.convertFromImage( img );
1582 QBrush *b = new QBrush( QColor(), pm ); 1562 QBrush *b = new QBrush( QColor(), pm );
1583 setPaper( b ); 1563 setPaper( b );
1584 } 1564 }
1585 } 1565 }
1586 if ( attr.contains( "text" ) ) { 1566 if ( attr.contains( "text" ) ) {
1587 QColor c( attr["text"] ); 1567 QColor c( attr["text"] );
1588 if ( formatCollection()->defaultFormat()->color() != c ) { 1568 if ( formatCollection()->defaultFormat()->color() != c ) {
1589 QDict<QTextFormat> formats = formatCollection()->dict(); 1569 QDict<QTextFormat> formats = formatCollection()->dict();
1590 QDictIterator<QTextFormat> it( formats ); 1570 QDictIterator<QTextFormat> it( formats );
1591 while ( it.current() ) { 1571 while ( it.current() ) {
1592 if ( it.current() == formatCollection()->defaultFormat() ) { 1572 if ( it.current() == formatCollection()->defaultFormat() ) {
1593 ++it; 1573 ++it;
1594 continue; 1574 continue;
1595 } 1575 }
1596 it.current()->setColor( c ); 1576 it.current()->setColor( c );
1597 ++it; 1577 ++it;
1598 } 1578 }
1599 formatCollection()->defaultFormat()->setColor( c ); 1579 formatCollection()->defaultFormat()->setColor( c );
1600 curtag.format.setColor( c ); 1580 curtag.format.setColor( c );
1601 } 1581 }
1602 } 1582 }
1603 if ( attr.contains( "link" ) ) 1583 if ( attr.contains( "link" ) )
1604 linkColor = QColor( attr["link"] ); 1584 linkColor = QColor( attr["link"] );
1605 if ( attr.contains( "title" ) ) 1585 if ( attr.contains( "title" ) )
1606 attribs.replace( "title", attr["title"] ); 1586 attribs.replace( "title", attr["title"] );
1607 1587
1608 if ( textEditMode ) { 1588 if ( textEditMode ) {
1609 if ( attr.contains("style" ) ) { 1589 if ( attr.contains("style" ) ) {
1610 QString a = attr["style"]; 1590 QString a = attr["style"];
1611 for ( int s = 0; s < a.contains(';')+1; s++ ) { 1591 for ( int s = 0; s < a.contains(';')+1; s++ ) {
1612 QString style = QTextDocument::section( a, ";", s, s ); 1592 QString style = QTextDocument::section( a, ";", s, s );
1613 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) { 1593 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) {
1614 scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) / 1594 scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) /
1615 style.mid( 10, style.length() - 12 ).toInt(); 1595 style.mid( 10, style.length() - 12 ).toInt();
1616 } 1596 }
1617 } 1597 }
1618 } 1598 }
1619 nstyle = 0; // ignore body in textEditMode 1599 nstyle = 0; // ignore body in textEditMode
1620 } 1600 }
1621 // end qt- and body-tag handling 1601 // end qt- and body-tag handling
1622 } else if ( tagname == "meta" ) { 1602 } else if ( tagname == "meta" ) {
1623 if ( attr["name"] == "qrichtext" && attr["content"] == "1" ) 1603 if ( attr["name"] == "qrichtext" && attr["content"] == "1" )
1624 textEditMode = TRUE; 1604 textEditMode = TRUE;
1625 } else if ( tagname == "title" ) { 1605 } else if ( tagname == "title" ) {
1626 QString title; 1606 QString title;
1627 while ( pos < length ) { 1607 while ( pos < length ) {
1628 if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) && 1608 if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) &&
1629 parseCloseTag( doc, length, pos ) == "title" ) 1609 parseCloseTag( doc, length, pos ) == "title" )
1630 break; 1610 break;
1631 title += doc[ pos ]; 1611 title += doc[ pos ];
1632 ++pos; 1612 ++pos;
1633 } 1613 }
1634 attribs.replace( "title", title ); 1614 attribs.replace( "title", title );
1635 } 1615 }
1636 } // end of well-known tag handling 1616 } // end of well-known tag handling
1637 1617
1638 if ( !custom ) // try generic custom item 1618 if ( !custom ) // try generic custom item
1639 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); 1619 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
1640 1620
1641 if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it 1621 if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it
1642 continue; 1622 continue;
1643 1623
1644 if ( custom ) { 1624 if ( custom ) {
1645 int index = QMAX( curpar->length(),1) - 1; 1625 int index = QMAX( curpar->length(),1) - 1;
1646 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1626 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1647 curpar->append( QChar('*') ); 1627 curpar->append( QChar('*') );
1648 curpar->setFormat( index, 1, &format ); 1628 curpar->setFormat( index, 1, &format );
1649 curpar->at( index )->setCustomItem( custom ); 1629 curpar->at( index )->setCustomItem( custom );
1650 if ( !curtag.anchorHref.isEmpty() ) 1630 if ( !curtag.anchorHref.isEmpty() )
1651 curpar->at(index)->setAnchor( QString::null, curtag.anchorHref ); 1631 curpar->at(index)->setAnchor( QString::null, curtag.anchorHref );
1652 if ( !anchorName.isEmpty() ) { 1632 if ( !anchorName.isEmpty() ) {
1653 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); 1633 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
1654 anchorName = QString::null; 1634 anchorName = QString::null;
1655 } 1635 }
1656 registerCustomItem( custom, curpar ); 1636 registerCustomItem( custom, curpar );
1657 hasNewPar = FALSE; 1637 hasNewPar = FALSE;
1658 } else if ( !emptyTag ) { 1638 } else if ( !emptyTag ) {
1659 /* if we do nesting, push curtag on the stack, 1639 /* if we do nesting, push curtag on the stack,
1660 otherwise reinint curag. */ 1640 otherwise reinint curag. */
1661 if ( curtag.style->name() != tagname || nstyle->selfNesting() ) { 1641 if ( curtag.style->name() != tagname || nstyle->selfNesting() ) {
1662 tags.push( curtag ); 1642 tags.push( curtag );
1663 } else { 1643 } else {
1664 if ( !tags.isEmpty() ) 1644 if ( !tags.isEmpty() )
1665 curtag = tags.top(); 1645 curtag = tags.top();
1666 else 1646 else
1667 curtag = initag; 1647 curtag = initag;
1668 } 1648 }
1669 1649
1670 curtag.name = tagname; 1650 curtag.name = tagname;
1671 curtag.style = nstyle; 1651 curtag.style = nstyle;
1672 curtag.name = tagname; 1652 curtag.name = tagname;
1673 curtag.style = nstyle; 1653 curtag.style = nstyle;
1674 if ( int(nstyle->whiteSpaceMode()) != QStyleSheetItem::Undefined ) 1654 if ( int(nstyle->whiteSpaceMode()) != QStyleSheetItem::Undefined )
1675 curtag.wsm = nstyle->whiteSpaceMode(); 1655 curtag.wsm = nstyle->whiteSpaceMode();
1676 1656
1677 /* ignore whitespace for inline elements if there 1657 /* ignore whitespace for inline elements if there
1678 was already one*/ 1658 was already one*/
1679 if ( !textEditMode && curtag.wsm == QStyleSheetItem::WhiteSpaceNormal 1659 if ( !textEditMode && curtag.wsm == QStyleSheetItem::WhiteSpaceNormal
1680 && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) ) 1660 && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) )
1681 eatSpace( doc, length, pos ); 1661 eatSpace( doc, length, pos );
1682 1662
1683 curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor ); 1663 curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1684 if ( nstyle->isAnchor() ) { 1664 if ( nstyle->isAnchor() ) {
1685 if ( !anchorName.isEmpty() ) 1665 if ( !anchorName.isEmpty() )
1686 anchorName += "#" + attr["name"]; 1666 anchorName += "#" + attr["name"];
1687 else 1667 else
1688 anchorName = attr["name"]; 1668 anchorName = attr["name"];
1689 curtag.anchorHref = attr["href"]; 1669 curtag.anchorHref = attr["href"];
1690 } 1670 }
1691 1671
1692 if ( nstyle->alignment() != QStyleSheetItem::Undefined ) 1672 if ( nstyle->alignment() != QStyleSheetItem::Undefined )
1693 curtag.alignment = nstyle->alignment(); 1673 curtag.alignment = nstyle->alignment();
1694 1674
1695 if ( (int) nstyle->listStyle() != QStyleSheetItem::Undefined ) 1675 if ( (int) nstyle->listStyle() != QStyleSheetItem::Undefined )
1696 curtag.liststyle = nstyle->listStyle(); 1676 curtag.liststyle = nstyle->listStyle();
1697 1677
1698 if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock 1678 if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock
1699 || nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) { 1679 || nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) {
1700 1680
1701 if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") { 1681 if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") {
1702 QString type = attr["type"]; 1682 QString type = attr["type"];
1703 if ( !type.isEmpty() ) { 1683 if ( !type.isEmpty() ) {
1704 if ( type == "1" ) { 1684 if ( type == "1" ) {
1705 curtag.liststyle = QStyleSheetItem::ListDecimal; 1685 curtag.liststyle = QStyleSheetItem::ListDecimal;
1706 } else if ( type == "a" ) { 1686 } else if ( type == "a" ) {
1707 curtag.liststyle = QStyleSheetItem::ListLowerAlpha; 1687 curtag.liststyle = QStyleSheetItem::ListLowerAlpha;
1708 } else if ( type == "A" ) { 1688 } else if ( type == "A" ) {
1709 curtag.liststyle = QStyleSheetItem::ListUpperAlpha; 1689 curtag.liststyle = QStyleSheetItem::ListUpperAlpha;
1710 } else { 1690 } else {
1711 type = type.lower(); 1691 type = type.lower();
1712 if ( type == "square" ) 1692 if ( type == "square" )
1713 curtag.liststyle = QStyleSheetItem::ListSquare; 1693 curtag.liststyle = QStyleSheetItem::ListSquare;
1714 else if ( type == "disc" ) 1694 else if ( type == "disc" )
1715 curtag.liststyle = QStyleSheetItem::ListDisc; 1695 curtag.liststyle = QStyleSheetItem::ListDisc;
1716 else if ( type == "circle" ) 1696 else if ( type == "circle" )
1717 curtag.liststyle = QStyleSheetItem::ListCircle; 1697 curtag.liststyle = QStyleSheetItem::ListCircle;
1718 } 1698 }
1719 } 1699 }
1720 } 1700 }
1721 1701
1722 1702
1723 /* Internally we treat ordered and bullet 1703 /* Internally we treat ordered and bullet
1724 lists the same for margin calculations. In 1704 lists the same for margin calculations. In
1725 order to have fast pointer compares in the 1705 order to have fast pointer compares in the
1726 xMargin() functions we restrict ourselves to 1706 xMargin() functions we restrict ourselves to
1727 <ol>. Once we calculate the margins in the 1707 <ol>. Once we calculate the margins in the
1728 parser rathern than later, the unelegance of 1708 parser rathern than later, the unelegance of
1729 this approach goes awy 1709 this approach goes awy
1730 */ 1710 */
1731 if ( nstyle->name() == "ul" ) 1711 if ( nstyle->name() == "ul" )
1732 curtag.style = sheet_->item( "ol" ); 1712 curtag.style = sheet_->item( "ol" );
1733 1713
1734 if ( attr.contains( "align" ) ) { 1714 if ( attr.contains( "align" ) ) {
1735 QString align = attr["align"]; 1715 QString align = attr["align"];
1736 if ( align == "center" ) 1716 if ( align == "center" )
1737 curtag.alignment = Qt::AlignCenter; 1717 curtag.alignment = Qt::AlignCenter;
1738 else if ( align == "right" ) 1718 else if ( align == "right" )
1739 curtag.alignment = Qt::AlignRight; 1719 curtag.alignment = Qt::AlignRight;
1740 else if ( align == "justify" ) 1720 else if ( align == "justify" )
1741 curtag.alignment = Qt3::AlignJustify; 1721 curtag.alignment = Qt3::AlignJustify;
1742 } 1722 }
1743 if ( attr.contains( "dir" ) ) { 1723 if ( attr.contains( "dir" ) ) {
1744 QString dir = attr["dir"]; 1724 QString dir = attr["dir"];
1745 if ( dir == "rtl" ) 1725 if ( dir == "rtl" )
1746 curtag.direction = QChar::DirR; 1726 curtag.direction = QChar::DirR;
1747 else if ( dir == "ltr" ) 1727 else if ( dir == "ltr" )
1748 curtag.direction = QChar::DirL; 1728 curtag.direction = QChar::DirL;
1749 } 1729 }
1750 1730
1751 NEWPAR; 1731 NEWPAR;
1752 1732
1753 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1733 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1754 if ( attr.contains( "value " ) ) 1734 if ( attr.contains( "value " ) )
1755 curpar->setListValue( attr["value"].toInt() ); 1735 curpar->setListValue( attr["value"].toInt() );
1756 } 1736 }
1757 1737
1758 if ( attr.contains( "style" ) ) { 1738 if ( attr.contains( "style" ) ) {
1759 QString a = attr["style"]; 1739 QString a = attr["style"];
1760 bool ok = TRUE; 1740 bool ok = TRUE;
1761 for ( int s = 0; ok && s < a.contains(';')+1; s++ ) { 1741 for ( int s = 0; ok && s < a.contains(';')+1; s++ ) {
1762 QString style = QTextDocument::section( a, ";", s, s ); 1742 QString style = QTextDocument::section( a, ";", s, s );
1763 if ( style.startsWith("margin-top:" ) && QTextDocument::endsWith(style, "px") ) 1743 if ( style.startsWith("margin-top:" ) && QTextDocument::endsWith(style, "px") )
1764 curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok); 1744 curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok);
1765 else if ( style.startsWith("margin-bottom:" ) && QTextDocument::endsWith(style, "px") ) 1745 else if ( style.startsWith("margin-bottom:" ) && QTextDocument::endsWith(style, "px") )
1766 curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok); 1746 curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok);
1767 else if ( style.startsWith("margin-left:" ) && QTextDocument::endsWith(style, "px") ) 1747 else if ( style.startsWith("margin-left:" ) && QTextDocument::endsWith(style, "px") )
1768 curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok); 1748 curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok);
1769 else if ( style.startsWith("margin-right:" ) && QTextDocument::endsWith(style, "px") ) 1749 else if ( style.startsWith("margin-right:" ) && QTextDocument::endsWith(style, "px") )
1770 curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok); 1750 curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok);
1771 else if ( style.startsWith("text-indent:" ) && QTextDocument::endsWith(style, "px") ) 1751 else if ( style.startsWith("text-indent:" ) && QTextDocument::endsWith(style, "px") )
1772 curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok); 1752 curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok);
1773 } 1753 }
1774 if ( !ok ) // be pressmistic 1754 if ( !ok ) // be pressmistic
1775 curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0; 1755 curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0;
1776 } 1756 }
1777 } 1757 }
1778 } 1758 }
1779 } else { 1759 } else {
1780 QString tagname = parseCloseTag( doc, length, pos ); 1760 QString tagname = parseCloseTag( doc, length, pos );
1781 if ( tagname.isEmpty() ) 1761 if ( tagname.isEmpty() )
1782 continue; // nothing we could do with this, probably parse error 1762 continue; // nothing we could do with this, probably parse error
1783 if ( !sheet_->item( tagname ) ) // ignore unknown tags 1763 if ( !sheet_->item( tagname ) ) // ignore unknown tags
1784 continue; 1764 continue;
1785 1765
1786 // we close a block item. Since the text may continue, we need to have a new paragraph 1766 // we close a block item. Since the text may continue, we need to have a new paragraph
1787 bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock 1767 bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock
1788 || curtag.style->displayMode() == QStyleSheetItem::DisplayListItem; 1768 || curtag.style->displayMode() == QStyleSheetItem::DisplayListItem;
1789 1769
1790 1770
1791 // html slopiness: handle unbalanched tag closing 1771 // html slopiness: handle unbalanched tag closing
1792 while ( curtag.name != tagname ) { 1772 while ( curtag.name != tagname ) {
1793 QString msg; 1773 QString msg;
1794 msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)", 1774 msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)",
1795 curtag.name.ascii(), tagname.ascii(), pos); 1775 curtag.name.ascii(), tagname.ascii(), pos);
1796 sheet_->error( msg ); 1776 sheet_->error( msg );
1797 if ( tags.isEmpty() ) 1777 if ( tags.isEmpty() )
1798 break; 1778 break;
1799 curtag = tags.pop(); 1779 curtag = tags.pop();
1800 } 1780 }
1801 1781
1802 1782
1803 // close the tag 1783 // close the tag
1804 if ( !tags.isEmpty() ) 1784 if ( !tags.isEmpty() )
1805 curtag = tags.pop(); 1785 curtag = tags.pop();
1806 else 1786 else
1807 curtag = initag; 1787 curtag = initag;
1808 1788
1809 if ( needNewPar ) { 1789 if ( needNewPar ) {
1810 if ( textEditMode && tagname == "p" ) // preserve empty paragraphs 1790 if ( textEditMode && tagname == "p" ) // preserve empty paragraphs
1811 hasNewPar = FALSE; 1791 hasNewPar = FALSE;
1812 NEWPAR; 1792 NEWPAR;
1813 } 1793 }
1814 } 1794 }
1815 } else { 1795 } else {
1816 // normal contents 1796 // normal contents
1817 QString s; 1797 QString s;
1818 QChar c; 1798 QChar c;
1819 while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){ 1799 while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){
1820 if ( textEditMode ) { 1800 if ( textEditMode ) {
1821 // text edit mode: we handle all white space but ignore newlines 1801 // text edit mode: we handle all white space but ignore newlines
1822 c = parseChar( doc, length, pos, QStyleSheetItem::WhiteSpacePre ); 1802 c = parseChar( doc, length, pos, QStyleSheetItem::WhiteSpacePre );
1823 if ( c == QChar_linesep ) 1803 if ( c == QChar_linesep )
1824 break; 1804 break;
1825 } else { 1805 } else {
1826 int l = pos; 1806 int l = pos;
1827 c = parseChar( doc, length, pos, curtag.wsm ); 1807 c = parseChar( doc, length, pos, curtag.wsm );
1828 1808
1829 // in white space pre mode: treat any space as non breakable 1809 // in white space pre mode: treat any space as non breakable
1830 if ( c == ' ' && curtag.wsm == QStyleSheetItem::WhiteSpacePre ) 1810 if ( c == ' ' && curtag.wsm == QStyleSheetItem::WhiteSpacePre )
1831 c = QChar::nbsp; 1811 c = QChar::nbsp;
1832 1812
1833 if ( c == ' ' || c == QChar_linesep ) { 1813 if ( c == ' ' || c == QChar_linesep ) {
1834 /* avoid overlong paragraphs by forcing a new 1814 /* avoid overlong paragraphs by forcing a new
1835 paragraph after 4096 characters. This case can 1815 paragraph after 4096 characters. This case can
1836 occur when loading undiscovered plain text 1816 occur when loading undiscovered plain text
1837 documents in rich text mode. Instead of hanging 1817 documents in rich text mode. Instead of hanging
1838 forever, we do the trick. 1818 forever, we do the trick.
1839 */ 1819 */
1840 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do { 1820 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do {
1841 if ( doc[l] == '\n' ) { 1821 if ( doc[l] == '\n' ) {
1842 hasNewPar = FALSE; // for a new paragraph ... 1822 hasNewPar = FALSE; // for a new paragraph ...
1843 NEWPAR; 1823 NEWPAR;
1844 hasNewPar = FALSE; // ... and make it non-reusable 1824 hasNewPar = FALSE; // ... and make it non-reusable
1845 c = '\n'; // make sure we break below 1825 c = '\n'; // make sure we break below
1846 break; 1826 break;
1847 } 1827 }
1848 } while ( ++l < pos ); 1828 } while ( ++l < pos );
1849 } 1829 }
1850 } 1830 }
1851 1831
1852 if ( c == '\n' ) 1832 if ( c == '\n' )
1853 break; // break on newlines, pre delievers a QChar_linesep 1833 break; // break on newlines, pre delievers a QChar_linesep
1854 1834
1855 bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode; 1835 bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode;
1856 1836
1857 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space ) 1837 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space )
1858 continue; 1838 continue;
1859 if ( c == '\r' ) 1839 if ( c == '\r' )
1860 continue; 1840 continue;
1861 space = c_isSpace; 1841 space = c_isSpace;
1862 s += c; 1842 s += c;
1863 } 1843 }
1864 if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) { 1844 if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) {
1865 hasNewPar = FALSE; 1845 hasNewPar = FALSE;
1866 int index = QMAX( curpar->length(),1) - 1; 1846 int index = QMAX( curpar->length(),1) - 1;
1867 curpar->append( s ); 1847 curpar->append( s );
1868 QTextFormat* f = formatCollection()->format( &curtag.format ); 1848 QTextFormat* f = formatCollection()->format( &curtag.format );
1869 curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already 1849 curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already
1870 f->ref += s.length() -1; // that what friends are for... 1850 f->ref += s.length() -1; // that what friends are for...
1871 if ( !curtag.anchorHref.isEmpty() ) { 1851 if ( !curtag.anchorHref.isEmpty() ) {
1872 for ( int i = 0; i < int(s.length()); i++ ) 1852 for ( int i = 0; i < int(s.length()); i++ )
1873 curpar->at(index + i)->setAnchor( QString::null, curtag.anchorHref ); 1853 curpar->at(index + i)->setAnchor( QString::null, curtag.anchorHref );
1874 } 1854 }
1875 if ( !anchorName.isEmpty() ) { 1855 if ( !anchorName.isEmpty() ) {
1876 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); 1856 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
1877 anchorName = QString::null; 1857 anchorName = QString::null;
1878 } 1858 }
1879 } 1859 }
1880 } 1860 }
1881 } 1861 }
1882 if ( hasNewPar && curpar != fParag && !cursor ) { 1862 if ( hasNewPar && curpar != fParag && !cursor ) {
1883 // cleanup unused last paragraphs 1863 // cleanup unused last paragraphs
1884 curpar = curpar->p; 1864 curpar = curpar->p;
1885 delete curpar->n; 1865 delete curpar->n;
1886 } 1866 }
1887 if ( !anchorName.isEmpty() ) { 1867 if ( !anchorName.isEmpty() ) {
1888 curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() ); 1868 curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() );
1889 anchorName = QString::null; 1869 anchorName = QString::null;
1890 } 1870 }
1891 1871
1892 1872
1893 setRichTextMarginsInternal( styles, stylesPar ); 1873 setRichTextMarginsInternal( styles, stylesPar );
1894 1874
1895 if ( cursor ) { 1875 if ( cursor ) {
1896 cursor->gotoPreviousLetter(); 1876 cursor->gotoPreviousLetter();
1897 cursor->remove(); 1877 cursor->remove();
1898 } 1878 }
1899 1879
1900} 1880}
1901 1881
1902void QTextDocument::setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar ) 1882void QTextDocument::setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar )
1903{ 1883{
1904 // margin and line spacing calculation 1884 // margin and line spacing calculation
1905 QPtrVector<QStyleSheetItem>* prevStyle = 0; 1885 QPtrVector<QStyleSheetItem>* prevStyle = 0;
1906 QPtrVector<QStyleSheetItem>* curStyle = styles.first(); 1886 QPtrVector<QStyleSheetItem>* curStyle = styles.first();
1907 QPtrVector<QStyleSheetItem>* nextStyle = styles.next(); 1887 QPtrVector<QStyleSheetItem>* nextStyle = styles.next();
1908 while ( stylesPar ) { 1888 while ( stylesPar ) {
1909 if ( !curStyle ) { 1889 if ( !curStyle ) {
1910 stylesPar = stylesPar->next(); 1890 stylesPar = stylesPar->next();
1911 prevStyle = curStyle; 1891 prevStyle = curStyle;
1912 curStyle = nextStyle; 1892 curStyle = nextStyle;
1913 nextStyle = styles.next(); 1893 nextStyle = styles.next();
1914 continue; 1894 continue;
1915 } 1895 }
1916 1896
1917 int i, mar; 1897 int i, mar;
1918 QStyleSheetItem* mainStyle = (*curStyle)[curStyle->size()-1]; 1898 QStyleSheetItem* mainStyle = curStyle->size() ? (*curStyle)[curStyle->size()-1] : 0;
1919 if ( !mainStyle ) 1899 if ( mainStyle && mainStyle->displayMode() == QStyleSheetItem::DisplayListItem )
1920 return;
1921
1922 if ( mainStyle->displayMode() == QStyleSheetItem::DisplayListItem )
1923 stylesPar->setListItem( TRUE ); 1900 stylesPar->setListItem( TRUE );
1924 int numLists = 0; 1901 int numLists = 0;
1925 for ( i = 0; i < (int)curStyle->size(); ++i ) { 1902 for ( i = 0; i < (int)curStyle->size(); ++i ) {
1926 if ( (*curStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock 1903 if ( (*curStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock
1927 && int((*curStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) 1904 && int((*curStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined )
1928 numLists++; 1905 numLists++;
1929 } 1906 }
1930 stylesPar->ldepth = numLists; 1907 stylesPar->ldepth = numLists;
1931 if ( stylesPar->next() && nextStyle ) { 1908 if ( stylesPar->next() && nextStyle ) {
1932 // also set the depth of the next paragraph, required for the margin calculation 1909 // also set the depth of the next paragraph, required for the margin calculation
1933 numLists = 0; 1910 numLists = 0;
1934 for ( i = 0; i < (int)nextStyle->size(); ++i ) { 1911 for ( i = 0; i < (int)nextStyle->size(); ++i ) {
1935 if ( (*nextStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock 1912 if ( (*nextStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock
1936 && int((*nextStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined ) 1913 && int((*nextStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined )
1937 numLists++; 1914 numLists++;
1938 } 1915 }
1939 stylesPar->next()->ldepth = numLists; 1916 stylesPar->next()->ldepth = numLists;
1940 } 1917 }
1941 1918
1942 // do the top margin 1919 // do the top margin
1943 QStyleSheetItem* item = mainStyle; 1920 QStyleSheetItem* item = mainStyle;
1944 int m; 1921 int m;
1945 if (stylesPar->utm > 0 ) { 1922 if (stylesPar->utm > 0 ) {
1946 m = stylesPar->utm-1; 1923 m = stylesPar->utm-1;
1947 stylesPar->utm = 0; 1924 stylesPar->utm = 0;
1948 } else { 1925 } else {
1949 m = QMAX(0, item->margin( QStyleSheetItem::MarginTop ) ); 1926 m = QMAX(0, item->margin( QStyleSheetItem::MarginTop ) );
1950 if ( item->displayMode() == QStyleSheetItem::DisplayListItem 1927 if ( item->displayMode() == QStyleSheetItem::DisplayListItem
1951 && stylesPar->ldepth ) 1928 && stylesPar->ldepth )
1952 m /= stylesPar->ldepth; 1929 m /= stylesPar->ldepth;
1953 } 1930 }
1954 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 1931 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1955 item = (*curStyle)[ i ]; 1932 item = (*curStyle)[ i ];
1956 if ( prevStyle && i < (int) prevStyle->size() && 1933 if ( prevStyle && i < (int) prevStyle->size() &&
1957 ( item->displayMode() == QStyleSheetItem::DisplayBlock && 1934 ( item->displayMode() == QStyleSheetItem::DisplayBlock &&
1958 (*prevStyle)[ i ] == item ) ) 1935 (*prevStyle)[ i ] == item ) )
1959 break; 1936 break;
1960 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags 1937 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags
1961 if ( int(item->listStyle()) != QStyleSheetItem::Undefined && 1938 if ( int(item->listStyle()) != QStyleSheetItem::Undefined &&
1962 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) 1939 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) )
1963 continue; 1940 continue;
1964 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginTop ) ); 1941 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginTop ) );
1965 m = QMAX( m, mar ); 1942 m = QMAX( m, mar );
1966 } 1943 }
1967 stylesPar->utm = m - stylesPar->topMargin(); 1944 stylesPar->utm = m - stylesPar->topMargin();
1968 1945
1969 // do the bottom margin 1946 // do the bottom margin
1970 item = mainStyle; 1947 item = mainStyle;
1971 if (stylesPar->ubm > 0 ) { 1948 if (stylesPar->ubm > 0 ) {
1972 m = stylesPar->ubm-1; 1949 m = stylesPar->ubm-1;
1973 stylesPar->ubm = 0; 1950 stylesPar->ubm = 0;
1974 } else { 1951 } else {
1975 m = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); 1952 m = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) );
1976 if ( item->displayMode() == QStyleSheetItem::DisplayListItem 1953 if ( item->displayMode() == QStyleSheetItem::DisplayListItem
1977 && stylesPar->ldepth ) 1954 && stylesPar->ldepth )
1978 m /= stylesPar->ldepth; 1955 m /= stylesPar->ldepth;
1979 } 1956 }
1980 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 1957 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1981 item = (*curStyle)[ i ]; 1958 item = (*curStyle)[ i ];
1982 if ( nextStyle && i < (int) nextStyle->size() && 1959 if ( nextStyle && i < (int) nextStyle->size() &&
1983 ( item->displayMode() == QStyleSheetItem::DisplayBlock && 1960 ( item->displayMode() == QStyleSheetItem::DisplayBlock &&
1984 (*nextStyle)[ i ] == item ) ) 1961 (*nextStyle)[ i ] == item ) )
1985 break; 1962 break;
1986 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags 1963 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags
1987 if ( int(item->listStyle()) != QStyleSheetItem::Undefined && 1964 if ( int(item->listStyle()) != QStyleSheetItem::Undefined &&
1988 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) ) 1965 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) )
1989 continue; 1966 continue;
1990 mar = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) ); 1967 mar = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) );
1991 m = QMAX( m, mar ); 1968 m = QMAX( m, mar );
1992 } 1969 }
1993 stylesPar->ubm = m - stylesPar->bottomMargin(); 1970 stylesPar->ubm = m - stylesPar->bottomMargin();
1994 1971
1995 // do the left margin, simplyfied 1972 // do the left margin, simplyfied
1996 item = mainStyle; 1973 item = mainStyle;
1997 if (stylesPar->ulm > 0 ) { 1974 if (stylesPar->ulm > 0 ) {
1998 m = stylesPar->ulm-1; 1975 m = stylesPar->ulm-1;
1999 stylesPar->ulm = 0; 1976 stylesPar->ulm = 0;
2000 } else { 1977 } else {
2001 m = QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); 1978 m = QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) );
2002 } 1979 }
2003 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 1980 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
2004 item = (*curStyle)[ i ]; 1981 item = (*curStyle)[ i ];
2005 m += QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) ); 1982 m += QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) );
2006 } 1983 }
2007 stylesPar->ulm = m - stylesPar->leftMargin(); 1984 stylesPar->ulm = m - stylesPar->leftMargin();
2008 1985
2009 // do the right margin, simplyfied 1986 // do the right margin, simplyfied
2010 item = mainStyle; 1987 item = mainStyle;
2011 if (stylesPar->urm > 0 ) { 1988 if (stylesPar->urm > 0 ) {
2012 m = stylesPar->urm-1; 1989 m = stylesPar->urm-1;
2013 stylesPar->urm = 0; 1990 stylesPar->urm = 0;
2014 } else { 1991 } else {
2015 m = QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); 1992 m = QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) );
2016 } 1993 }
2017 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 1994 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
2018 item = (*curStyle)[ i ]; 1995 item = (*curStyle)[ i ];
2019 m += QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) ); 1996 m += QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) );
2020 } 1997 }
2021 stylesPar->urm = m - stylesPar->rightMargin(); 1998 stylesPar->urm = m - stylesPar->rightMargin();
2022 1999
2023 // do the first line margin, which really should be called text-indent 2000 // do the first line margin, which really should be called text-indent
2024 item = mainStyle; 2001 item = mainStyle;
2025 if (stylesPar->uflm > 0 ) { 2002 if (stylesPar->uflm > 0 ) {
2026 m = stylesPar->uflm-1; 2003 m = stylesPar->uflm-1;
2027 stylesPar->uflm = 0; 2004 stylesPar->uflm = 0;
2028 } else { 2005 } else {
2029 m = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); 2006 m = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) );
2030 } 2007 }
2031 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) { 2008 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
2032 item = (*curStyle)[ i ]; 2009 item = (*curStyle)[ i ];
2033 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) ); 2010 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) );
2034 m = QMAX( m, mar ); 2011 m = QMAX( m, mar );
2035 } 2012 }
2036 stylesPar->uflm =m - stylesPar->firstLineMargin(); 2013 stylesPar->uflm =m - stylesPar->firstLineMargin();
2037 2014
2038 // do the bogus line "spacing", which really is just an extra margin 2015 // do the bogus line "spacing", which really is just an extra margin
2039 item = mainStyle; 2016 item = mainStyle;
2040 for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) { 2017 for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) {
2041 item = (*curStyle)[ i ]; 2018 item = (*curStyle)[ i ];
2042 if ( item->lineSpacing() != QStyleSheetItem::Undefined ) { 2019 if ( item->lineSpacing() != QStyleSheetItem::Undefined ) {
2043 stylesPar->ulinespacing = item->lineSpacing(); 2020 stylesPar->ulinespacing = item->lineSpacing();
2044 if ( formatCollection() && 2021 if ( formatCollection() &&
2045 stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() ) 2022 stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() )
2046 stylesPar->ulinespacing += formatCollection()->defaultFormat()->height(); 2023 stylesPar->ulinespacing += formatCollection()->defaultFormat()->height();
2047 break; 2024 break;
2048 } 2025 }
2049 } 2026 }
2050 2027
2051 stylesPar = stylesPar->next(); 2028 stylesPar = stylesPar->next();
2052 prevStyle = curStyle; 2029 prevStyle = curStyle;
2053 curStyle = nextStyle; 2030 curStyle = nextStyle;
2054 nextStyle = styles.next(); 2031 nextStyle = styles.next();
2055 } 2032 }
2056} 2033}
2057 2034
2058void QTextDocument::setText( const QString &text, const QString &context ) 2035void QTextDocument::setText( const QString &text, const QString &context )
2059{ 2036{
2060 focusIndicator.parag = 0; 2037 focusIndicator.parag = 0;
2061 selections.clear(); 2038 selections.clear();
2062 if ( txtFormat == Qt::AutoText && QStyleSheet::mightBeRichText( text ) || 2039 if ( txtFormat == Qt::AutoText && QStyleSheet::mightBeRichText( text ) ||
2063 txtFormat == Qt::RichText ) 2040 txtFormat == Qt::RichText )
2064 setRichText( text, context ); 2041 setRichText( text, context );
2065 else 2042 else
2066 setPlainText( text ); 2043 setPlainText( text );
2067} 2044}
2068 2045
2069QString QTextDocument::plainText() const 2046QString QTextDocument::plainText() const
2070{ 2047{
2071 QString buffer; 2048 QString buffer;
2072 QString s; 2049 QString s;
2073 QTextParagraph *p = fParag; 2050 QTextParagraph *p = fParag;
2074 while ( p ) { 2051 while ( p ) {
2075 if ( !p->mightHaveCustomItems ) { 2052 if ( !p->mightHaveCustomItems ) {
2076 s = p->string()->toString(); 2053 s = p->string()->toString();
2077 } else { 2054 } else {
2078 for ( int i = 0; i < p->length() - 1; ++i ) { 2055 for ( int i = 0; i < p->length() - 1; ++i ) {
2079 if ( p->at( i )->isCustom() ) { 2056 if ( p->at( i )->isCustom() ) {
2080 if ( p->at( i )->customItem()->isNested() ) { 2057 if ( p->at( i )->customItem()->isNested() ) {
2081 s += "\n"; 2058 s += "\n";
2082 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2059 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2083 QPtrList<QTextTableCell> cells = t->tableCells(); 2060 QPtrList<QTextTableCell> cells = t->tableCells();
2084 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2061 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2085 s += c->richText()->plainText() + "\n"; 2062 s += c->richText()->plainText() + "\n";
2086 s += "\n"; 2063 s += "\n";
2087 } 2064 }
2088 } else { 2065 } else {
2089 s += p->at( i )->c; 2066 s += p->at( i )->c;
2090 } 2067 }
2091 } 2068 }
2092 } 2069 }
2093 s.remove( s.length() - 1, 1 ); 2070 s.remove( s.length() - 1, 1 );
2094 if ( p->next() ) 2071 if ( p->next() )
2095 s += "\n"; 2072 s += "\n";
2096 buffer += s; 2073 buffer += s;
2097 p = p->next(); 2074 p = p->next();
2098 } 2075 }
2099 return buffer; 2076 return buffer;
2100} 2077}
2101 2078
2102static QString align_to_string( int a ) 2079static QString align_to_string( int a )
2103{ 2080{
2104 if ( a & Qt::AlignRight ) 2081 if ( a & Qt::AlignRight )
2105 return " align=\"right\""; 2082 return " align=\"right\"";
2106 if ( a & Qt::AlignHCenter ) 2083 if ( a & Qt::AlignHCenter )
2107 return " align=\"center\""; 2084 return " align=\"center\"";
2108 if ( a & Qt3::AlignJustify ) 2085 if ( a & Qt3::AlignJustify )
2109 return " align=\"justify\""; 2086 return " align=\"justify\"";
2110 return QString::null; 2087 return QString::null;
2111} 2088}
2112 2089
2113static QString direction_to_string( int d ) 2090static QString direction_to_string( int d )
2114{ 2091{
2115 if ( d != QChar::DirON ) 2092 if ( d != QChar::DirON )
2116 return ( d == QChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" ); 2093 return ( d == QChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" );
2117 return QString::null; 2094 return QString::null;
2118} 2095}
2119 2096
2120static QString list_value_to_string( int v ) 2097static QString list_value_to_string( int v )
2121{ 2098{
2122 if ( v != -1 ) 2099 if ( v != -1 )
2123 return " listvalue=\"" + QString::number( v ) + "\""; 2100 return " listvalue=\"" + QString::number( v ) + "\"";
2124 return QString::null; 2101 return QString::null;
2125} 2102}
2126 2103
2127static QString list_style_to_string( int v ) 2104static QString list_style_to_string( int v )
2128{ 2105{
2129 switch( v ) { 2106 switch( v ) {
2130 case QStyleSheetItem::ListDecimal: return "\"1\""; 2107 case QStyleSheetItem::ListDecimal: return "\"1\"";
2131 case QStyleSheetItem::ListLowerAlpha: return "\"a\""; 2108 case QStyleSheetItem::ListLowerAlpha: return "\"a\"";
2132 case QStyleSheetItem::ListUpperAlpha: return "\"A\""; 2109 case QStyleSheetItem::ListUpperAlpha: return "\"A\"";
2133 case QStyleSheetItem::ListDisc: return "\"disc\""; 2110 case QStyleSheetItem::ListDisc: return "\"disc\"";
2134 case QStyleSheetItem::ListSquare: return "\"square\""; 2111 case QStyleSheetItem::ListSquare: return "\"square\"";
2135 case QStyleSheetItem::ListCircle: return "\"circle\""; 2112 case QStyleSheetItem::ListCircle: return "\"circle\"";
2136 default: 2113 default:
2137 return QString::null; 2114 return QString::null;
2138 } 2115 }
2139} 2116}
2140 2117
2141static inline bool list_is_ordered( int v ) 2118static inline bool list_is_ordered( int v )
2142{ 2119{
2143 return v == QStyleSheetItem::ListDecimal || 2120 return v == QStyleSheetItem::ListDecimal ||
2144 v == QStyleSheetItem::ListLowerAlpha || 2121 v == QStyleSheetItem::ListLowerAlpha ||
2145 v == QStyleSheetItem::ListUpperAlpha; 2122 v == QStyleSheetItem::ListUpperAlpha;
2146} 2123}
2147 2124
2148 2125
2149static QString margin_to_string( QStyleSheetItem* style, int t, int b, int l, int r, int fl ) 2126static QString margin_to_string( QStyleSheetItem* style, int t, int b, int l, int r, int fl )
2150{ 2127{
2151 QString s; 2128 QString s;
2152 if ( l > 0 ) 2129 if ( l > 0 )
2153 s += QString(!!s?";":"") + "margin-left:" + QString::number(l+QMAX(0,style->margin(QStyleSheetItem::MarginLeft))) + "px"; 2130 s += QString(!!s?";":"") + "margin-left:" + QString::number(l+QMAX(0,style->margin(QStyleSheetItem::MarginLeft))) + "px";
2154 if ( r > 0 ) 2131 if ( r > 0 )
2155 s += QString(!!s?";":"") + "margin-right:" + QString::number(r+QMAX(0,style->margin(QStyleSheetItem::MarginRight))) + "px"; 2132 s += QString(!!s?";":"") + "margin-right:" + QString::number(r+QMAX(0,style->margin(QStyleSheetItem::MarginRight))) + "px";
2156 if ( t > 0 ) 2133 if ( t > 0 )
2157 s += QString(!!s?";":"") + "margin-top:" + QString::number(t+QMAX(0,style->margin(QStyleSheetItem::MarginTop))) + "px"; 2134 s += QString(!!s?";":"") + "margin-top:" + QString::number(t+QMAX(0,style->margin(QStyleSheetItem::MarginTop))) + "px";
2158 if ( b > 0 ) 2135 if ( b > 0 )
2159 s += QString(!!s?";":"") + "margin-bottom:" + QString::number(b+QMAX(0,style->margin(QStyleSheetItem::MarginBottom))) + "px"; 2136 s += QString(!!s?";":"") + "margin-bottom:" + QString::number(b+QMAX(0,style->margin(QStyleSheetItem::MarginBottom))) + "px";
2160 if ( fl > 0 ) 2137 if ( fl > 0 )
2161 s += QString(!!s?";":"") + "text-indent:" + QString::number(fl+QMAX(0,style->margin(QStyleSheetItem::MarginFirstLine))) + "px"; 2138 s += QString(!!s?";":"") + "text-indent:" + QString::number(fl+QMAX(0,style->margin(QStyleSheetItem::MarginFirstLine))) + "px";
2162 if ( !!s ) 2139 if ( !!s )
2163 return " style=\"" + s + "\""; 2140 return " style=\"" + s + "\"";
2164 return QString::null; 2141 return QString::null;
2165} 2142}
2166 2143
2167QString QTextDocument::richText() const 2144QString QTextDocument::richText() const
2168{ 2145{
2169 QString s = ""; 2146 QString s = "";
2170 if ( !par ) { 2147 if ( !par ) {
2171 s += "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\"font-size:" ; 2148 s += "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\"font-size:" ;
2172 s += QString::number( formatCollection()->defaultFormat()->font().pointSize() ); 2149 s += QString::number( formatCollection()->defaultFormat()->font().pointSize() );
2173 s += "pt;font-family:"; 2150 s += "pt;font-family:";
2174 s += formatCollection()->defaultFormat()->font().family(); 2151 s += formatCollection()->defaultFormat()->font().family();
2175 s +="\">"; 2152 s +="\">";
2176 } 2153 }
2177 QTextParagraph* p = fParag; 2154 QTextParagraph* p = fParag;
2178 2155
2179 QStyleSheetItem* item_p = styleSheet()->item("p"); 2156 QStyleSheetItem* item_p = styleSheet()->item("p");
2180 QStyleSheetItem* item_ul = styleSheet()->item("ul"); 2157 QStyleSheetItem* item_ul = styleSheet()->item("ul");
2181 QStyleSheetItem* item_ol = styleSheet()->item("ol"); 2158 QStyleSheetItem* item_ol = styleSheet()->item("ol");
2182 QStyleSheetItem* item_li = styleSheet()->item("li"); 2159 QStyleSheetItem* item_li = styleSheet()->item("li");
2183 if ( !item_p || !item_ul || !item_ol || !item_li ) { 2160 if ( !item_p || !item_ul || !item_ol || !item_li ) {
2184 owarn << "QTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, ul, ol, or li)" << oendl; 2161 owarn << "QTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, ul, ol, or li)" << oendl;
2185 return QString::null; 2162 return QString::null;
2186 } 2163 }
2187 int pastListDepth = 0; 2164 int pastListDepth = 0;
2188 int listDepth = 0; 2165 int listDepth = 0;
2189 int futureListDepth = 0; 2166 int futureListDepth = 0;
2190 QMemArray<int> listStyles(10); 2167 QMemArray<int> listStyles(10);
2191 2168
2192 while ( p ) { 2169 while ( p ) {
2193 listDepth = p->listDepth(); 2170 listDepth = p->listDepth();
2194 if ( listDepth < pastListDepth ) { 2171 if ( listDepth < pastListDepth ) {
2195 for ( int i = listDepth+1; i <= pastListDepth; i++ ) 2172 for ( int i = listDepth+1; i <= pastListDepth; i++ )
2196 s += list_is_ordered( listStyles[i] ) ? "</ol>" : "</ul>"; 2173 s += list_is_ordered( listStyles[i] ) ? "</ol>" : "</ul>";
2197 s += '\n'; 2174 s += '\n';
2198 } else if ( listDepth > pastListDepth ) { 2175 } else if ( listDepth > pastListDepth ) {
2199 s += '\n'; 2176 s += '\n';
2200 listStyles.resize( QMAX( (int)listStyles.size(), listDepth+1 ) ); 2177 listStyles.resize( QMAX( (int)listStyles.size(), listDepth+1 ) );
2201 QString list_type; 2178 QString list_type;
2202 listStyles[listDepth] = p->listStyle(); 2179 listStyles[listDepth] = p->listStyle();
2203 if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() ) 2180 if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() )
2204 list_type = " type=" + list_style_to_string( p->listStyle() ); 2181 list_type = " type=" + list_style_to_string( p->listStyle() );
2205 for ( int i = pastListDepth; i < listDepth; i++ ) { 2182 for ( int i = pastListDepth; i < listDepth; i++ ) {
2206 s += list_is_ordered( p->listStyle() ) ? "<ol" : "<ul" ; 2183 s += list_is_ordered( p->listStyle() ) ? "<ol" : "<ul" ;
2207 s += list_type + ">"; 2184 s += list_type + ">";
2208 } 2185 }
2209 } else { 2186 } else {
2210 s += '\n'; 2187 s += '\n';
2211 } 2188 }
2212 2189
2213 QString ps = p->richText(); 2190 QString ps = p->richText();
2214 2191
2215 // for the bottom margin we need to know whether we are at the end of a list 2192 // for the bottom margin we need to know whether we are at the end of a list
2216 futureListDepth = 0; 2193 futureListDepth = 0;
2217 if ( listDepth > 0 && p->next() ) 2194 if ( listDepth > 0 && p->next() )
2218 futureListDepth = p->next()->listDepth(); 2195 futureListDepth = p->next()->listDepth();
2219 2196
2220 if ( richTextExportStart && richTextExportStart->paragraph() ==p && 2197 if ( richTextExportStart && richTextExportStart->paragraph() ==p &&
2221 richTextExportStart->index() == 0 ) 2198 richTextExportStart->index() == 0 )
2222 s += "<selstart/>"; 2199 s += "<selstart/>";
2223 2200
2224 if ( p->isListItem() ) { 2201 if ( p->isListItem() ) {
2225 s += "<li"; 2202 s += "<li";
2226 if ( p->listStyle() != listStyles[listDepth] ) 2203 if ( p->listStyle() != listStyles[listDepth] )
2227 s += " type=" + list_style_to_string( p->listStyle() ); 2204 s += " type=" + list_style_to_string( p->listStyle() );
2228 s +=align_to_string( p->alignment() ); 2205 s +=align_to_string( p->alignment() );
2229 s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); 2206 s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm );
2230 s += list_value_to_string( p->listValue() ); 2207 s += list_value_to_string( p->listValue() );
2231 s += direction_to_string( p->direction() ); 2208 s += direction_to_string( p->direction() );
2232 s +=">"; 2209 s +=">";
2233 s += ps; 2210 s += ps;
2234 s += "</li>"; 2211 s += "</li>";
2235 } else { 2212 } else {
2236 // normal paragraph item 2213 // normal paragraph item
2237 s += "<p"; 2214 s += "<p";
2238 s += align_to_string( p->alignment() ); 2215 s += align_to_string( p->alignment() );
2239 s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm ); 2216 s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm );
2240 s +=direction_to_string( p->direction() ); 2217 s +=direction_to_string( p->direction() );
2241 s += ">"; 2218 s += ">";
2242 s += ps; 2219 s += ps;
2243 s += "</p>"; 2220 s += "</p>";
2244 } 2221 }
2245 pastListDepth = listDepth; 2222 pastListDepth = listDepth;
2246 p = p->next(); 2223 p = p->next();
2247 } 2224 }
2248 while ( listDepth > 0 ) { 2225 while ( listDepth > 0 ) {
2249 s += list_is_ordered( listStyles[listDepth] ) ? "</ol>" : "</ul>"; 2226 s += list_is_ordered( listStyles[listDepth] ) ? "</ol>" : "</ul>";
2250 listDepth--; 2227 listDepth--;
2251 } 2228 }
2252 2229
2253 if ( !par ) 2230 if ( !par )
2254 s += "\n</body></html>\n"; 2231 s += "\n</body></html>\n";
2255 2232
2256 return s; 2233 return s;
2257} 2234}
2258 2235
2259QString QTextDocument::text() const 2236QString QTextDocument::text() const
2260{ 2237{
2261 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) 2238 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText )
2262 return richText(); 2239 return richText();
2263 return plainText(); 2240 return plainText();
2264} 2241}
2265 2242
2266QString QTextDocument::text( int parag ) const 2243QString QTextDocument::text( int parag ) const
2267{ 2244{
2268 QTextParagraph *p = paragAt( parag ); 2245 QTextParagraph *p = paragAt( parag );
2269 if ( !p ) 2246 if ( !p )
2270 return QString::null; 2247 return QString::null;
2271 2248
2272 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) 2249 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText )
2273 return p->richText(); 2250 return p->richText();
2274 else 2251 else
2275 return p->string()->toString(); 2252 return p->string()->toString();
2276} 2253}
2277 2254
2278void QTextDocument::invalidate() 2255void QTextDocument::invalidate()
2279{ 2256{
2280 QTextParagraph *s = fParag; 2257 QTextParagraph *s = fParag;
2281 while ( s ) { 2258 while ( s ) {
2282 s->invalidate( 0 ); 2259 s->invalidate( 0 );
2283 s = s->next(); 2260 s = s->next();
2284 } 2261 }
2285} 2262}
2286 2263
2287void QTextDocument::selectionStart( int id, int &paragId, int &index ) 2264void QTextDocument::selectionStart( int id, int &paragId, int &index )
2288{ 2265{
2289 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2266 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2290 if ( it == selections.end() ) 2267 if ( it == selections.end() )
2291 return; 2268 return;
2292 QTextDocumentSelection &sel = *it; 2269 QTextDocumentSelection &sel = *it;
2293 paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); 2270 paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId();
2294 index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); 2271 index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index();
2295} 2272}
2296 2273
2297QTextCursor QTextDocument::selectionStartCursor( int id) 2274QTextCursor QTextDocument::selectionStartCursor( int id)
2298{ 2275{
2299 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2276 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2300 if ( it == selections.end() ) 2277 if ( it == selections.end() )
2301 return QTextCursor( this ); 2278 return QTextCursor( this );
2302 QTextDocumentSelection &sel = *it; 2279 QTextDocumentSelection &sel = *it;
2303 if ( sel.swapped ) 2280 if ( sel.swapped )
2304 return sel.endCursor; 2281 return sel.endCursor;
2305 return sel.startCursor; 2282 return sel.startCursor;
2306} 2283}
2307 2284
2308QTextCursor QTextDocument::selectionEndCursor( int id) 2285QTextCursor QTextDocument::selectionEndCursor( int id)
2309{ 2286{
2310 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2287 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2311 if ( it == selections.end() ) 2288 if ( it == selections.end() )
2312 return QTextCursor( this ); 2289 return QTextCursor( this );
2313 QTextDocumentSelection &sel = *it; 2290 QTextDocumentSelection &sel = *it;
2314 if ( !sel.swapped ) 2291 if ( !sel.swapped )
2315 return sel.endCursor; 2292 return sel.endCursor;
2316 return sel.startCursor; 2293 return sel.startCursor;
2317} 2294}
2318 2295
2319void QTextDocument::selectionEnd( int id, int &paragId, int &index ) 2296void QTextDocument::selectionEnd( int id, int &paragId, int &index )
2320{ 2297{
2321 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2298 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2322 if ( it == selections.end() ) 2299 if ( it == selections.end() )
2323 return; 2300 return;
2324 QTextDocumentSelection &sel = *it; 2301 QTextDocumentSelection &sel = *it;
2325 paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId(); 2302 paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId();
2326 index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); 2303 index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index();
2327} 2304}
2328 2305
2329void QTextDocument::addSelection( int id ) 2306void QTextDocument::addSelection( int id )
2330{ 2307{
2331 nSelections = QMAX( nSelections, id + 1 ); 2308 nSelections = QMAX( nSelections, id + 1 );
2332} 2309}
2333 2310
2334static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCursor &start, QTextCursor &end ) 2311static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCursor &start, QTextCursor &end )
2335{ 2312{
2336 QTextCursor c1 = start; 2313 QTextCursor c1 = start;
2337 QTextCursor c2 = end; 2314 QTextCursor c2 = end;
2338 if ( sel.swapped ) { 2315 if ( sel.swapped ) {
2339 c1 = end; 2316 c1 = end;
2340 c2 = start; 2317 c2 = start;
2341 } 2318 }
2342 2319
2343 c1.paragraph()->removeSelection( id ); 2320 c1.paragraph()->removeSelection( id );
2344 c2.paragraph()->removeSelection( id ); 2321 c2.paragraph()->removeSelection( id );
2345 if ( c1.paragraph() != c2.paragraph() ) { 2322 if ( c1.paragraph() != c2.paragraph() ) {
2346 c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 ); 2323 c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 );
2347 c2.paragraph()->setSelection( id, 0, c2.index() ); 2324 c2.paragraph()->setSelection( id, 0, c2.index() );
2348 } else { 2325 } else {
2349 c1.paragraph()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) ); 2326 c1.paragraph()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) );
2350 } 2327 }
2351 2328
2352 sel.startCursor = start; 2329 sel.startCursor = start;
2353 sel.endCursor = end; 2330 sel.endCursor = end;
2354 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) 2331 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() )
2355 sel.swapped = sel.startCursor.index() > sel.endCursor.index(); 2332 sel.swapped = sel.startCursor.index() > sel.endCursor.index();
2356} 2333}
2357 2334
2358bool QTextDocument::setSelectionEnd( int id, const QTextCursor &cursor ) 2335bool QTextDocument::setSelectionEnd( int id, const QTextCursor &cursor )
2359{ 2336{
2360 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2337 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2361 if ( it == selections.end() ) 2338 if ( it == selections.end() )
2362 return FALSE; 2339 return FALSE;
2363 QTextDocumentSelection &sel = *it; 2340 QTextDocumentSelection &sel = *it;
2364 2341
2365 QTextCursor start = sel.startCursor; 2342 QTextCursor start = sel.startCursor;
2366 QTextCursor end = cursor; 2343 QTextCursor end = cursor;
2367 2344
2368 if ( start == end ) { 2345 if ( start == end ) {
2369 removeSelection( id ); 2346 removeSelection( id );
2370 setSelectionStart( id, cursor ); 2347 setSelectionStart( id, cursor );
2371 return TRUE; 2348 return TRUE;
2372 } 2349 }
2373 2350
2374 if ( sel.endCursor.paragraph() == end.paragraph() ) { 2351 if ( sel.endCursor.paragraph() == end.paragraph() ) {
2375 setSelectionEndHelper( id, sel, start, end ); 2352 setSelectionEndHelper( id, sel, start, end );
2376 return TRUE; 2353 return TRUE;
2377 } 2354 }
2378 2355
2379 bool inSelection = FALSE; 2356 bool inSelection = FALSE;
2380 QTextCursor c( this ); 2357 QTextCursor c( this );
2381 QTextCursor tmp = sel.startCursor; 2358 QTextCursor tmp = sel.startCursor;
2382 if ( sel.swapped ) 2359 if ( sel.swapped )
2383 tmp = sel.endCursor; 2360 tmp = sel.endCursor;
2384 tmp.restoreState(); 2361 tmp.restoreState();
2385 QTextCursor tmp2 = cursor; 2362 QTextCursor tmp2 = cursor;
2386 tmp2.restoreState(); 2363 tmp2.restoreState();
2387 c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() ); 2364 c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() );
2388 bool hadStart = FALSE; 2365 bool hadStart = FALSE;
2389 bool hadEnd = FALSE; 2366 bool hadEnd = FALSE;
2390 bool hadStartParag = FALSE; 2367 bool hadStartParag = FALSE;
2391 bool hadEndParag = FALSE; 2368 bool hadEndParag = FALSE;
2392 bool hadOldStart = FALSE; 2369 bool hadOldStart = FALSE;
2393 bool hadOldEnd = FALSE; 2370 bool hadOldEnd = FALSE;
2394 bool leftSelection = FALSE; 2371 bool leftSelection = FALSE;
2395 sel.swapped = FALSE; 2372 sel.swapped = FALSE;
2396 for ( ;; ) { 2373 for ( ;; ) {
2397 if ( c == start ) 2374 if ( c == start )
2398 hadStart = TRUE; 2375 hadStart = TRUE;
2399 if ( c == end ) 2376 if ( c == end )
2400 hadEnd = TRUE; 2377 hadEnd = TRUE;
2401 if ( c.paragraph() == start.paragraph() ) 2378 if ( c.paragraph() == start.paragraph() )
2402 hadStartParag = TRUE; 2379 hadStartParag = TRUE;
2403 if ( c.paragraph() == end.paragraph() ) 2380 if ( c.paragraph() == end.paragraph() )
2404 hadEndParag = TRUE; 2381 hadEndParag = TRUE;
2405 if ( c == sel.startCursor ) 2382 if ( c == sel.startCursor )
2406 hadOldStart = TRUE; 2383 hadOldStart = TRUE;
2407 if ( c == sel.endCursor ) 2384 if ( c == sel.endCursor )
2408 hadOldEnd = TRUE; 2385 hadOldEnd = TRUE;
2409 2386
2410 if ( !sel.swapped && 2387 if ( !sel.swapped &&
2411 ( hadEnd && !hadStart || 2388 ( hadEnd && !hadStart ||
2412 hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) ) 2389 hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) )
2413 sel.swapped = TRUE; 2390 sel.swapped = TRUE;
2414 2391
2415 if ( c == end && hadStartParag || 2392 if ( c == end && hadStartParag ||
2416 c == start && hadEndParag ) { 2393 c == start && hadEndParag ) {
2417 QTextCursor tmp = c; 2394 QTextCursor tmp = c;
2418 tmp.restoreState(); 2395 tmp.restoreState();
2419 if ( tmp.paragraph() != c.paragraph() ) { 2396 if ( tmp.paragraph() != c.paragraph() ) {
2420 int sstart = tmp.paragraph()->selectionStart( id ); 2397 int sstart = tmp.paragraph()->selectionStart( id );
2421 tmp.paragraph()->removeSelection( id ); 2398 tmp.paragraph()->removeSelection( id );
2422 tmp.paragraph()->setSelection( id, sstart, tmp.index() ); 2399 tmp.paragraph()->setSelection( id, sstart, tmp.index() );
2423 } 2400 }
2424 } 2401 }
2425 2402
2426 if ( inSelection && 2403 if ( inSelection &&
2427 ( c == end && hadStart || c == start && hadEnd ) ) 2404 ( c == end && hadStart || c == start && hadEnd ) )
2428 leftSelection = TRUE; 2405 leftSelection = TRUE;
2429 else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) ) 2406 else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) )
2430 inSelection = TRUE; 2407 inSelection = TRUE;
2431 2408
2432 bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd(); 2409 bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd();
2433 c.paragraph()->removeSelection( id ); 2410 c.paragraph()->removeSelection( id );
2434 if ( inSelection ) { 2411 if ( inSelection ) {
2435 if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) { 2412 if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) {
2436 c.paragraph()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) ); 2413 c.paragraph()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) );
2437 } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) { 2414 } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) {
2438 c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 ); 2415 c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 );
2439 } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) { 2416 } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) {
2440 c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 ); 2417 c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 );
2441 } else if ( c.paragraph() == end.paragraph() && hadEndParag ) { 2418 } else if ( c.paragraph() == end.paragraph() && hadEndParag ) {
2442 c.paragraph()->setSelection( id, 0, end.index() ); 2419 c.paragraph()->setSelection( id, 0, end.index() );
2443 } else if ( c.paragraph() == start.paragraph() && hadStartParag ) { 2420 } else if ( c.paragraph() == start.paragraph() && hadStartParag ) {
2444 c.paragraph()->setSelection( id, 0, start.index() ); 2421 c.paragraph()->setSelection( id, 0, start.index() );
2445 } else { 2422 } else {
2446 c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 ); 2423 c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 );
2447 } 2424 }
2448 } 2425 }
2449 2426
2450 if ( leftSelection ) 2427 if ( leftSelection )
2451 inSelection = FALSE; 2428 inSelection = FALSE;
2452 2429
2453 if ( noSelectionAnymore ) 2430 if ( noSelectionAnymore )
2454 break; 2431 break;
2455 // *ugle*hack optimization 2432 // *ugle*hack optimization
2456 QTextParagraph *p = c.paragraph(); 2433 QTextParagraph *p = c.paragraph();
2457 if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) { 2434 if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) {
2458 c.gotoNextLetter(); 2435 c.gotoNextLetter();
2459 if ( p == lastParagraph() && c.atParagEnd() ) 2436 if ( p == lastParagraph() && c.atParagEnd() )
2460 break; 2437 break;
2461 } else { 2438 } else {
2462 if ( p->document()->parent() ) 2439 if ( p->document()->parent() )
2463 do { 2440 do {
2464 c.gotoNextLetter(); 2441 c.gotoNextLetter();
2465 } while ( c.paragraph() == p ); 2442 } while ( c.paragraph() == p );
2466 else 2443 else
2467 c.setParagraph( p->next() ); 2444 c.setParagraph( p->next() );
2468 } 2445 }
2469 } 2446 }
2470 2447
2471 if ( !sel.swapped ) 2448 if ( !sel.swapped )
2472 sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 ); 2449 sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 );
2473 2450
2474 sel.startCursor = start; 2451 sel.startCursor = start;
2475 sel.endCursor = end; 2452 sel.endCursor = end;
2476 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() ) 2453 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() )
2477 sel.swapped = sel.startCursor.index() > sel.endCursor.index(); 2454 sel.swapped = sel.startCursor.index() > sel.endCursor.index();
2478 2455
2479 setSelectionEndHelper( id, sel, start, end ); 2456 setSelectionEndHelper( id, sel, start, end );
2480 2457
2481 return TRUE; 2458 return TRUE;
2482} 2459}
2483 2460
2484void QTextDocument::selectAll( int id ) 2461void QTextDocument::selectAll( int id )
2485{ 2462{
2486 removeSelection( id ); 2463 removeSelection( id );
2487 2464
2488 QTextDocumentSelection sel; 2465 QTextDocumentSelection sel;
2489 sel.swapped = FALSE; 2466 sel.swapped = FALSE;
2490 QTextCursor c( this ); 2467 QTextCursor c( this );
2491 2468
2492 c.setParagraph( fParag ); 2469 c.setParagraph( fParag );
2493 c.setIndex( 0 ); 2470 c.setIndex( 0 );
2494 sel.startCursor = c; 2471 sel.startCursor = c;
2495 2472
2496 c.setParagraph( lParag ); 2473 c.setParagraph( lParag );
2497 c.setIndex( lParag->length() - 1 ); 2474 c.setIndex( lParag->length() - 1 );
2498 sel.endCursor = c; 2475 sel.endCursor = c;
2499 2476
2500 selections.insert( id, sel ); 2477 selections.insert( id, sel );
2501 2478
2502 QTextParagraph *p = fParag; 2479 QTextParagraph *p = fParag;
2503 while ( p ) { 2480 while ( p ) {
2504 p->setSelection( id, 0, p->length() - 1 ); 2481 p->setSelection( id, 0, p->length() - 1 );
2505 p = p->next(); 2482 p = p->next();
2506 } 2483 }
2507 2484
2508 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 2485 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
2509 d->selectAll( id ); 2486 d->selectAll( id );
2510} 2487}
2511 2488
2512bool QTextDocument::removeSelection( int id ) 2489bool QTextDocument::removeSelection( int id )
2513{ 2490{
2514 if ( !selections.contains( id ) ) 2491 if ( !selections.contains( id ) )
2515 return FALSE; 2492 return FALSE;
2516 2493
2517 QTextDocumentSelection &sel = selections[ id ]; 2494 QTextDocumentSelection &sel = selections[ id ];
2518 2495
2519 QTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor; 2496 QTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor;
2520 QTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor; 2497 QTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor;
2521 QTextParagraph* p = 0; 2498 QTextParagraph* p = 0;
2522 while ( start != end ) { 2499 while ( start != end ) {
2523 if ( p != start.paragraph() ) { 2500 if ( p != start.paragraph() ) {
2524 p = start.paragraph(); 2501 p = start.paragraph();
2525 p->removeSelection( id ); 2502 p->removeSelection( id );
2526 } 2503 }
2527 start.gotoNextLetter(); 2504 start.gotoNextLetter();
2528 } 2505 }
2529 selections.remove( id ); 2506 selections.remove( id );
2530 return TRUE; 2507 return TRUE;
2531} 2508}
2532 2509
2533QString QTextDocument::selectedText( int id, bool asRichText ) const 2510QString QTextDocument::selectedText( int id, bool asRichText ) const
2534{ 2511{
2535 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id ); 2512 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id );
2536 if ( it == selections.end() ) 2513 if ( it == selections.end() )
2537 return QString::null; 2514 return QString::null;
2538 2515
2539 QTextDocumentSelection sel = *it; 2516 QTextDocumentSelection sel = *it;
2540 2517
2541 2518
2542 QTextCursor c1 = sel.startCursor; 2519 QTextCursor c1 = sel.startCursor;
2543 QTextCursor c2 = sel.endCursor; 2520 QTextCursor c2 = sel.endCursor;
2544 if ( sel.swapped ) { 2521 if ( sel.swapped ) {
2545 c2 = sel.startCursor; 2522 c2 = sel.startCursor;
2546 c1 = sel.endCursor; 2523 c1 = sel.endCursor;
2547 } 2524 }
2548 2525
2549 /* 3.0.3 improvement: Make it possible to get a reasonable 2526 /* 3.0.3 improvement: Make it possible to get a reasonable
2550 selection inside a table. This approach is very conservative: 2527 selection inside a table. This approach is very conservative:
2551 make sure that both cursors have the same depth level and point 2528 make sure that both cursors have the same depth level and point
2552 to paragraphs within the same text document. 2529 to paragraphs within the same text document.
2553 2530
2554 Meaning if you select text in two table cells, you will get the 2531 Meaning if you select text in two table cells, you will get the
2555 entire table. This is still far better than the 3.0.2, where 2532 entire table. This is still far better than the 3.0.2, where
2556 you always got the entire table. 2533 you always got the entire table.
2557 2534
2558 ### Fix this properly when refactoring 2535 ### Fix this properly when refactoring
2559 */ 2536 */
2560 while ( c2.nestedDepth() > c1.nestedDepth() ) 2537 while ( c2.nestedDepth() > c1.nestedDepth() )
2561 c2.oneUp(); 2538 c2.oneUp();
2562 while ( c1.nestedDepth() > c2.nestedDepth() ) 2539 while ( c1.nestedDepth() > c2.nestedDepth() )
2563 c1.oneUp(); 2540 c1.oneUp();
2564 while ( c1.nestedDepth() && c2.nestedDepth() && 2541 while ( c1.nestedDepth() && c2.nestedDepth() &&
2565 c1.paragraph()->document() != c2.paragraph()->document() ) { 2542 c1.paragraph()->document() != c2.paragraph()->document() ) {
2566 c1.oneUp(); 2543 c1.oneUp();
2567 c2.oneUp(); 2544 c2.oneUp();
2568 } 2545 }
2569 // do not trust sel_swapped with tables. Fix this properly when refactoring as well 2546 // do not trust sel_swapped with tables. Fix this properly when refactoring as well
2570 if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() || 2547 if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() ||
2571 (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) { 2548 (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) {
2572 QTextCursor tmp = c1; 2549 QTextCursor tmp = c1;
2573 c2 = c1; 2550 c2 = c1;
2574 c1 = tmp; 2551 c1 = tmp;
2575 } 2552 }
2576 2553
2577 // end selection 3.0.3 improvement 2554 // end selection 3.0.3 improvement
2578 2555
2579 if ( asRichText && !parent() ) { 2556 if ( asRichText && !parent() ) {
2580 richTextExportStart = &c1; 2557 richTextExportStart = &c1;
2581 richTextExportEnd = &c2; 2558 richTextExportEnd = &c2;
2582 2559
2583 QString sel = richText(); 2560 QString sel = richText();
2584 int from = sel.find( "<selstart/>" ); 2561 int from = sel.find( "<selstart/>" );
2585 int to = sel.findRev( "<selend/>" ); 2562 int to = sel.findRev( "<selend/>" );
2586 if ( from >= 0 && from <= to ) 2563 if ( from >= 0 && from <= to )
2587 sel = sel.mid( from, to - from ); 2564 sel = sel.mid( from, to - from );
2588 richTextExportStart = richTextExportEnd = 0; 2565 richTextExportStart = richTextExportEnd = 0;
2589 return sel; 2566 return sel;
2590 } 2567 }
2591 2568
2592 QString s; 2569 QString s;
2593 if ( c1.paragraph() == c2.paragraph() ) { 2570 if ( c1.paragraph() == c2.paragraph() ) {
2594 QTextParagraph *p = c1.paragraph(); 2571 QTextParagraph *p = c1.paragraph();
2595 int end = c2.index(); 2572 int end = c2.index();
2596 if ( p->at( QMAX( 0, end - 1 ) )->isCustom() ) 2573 if ( p->at( QMAX( 0, end - 1 ) )->isCustom() )
2597 ++end; 2574 ++end;
2598 if ( !p->mightHaveCustomItems ) { 2575 if ( !p->mightHaveCustomItems ) {
2599 s += p->string()->toString().mid( c1.index(), end - c1.index() ); 2576 s += p->string()->toString().mid( c1.index(), end - c1.index() );
2600 } else { 2577 } else {
2601 for ( int i = c1.index(); i < end; ++i ) { 2578 for ( int i = c1.index(); i < end; ++i ) {
2602 if ( p->at( i )->isCustom() ) { 2579 if ( p->at( i )->isCustom() ) {
2603 if ( p->at( i )->customItem()->isNested() ) { 2580 if ( p->at( i )->customItem()->isNested() ) {
2604 s += "\n"; 2581 s += "\n";
2605 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2582 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2606 QPtrList<QTextTableCell> cells = t->tableCells(); 2583 QPtrList<QTextTableCell> cells = t->tableCells();
2607 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2584 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2608 s += c->richText()->plainText() + "\n"; 2585 s += c->richText()->plainText() + "\n";
2609 s += "\n"; 2586 s += "\n";
2610 } 2587 }
2611 } else { 2588 } else {
2612 s += p->at( i )->c; 2589 s += p->at( i )->c;
2613 } 2590 }
2614 } 2591 }
2615 } 2592 }
2616 } else { 2593 } else {
2617 QTextParagraph *p = c1.paragraph(); 2594 QTextParagraph *p = c1.paragraph();
2618 int start = c1.index(); 2595 int start = c1.index();
2619 while ( p ) { 2596 while ( p ) {
2620 int end = p == c2.paragraph() ? c2.index() : p->length() - 1; 2597 int end = p == c2.paragraph() ? c2.index() : p->length() - 1;
2621 if ( p == c2.paragraph() && p->at( QMAX( 0, end - 1 ) )->isCustom() ) 2598 if ( p == c2.paragraph() && p->at( QMAX( 0, end - 1 ) )->isCustom() )
2622 ++end; 2599 ++end;
2623 if ( !p->mightHaveCustomItems ) { 2600 if ( !p->mightHaveCustomItems ) {
2624 s += p->string()->toString().mid( start, end - start ); 2601 s += p->string()->toString().mid( start, end - start );
2625 if ( p != c2.paragraph() ) 2602 if ( p != c2.paragraph() )
2626 s += "\n"; 2603 s += "\n";
2627 } else { 2604 } else {
2628 for ( int i = start; i < end; ++i ) { 2605 for ( int i = start; i < end; ++i ) {
2629 if ( p->at( i )->isCustom() ) { 2606 if ( p->at( i )->isCustom() ) {
2630 if ( p->at( i )->customItem()->isNested() ) { 2607 if ( p->at( i )->customItem()->isNested() ) {
2631 s += "\n"; 2608 s += "\n";
2632 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2609 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2633 QPtrList<QTextTableCell> cells = t->tableCells(); 2610 QPtrList<QTextTableCell> cells = t->tableCells();
2634 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2611 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2635 s += c->richText()->plainText() + "\n"; 2612 s += c->richText()->plainText() + "\n";
2636 s += "\n"; 2613 s += "\n";
2637 } 2614 }
2638 } else { 2615 } else {
2639 s += p->at( i )->c; 2616 s += p->at( i )->c;
2640 } 2617 }
2641 } 2618 }
2642 } 2619 }
2643 start = 0; 2620 start = 0;
2644 if ( p == c2.paragraph() ) 2621 if ( p == c2.paragraph() )
2645 break; 2622 break;
2646 p = p->next(); 2623 p = p->next();
2647 } 2624 }
2648 } 2625 }
2649 // ### workaround for plain text export until we get proper 2626 // ### workaround for plain text export until we get proper
2650 // mime types: turn unicode line seperators into the more 2627 // mime types: turn unicode line seperators into the more
2651 // widely understood \n. Makes copy and pasting code snipplets 2628 // widely understood \n. Makes copy and pasting code snipplets
2652 // from within Assistent possible 2629 // from within Assistent possible
2653 QChar* uc = (QChar*) s.unicode(); 2630 QChar* uc = (QChar*) s.unicode();
2654 for ( uint ii = 0; ii < s.length(); ii++ ) 2631 for ( uint ii = 0; ii < s.length(); ii++ )
2655 if ( uc[(int)ii] == QChar_linesep ) 2632 if ( uc[(int)ii] == QChar_linesep )
2656 uc[(int)ii] = QChar('\n'); 2633 uc[(int)ii] = QChar('\n');
2657 return s; 2634 return s;
2658} 2635}
2659 2636
2660void QTextDocument::setFormat( int id, QTextFormat *f, int flags ) 2637void QTextDocument::setFormat( int id, QTextFormat *f, int flags )
2661{ 2638{
2662 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id ); 2639 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id );
2663 if ( it == selections.end() ) 2640 if ( it == selections.end() )
2664 return; 2641 return;
2665 2642
2666 QTextDocumentSelection sel = *it; 2643 QTextDocumentSelection sel = *it;
2667 2644
2668 QTextCursor c1 = sel.startCursor; 2645 QTextCursor c1 = sel.startCursor;
2669 QTextCursor c2 = sel.endCursor; 2646 QTextCursor c2 = sel.endCursor;
2670 if ( sel.swapped ) { 2647 if ( sel.swapped ) {
2671 c2 = sel.startCursor; 2648 c2 = sel.startCursor;
2672 c1 = sel.endCursor; 2649 c1 = sel.endCursor;
2673 } 2650 }
2674 2651
2675 c2.restoreState(); 2652 c2.restoreState();
2676 c1.restoreState(); 2653 c1.restoreState();
2677 2654
2678 if ( c1.paragraph() == c2.paragraph() ) { 2655 if ( c1.paragraph() == c2.paragraph() ) {
2679 c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags ); 2656 c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags );
2680 return; 2657 return;
2681 } 2658 }
2682 2659
2683 c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags ); 2660 c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags );
2684 QTextParagraph *p = c1.paragraph()->next(); 2661 QTextParagraph *p = c1.paragraph()->next();
2685 while ( p && p != c2.paragraph() ) { 2662 while ( p && p != c2.paragraph() ) {
2686 p->setFormat( 0, p->length(), f, TRUE, flags ); 2663 p->setFormat( 0, p->length(), f, TRUE, flags );
2687 p = p->next(); 2664 p = p->next();
2688 } 2665 }
2689 c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags ); 2666 c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags );
2690} 2667}
2691 2668
2692void QTextDocument::removeSelectedText( int id, QTextCursor *cursor ) 2669void QTextDocument::removeSelectedText( int id, QTextCursor *cursor )
2693{ 2670{
2694 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2671 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2695 if ( it == selections.end() ) 2672 if ( it == selections.end() )
2696 return; 2673 return;
2697 2674
2698 QTextDocumentSelection sel = *it; 2675 QTextDocumentSelection sel = *it;
2699 2676
2700 QTextCursor c1 = sel.startCursor; 2677 QTextCursor c1 = sel.startCursor;
2701 QTextCursor c2 = sel.endCursor; 2678 QTextCursor c2 = sel.endCursor;
2702 if ( sel.swapped ) { 2679 if ( sel.swapped ) {
2703 c2 = sel.startCursor; 2680 c2 = sel.startCursor;
2704 c1 = sel.endCursor; 2681 c1 = sel.endCursor;
2705 } 2682 }
2706 2683
2707 // ### no support for editing tables yet 2684 // ### no support for editing tables yet
2708 if ( c1.nestedDepth() || c2.nestedDepth() ) 2685 if ( c1.nestedDepth() || c2.nestedDepth() )
2709 return; 2686 return;
2710 2687
2711 c2.restoreState(); 2688 c2.restoreState();
2712 c1.restoreState(); 2689 c1.restoreState();
2713 2690
2714 *cursor = c1; 2691 *cursor = c1;
2715 removeSelection( id ); 2692 removeSelection( id );
2716 2693
2717 if ( c1.paragraph() == c2.paragraph() ) { 2694 if ( c1.paragraph() == c2.paragraph() ) {
2718 c1.paragraph()->remove( c1.index(), c2.index() - c1.index() ); 2695 c1.paragraph()->remove( c1.index(), c2.index() - c1.index() );
2719 return; 2696 return;
2720 } 2697 }
2721 2698
2722 if ( c1.paragraph() == fParag && c1.index() == 0 && 2699 if ( c1.paragraph() == fParag && c1.index() == 0 &&
2723 c2.paragraph() == lParag && c2.index() == lParag->length() - 1 ) 2700 c2.paragraph() == lParag && c2.index() == lParag->length() - 1 )
2724 cursor->setValid( FALSE ); 2701 cursor->setValid( FALSE );
2725 2702
2726 bool didGoLeft = FALSE; 2703 bool didGoLeft = FALSE;
2727 if ( c1.index() == 0 && c1.paragraph() != fParag ) { 2704 if ( c1.index() == 0 && c1.paragraph() != fParag ) {
2728 cursor->gotoPreviousLetter(); 2705 cursor->gotoPreviousLetter();
2729 if ( cursor->isValid() ) 2706 if ( cursor->isValid() )
2730 didGoLeft = TRUE; 2707 didGoLeft = TRUE;
2731 } 2708 }
2732 2709
2733 c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() ); 2710 c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() );
2734 QTextParagraph *p = c1.paragraph()->next(); 2711 QTextParagraph *p = c1.paragraph()->next();
2735 int dy = 0; 2712 int dy = 0;
2736 QTextParagraph *tmp; 2713 QTextParagraph *tmp;
2737 while ( p && p != c2.paragraph() ) { 2714 while ( p && p != c2.paragraph() ) {
2738 tmp = p->next(); 2715 tmp = p->next();
2739 dy -= p->rect().height(); 2716 dy -= p->rect().height();
2740 delete p; 2717 delete p;
2741 p = tmp; 2718 p = tmp;
2742 } 2719 }
2743 c2.paragraph()->remove( 0, c2.index() ); 2720 c2.paragraph()->remove( 0, c2.index() );
2744 while ( p ) { 2721 while ( p ) {
2745 p->move( dy ); 2722 p->move( dy );
2746 p->invalidate( 0 ); 2723 p->invalidate( 0 );
2747 p->setEndState( -1 ); 2724 p->setEndState( -1 );
2748 p = p->next(); 2725 p = p->next();
2749 } 2726 }
2750 2727
2751 c1.paragraph()->join( c2.paragraph() ); 2728 c1.paragraph()->join( c2.paragraph() );
2752 2729
2753 if ( didGoLeft ) 2730 if ( didGoLeft )
2754 cursor->gotoNextLetter(); 2731 cursor->gotoNextLetter();
2755} 2732}
2756 2733
2757void QTextDocument::indentSelection( int id ) 2734void QTextDocument::indentSelection( int id )
2758{ 2735{
2759 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2736 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2760 if ( it == selections.end() ) 2737 if ( it == selections.end() )
2761 return; 2738 return;
2762 2739
2763 QTextDocumentSelection sel = *it; 2740 QTextDocumentSelection sel = *it;
2764 QTextParagraph *startParag = sel.startCursor.paragraph(); 2741 QTextParagraph *startParag = sel.startCursor.paragraph();
2765 QTextParagraph *endParag = sel.endCursor.paragraph(); 2742 QTextParagraph *endParag = sel.endCursor.paragraph();
2766 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { 2743 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) {
2767 endParag = sel.startCursor.paragraph(); 2744 endParag = sel.startCursor.paragraph();
2768 startParag = sel.endCursor.paragraph(); 2745 startParag = sel.endCursor.paragraph();
2769 } 2746 }
2770 2747
2771 QTextParagraph *p = startParag; 2748 QTextParagraph *p = startParag;
2772 while ( p && p != endParag ) { 2749 while ( p && p != endParag ) {
2773 p->indent(); 2750 p->indent();
2774 p = p->next(); 2751 p = p->next();
2775 } 2752 }
2776} 2753}
2777 2754
2778void QTextDocument::addCommand( QTextCommand *cmd ) 2755void QTextDocument::addCommand( QTextCommand *cmd )
2779{ 2756{
2780 commandHistory->addCommand( cmd ); 2757 commandHistory->addCommand( cmd );
2781} 2758}
2782 2759
2783QTextCursor *QTextDocument::undo( QTextCursor *c ) 2760QTextCursor *QTextDocument::undo( QTextCursor *c )
2784{ 2761{
2785 return commandHistory->undo( c ); 2762 return commandHistory->undo( c );
2786} 2763}
2787 2764
2788QTextCursor *QTextDocument::redo( QTextCursor *c ) 2765QTextCursor *QTextDocument::redo( QTextCursor *c )
2789{ 2766{
2790 return commandHistory->redo( c ); 2767 return commandHistory->redo( c );
2791} 2768}
2792 2769
2793bool QTextDocument::find( QTextCursor& cursor, const QString &e, bool cs, bool wo, bool forward ) 2770bool QTextDocument::find( QTextCursor& cursor, const QString &e, bool cs, bool wo, bool forward )
2794{ 2771{
2795 removeSelection( Standard ); 2772 removeSelection( Standard );
2796 QTextParagraph *p = 0; 2773 QTextParagraph *p = 0;
2797 QString expr = e; 2774 QString expr = e;
2798 // if we search for 'word only' than we have to be sure that 2775 // if we search for 'word only' than we have to be sure that
2799 // the expression contains no space or punct character at the 2776 // the expression contains no space or punct character at the
2800 // beginning or in the end. Otherwise we would run into a 2777 // beginning or in the end. Otherwise we would run into a
2801 // endlessloop. 2778 // endlessloop.
2802 if ( wo ) { 2779 if ( wo ) {
2803 for ( ;; ) { 2780 for ( ;; ) {
2804 if ( expr[ 0 ].isSpace() || expr[ 0 ].isPunct() ) 2781 if ( expr[ 0 ].isSpace() || expr[ 0 ].isPunct() )
2805 expr = expr.right( expr.length() - 1 ); 2782 expr = expr.right( expr.length() - 1 );
2806 else 2783 else
2807 break; 2784 break;
2808 } 2785 }
2809 for ( ;; ) { 2786 for ( ;; ) {
2810 if ( expr.at( expr.length() - 1 ).isSpace() || expr.at( expr.length() - 1 ).isPunct() ) 2787 if ( expr.at( expr.length() - 1 ).isSpace() || expr.at( expr.length() - 1 ).isPunct() )
2811 expr = expr.left( expr.length() - 1 ); 2788 expr = expr.left( expr.length() - 1 );
2812 else 2789 else
2813 break; 2790 break;
2814 } 2791 }
2815 } 2792 }
2816 for (;;) { 2793 for (;;) {
2817 if ( p != cursor.paragraph() ) { 2794 if ( p != cursor.paragraph() ) {
2818 p = cursor.paragraph(); 2795 p = cursor.paragraph();
2819 QString s = cursor.paragraph()->string()->toString(); 2796 QString s = cursor.paragraph()->string()->toString();
2820 int start = cursor.index(); 2797 int start = cursor.index();
2821 for ( ;; ) { 2798 for ( ;; ) {
2822 int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs ); 2799 int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs );
2823 int end = res + expr.length(); 2800 int end = res + expr.length();
2824 if ( res == -1 || ( !forward && start < end ) ) 2801 if ( res == -1 || ( !forward && start < end ) )
2825 break; 2802 break;
2826 if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) && 2803 if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) &&
2827 ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) { 2804 ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) {
2828 removeSelection( Standard ); 2805 removeSelection( Standard );
2829 cursor.setIndex( forward ? end : res ); 2806 cursor.setIndex( forward ? end : res );
2830 setSelectionStart( Standard, cursor ); 2807 setSelectionStart( Standard, cursor );
2831 cursor.setIndex( forward ? res : end ); 2808 cursor.setIndex( forward ? res : end );
2832 setSelectionEnd( Standard, cursor ); 2809 setSelectionEnd( Standard, cursor );
2833 return TRUE; 2810 return TRUE;
2834 } 2811 }
2835 start = res + (forward ? 1 : -1); 2812 start = res + (forward ? 1 : -1);
2836 } 2813 }
2837 } 2814 }
2838 if ( forward ) { 2815 if ( forward ) {
2839 if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd () ) 2816 if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd () )
2840 break; 2817 break;
2841 cursor.gotoNextLetter(); 2818 cursor.gotoNextLetter();
2842 } else { 2819 } else {
2843 if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() ) 2820 if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() )
2844 break; 2821 break;
2845 cursor.gotoPreviousLetter(); 2822 cursor.gotoPreviousLetter();
2846 } 2823 }
2847 } 2824 }
2848 return FALSE; 2825 return FALSE;
2849} 2826}
2850 2827
2851void QTextDocument::setTextFormat( Qt::TextFormat f ) 2828void QTextDocument::setTextFormat( Qt::TextFormat f )
2852{ 2829{
2853 txtFormat = f; 2830 txtFormat = f;
2854 if ( fParag == lParag && fParag->length() <= 1 ) 2831 if ( fParag == lParag && fParag->length() <= 1 )
2855 fParag->rtext = ( f == Qt::RichText ); 2832 fParag->rtext = ( f == Qt::RichText );
2856} 2833}
2857 2834
2858Qt::TextFormat QTextDocument::textFormat() const 2835Qt::TextFormat QTextDocument::textFormat() const
2859{ 2836{
2860 return txtFormat; 2837 return txtFormat;
2861} 2838}
2862 2839
2863bool QTextDocument::inSelection( int selId, const QPoint &pos ) const 2840bool QTextDocument::inSelection( int selId, const QPoint &pos ) const
2864{ 2841{
2865 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( selId ); 2842 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( selId );
2866 if ( it == selections.end() ) 2843 if ( it == selections.end() )
2867 return FALSE; 2844 return FALSE;
2868 2845
2869 QTextDocumentSelection sel = *it; 2846 QTextDocumentSelection sel = *it;
2870 QTextParagraph *startParag = sel.startCursor.paragraph(); 2847 QTextParagraph *startParag = sel.startCursor.paragraph();
2871 QTextParagraph *endParag = sel.endCursor.paragraph(); 2848 QTextParagraph *endParag = sel.endCursor.paragraph();
2872 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() && 2849 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() &&
2873 sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) ) 2850 sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) )
2874 return FALSE; 2851 return FALSE;
2875 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) { 2852 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) {
2876 endParag = sel.startCursor.paragraph(); 2853 endParag = sel.startCursor.paragraph();
2877 startParag = sel.endCursor.paragraph(); 2854 startParag = sel.endCursor.paragraph();
2878 } 2855 }
2879 2856
2880 QTextParagraph *p = startParag; 2857 QTextParagraph *p = startParag;
2881 while ( p ) { 2858 while ( p ) {
2882 if ( p->rect().contains( pos ) ) { 2859 if ( p->rect().contains( pos ) ) {
2883 bool inSel = FALSE; 2860 bool inSel = FALSE;
2884 int selStart = p->selectionStart( selId ); 2861 int selStart = p->selectionStart( selId );
2885 int selEnd = p->selectionEnd( selId ); 2862 int selEnd = p->selectionEnd( selId );
2886 int y = 0; 2863 int y = 0;
2887 int h = 0; 2864 int h = 0;
2888 for ( int i = 0; i < p->length(); ++i ) { 2865 for ( int i = 0; i < p->length(); ++i ) {
2889 if ( i == selStart ) 2866 if ( i == selStart )
2890 inSel = TRUE; 2867 inSel = TRUE;
2891 if ( i == selEnd ) 2868 if ( i == selEnd )
2892 break; 2869 break;
2893 if ( p->at( i )->lineStart ) { 2870 if ( p->at( i )->lineStart ) {
2894 y = (*p->lineStarts.find( i ))->y; 2871 y = (*p->lineStarts.find( i ))->y;
2895 h = (*p->lineStarts.find( i ))->h; 2872 h = (*p->lineStarts.find( i ))->h;
2896 } 2873 }
2897 if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) { 2874 if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) {
2898 if ( inSel && pos.x() >= p->at( i )->x && 2875 if ( inSel && pos.x() >= p->at( i )->x &&
2899 pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) ) 2876 pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) )
2900 return TRUE; 2877 return TRUE;
2901 } 2878 }
2902 } 2879 }
2903 } 2880 }
2904 if ( pos.y() < p->rect().y() ) 2881 if ( pos.y() < p->rect().y() )
2905 break; 2882 break;
2906 if ( p == endParag ) 2883 if ( p == endParag )
2907 break; 2884 break;
2908 p = p->next(); 2885 p = p->next();
2909 } 2886 }
2910 2887
2911 return FALSE; 2888 return FALSE;
2912} 2889}
2913 2890
2914void QTextDocument::doLayout( QPainter *p, int w ) 2891void QTextDocument::doLayout( QPainter *p, int w )
2915{ 2892{
2916 minw = wused = 0; 2893 minw = wused = 0;
2917 if ( !is_printer( p ) ) 2894 if ( !is_printer( p ) )
2918 p = 0; 2895 p = 0;
2919 withoutDoubleBuffer = ( p != 0 ); 2896 withoutDoubleBuffer = ( p != 0 );
2920 QPainter * oldPainter = QTextFormat::painter(); 2897 QPainter * oldPainter = QTextFormat::painter();
2921 QTextFormat::setPainter( p ); 2898 QTextFormat::setPainter( p );
2922 flow_->setWidth( w ); 2899 flow_->setWidth( w );
2923 cw = w; 2900 cw = w;
2924 vw = w; 2901 vw = w;
2925 QTextParagraph *parag = fParag; 2902 QTextParagraph *parag = fParag;
2926 while ( parag ) { 2903 while ( parag ) {
2927 parag->invalidate( 0 ); 2904 parag->invalidate( 0 );
2928 if ( p ) 2905 if ( p )
2929 parag->adjustToPainter( p ); 2906 parag->adjustToPainter( p );
2930 parag->format(); 2907 parag->format();
2931 parag = parag->next(); 2908 parag = parag->next();
2932 } 2909 }
2933 QTextFormat::setPainter( oldPainter ); 2910 QTextFormat::setPainter( oldPainter );
2934} 2911}
2935 2912
2936QPixmap *QTextDocument::bufferPixmap( const QSize &s ) 2913QPixmap *QTextDocument::bufferPixmap( const QSize &s )
2937{ 2914{
2938 if ( !buf_pixmap ) 2915 if ( !buf_pixmap )
2939 buf_pixmap = new QPixmap( s.expandedTo( QSize(1,1) ) ); 2916 buf_pixmap = new QPixmap( s.expandedTo( QSize(1,1) ) );
2940 else if ( buf_pixmap->size() != s ) 2917 else if ( buf_pixmap->size() != s )
2941 buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) ); 2918 buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) );
2942 return buf_pixmap; 2919 return buf_pixmap;
2943} 2920}
2944 2921
2945void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper ) 2922void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper )
2946{ 2923{
2947 if ( !firstParagraph() ) 2924 if ( !firstParagraph() )
2948 return; 2925 return;
2949 2926
2950 if ( paper ) { 2927 if ( paper ) {
2951 p->setBrushOrigin( 0, 0 ); 2928 p->setBrushOrigin( 0, 0 );
2952 2929
2953 p->fillRect( rect, *paper ); 2930 p->fillRect( rect, *paper );
2954 } 2931 }
2955 2932
2956 if ( formatCollection()->defaultFormat()->color() != cg.text() ) 2933 if ( formatCollection()->defaultFormat()->color() != cg.text() )
2957 setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() ); 2934 setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() );
2958 2935
2959 QTextParagraph *parag = firstParagraph(); 2936 QTextParagraph *parag = firstParagraph();
2960 while ( parag ) { 2937 while ( parag ) {
2961 if ( !parag->isValid() ) 2938 if ( !parag->isValid() )
2962 parag->format(); 2939 parag->format();
2963 int y = parag->rect().y(); 2940 int y = parag->rect().y();
2964 QRect pr( parag->rect() ); 2941 QRect pr( parag->rect() );
2965 pr.setX( 0 ); 2942 pr.setX( 0 );
2966 pr.setWidth( QWIDGETSIZE_MAX ); 2943 pr.setWidth( QWIDGETSIZE_MAX );
2967 if ( !rect.isNull() && !rect.intersects( pr ) ) { 2944 if ( !rect.isNull() && !rect.intersects( pr ) ) {
2968 parag = parag->next(); 2945 parag = parag->next();
2969 continue; 2946 continue;
2970 } 2947 }
2971 p->translate( 0, y ); 2948 p->translate( 0, y );
2972 if ( rect.isValid() ) 2949 if ( rect.isValid() )
2973 parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() ); 2950 parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() );
2974 else 2951 else
2975 parag->paint( *p, cg, 0, FALSE ); 2952 parag->paint( *p, cg, 0, FALSE );
2976 p->translate( 0, -y ); 2953 p->translate( 0, -y );
2977 parag = parag->next(); 2954 parag = parag->next();
2978 if ( !flow()->isEmpty() ) 2955 if ( !flow()->isEmpty() )
2979 flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE ); 2956 flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE );
2980 } 2957 }
2981} 2958}
2982 2959
2983void QTextDocument::drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch, 2960void QTextDocument::drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch,
2984 QPixmap *&doubleBuffer, const QColorGroup &cg, 2961 QPixmap *&doubleBuffer, const QColorGroup &cg,
2985 bool drawCursor, QTextCursor *cursor, bool resetChanged ) 2962 bool drawCursor, QTextCursor *cursor, bool resetChanged )
2986{ 2963{
2987 QPainter *painter = 0; 2964 QPainter *painter = 0;
2988 if ( resetChanged ) 2965 if ( resetChanged )
2989 parag->setChanged( FALSE ); 2966 parag->setChanged( FALSE );
2990 QRect ir( parag->rect() ); 2967 QRect ir( parag->rect() );
2991 bool useDoubleBuffer = !parag->document()->parent(); 2968 bool useDoubleBuffer = !parag->document()->parent();
2992 if ( !useDoubleBuffer && parag->document()->nextDoubleBuffered ) 2969 if ( !useDoubleBuffer && parag->document()->nextDoubleBuffered )
2993 useDoubleBuffer = TRUE; 2970 useDoubleBuffer = TRUE;
2994 if ( is_printer( p ) ) 2971 if ( is_printer( p ) )
2995 useDoubleBuffer = FALSE; 2972 useDoubleBuffer = FALSE;
2996 2973
2997 if ( useDoubleBuffer ) { 2974 if ( useDoubleBuffer ) {
2998 painter = new QPainter; 2975 painter = new QPainter;
2999 if ( cx >= 0 && cy >= 0 ) 2976 if ( cx >= 0 && cy >= 0 )
3000 ir = ir.intersect( QRect( cx, cy, cw, ch ) ); 2977 ir = ir.intersect( QRect( cx, cy, cw, ch ) );
3001 if ( !doubleBuffer || 2978 if ( !doubleBuffer ||
3002 ir.width() > doubleBuffer->width() || 2979 ir.width() > doubleBuffer->width() ||
3003 ir.height() > doubleBuffer->height() ) { 2980 ir.height() > doubleBuffer->height() ) {
3004 doubleBuffer = bufferPixmap( ir.size() ); 2981 doubleBuffer = bufferPixmap( ir.size() );
3005 painter->begin( doubleBuffer ); 2982 painter->begin( doubleBuffer );
3006 } else { 2983 } else {
3007 painter->begin( doubleBuffer ); 2984 painter->begin( doubleBuffer );
3008 } 2985 }
3009 } else { 2986 } else {
3010 painter = p; 2987 painter = p;
3011 painter->translate( ir.x(), ir.y() ); 2988 painter->translate( ir.x(), ir.y() );
3012 } 2989 }
3013 2990
3014 painter->setBrushOrigin( -ir.x(), -ir.y() ); 2991 painter->setBrushOrigin( -ir.x(), -ir.y() );
3015 2992
3016 if ( useDoubleBuffer || is_printer( painter ) ) 2993 if ( useDoubleBuffer || is_printer( painter ) )
3017 painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) ); 2994 painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) );
3018 else if ( cursor && cursor->paragraph() == parag ) 2995 else if ( cursor && cursor->paragraph() == parag )
3019 painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ), 2996 painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ),
3020 parag->backgroundBrush( cg ) ); 2997 parag->backgroundBrush( cg ) );
3021 2998
3022 painter->translate( -( ir.x() - parag->rect().x() ), 2999 painter->translate( -( ir.x() - parag->rect().x() ),
3023 -( ir.y() - parag->rect().y() ) ); 3000 -( ir.y() - parag->rect().y() ) );
3024 parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch ); 3001 parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch );
3025 3002
3026 if ( useDoubleBuffer ) { 3003 if ( useDoubleBuffer ) {
3027 delete painter; 3004 delete painter;
3028 painter = 0; 3005 painter = 0;
3029 p->drawPixmap( ir.topLeft(), *doubleBuffer, QRect( QPoint( 0, 0 ), ir.size() ) ); 3006 p->drawPixmap( ir.topLeft(), *doubleBuffer, QRect( QPoint( 0, 0 ), ir.size() ) );
3030 } else { 3007 } else {
3031 painter->translate( -ir.x(), -ir.y() ); 3008 painter->translate( -ir.x(), -ir.y() );
3032 } 3009 }
3033 3010
3034 if ( useDoubleBuffer ) { 3011 if ( useDoubleBuffer ) {
3035 if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) { 3012 if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) {
3036 p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(), 3013 p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(),
3037 ( parag->document()->x() + parag->document()->width() ) - 3014 ( parag->document()->x() + parag->document()->width() ) -
3038 ( parag->rect().x() + parag->rect().width() ), 3015 ( parag->rect().x() + parag->rect().width() ),
3039 parag->rect().height(), cg.brush( QColorGroup::Base ) ); 3016 parag->rect().height(), cg.brush( QColorGroup::Base ) );
3040 } 3017 }
3041 } 3018 }
3042 3019
3043 parag->document()->nextDoubleBuffered = FALSE; 3020 parag->document()->nextDoubleBuffered = FALSE;
3044} 3021}
3045 3022
3046QTextParagraph *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, 3023QTextParagraph *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg,
3047 bool onlyChanged, bool drawCursor, QTextCursor *cursor, bool resetChanged ) 3024 bool onlyChanged, bool drawCursor, QTextCursor *cursor, bool resetChanged )
3048{ 3025{
3049 if ( withoutDoubleBuffer || par && par->withoutDoubleBuffer ) { 3026 if ( withoutDoubleBuffer || par && par->withoutDoubleBuffer ) {
3050 withoutDoubleBuffer = TRUE; 3027 withoutDoubleBuffer = TRUE;
3051 QRect r; 3028 QRect r;
3052 draw( p, r, cg ); 3029 draw( p, r, cg );
3053 return 0; 3030 return 0;
3054 } 3031 }
3055 withoutDoubleBuffer = FALSE; 3032 withoutDoubleBuffer = FALSE;
3056 3033
3057 if ( !firstParagraph() ) 3034 if ( !firstParagraph() )
3058 return 0; 3035 return 0;
3059 3036
3060 if ( cx < 0 && cy < 0 ) { 3037 if ( cx < 0 && cy < 0 ) {
3061 cx = 0; 3038 cx = 0;
3062 cy = 0; 3039 cy = 0;
3063 cw = width(); 3040 cw = width();
3064 ch = height(); 3041 ch = height();
3065 } 3042 }
3066 3043
3067 QTextParagraph *lastFormatted = 0; 3044 QTextParagraph *lastFormatted = 0;
3068 QTextParagraph *parag = firstParagraph(); 3045 QTextParagraph *parag = firstParagraph();
3069 3046
3070 QPixmap *doubleBuffer = 0; 3047 QPixmap *doubleBuffer = 0;
3071 QPainter painter; 3048 QPainter painter;
3072 3049
3073 bool fullWidthSelection = FALSE;
3074 while ( parag ) { 3050 while ( parag ) {
3075 lastFormatted = parag; 3051 lastFormatted = parag;
3076 if ( !parag->isValid() ) 3052 if ( !parag->isValid() )
3077 parag->format(); 3053 parag->format();
3078 3054
3079 QRect pr = parag->rect(); 3055 QRect pr = parag->rect();
3080 if ( fullWidthSelection )
3081 pr.setWidth( parag->document()->width() );
3082 if ( pr.y() > cy + ch ) 3056 if ( pr.y() > cy + ch )
3083 goto floating; 3057 goto floating;
3084 if ( !pr.intersects( QRect( cx, cy, cw, ch ) ) || ( onlyChanged && !parag->hasChanged() ) ) { 3058 if ( !pr.intersects( QRect( cx, cy, cw, ch ) ) || ( onlyChanged && !parag->hasChanged() ) ) {
3085 parag = parag->next(); 3059 parag = parag->next();
3086 continue; 3060 continue;
3087 } 3061 }
3088 3062
3089 drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged ); 3063 drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged );
3090 parag = parag->next(); 3064 parag = parag->next();
3091 } 3065 }
3092 3066
3093 parag = lastParagraph(); 3067 parag = lastParagraph();
3094 3068
3095 floating: 3069 floating:
3096 if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) { 3070 if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) {
3097 if ( !parag->document()->parent() ) { 3071 if ( !parag->document()->parent() ) {
3098 p->fillRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(), 3072 p->fillRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(),
3099 parag->document()->height() - ( parag->rect().y() + parag->rect().height() ), 3073 parag->document()->height() - ( parag->rect().y() + parag->rect().height() ),
3100 cg.brush( QColorGroup::Base ) ); 3074 cg.brush( QColorGroup::Base ) );
3101 } 3075 }
3102 if ( !flow()->isEmpty() ) { 3076 if ( !flow()->isEmpty() ) {
3103 QRect cr( cx, cy, cw, ch ); 3077 QRect cr( cx, cy, cw, ch );
3104 flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE ); 3078 flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE );
3105 } 3079 }
3106 } 3080 }
3107 3081
3108 if ( buf_pixmap && buf_pixmap->height() > 300 ) { 3082 if ( buf_pixmap && buf_pixmap->height() > 300 ) {
3109 delete buf_pixmap; 3083 delete buf_pixmap;
3110 buf_pixmap = 0; 3084 buf_pixmap = 0;
3111 } 3085 }
3112 3086
3113 return lastFormatted; 3087 return lastFormatted;
3114} 3088}
3115 3089
3116/* 3090/*
3117 #### this function only sets the default font size in the format collection 3091 #### this function only sets the default font size in the format collection
3118 */ 3092 */
3119void QTextDocument::setDefaultFormat( const QFont &font, const QColor &color ) 3093void QTextDocument::setDefaultFormat( const QFont &font, const QColor &color )
3120{ 3094{
3121 bool reformat = font != fCollection->defaultFormat()->font(); 3095 bool reformat = font != fCollection->defaultFormat()->font();
3122 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 3096 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
3123 d->setDefaultFormat( font, color ); 3097 d->setDefaultFormat( font, color );
3124 fCollection->updateDefaultFormat( font, color, sheet_ ); 3098 fCollection->updateDefaultFormat( font, color, sheet_ );
3125 3099
3126 if ( !reformat ) 3100 if ( !reformat )
3127 return; 3101 return;
3128 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; 3102 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8;
3129 3103
3130 // invalidate paragraphs and custom items 3104 // invalidate paragraphs and custom items
3131 QTextParagraph *p = fParag; 3105 QTextParagraph *p = fParag;
3132 while ( p ) { 3106 while ( p ) {
3133 p->invalidate( 0 ); 3107 p->invalidate( 0 );
3134 for ( int i = 0; i < p->length() - 1; ++i ) 3108 for ( int i = 0; i < p->length() - 1; ++i )
3135 if ( p->at( i )->isCustom() ) 3109 if ( p->at( i )->isCustom() )
3136 p->at( i )->customItem()->invalidate(); 3110 p->at( i )->customItem()->invalidate();
3137 p = p->next(); 3111 p = p->next();
3138 } 3112 }
3139} 3113}
3140 3114
3141void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParagraph *p ) 3115void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParagraph *p )
3142{ 3116{
3143 if ( i && i->placement() != QTextCustomItem::PlaceInline ) { 3117 if ( i && i->placement() != QTextCustomItem::PlaceInline ) {
3144 flow_->registerFloatingItem( i ); 3118 flow_->registerFloatingItem( i );
3145 p->registerFloatingItem( i ); 3119 p->registerFloatingItem( i );
3146 i->setParagraph( p ); 3120 i->setParagraph( p );
3147 } 3121 }
3148 p->mightHaveCustomItems = mightHaveCustomItems = TRUE; 3122 p->mightHaveCustomItems = mightHaveCustomItems = TRUE;
3149} 3123}
3150 3124
3151void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p ) 3125void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p )
3152{ 3126{
3153 flow_->unregisterFloatingItem( i ); 3127 flow_->unregisterFloatingItem( i );
3154 p->unregisterFloatingItem( i ); 3128 p->unregisterFloatingItem( i );
3155 i->setParagraph( 0 ); 3129 i->setParagraph( 0 );
3156} 3130}
3157 3131
3158bool QTextDocument::hasFocusParagraph() const 3132bool QTextDocument::hasFocusParagraph() const
3159{ 3133{
3160 return !!focusIndicator.parag; 3134 return !!focusIndicator.parag;
3161} 3135}
3162 3136
3163QString QTextDocument::focusHref() const 3137QString QTextDocument::focusHref() const
3164{ 3138{
3165 return focusIndicator.href; 3139 return focusIndicator.href;
3166} 3140}
3167 3141
3168bool QTextDocument::focusNextPrevChild( bool next ) 3142bool QTextDocument::focusNextPrevChild( bool next )
3169{ 3143{
3170 if ( !focusIndicator.parag ) { 3144 if ( !focusIndicator.parag ) {
3171 if ( next ) { 3145 if ( next ) {
3172 focusIndicator.parag = fParag; 3146 focusIndicator.parag = fParag;
3173 focusIndicator.start = 0; 3147 focusIndicator.start = 0;
3174 focusIndicator.len = 0; 3148 focusIndicator.len = 0;
3175 } else { 3149 } else {
3176 focusIndicator.parag = lParag; 3150 focusIndicator.parag = lParag;
3177 focusIndicator.start = lParag->length(); 3151 focusIndicator.start = lParag->length();
3178 focusIndicator.len = 0; 3152 focusIndicator.len = 0;
3179 } 3153 }
3180 } else { 3154 } else {
3181 focusIndicator.parag->setChanged( TRUE ); 3155 focusIndicator.parag->setChanged( TRUE );
3182 } 3156 }
3183 focusIndicator.href = QString::null; 3157 focusIndicator.href = QString::null;
3184 3158
3185 if ( next ) { 3159 if ( next ) {
3186 QTextParagraph *p = focusIndicator.parag; 3160 QTextParagraph *p = focusIndicator.parag;
3187 int index = focusIndicator.start + focusIndicator.len; 3161 int index = focusIndicator.start + focusIndicator.len;
3188 while ( p ) { 3162 while ( p ) {
3189 for ( int i = index; i < p->length(); ++i ) { 3163 for ( int i = index; i < p->length(); ++i ) {
3190 if ( p->at( i )->isAnchor() ) { 3164 if ( p->at( i )->isAnchor() ) {
3191 p->setChanged( TRUE ); 3165 p->setChanged( TRUE );
3192 focusIndicator.parag = p; 3166 focusIndicator.parag = p;
3193 focusIndicator.start = i; 3167 focusIndicator.start = i;
3194 focusIndicator.len = 0; 3168 focusIndicator.len = 0;
3195 focusIndicator.href = p->at( i )->anchorHref(); 3169 focusIndicator.href = p->at( i )->anchorHref();
3196 while ( i < p->length() ) { 3170 while ( i < p->length() ) {
3197 if ( !p->at( i )->isAnchor() ) 3171 if ( !p->at( i )->isAnchor() )
3198 return TRUE; 3172 return TRUE;
3199 focusIndicator.len++; 3173 focusIndicator.len++;
3200 i++; 3174 i++;
3201 } 3175 }
3202 } else if ( p->at( i )->isCustom() ) { 3176 } else if ( p->at( i )->isCustom() ) {
3203 if ( p->at( i )->customItem()->isNested() ) { 3177 if ( p->at( i )->customItem()->isNested() ) {
3204 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 3178 QTextTable *t = (QTextTable*)p->at( i )->customItem();
3205 QPtrList<QTextTableCell> cells = t->tableCells(); 3179 QPtrList<QTextTableCell> cells = t->tableCells();
3206 // first try to continue 3180 // first try to continue
3207 QTextTableCell *c; 3181 QTextTableCell *c;
3208 bool resetCells = TRUE; 3182 bool resetCells = TRUE;
3209 for ( c = cells.first(); c; c = cells.next() ) { 3183 for ( c = cells.first(); c; c = cells.next() ) {
3210 if ( c->richText()->hasFocusParagraph() ) { 3184 if ( c->richText()->hasFocusParagraph() ) {
3211 if ( c->richText()->focusNextPrevChild( next ) ) { 3185 if ( c->richText()->focusNextPrevChild( next ) ) {
3212 p->setChanged( TRUE ); 3186 p->setChanged( TRUE );
3213 focusIndicator.parag = p; 3187 focusIndicator.parag = p;
3214 focusIndicator.start = i; 3188 focusIndicator.start = i;
3215 focusIndicator.len = 0; 3189 focusIndicator.len = 0;
3216 focusIndicator.href = c->richText()->focusHref(); 3190 focusIndicator.href = c->richText()->focusHref();
3217 return TRUE; 3191 return TRUE;
3218 } else { 3192 } else {
3219 resetCells = FALSE; 3193 resetCells = FALSE;
3220 c = cells.next(); 3194 c = cells.next();
3221 break; 3195 break;
3222 } 3196 }
3223 } 3197 }
3224 } 3198 }
3225 // now really try 3199 // now really try
3226 if ( resetCells ) 3200 if ( resetCells )
3227 c = cells.first(); 3201 c = cells.first();
3228 for ( ; c; c = cells.next() ) { 3202 for ( ; c; c = cells.next() ) {
3229 if ( c->richText()->focusNextPrevChild( next ) ) { 3203 if ( c->richText()->focusNextPrevChild( next ) ) {
3230 p->setChanged( TRUE ); 3204 p->setChanged( TRUE );
3231 focusIndicator.parag = p; 3205 focusIndicator.parag = p;
3232 focusIndicator.start = i; 3206 focusIndicator.start = i;
3233 focusIndicator.len = 0; 3207 focusIndicator.len = 0;
3234 focusIndicator.href = c->richText()->focusHref(); 3208 focusIndicator.href = c->richText()->focusHref();
3235 return TRUE; 3209 return TRUE;
3236 } 3210 }
3237 } 3211 }
3238 } 3212 }
3239 } 3213 }
3240 } 3214 }
3241 index = 0; 3215 index = 0;
3242 p = p->next(); 3216 p = p->next();
3243 } 3217 }
3244 } else { 3218 } else {
3245 QTextParagraph *p = focusIndicator.parag; 3219 QTextParagraph *p = focusIndicator.parag;
3246 int index = focusIndicator.start - 1; 3220 int index = focusIndicator.start - 1;
3247 if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 ) 3221 if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 )
3248 index++; 3222 index++;
3249 while ( p ) { 3223 while ( p ) {
3250 for ( int i = index; i >= 0; --i ) { 3224 for ( int i = index; i >= 0; --i ) {
3251 if ( p->at( i )->isAnchor() ) { 3225 if ( p->at( i )->isAnchor() ) {
3252 p->setChanged( TRUE ); 3226 p->setChanged( TRUE );
3253 focusIndicator.parag = p; 3227 focusIndicator.parag = p;
3254 focusIndicator.start = i; 3228 focusIndicator.start = i;
3255 focusIndicator.len = 0; 3229 focusIndicator.len = 0;
3256 focusIndicator.href = p->at( i )->anchorHref(); 3230 focusIndicator.href = p->at( i )->anchorHref();
3257 while ( i >= -1 ) { 3231 while ( i >= -1 ) {
3258 if ( i < 0 || !p->at( i )->isAnchor() ) { 3232 if ( i < 0 || !p->at( i )->isAnchor() ) {
3259 focusIndicator.start++; 3233 focusIndicator.start++;
3260 return TRUE; 3234 return TRUE;
3261 } 3235 }
3262 if ( i < 0 ) 3236 if ( i < 0 )
3263 break; 3237 break;
3264 focusIndicator.len++; 3238 focusIndicator.len++;
3265 focusIndicator.start--; 3239 focusIndicator.start--;
3266 i--; 3240 i--;
3267 } 3241 }
3268 } else if ( p->at( i )->isCustom() ) { 3242 } else if ( p->at( i )->isCustom() ) {
3269 if ( p->at( i )->customItem()->isNested() ) { 3243 if ( p->at( i )->customItem()->isNested() ) {
3270 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 3244 QTextTable *t = (QTextTable*)p->at( i )->customItem();
3271 QPtrList<QTextTableCell> cells = t->tableCells(); 3245 QPtrList<QTextTableCell> cells = t->tableCells();
3272 // first try to continue 3246 // first try to continue
3273 QTextTableCell *c; 3247 QTextTableCell *c;
3274 bool resetCells = TRUE; 3248 bool resetCells = TRUE;
3275 for ( c = cells.last(); c; c = cells.prev() ) { 3249 for ( c = cells.last(); c; c = cells.prev() ) {
3276 if ( c->richText()->hasFocusParagraph() ) { 3250 if ( c->richText()->hasFocusParagraph() ) {
3277 if ( c->richText()->focusNextPrevChild( next ) ) { 3251 if ( c->richText()->focusNextPrevChild( next ) ) {
3278 p->setChanged( TRUE ); 3252 p->setChanged( TRUE );
3279 focusIndicator.parag = p; 3253 focusIndicator.parag = p;
3280 focusIndicator.start = i; 3254 focusIndicator.start = i;
3281 focusIndicator.len = 0; 3255 focusIndicator.len = 0;
3282 focusIndicator.href = c->richText()->focusHref(); 3256 focusIndicator.href = c->richText()->focusHref();
3283 return TRUE; 3257 return TRUE;
3284 } else { 3258 } else {
3285 resetCells = FALSE; 3259 resetCells = FALSE;
3286 c = cells.prev(); 3260 c = cells.prev();
3287 break; 3261 break;
3288 } 3262 }
3289 } 3263 }
3290 if ( cells.at() == 0 ) 3264 if ( cells.at() == 0 )
3291 break; 3265 break;
3292 } 3266 }
3293 // now really try 3267 // now really try
3294 if ( resetCells ) 3268 if ( resetCells )
3295 c = cells.last(); 3269 c = cells.last();
3296 for ( ; c; c = cells.prev() ) { 3270 for ( ; c; c = cells.prev() ) {
3297 if ( c->richText()->focusNextPrevChild( next ) ) { 3271 if ( c->richText()->focusNextPrevChild( next ) ) {
3298 p->setChanged( TRUE ); 3272 p->setChanged( TRUE );
3299 focusIndicator.parag = p; 3273 focusIndicator.parag = p;
3300 focusIndicator.start = i; 3274 focusIndicator.start = i;
3301 focusIndicator.len = 0; 3275 focusIndicator.len = 0;
3302 focusIndicator.href = c->richText()->focusHref(); 3276 focusIndicator.href = c->richText()->focusHref();
3303 return TRUE; 3277 return TRUE;
3304 } 3278 }
3305 if ( cells.at() == 0 ) 3279 if ( cells.at() == 0 )
3306 break; 3280 break;
3307 } 3281 }
3308 } 3282 }
3309 } 3283 }
3310 } 3284 }
3311 p = p->prev(); 3285 p = p->prev();
3312 if ( p ) 3286 if ( p )
3313 index = p->length() - 1; 3287 index = p->length() - 1;
3314 } 3288 }
3315 } 3289 }
3316 3290
3317 focusIndicator.parag = 0; 3291 focusIndicator.parag = 0;
3318 3292
3319 return FALSE; 3293 return FALSE;
3320} 3294}
3321 3295
3322int QTextDocument::length() const 3296int QTextDocument::length() const
3323{ 3297{
3324 int l = 0; 3298 int l = 0;
3325 QTextParagraph *p = fParag; 3299 QTextParagraph *p = fParag;
3326 while ( p ) { 3300 while ( p ) {
3327 l += p->length() - 1; // don't count trailing space 3301 l += p->length() - 1; // don't count trailing space
3328 p = p->next(); 3302 p = p->next();
3329 } 3303 }
3330 return l; 3304 return l;
3331} 3305}
3332 3306
3333// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3307// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3334 3308
3335int QTextFormat::width( const QChar &c ) const 3309int QTextFormat::width( const QChar &c ) const
3336{ 3310{
3337 if ( c.unicode() == 0xad ) // soft hyphen 3311 if ( c.unicode() == 0xad ) // soft hyphen
3338 return 0; 3312 return 0;
3339 if ( !pntr || !pntr->isActive() ) { 3313 if ( !pntr || !pntr->isActive() ) {
3340 if ( c == '\t' ) 3314 if ( c == '\t' )
3341 return fm.width( 'x' ) * 8; 3315 return fm.width( 'x' ) * 8;
3342 if ( ha == AlignNormal ) { 3316 if ( ha == AlignNormal ) {
3343 int w; 3317 int w;
3344 if ( c.row() ) 3318 if ( c.row() )
3345 w = fm.width( c ); 3319 w = fm.width( c );
3346 else 3320 else
3347 w = widths[ c.unicode() ]; 3321 w = widths[ c.unicode() ];
3348 if ( w == 0 && !c.row() ) { 3322 if ( w == 0 && !c.row() ) {
3349 w = fm.width( c ); 3323 w = fm.width( c );
3350 ( (QTextFormat*)this )->widths[ c.unicode() ] = w; 3324 ( (QTextFormat*)this )->widths[ c.unicode() ] = w;
3351 } 3325 }
3352 return w; 3326 return w;
3353 } else { 3327 } else {
3354 QFont f( fn ); 3328 QFont f( fn );
3355 if ( usePixelSizes ) 3329 if ( usePixelSizes )
3356 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3330 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3357 else 3331 else
3358 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3332 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3359 QFontMetrics fm_( f ); 3333 QFontMetrics fm_( f );
3360 return fm_.width( c ); 3334 return fm_.width( c );
3361 } 3335 }
3362 } 3336 }
3363 3337
3364 QFont f( fn ); 3338 QFont f( fn );
3365 if ( ha != AlignNormal ) { 3339 if ( ha != AlignNormal ) {
3366 if ( usePixelSizes ) 3340 if ( usePixelSizes )
3367 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3341 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3368 else 3342 else
3369 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3343 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3370 } 3344 }
3371 pntr->setFont( f ); 3345 pntr->setFont( f );
3372 3346
3373 return pntr->fontMetrics().width( c ); 3347 return pntr->fontMetrics().width( c );
3374} 3348}
3375 3349
3376int QTextFormat::width( const QString &str, int pos ) const 3350int QTextFormat::width( const QString &str, int pos ) const
3377{ 3351{
3378 int w = 0; 3352 int w = 0;
3379 if ( str[ pos ].unicode() == 0xad ) 3353 if ( str[ pos ].unicode() == 0xad )
3380 return w; 3354 return w;
3381 if ( !pntr || !pntr->isActive() ) { 3355 if ( !pntr || !pntr->isActive() ) {
3382 if ( ha == AlignNormal ) { 3356 if ( ha == AlignNormal ) {
3383 w = fm.width( str[ pos ] ); 3357 w = fm.width( str[ pos ] );
3384 } else { 3358 } else {
3385 QFont f( fn ); 3359 QFont f( fn );
3386 if ( usePixelSizes ) 3360 if ( usePixelSizes )
3387 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3361 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3388 else 3362 else
3389 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3363 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3390 QFontMetrics fm_( f ); 3364 QFontMetrics fm_( f );
3391 w = fm_.width( str[ pos ] ); 3365 w = fm_.width( str[ pos ] );
3392 } 3366 }
3393 } else { 3367 } else {
3394 QFont f( fn ); 3368 QFont f( fn );
3395 if ( ha != AlignNormal ) { 3369 if ( ha != AlignNormal ) {
3396 if ( usePixelSizes ) 3370 if ( usePixelSizes )
3397 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3371 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3398 else 3372 else
3399 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3373 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3400 } 3374 }
3401 pntr->setFont( f ); 3375 pntr->setFont( f );
3402 w = pntr->fontMetrics().width( str[ pos ] ); 3376 w = pntr->fontMetrics().width( str[ pos ] );
3403 } 3377 }
3404 return w; 3378 return w;
3405} 3379}
3406 3380
3407// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3381// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3408 3382
3409QTextString::QTextString() 3383QTextString::QTextString()
3410{ 3384{
3411 bidiDirty = FALSE; 3385 bidiDirty = FALSE;
3412 bidi = FALSE; 3386 bidi = FALSE;
3413 rightToLeft = FALSE; 3387 rightToLeft = FALSE;
3414 dir = QChar::DirON; 3388 dir = QChar::DirON;
3415} 3389}
3416 3390
3417QTextString::QTextString( const QTextString &s ) 3391QTextString::QTextString( const QTextString &s )
3418{ 3392{
3419 bidiDirty = s.bidiDirty; 3393 bidiDirty = s.bidiDirty;
3420 bidi = s.bidi; 3394 bidi = s.bidi;
3421 rightToLeft = s.rightToLeft; 3395 rightToLeft = s.rightToLeft;
3422 dir = s.dir; 3396 dir = s.dir;
3423 data = s.subString(); 3397 data = s.subString();
3424} 3398}
3425 3399
3426void QTextString::insert( int index, const QString &s, QTextFormat *f ) 3400void QTextString::insert( int index, const QString &s, QTextFormat *f )
3427{ 3401{
3428 insert( index, s.unicode(), s.length(), f ); 3402 insert( index, s.unicode(), s.length(), f );
3429} 3403}
3430 3404
3431void QTextString::insert( int index, const QChar *unicode, int len, QTextFormat *f ) 3405void QTextString::insert( int index, const QChar *unicode, int len, QTextFormat *f )
3432{ 3406{
3433 int os = data.size(); 3407 int os = data.size();
3434 data.resize( data.size() + len ); 3408 data.resize( data.size() + len );
3435 if ( index < os ) { 3409 if ( index < os ) {
3436 memmove( data.data() + index + len, data.data() + index, 3410 memmove( data.data() + index + len, data.data() + index,
3437 sizeof( QTextStringChar ) * ( os - index ) ); 3411 sizeof( QTextStringChar ) * ( os - index ) );
3438 } 3412 }
3439 for ( int i = 0; i < len; ++i ) { 3413 for ( int i = 0; i < len; ++i ) {
3440 data[ (int)index + i ].x = 0; 3414 data[ (int)index + i ].x = 0;
3441 data[ (int)index + i ].lineStart = 0; 3415 data[ (int)index + i ].lineStart = 0;
3442 data[ (int)index + i ].d.format = 0; 3416 data[ (int)index + i ].d.format = 0;
3443 data[ (int)index + i ].type = QTextStringChar::Regular; 3417 data[ (int)index + i ].type = QTextStringChar::Regular;
3444 data[ (int)index + i ].rightToLeft = 0; 3418 data[ (int)index + i ].rightToLeft = 0;
3445 data[ (int)index + i ].startOfRun = 0; 3419 data[ (int)index + i ].startOfRun = 0;
3446 data[ (int)index + i ].c = unicode[i]; 3420 data[ (int)index + i ].c = unicode[i];
3447 data[ (int)index + i ].setFormat( f ); 3421 data[ (int)index + i ].setFormat( f );
3448 } 3422 }
3449 bidiDirty = TRUE; 3423 bidiDirty = TRUE;
3450} 3424}
3451 3425
3452QTextString::~QTextString() 3426QTextString::~QTextString()
3453{ 3427{
3454 clear(); 3428 clear();
3455} 3429}
3456 3430
3457void QTextString::insert( int index, QTextStringChar *c, bool doAddRefFormat ) 3431void QTextString::insert( int index, QTextStringChar *c, bool doAddRefFormat )
3458{ 3432{
3459 int os = data.size(); 3433 int os = data.size();
3460 data.resize( data.size() + 1 ); 3434 data.resize( data.size() + 1 );
3461 if ( index < os ) { 3435 if ( index < os ) {
3462 memmove( data.data() + index + 1, data.data() + index, 3436 memmove( data.data() + index + 1, data.data() + index,
3463 sizeof( QTextStringChar ) * ( os - index ) ); 3437 sizeof( QTextStringChar ) * ( os - index ) );
3464 } 3438 }
3465 data[ (int)index ].c = c->c; 3439 data[ (int)index ].c = c->c;
3466 data[ (int)index ].x = 0; 3440 data[ (int)index ].x = 0;
3467 data[ (int)index ].lineStart = 0; 3441 data[ (int)index ].lineStart = 0;
3468 data[ (int)index ].rightToLeft = 0; 3442 data[ (int)index ].rightToLeft = 0;
3469 data[ (int)index ].d.format = 0; 3443 data[ (int)index ].d.format = 0;
3470 data[ (int)index ].type = QTextStringChar::Regular; 3444 data[ (int)index ].type = QTextStringChar::Regular;
3471 if ( doAddRefFormat && c->format() ) 3445 if ( doAddRefFormat && c->format() )
3472 c->format()->addRef(); 3446 c->format()->addRef();
3473 data[ (int)index ].setFormat( c->format() ); 3447 data[ (int)index ].setFormat( c->format() );
3474 bidiDirty = TRUE; 3448 bidiDirty = TRUE;
3475} 3449}
3476 3450
3477void QTextString::truncate( int index ) 3451void QTextString::truncate( int index )
3478{ 3452{
3479 index = QMAX( index, 0 ); 3453 index = QMAX( index, 0 );
3480 index = QMIN( index, (int)data.size() - 1 ); 3454 index = QMIN( index, (int)data.size() - 1 );
3481 if ( index < (int)data.size() ) { 3455 if ( index < (int)data.size() ) {
3482 for ( int i = index + 1; i < (int)data.size(); ++i ) { 3456 for ( int i = index + 1; i < (int)data.size(); ++i ) {
3483 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3457 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3484 delete data[ i ].customItem(); 3458 delete data[ i ].customItem();
3485 if ( data[ i ].d.custom->format ) 3459 if ( data[ i ].d.custom->format )
3486 data[ i ].d.custom->format->removeRef(); 3460 data[ i ].d.custom->format->removeRef();
3487 delete data[ i ].d.custom; 3461 delete data[ i ].d.custom;
3488 data[ i ].d.custom = 0; 3462 data[ i ].d.custom = 0;
3489 } else if ( data[ i ].format() ) { 3463 } else if ( data[ i ].format() ) {
3490 data[ i ].format()->removeRef(); 3464 data[ i ].format()->removeRef();
3491 } 3465 }
3492 } 3466 }
3493 } 3467 }
3494 data.truncate( index ); 3468 data.truncate( index );
3495 bidiDirty = TRUE; 3469 bidiDirty = TRUE;
3496} 3470}
3497 3471
3498void QTextString::remove( int index, int len ) 3472void QTextString::remove( int index, int len )
3499{ 3473{
3500 for ( int i = index; i < (int)data.size() && i - index < len; ++i ) { 3474 for ( int i = index; i < (int)data.size() && i - index < len; ++i ) {
3501 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3475 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3502 delete data[ i ].customItem(); 3476 delete data[ i ].customItem();
3503 if ( data[ i ].d.custom->format ) 3477 if ( data[ i ].d.custom->format )
3504 data[ i ].d.custom->format->removeRef(); 3478 data[ i ].d.custom->format->removeRef();
3505 delete data[ i ].d.custom; 3479 delete data[ i ].d.custom;
3506 data[ i ].d.custom = 0; 3480 data[ i ].d.custom = 0;
3507 } else if ( data[ i ].format() ) { 3481 } else if ( data[ i ].format() ) {
3508 data[ i ].format()->removeRef(); 3482 data[ i ].format()->removeRef();
3509 } 3483 }
3510 } 3484 }
3511 memmove( data.data() + index, data.data() + index + len, 3485 memmove( data.data() + index, data.data() + index + len,
3512 sizeof( QTextStringChar ) * ( data.size() - index - len ) ); 3486 sizeof( QTextStringChar ) * ( data.size() - index - len ) );
3513 data.resize( data.size() - len ); 3487 data.resize( data.size() - len );
3514 bidiDirty = TRUE; 3488 bidiDirty = TRUE;
3515} 3489}
3516 3490
3517void QTextString::clear() 3491void QTextString::clear()
3518{ 3492{
3519 for ( int i = 0; i < (int)data.count(); ++i ) { 3493 for ( int i = 0; i < (int)data.count(); ++i ) {
3520 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3494 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3521 delete data[ i ].customItem(); 3495 delete data[ i ].customItem();
3522 if ( data[ i ].d.custom->format ) 3496 if ( data[ i ].d.custom->format )
3523 data[ i ].d.custom->format->removeRef(); 3497 data[ i ].d.custom->format->removeRef();
3524 delete data[ i ].d.custom; 3498 delete data[ i ].d.custom;
3525 data[ i ].d.custom = 0; 3499 data[ i ].d.custom = 0;
3526 } else if ( data[ i ].format() ) { 3500 } else if ( data[ i ].format() ) {
3527 data[ i ].format()->removeRef(); 3501 data[ i ].format()->removeRef();
3528 } 3502 }
3529 } 3503 }
3530 data.resize( 0 ); 3504 data.resize( 0 );
3531} 3505}
3532 3506
3533void QTextString::setFormat( int index, QTextFormat *f, bool useCollection ) 3507void QTextString::setFormat( int index, QTextFormat *f, bool useCollection )
3534{ 3508{
3535 if ( useCollection && data[ index ].format() ) 3509 if ( useCollection && data[ index ].format() )
3536 data[ index ].format()->removeRef(); 3510 data[ index ].format()->removeRef();
3537 data[ index ].setFormat( f ); 3511 data[ index ].setFormat( f );
3538} 3512}
3539 3513
3540void QTextString::checkBidi() const 3514void QTextString::checkBidi() const
3541{ 3515{
3542 bool rtlKnown = FALSE; 3516 bool rtlKnown = FALSE;
3543 if ( dir == QChar::DirR ) { 3517 if ( dir == QChar::DirR ) {
3544 ((QTextString *)this)->bidi = TRUE; 3518 ((QTextString *)this)->bidi = TRUE;
3545 ((QTextString *)this)->rightToLeft = TRUE; 3519 ((QTextString *)this)->rightToLeft = TRUE;
3546 rtlKnown = TRUE; 3520 rtlKnown = TRUE;
3547 return; 3521 return;
3548 } else if ( dir == QChar::DirL ) { 3522 } else if ( dir == QChar::DirL ) {
3549 ((QTextString *)this)->rightToLeft = FALSE; 3523 ((QTextString *)this)->rightToLeft = FALSE;
3550 rtlKnown = TRUE; 3524 rtlKnown = TRUE;
3551 } else { 3525 } else {
3552 ((QTextString *)this)->rightToLeft = FALSE; 3526 ((QTextString *)this)->rightToLeft = FALSE;
3553 } 3527 }
3554 3528
3555 int len = data.size(); 3529 int len = data.size();
3556 const QTextStringChar *c = data.data(); 3530 const QTextStringChar *c = data.data();
3557 ((QTextString *)this)->bidi = FALSE; 3531 ((QTextString *)this)->bidi = FALSE;
3558 while( len ) { 3532 while( len ) {
3559 if ( !rtlKnown ) { 3533 if ( !rtlKnown ) {
3560 switch( c->c.direction() ) 3534 switch( c->c.direction() )
3561 { 3535 {
3562 case QChar::DirL: 3536 case QChar::DirL:
3563 case QChar::DirLRO: 3537 case QChar::DirLRO:
3564 case QChar::DirLRE: 3538 case QChar::DirLRE:
3565 ((QTextString *)this)->rightToLeft = FALSE; 3539 ((QTextString *)this)->rightToLeft = FALSE;
3566 rtlKnown = TRUE; 3540 rtlKnown = TRUE;
3567 break; 3541 break;
3568 case QChar::DirR: 3542 case QChar::DirR:
3569 case QChar::DirAL: 3543 case QChar::DirAL:
3570 case QChar::DirRLO: 3544 case QChar::DirRLO:
3571 case QChar::DirRLE: 3545 case QChar::DirRLE:
3572 ((QTextString *)this)->rightToLeft = TRUE; 3546 ((QTextString *)this)->rightToLeft = TRUE;
3573 rtlKnown = TRUE; 3547 rtlKnown = TRUE;
3574 break; 3548 break;
3575 default: 3549 default:
3576 break; 3550 break;
3577 } 3551 }
3578 } 3552 }
3579 uchar row = c->c.row(); 3553 uchar row = c->c.row();
3580 if( (row > 0x04 && row < 0x09) || (row > 0xfa && row < 0xff) ) { 3554 if( (row > 0x04 && row < 0x09) || (row > 0xfa && row < 0xff) ) {
3581 ((QTextString *)this)->bidi = TRUE; 3555 ((QTextString *)this)->bidi = TRUE;
3582 if ( rtlKnown ) 3556 if ( rtlKnown )
3583 return; 3557 return;
3584 } 3558 }
3585 len--; 3559 len--;
3586 ++c; 3560 ++c;
3587 } 3561 }
3588} 3562}
3589 3563
3590void QTextDocument::setStyleSheet( QStyleSheet *s ) 3564void QTextDocument::setStyleSheet( QStyleSheet *s )
3591{ 3565{
3592 if ( !s ) 3566 if ( !s )
3593 return; 3567 return;
3594 sheet_ = s; 3568 sheet_ = s;
3595 list_tm = list_bm = par_tm = par_bm = 12; 3569 list_tm = list_bm = par_tm = par_bm = 12;
3596 list_lm = 40; 3570 list_lm = 40;
3597 li_tm = li_bm = 0; 3571 li_tm = li_bm = 0;
3598 QStyleSheetItem* item = s->item( "ol" ); 3572 QStyleSheetItem* item = s->item( "ol" );
3599 if ( item ) { 3573 if ( item ) {
3600 list_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); 3574 list_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3601 list_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); 3575 list_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3602 list_lm = QMAX(0,item->margin( QStyleSheetItem::MarginLeft )); 3576 list_lm = QMAX(0,item->margin( QStyleSheetItem::MarginLeft ));
3603 } 3577 }
3604 if ( (item = s->item( "li" ) ) ) { 3578 if ( (item = s->item( "li" ) ) ) {
3605 li_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); 3579 li_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3606 li_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); 3580 li_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3607 } 3581 }
3608 if ( (item = s->item( "p" ) ) ) { 3582 if ( (item = s->item( "p" ) ) ) {
3609 par_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop )); 3583 par_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3610 par_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom )); 3584 par_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3611 } 3585 }
3612} 3586}
3613 3587
3614void QTextDocument::setUnderlineLinks( bool b ) { 3588void QTextDocument::setUnderlineLinks( bool b ) {
3615 underlLinks = b; 3589 underlLinks = b;
3616 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 3590 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
3617 d->setUnderlineLinks( b ); 3591 d->setUnderlineLinks( b );
3618} 3592}
3619 3593
3620void QTextStringChar::setFormat( QTextFormat *f ) 3594void QTextStringChar::setFormat( QTextFormat *f )
3621{ 3595{
3622 if ( type == Regular ) { 3596 if ( type == Regular ) {
3623 d.format = f; 3597 d.format = f;
3624 } else { 3598 } else {
3625 if ( !d.custom ) { 3599 if ( !d.custom ) {
3626 d.custom = new CustomData; 3600 d.custom = new CustomData;
3627 d.custom->custom = 0; 3601 d.custom->custom = 0;
3628 } 3602 }
3629 d.custom->format = f; 3603 d.custom->format = f;
3630 } 3604 }
3631} 3605}
3632 3606
3633void QTextStringChar::setCustomItem( QTextCustomItem *i ) 3607void QTextStringChar::setCustomItem( QTextCustomItem *i )
3634{ 3608{
3635 if ( type == Regular ) { 3609 if ( type == Regular ) {
3636 QTextFormat *f = format(); 3610 QTextFormat *f = format();
3637 d.custom = new CustomData; 3611 d.custom = new CustomData;
3638 d.custom->format = f; 3612 d.custom->format = f;
3639 } else { 3613 } else {
3640 delete d.custom->custom; 3614 delete d.custom->custom;
3641 } 3615 }
3642 d.custom->custom = i; 3616 d.custom->custom = i;
3643 type = (type == Anchor ? CustomAnchor : Custom); 3617 type = (type == Anchor ? CustomAnchor : Custom);
3644} 3618}
3645 3619
3646void QTextStringChar::loseCustomItem() 3620void QTextStringChar::loseCustomItem()
3647{ 3621{
3648 if ( type == Custom ) { 3622 if ( type == Custom ) {
3649 QTextFormat *f = d.custom->format; 3623 QTextFormat *f = d.custom->format;
3650 d.custom->custom = 0; 3624 d.custom->custom = 0;
3651 delete d.custom; 3625 delete d.custom;
3652 type = Regular; 3626 type = Regular;
3653 d.format = f; 3627 d.format = f;
3654 } else if ( type == CustomAnchor ) { 3628 } else if ( type == CustomAnchor ) {
3655 d.custom->custom = 0; 3629 d.custom->custom = 0;
3656 type = Anchor; 3630 type = Anchor;
3657 } 3631 }
3658} 3632}
3659 3633
3660QString QTextStringChar::anchorName() const 3634QString QTextStringChar::anchorName() const
3661{ 3635{
3662 if ( type == Regular ) 3636 if ( type == Regular )
3663 return QString::null; 3637 return QString::null;
3664 else 3638 else
3665 return d.custom->anchorName; 3639 return d.custom->anchorName;
3666} 3640}
3667 3641
3668QString QTextStringChar::anchorHref() const 3642QString QTextStringChar::anchorHref() const
3669{ 3643{
3670 if ( type == Regular ) 3644 if ( type == Regular )
3671 return QString::null; 3645 return QString::null;
3672 else 3646 else
3673 return d.custom->anchorHref; 3647 return d.custom->anchorHref;
3674} 3648}
3675 3649
3676void QTextStringChar::setAnchor( const QString& name, const QString& href ) 3650void QTextStringChar::setAnchor( const QString& name, const QString& href )
3677{ 3651{
3678 if ( type == Regular ) { 3652 if ( type == Regular ) {
3679 QTextFormat *f = format(); 3653 QTextFormat *f = format();
3680 d.custom = new CustomData; 3654 d.custom = new CustomData;
3681 d.custom->custom = 0; 3655 d.custom->custom = 0;
3682 d.custom->format = f; 3656 d.custom->format = f;
3683 type = Anchor; 3657 type = Anchor;
3684 } else if ( type == Custom ) { 3658 } else if ( type == Custom ) {
3685 type = CustomAnchor; 3659 type = CustomAnchor;
3686 } 3660 }
3687 d.custom->anchorName = name; 3661 d.custom->anchorName = name;
3688 d.custom->anchorHref = href; 3662 d.custom->anchorHref = href;
3689} 3663}
3690 3664
3691 3665
3692int QTextString::width( int idx ) const 3666int QTextString::width( int idx ) const
3693{ 3667{
3694 int w = 0; 3668 int w = 0;
3695 QTextStringChar *c = &at( idx ); 3669 QTextStringChar *c = &at( idx );
3696 if ( c->c.unicode() == 0xad || c->c.unicode() == 0x2028 ) 3670 if ( c->c.unicode() == 0xad || c->c.unicode() == 0x2028 )
3697 return 0; 3671 return 0;
3698 if( c->isCustom() ) { 3672 if( c->isCustom() ) {
3699 if( c->customItem()->placement() == QTextCustomItem::PlaceInline ) 3673 if( c->customItem()->placement() == QTextCustomItem::PlaceInline )
3700 w = c->customItem()->width; 3674 w = c->customItem()->width;
3701 } else { 3675 } else {
3702 int r = c->c.row(); 3676 int r = c->c.row();
3703 if( r < 0x06 || r > 0x1f ) 3677 if( r < 0x06 || r > 0x1f )
3704 w = c->format()->width( c->c ); 3678 w = c->format()->width( c->c );
3705 else { 3679 else {
3706 // complex text. We need some hacks to get the right metric here 3680 // complex text. We need some hacks to get the right metric here
3707 QString str; 3681 QString str;
3708 int pos = 0; 3682 int pos = 0;
3709 if( idx > 4 ) 3683 if( idx > 4 )
3710 pos = idx - 4; 3684 pos = idx - 4;
3711 int off = idx - pos; 3685 int off = idx - pos;
3712 int end = QMIN( length(), idx + 4 ); 3686 int end = QMIN( length(), idx + 4 );
3713 while ( pos < end ) { 3687 while ( pos < end ) {
3714 str += at(pos).c; 3688 str += at(pos).c;
3715 pos++; 3689 pos++;
3716 } 3690 }
3717 w = c->format()->width( str, off ); 3691 w = c->format()->width( str, off );
3718 } 3692 }
3719 } 3693 }
3720 return w; 3694 return w;
3721} 3695}
3722 3696
3723QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const 3697QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const
3724{ 3698{
3725 if ( len == 0xFFFFFF ) 3699 if ( len == 0xFFFFFF )
3726 len = data.size(); 3700 len = data.size();
3727 QMemArray<QTextStringChar> a; 3701 QMemArray<QTextStringChar> a;
3728 a.resize( len ); 3702 a.resize( len );
3729 for ( int i = 0; i < len; ++i ) { 3703 for ( int i = 0; i < len; ++i ) {
3730 QTextStringChar *c = &data[ i + start ]; 3704 QTextStringChar *c = &data[ i + start ];
3731 a[ i ].c = c->c; 3705 a[ i ].c = c->c;
3732 a[ i ].x = 0; 3706 a[ i ].x = 0;
3733 a[ i ].lineStart = 0; 3707 a[ i ].lineStart = 0;
3734 a[ i ].rightToLeft = 0; 3708 a[ i ].rightToLeft = 0;
3735 a[ i ].d.format = 0; 3709 a[ i ].d.format = 0;
3736 a[ i ].type = QTextStringChar::Regular; 3710 a[ i ].type = QTextStringChar::Regular;
3737 a[ i ].setFormat( c->format() ); 3711 a[ i ].setFormat( c->format() );
3738 if ( c->format() ) 3712 if ( c->format() )
3739 c->format()->addRef(); 3713 c->format()->addRef();
3740 } 3714 }
3741 return a; 3715 return a;
3742} 3716}
3743 3717
3744// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3718// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3745 3719
3746QTextParagraph::QTextParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds ) 3720QTextParagraph::QTextParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds )
3747 : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ), 3721 : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ),
3748 changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE), 3722 changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE),
3749 lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE), 3723 lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE),
3750 mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE), 3724 mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE),
3751 align( 0 ),mSelections( 0 ), 3725 align( 0 ),mSelections( 0 ),
3752 mFloatingItems( 0 ), lstyle( QStyleSheetItem::ListDisc ), 3726 mFloatingItems( 0 ), lstyle( QStyleSheetItem::ListDisc ),
3753 utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ), 3727 utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ),
3754 tArray(0), tabStopWidth(0), eData( 0 ), ldepth( 0 ) 3728 tArray(0), tabStopWidth(0), eData( 0 ), ldepth( 0 )
3755{ 3729{
3756 lstyle = QStyleSheetItem::ListDisc; 3730 lstyle = QStyleSheetItem::ListDisc;
3757 if ( !hasdoc ) 3731 if ( !hasdoc )
3758 docOrPseudo = new QTextParagraphPseudoDocument; 3732 docOrPseudo = new QTextParagraphPseudoDocument;
3759 bgcol = 0; 3733 bgcol = 0;
3760 list_val = -1; 3734 list_val = -1;
3761 QTextFormat* defFormat = formatCollection()->defaultFormat(); 3735 QTextFormat* defFormat = formatCollection()->defaultFormat();
3762 if ( !hasdoc ) { 3736 if ( !hasdoc ) {
3763 tabStopWidth = defFormat->width( 'x' ) * 8; 3737 tabStopWidth = defFormat->width( 'x' ) * 8;
3764 pseudoDocument()->commandHistory = new QTextCommandHistory( 100 ); 3738 pseudoDocument()->commandHistory = new QTextCommandHistory( 100 );
3765 } 3739 }
3766 3740
3767 if ( p ) 3741 if ( p )
3768 p->n = this; 3742 p->n = this;
3769 if ( n ) 3743 if ( n )
3770 n->p = this; 3744 n->p = this;
3771 3745
3772 3746
3773 if ( !p && hasdoc ) 3747 if ( !p && hasdoc )
3774 document()->setFirstParagraph( this ); 3748 document()->setFirstParagraph( this );
3775 if ( !n && hasdoc ) 3749 if ( !n && hasdoc )
3776 document()->setLastParagraph( this ); 3750 document()->setLastParagraph( this );
3777 3751
3778 state = -1; 3752 state = -1;
3779 3753
3780 if ( p ) 3754 if ( p )
3781 id = p->id + 1; 3755 id = p->id + 1;
3782 else 3756 else
3783 id = 0; 3757 id = 0;
3784 if ( n && updateIds ) { 3758 if ( n && updateIds ) {
3785 QTextParagraph *s = n; 3759 QTextParagraph *s = n;
3786 while ( s ) { 3760 while ( s ) {
3787 s->id = s->p->id + 1; 3761 s->id = s->p->id + 1;
3788 s->invalidateStyleCache(); 3762 s->invalidateStyleCache();
3789 s = s->n; 3763 s = s->n;
3790 } 3764 }
3791 } 3765 }
3792 3766
3793 str = new QTextString(); 3767 str = new QTextString();
3794 str->insert( 0, " ", formatCollection()->defaultFormat() ); 3768 str->insert( 0, " ", formatCollection()->defaultFormat() );
3795} 3769}
3796 3770
3797QTextParagraph::~QTextParagraph() 3771QTextParagraph::~QTextParagraph()
3798{ 3772{
3799 delete str; 3773 delete str;
3800 if ( hasdoc ) { 3774 if ( hasdoc ) {
3801 register QTextDocument *doc = document(); 3775 register QTextDocument *doc = document();
3802 if ( this == doc->minwParag ) { 3776 if ( this == doc->minwParag ) {
3803 doc->minwParag = 0; 3777 doc->minwParag = 0;
3804 doc->minw = 0; 3778 doc->minw = 0;
3805 } 3779 }
3806 if ( this == doc->curParag ) 3780 if ( this == doc->curParag )
3807 doc->curParag = 0; 3781 doc->curParag = 0;
3808 } else { 3782 } else {
3809 delete pseudoDocument(); 3783 delete pseudoDocument();
3810 } 3784 }
3811 if ( tArray ) 3785 if ( tArray )
3812 delete [] tArray; 3786 delete [] tArray;
3813 delete eData; 3787 delete eData;
3814 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin(); 3788 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin();
3815 for ( ; it != lineStarts.end(); ++it ) 3789 for ( ; it != lineStarts.end(); ++it )
3816 delete *it; 3790 delete *it;
3817 if ( mSelections ) 3791 if ( mSelections )
3818 delete mSelections; 3792 delete mSelections;
3819 if ( mFloatingItems ) 3793 if ( mFloatingItems )
3820 delete mFloatingItems; 3794 delete mFloatingItems;
3821 if ( p ) 3795 if ( p )
3822 p->setNext( n ); 3796 p->setNext( n );
3823 if ( n ) 3797 if ( n )
3824 n->setPrev( p ); 3798 n->setPrev( p );
3825} 3799}
3826 3800
3827void QTextParagraph::setNext( QTextParagraph *s ) 3801void QTextParagraph::setNext( QTextParagraph *s )
3828{ 3802{
3829 n = s; 3803 n = s;
3830 if ( !n && hasdoc ) 3804 if ( !n && hasdoc )
3831 document()->setLastParagraph( this ); 3805 document()->setLastParagraph( this );
3832} 3806}
3833 3807
3834void QTextParagraph::setPrev( QTextParagraph *s ) 3808void QTextParagraph::setPrev( QTextParagraph *s )
3835{ 3809{
3836 p = s; 3810 p = s;
3837 if ( !p && hasdoc ) 3811 if ( !p && hasdoc )
3838 document()->setFirstParagraph( this ); 3812 document()->setFirstParagraph( this );
3839} 3813}
3840 3814
3841void QTextParagraph::invalidate( int chr ) 3815void QTextParagraph::invalidate( int chr )
3842{ 3816{
3843 if ( invalid < 0 ) 3817 if ( invalid < 0 )
3844 invalid = chr; 3818 invalid = chr;
3845 else 3819 else
3846 invalid = QMIN( invalid, chr ); 3820 invalid = QMIN( invalid, chr );
3847 if ( mFloatingItems ) { 3821 if ( mFloatingItems ) {
3848 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) 3822 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() )
3849 i->ypos = -1; 3823 i->ypos = -1;
3850 } 3824 }
3851 invalidateStyleCache(); 3825 invalidateStyleCache();
3852} 3826}
3853 3827
3854void QTextParagraph::invalidateStyleCache() 3828void QTextParagraph::invalidateStyleCache()
3855{ 3829{
3856 if ( list_val < 0 ) 3830 if ( list_val < 0 )
3857 list_val = -1; 3831 list_val = -1;
3858} 3832}
3859 3833
3860 3834
3861void QTextParagraph::insert( int index, const QString &s ) 3835void QTextParagraph::insert( int index, const QString &s )
3862{ 3836{
3863 insert( index, s.unicode(), s.length() ); 3837 insert( index, s.unicode(), s.length() );
3864} 3838}
3865 3839
3866void QTextParagraph::insert( int index, const QChar *unicode, int len ) 3840void QTextParagraph::insert( int index, const QChar *unicode, int len )
3867{ 3841{
3868 if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() ) 3842 if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() )
3869 str->insert( index, unicode, len, 3843 str->insert( index, unicode, len,
3870 document()->preProcessor()->format( QTextPreProcessor::Standard ) ); 3844 document()->preProcessor()->format( QTextPreProcessor::Standard ) );
3871 else 3845 else
3872 str->insert( index, unicode, len, formatCollection()->defaultFormat() ); 3846 str->insert( index, unicode, len, formatCollection()->defaultFormat() );
3873 invalidate( index ); 3847 invalidate( index );
3874 needPreProcess = TRUE; 3848 needPreProcess = TRUE;
3875} 3849}
3876 3850
3877void QTextParagraph::truncate( int index ) 3851void QTextParagraph::truncate( int index )
3878{ 3852{
3879 str->truncate( index ); 3853 str->truncate( index );
3880 insert( length(), " " ); 3854 insert( length(), " " );
3881 needPreProcess = TRUE; 3855 needPreProcess = TRUE;
3882} 3856}
3883 3857
3884void QTextParagraph::remove( int index, int len ) 3858void QTextParagraph::remove( int index, int len )
3885{ 3859{
3886 if ( index + len - str->length() > 0 ) 3860 if ( index + len - str->length() > 0 )
3887 return; 3861 return;
3888 for ( int i = index; i < index + len; ++i ) { 3862 for ( int i = index; i < index + len; ++i ) {
3889 QTextStringChar *c = at( i ); 3863 QTextStringChar *c = at( i );
3890 if ( hasdoc && c->isCustom() ) { 3864 if ( hasdoc && c->isCustom() ) {
3891 document()->unregisterCustomItem( c->customItem(), this ); 3865 document()->unregisterCustomItem( c->customItem(), this );
3892 } 3866 }
3893 } 3867 }
3894 str->remove( index, len ); 3868 str->remove( index, len );
3895 invalidate( 0 ); 3869 invalidate( 0 );
3896 needPreProcess = TRUE; 3870 needPreProcess = TRUE;
3897} 3871}
3898 3872
3899void QTextParagraph::join( QTextParagraph *s ) 3873void QTextParagraph::join( QTextParagraph *s )
3900{ 3874{
3901 int oh = r.height() + s->r.height(); 3875 int oh = r.height() + s->r.height();
3902 n = s->n; 3876 n = s->n;
3903 if ( n ) 3877 if ( n )
3904 n->p = this; 3878 n->p = this;
3905 else if ( hasdoc ) 3879 else if ( hasdoc )
3906 document()->setLastParagraph( this ); 3880 document()->setLastParagraph( this );
3907 3881
3908 int start = str->length(); 3882 int start = str->length();
3909 if ( length() > 0 && at( length() - 1 )->c == ' ' ) { 3883 if ( length() > 0 && at( length() - 1 )->c == ' ' ) {
3910 remove( length() - 1, 1 ); 3884 remove( length() - 1, 1 );
3911 --start; 3885 --start;
3912 } 3886 }
3913 append( s->str->toString(), TRUE ); 3887 append( s->str->toString(), TRUE );
3914 3888
3915 for ( int i = 0; i < s->length(); ++i ) { 3889 for ( int i = 0; i < s->length(); ++i ) {
3916 if ( !hasdoc || document()->useFormatCollection() ) { 3890 if ( !hasdoc || document()->useFormatCollection() ) {
3917 s->str->at( i ).format()->addRef(); 3891 s->str->at( i ).format()->addRef();
3918 str->setFormat( i + start, s->str->at( i ).format(), TRUE ); 3892 str->setFormat( i + start, s->str->at( i ).format(), TRUE );
3919 } 3893 }
3920 if ( s->str->at( i ).isCustom() ) { 3894 if ( s->str->at( i ).isCustom() ) {
3921 QTextCustomItem * item = s->str->at( i ).customItem(); 3895 QTextCustomItem * item = s->str->at( i ).customItem();
3922 str->at( i + start ).setCustomItem( item ); 3896 str->at( i + start ).setCustomItem( item );
3923 s->str->at( i ).loseCustomItem(); 3897 s->str->at( i ).loseCustomItem();
3924 if ( hasdoc ) { 3898 if ( hasdoc ) {
3925 document()->unregisterCustomItem( item, s ); 3899 document()->unregisterCustomItem( item, s );
3926 document()->registerCustomItem( item, this ); 3900 document()->registerCustomItem( item, this );
3927 } 3901 }
3928 } 3902 }
3929 if ( s->str->at( i ).isAnchor() ) { 3903 if ( s->str->at( i ).isAnchor() ) {
3930 str->at( i + start ).setAnchor( s->str->at( i ).anchorName(), 3904 str->at( i + start ).setAnchor( s->str->at( i ).anchorName(),
3931 s->str->at( i ).anchorHref() ); 3905 s->str->at( i ).anchorHref() );
3932 } 3906 }
3933 } 3907 }
3934 3908
3935 if ( !extraData() && s->extraData() ) { 3909 if ( !extraData() && s->extraData() ) {
3936 setExtraData( s->extraData() ); 3910 setExtraData( s->extraData() );
3937 s->setExtraData( 0 ); 3911 s->setExtraData( 0 );
3938 } else if ( extraData() && s->extraData() ) { 3912 } else if ( extraData() && s->extraData() ) {
3939 extraData()->join( s->extraData() ); 3913 extraData()->join( s->extraData() );
3940 } 3914 }
3941 delete s; 3915 delete s;
3942 invalidate( 0 ); 3916 invalidate( 0 );
3943 r.setHeight( oh ); 3917 r.setHeight( oh );
3944 needPreProcess = TRUE; 3918 needPreProcess = TRUE;
3945 if ( n ) { 3919 if ( n ) {
3946 QTextParagraph *s = n; 3920 QTextParagraph *s = n;
3947 s->invalidate( 0 ); 3921 s->invalidate( 0 );
3948 while ( s ) { 3922 while ( s ) {
3949 s->id = s->p->id + 1; 3923 s->id = s->p->id + 1;
3950 s->state = -1; 3924 s->state = -1;
3951 s->needPreProcess = TRUE; 3925 s->needPreProcess = TRUE;
3952 s->changed = TRUE; 3926 s->changed = TRUE;
3953 s->invalidateStyleCache(); 3927 s->invalidateStyleCache();
3954 s = s->n; 3928 s = s->n;
3955 } 3929 }
3956 } 3930 }
3957 format(); 3931 format();
3958 state = -1; 3932 state = -1;
3959} 3933}
3960 3934
3961void QTextParagraph::move( int &dy ) 3935void QTextParagraph::move( int &dy )
3962{ 3936{
3963 if ( dy == 0 ) 3937 if ( dy == 0 )
3964 return; 3938 return;
3965 changed = TRUE; 3939 changed = TRUE;
3966 r.moveBy( 0, dy ); 3940 r.moveBy( 0, dy );
3967 if ( mFloatingItems ) { 3941 if ( mFloatingItems ) {
3968 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) 3942 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() )
3969 i->ypos += dy; 3943 i->ypos += dy;
3970 } 3944 }
3971 if ( p ) 3945 if ( p )
3972 p->lastInFrame = TRUE; 3946 p->lastInFrame = TRUE;
3973 3947
3974 // do page breaks if required 3948 // do page breaks if required
3975 if ( hasdoc && document()->isPageBreakEnabled() ) { 3949 if ( hasdoc && document()->isPageBreakEnabled() ) {
3976 int shift; 3950 int shift;
3977 if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) { 3951 if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) {
3978 if ( p ) 3952 if ( p )
3979 p->setChanged( TRUE ); 3953 p->setChanged( TRUE );
3980 dy += shift; 3954 dy += shift;
3981 } 3955 }
3982 } 3956 }
3983} 3957}
3984 3958
3985void QTextParagraph::format( int start, bool doMove ) 3959void QTextParagraph::format( int start, bool doMove )
3986{ 3960{
3987 if ( !str || str->length() == 0 || !formatter() ) 3961 if ( !str || str->length() == 0 || !formatter() )
3988 return; 3962 return;
3989 3963
3990 if ( hasdoc && 3964 if ( hasdoc &&
3991 document()->preProcessor() && 3965 document()->preProcessor() &&
3992 ( needPreProcess || state == -1 ) ) 3966 ( needPreProcess || state == -1 ) )
3993 document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid ); 3967 document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid );
3994 needPreProcess = FALSE; 3968 needPreProcess = FALSE;
3995 3969
3996 if ( invalid == -1 ) 3970 if ( invalid == -1 )
3997 return; 3971 return;
3998 3972
3999 r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) ); 3973 r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) );
4000 if ( p ) 3974 if ( p )
4001 p->lastInFrame = FALSE; 3975 p->lastInFrame = FALSE;
4002 3976
4003 movedDown = FALSE; 3977 movedDown = FALSE;
4004 bool formattedAgain = FALSE; 3978 bool formattedAgain = FALSE;
4005 3979
4006 formatAgain: 3980 formatAgain:
4007 3981
4008 r.setWidth( documentWidth() ); 3982 r.setWidth( documentWidth() );
4009 if ( hasdoc && mFloatingItems ) { 3983 if ( hasdoc && mFloatingItems ) {
4010 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) { 3984 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) {
4011 i->ypos = r.y(); 3985 i->ypos = r.y();
4012 if ( i->placement() == QTextCustomItem::PlaceRight ) { 3986 if ( i->placement() == QTextCustomItem::PlaceRight ) {
4013 i->xpos = r.x() + r.width() - i->width; 3987 i->xpos = r.x() + r.width() - i->width;
4014 } 3988 }
4015 } 3989 }
4016 } 3990 }
4017 QMap<int, QTextLineStart*> oldLineStarts = lineStarts; 3991 QMap<int, QTextLineStart*> oldLineStarts = lineStarts;
4018 lineStarts.clear(); 3992 lineStarts.clear();
4019 int y = formatter()->format( document(), this, start, oldLineStarts ); 3993 int y = formatter()->format( document(), this, start, oldLineStarts );
4020 3994
4021 3995
4022 r.setWidth( QMAX( r.width(), formatter()->minimumWidth() ) ); 3996 r.setWidth( QMAX( r.width(), formatter()->minimumWidth() ) );
4023 3997
4024 3998
4025 QMap<int, QTextLineStart*>::Iterator it = oldLineStarts.begin(); 3999 QMap<int, QTextLineStart*>::Iterator it = oldLineStarts.begin();
4026 4000
4027 for ( ; it != oldLineStarts.end(); ++it ) 4001 for ( ; it != oldLineStarts.end(); ++it )
4028 delete *it; 4002 delete *it;
4029 4003
4030 QTextStringChar *c = 0; 4004 QTextStringChar *c = 0;
4031 // do not do this on mac, as the paragraph 4005 // do not do this on mac, as the paragraph
4032 // with has to be the full document width on mac as the selections 4006 // with has to be the full document width on mac as the selections
4033 // always extend completely to the right. This is a bit unefficient, 4007 // always extend completely to the right. This is a bit unefficient,
4034 // as this results in a bigger double buffer than needed but ok for 4008 // as this results in a bigger double buffer than needed but ok for
4035 // now. 4009 // now.
4036 if ( lineStarts.count() == 1 ) { 4010 if ( lineStarts.count() == 1 ) {
4037 if ( !string()->isBidi() ) { 4011 if ( !string()->isBidi() ) {
4038 c = &str->at( str->length() - 1 ); 4012 c = &str->at( str->length() - 1 );
4039 r.setWidth( c->x + str->width( str->length() - 1 ) ); 4013 r.setWidth( c->x + str->width( str->length() - 1 ) );
4040 } else { 4014 } else {
4041 r.setWidth( lineStarts[0]->w ); 4015 r.setWidth( lineStarts[0]->w );
4042 } 4016 }
4043 } 4017 }
4044 4018
4045 if ( !hasdoc ) { // qt_format_text bounding rect handling 4019 if ( !hasdoc ) { // qt_format_text bounding rect handling
4046 it = lineStarts.begin(); 4020 it = lineStarts.begin();
4047 int usedw = 0; 4021 int usedw = 0;
4048 for ( ; it != lineStarts.end(); ++it ) 4022 for ( ; it != lineStarts.end(); ++it )
4049 usedw = QMAX( usedw, (*it)->w ); 4023 usedw = QMAX( usedw, (*it)->w );
4050 if ( r.width() <= 0 ) { 4024 if ( r.width() <= 0 ) {
4051 // if the user specifies an invalid rect, this means that the 4025 // if the user specifies an invalid rect, this means that the
4052 // bounding box should grow to the width that the text actually 4026 // bounding box should grow to the width that the text actually
4053 // needs 4027 // needs
4054 r.setWidth( usedw ); 4028 r.setWidth( usedw );
4055 } else { 4029 } else {
4056 r.setWidth( QMIN( usedw, r.width() ) ); 4030 r.setWidth( QMIN( usedw, r.width() ) );
4057 } 4031 }
4058 } 4032 }
4059 4033
4060 if ( y != r.height() ) 4034 if ( y != r.height() )
4061 r.setHeight( y ); 4035 r.setHeight( y );
4062 4036
4063 if ( !visible ) { 4037 if ( !visible ) {
4064 r.setHeight( 0 ); 4038 r.setHeight( 0 );
4065 } else { 4039 } else {
4066 int minw = formatter()->minimumWidth(); 4040 int minw = formatter()->minimumWidth();
4067 int wused = formatter()->widthUsed(); 4041 int wused = formatter()->widthUsed();
4068 wused = QMAX( minw, wused ); 4042 wused = QMAX( minw, wused );
4069 if ( hasdoc ) { 4043 if ( hasdoc ) {
4070 document()->setMinimumWidth( minw, wused, this ); 4044 document()->setMinimumWidth( minw, wused, this );
4071 } else { 4045 } else {
4072 pseudoDocument()->minw = QMAX( pseudoDocument()->minw, minw ); 4046 pseudoDocument()->minw = QMAX( pseudoDocument()->minw, minw );
4073 pseudoDocument()->wused = QMAX( pseudoDocument()->wused, wused ); 4047 pseudoDocument()->wused = QMAX( pseudoDocument()->wused, wused );
4074 } 4048 }
4075 } 4049 }
4076 4050
4077 // do page breaks if required 4051 // do page breaks if required
4078 if ( hasdoc && document()->isPageBreakEnabled() ) { 4052 if ( hasdoc && document()->isPageBreakEnabled() ) {
4079 int shift = document()->formatter()->formatVertically( document(), this ); 4053 int shift = document()->formatter()->formatVertically( document(), this );
4080 if ( shift && !formattedAgain ) { 4054 if ( shift && !formattedAgain ) {
4081 formattedAgain = TRUE; 4055 formattedAgain = TRUE;
4082 goto formatAgain; 4056 goto formatAgain;
4083 } 4057 }
4084 } 4058 }
4085 4059
4086 if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) { 4060 if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) {
4087 int dy = ( r.y() + r.height() ) - n->r.y(); 4061 int dy = ( r.y() + r.height() ) - n->r.y();
4088 QTextParagraph *s = n; 4062 QTextParagraph *s = n;
4089 bool makeInvalid = p && p->lastInFrame; 4063 bool makeInvalid = p && p->lastInFrame;
4090 while ( s && dy ) { 4064 while ( s && dy ) {
4091 if ( !s->isFullWidth() ) 4065 if ( !s->isFullWidth() )
4092 makeInvalid = TRUE; 4066 makeInvalid = TRUE;
4093 if ( makeInvalid ) 4067 if ( makeInvalid )
4094 s->invalidate( 0 ); 4068 s->invalidate( 0 );
4095 s->move( dy ); 4069 s->move( dy );
4096 if ( s->lastInFrame ) 4070 if ( s->lastInFrame )
4097 makeInvalid = TRUE; 4071 makeInvalid = TRUE;
4098 s = s->n; 4072 s = s->n;
4099 } 4073 }
4100 } 4074 }
4101 4075
4102 firstFormat = FALSE; 4076 firstFormat = FALSE;
4103 changed = TRUE; 4077 changed = TRUE;
4104 invalid = -1; 4078 invalid = -1;
4105 //##### string()->setTextChanged( FALSE ); 4079 //##### string()->setTextChanged( FALSE );
4106} 4080}
4107 4081
4108int QTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const 4082int QTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const
4109{ 4083{
4110 if ( !isValid() ) 4084 if ( !isValid() )
4111 ( (QTextParagraph*)this )->format(); 4085 ( (QTextParagraph*)this )->format();
4112 4086
4113 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end(); 4087 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end();
4114 --it; 4088 --it;
4115 for ( ;; ) { 4089 for ( ;; ) {
4116 if ( i >= it.key() ) { 4090 if ( i >= it.key() ) {
4117 if ( bl ) 4091 if ( bl )
4118 *bl = ( *it )->baseLine; 4092 *bl = ( *it )->baseLine;
4119 if ( y ) 4093 if ( y )
4120 *y = ( *it )->y; 4094 *y = ( *it )->y;
4121 return ( *it )->h; 4095 return ( *it )->h;
4122 } 4096 }
4123 if ( it == lineStarts.begin() ) 4097 if ( it == lineStarts.begin() )
4124 break; 4098 break;
4125 --it; 4099 --it;
4126 } 4100 }
4127 4101
4128 owarn << "QTextParagraph::lineHeightOfChar: couldn't find lh for " << i << "" << oendl; 4102 owarn << "QTextParagraph::lineHeightOfChar: couldn't find lh for " << i << "" << oendl;
4129 return 15; 4103 return 15;
4130} 4104}
4131 4105
4132QTextStringChar *QTextParagraph::lineStartOfChar( int i, int *index, int *line ) const 4106QTextStringChar *QTextParagraph::lineStartOfChar( int i, int *index, int *line ) const
4133{ 4107{
4134 if ( !isValid() ) 4108 if ( !isValid() )
4135 ( (QTextParagraph*)this )->format(); 4109 ( (QTextParagraph*)this )->format();
4136 4110
4137 int l = (int)lineStarts.count() - 1; 4111 int l = (int)lineStarts.count() - 1;
4138 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end(); 4112 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end();
4139 --it; 4113 --it;
4140 for ( ;; ) { 4114 for ( ;; ) {
4141 if ( i >= it.key() ) { 4115 if ( i >= it.key() ) {
4142 if ( index ) 4116 if ( index )
4143 *index = it.key(); 4117 *index = it.key();
4144 if ( line ) 4118 if ( line )
4145 *line = l; 4119 *line = l;
4146 return &str->at( it.key() ); 4120 return &str->at( it.key() );
4147 } 4121 }
4148 if ( it == lineStarts.begin() ) 4122 if ( it == lineStarts.begin() )
4149 break; 4123 break;
4150 --it; 4124 --it;
4151 --l; 4125 --l;
4152 } 4126 }
4153 4127
4154 owarn << "QTextParagraph::lineStartOfChar: couldn't find " << i << "" << oendl; 4128 owarn << "QTextParagraph::lineStartOfChar: couldn't find " << i << "" << oendl;
4155 return 0; 4129 return 0;
4156} 4130}
4157 4131
4158int QTextParagraph::lines() const 4132int QTextParagraph::lines() const
4159{ 4133{
4160 if ( !isValid() ) 4134 if ( !isValid() )
4161 ( (QTextParagraph*)this )->format(); 4135 ( (QTextParagraph*)this )->format();
4162 4136
4163 return (int)lineStarts.count(); 4137 return (int)lineStarts.count();
4164} 4138}
4165 4139
4166QTextStringChar *QTextParagraph::lineStartOfLine( int line, int *index ) const 4140QTextStringChar *QTextParagraph::lineStartOfLine( int line, int *index ) const
4167{ 4141{
4168 if ( !isValid() ) 4142 if ( !isValid() )
4169 ( (QTextParagraph*)this )->format(); 4143 ( (QTextParagraph*)this )->format();
4170 4144
4171 if ( line >= 0 && line < (int)lineStarts.count() ) { 4145 if ( line >= 0 && line < (int)lineStarts.count() ) {
4172 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); 4146 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
4173 while ( line-- > 0 ) 4147 while ( line-- > 0 )
4174 ++it; 4148 ++it;
4175 int i = it.key(); 4149 int i = it.key();
4176 if ( index ) 4150 if ( index )
4177 *index = i; 4151 *index = i;
4178 return &str->at( i ); 4152 return &str->at( i );
4179 } 4153 }
4180 4154
4181 owarn << "QTextParagraph::lineStartOfLine: couldn't find " << line << "" << oendl; 4155 owarn << "QTextParagraph::lineStartOfLine: couldn't find " << line << "" << oendl;
4182 return 0; 4156 return 0;
4183} 4157}
4184 4158
4185int QTextParagraph::leftGap() const 4159int QTextParagraph::leftGap() const
4186{ 4160{
4187 if ( !isValid() ) 4161 if ( !isValid() )
4188 ( (QTextParagraph*)this )->format(); 4162 ( (QTextParagraph*)this )->format();
4189 4163
4190 int line = 0; 4164 int line = 0;
4191 int x = str->at(0).x; /* set x to x of first char */ 4165 int x = str->at(0).x; /* set x to x of first char */
4192 if ( str->isBidi() ) { 4166 if ( str->isBidi() ) {
4193 for ( int i = 1; i < str->length()-1; ++i ) 4167 for ( int i = 1; i < str->length()-1; ++i )
4194 x = QMIN(x, str->at(i).x); 4168 x = QMIN(x, str->at(i).x);
4195 return x; 4169 return x;
4196 } 4170 }
4197 4171
4198 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin(); 4172 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
4199 while (line < (int)lineStarts.count()) { 4173 while (line < (int)lineStarts.count()) {
4200 int i = it.key(); /* char index */ 4174 int i = it.key(); /* char index */
4201 x = QMIN(x, str->at(i).x); 4175 x = QMIN(x, str->at(i).x);
4202 ++it; 4176 ++it;
4203 ++line; 4177 ++line;
4204 } 4178 }
4205 return x; 4179 return x;
4206} 4180}
4207 4181
4208void QTextParagraph::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags ) 4182void QTextParagraph::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags )
4209{ 4183{
4210 if ( !f ) 4184 if ( !f )
4211 return; 4185 return;
4212 if ( index < 0 ) 4186 if ( index < 0 )
4213 index = 0; 4187 index = 0;
4214 if ( index > str->length() - 1 ) 4188 if ( index > str->length() - 1 )
4215 index = str->length() - 1; 4189 index = str->length() - 1;
4216 if ( index + len >= str->length() ) 4190 if ( index + len >= str->length() )
4217 len = str->length() - index; 4191 len = str->length() - index;
4218 4192
4219 QTextFormatCollection *fc = 0; 4193 QTextFormatCollection *fc = 0;
4220 if ( useCollection ) 4194 if ( useCollection )
4221 fc = formatCollection(); 4195 fc = formatCollection();
4222 QTextFormat *of; 4196 QTextFormat *of;
4223 for ( int i = 0; i < len; ++i ) { 4197 for ( int i = 0; i < len; ++i ) {
4224 of = str->at( i + index ).format(); 4198 of = str->at( i + index ).format();
4225 if ( !changed && f->key() != of->key() ) 4199 if ( !changed && f->key() != of->key() )
4226 changed = TRUE; 4200 changed = TRUE;
4227 if ( invalid == -1 && 4201 if ( invalid == -1 &&
4228 ( f->font().family() != of->font().family() || 4202 ( f->font().family() != of->font().family() ||
4229 f->font().pointSize() != of->font().pointSize() || 4203 f->font().pointSize() != of->font().pointSize() ||
4230 f->font().weight() != of->font().weight() || 4204 f->font().weight() != of->font().weight() ||
4231 f->font().italic() != of->font().italic() || 4205 f->font().italic() != of->font().italic() ||
4232 f->vAlign() != of->vAlign() ) ) { 4206 f->vAlign() != of->vAlign() ) ) {
4233 invalidate( 0 ); 4207 invalidate( 0 );
4234 } 4208 }
4235 if ( flags == -1 || flags == QTextFormat::Format || !fc ) { 4209 if ( flags == -1 || flags == QTextFormat::Format || !fc ) {
4236 if ( fc ) 4210 if ( fc )
4237 f = fc->format( f ); 4211 f = fc->format( f );
4238 str->setFormat( i + index, f, useCollection ); 4212 str->setFormat( i + index, f, useCollection );
4239 } else { 4213 } else {
4240 QTextFormat *fm = fc->format( of, f, flags ); 4214 QTextFormat *fm = fc->format( of, f, flags );
4241 str->setFormat( i + index, fm, useCollection ); 4215 str->setFormat( i + index, fm, useCollection );
4242 } 4216 }
4243 } 4217 }
4244} 4218}
4245 4219
4246void QTextParagraph::indent( int *oldIndent, int *newIndent ) 4220void QTextParagraph::indent( int *oldIndent, int *newIndent )
4247{ 4221{
4248 if ( !hasdoc || !document()->indent() || isListItem() ) { 4222 if ( !hasdoc || !document()->indent() || isListItem() ) {
4249 if ( oldIndent ) 4223 if ( oldIndent )
4250 *oldIndent = 0; 4224 *oldIndent = 0;
4251 if ( newIndent ) 4225 if ( newIndent )
4252 *newIndent = 0; 4226 *newIndent = 0;
4253 if ( oldIndent && newIndent ) 4227 if ( oldIndent && newIndent )
4254 *newIndent = *oldIndent; 4228 *newIndent = *oldIndent;
4255 return; 4229 return;
4256 } 4230 }
4257 document()->indent()->indent( document(), this, oldIndent, newIndent ); 4231 document()->indent()->indent( document(), this, oldIndent, newIndent );
4258} 4232}
4259 4233
4260void QTextParagraph::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections, 4234void QTextParagraph::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections,
4261 int clipx, int clipy, int clipw, int cliph ) 4235 int clipx, int clipy, int clipw, int cliph )
4262{ 4236{
4263 if ( !visible ) 4237 if ( !visible )
4264 return; 4238 return;
4265 QTextStringChar *chr = 0; 4239 QTextStringChar *chr = 0;
4266 int i, y, h, baseLine, xstart, xend; 4240 int i, y, h, baseLine, xstart, xend;
4267 i = y =h = baseLine = 0; 4241 i = y =h = baseLine = 0;
4268 QRect cursorRect; 4242 QRect cursorRect;
4269 drawSelections &= ( mSelections != 0 ); 4243 drawSelections &= ( mSelections != 0 );
4270 // macintosh full-width selection style 4244 // macintosh full-width selection style
4271 bool fullWidthStyle = FALSE; 4245 bool fullWidthStyle = FALSE;
4272 int fullSelectionWidth = 0; 4246 int fullSelectionWidth = 0;
4273 if ( drawSelections && fullWidthStyle ) 4247 if ( drawSelections && fullWidthStyle )
4274 fullSelectionWidth = (hasdoc ? document()->width() : r.width()); 4248 fullSelectionWidth = (hasdoc ? document()->width() : r.width());
4275 4249
4276 QString qstr = str->toString(); 4250 QString qstr = str->toString();
4277 // ### workaround so that \n are not drawn, actually this should 4251 // ### workaround so that \n are not drawn, actually this should
4278 // be fixed in QFont somewhere (under Windows you get ugly boxes 4252 // be fixed in QFont somewhere (under Windows you get ugly boxes
4279 // otherwise) 4253 // otherwise)
4280 QChar* uc = (QChar*) qstr.unicode(); 4254 QChar* uc = (QChar*) qstr.unicode();
4281 for ( uint ii = 0; ii < qstr.length(); ii++ ) 4255 for ( uint ii = 0; ii < qstr.length(); ii++ )
4282 if ( uc[(int)ii]== '\n' || uc[(int)ii] == QChar_linesep || uc[(int)ii] == '\t' ) 4256 if ( uc[(int)ii]== '\n' || uc[(int)ii] == QChar_linesep || uc[(int)ii] == '\t' )
4283 uc[(int)ii] = 0x20; 4257 uc[(int)ii] = 0x20;
4284 4258
4285 int line = -1; 4259 int line = -1;
4286 int paintStart = 0; 4260 int paintStart = 0;
4287 int selection = -1; 4261 int selection = -1;
4288 for ( i = 0; i < length(); i++ ) { 4262 for ( i = 0; i < length(); i++ ) {
4289 chr = at( i ); 4263 chr = at( i );
4290 4264
4291 // we flush at end of document 4265 // we flush at end of document
4292 bool flush = i== length()-1; 4266 bool flush = i== length()-1;
4293 bool selectionStateChanged = FALSE; 4267 bool selectionStateChanged = FALSE;
4294 if ( !flush ) { 4268 if ( !flush ) {
4295 QTextStringChar *nextchr = at( i+1 ); 4269 QTextStringChar *nextchr = at( i+1 );
4296 // we flush at end of line 4270 // we flush at end of line
4297 flush |= nextchr->lineStart; 4271 flush |= nextchr->lineStart;
4298 // we flush on format changes 4272 // we flush on format changes
4299 flush |= ( nextchr->format() != chr->format() ); 4273 flush |= ( nextchr->format() != chr->format() );
4300 // we flush on anchor changes 4274 // we flush on anchor changes
4301 flush |= ( nextchr->isAnchor() != chr->isAnchor() ); 4275 flush |= ( nextchr->isAnchor() != chr->isAnchor() );
4302 // we flush on start of run 4276 // we flush on start of run
4303 flush |= nextchr->startOfRun; 4277 flush |= nextchr->startOfRun;
4304 // we flush on bidi changes 4278 // we flush on bidi changes
4305 flush |= ( nextchr->rightToLeft != chr->rightToLeft ); 4279 flush |= ( nextchr->rightToLeft != chr->rightToLeft );
4306 // we flush on tab 4280 // we flush on tab
4307 flush |= ( chr->c == '\t' ); 4281 flush |= ( chr->c == '\t' );
4308 // we flush on soft hypens 4282 // we flush on soft hypens
4309 flush |= ( chr->c.unicode() == 0xad ); 4283 flush |= ( chr->c.unicode() == 0xad );
4310 // we flush on custom items 4284 // we flush on custom items
4311 flush |= chr->isCustom(); 4285 flush |= chr->isCustom();
4312 // we flush before custom items 4286 // we flush before custom items
4313 flush |= nextchr->isCustom(); 4287 flush |= nextchr->isCustom();
4314 // when painting justified, we flush on spaces 4288 // when painting justified, we flush on spaces
4315 if ((alignment() & Qt3::AlignJustify) == Qt3::AlignJustify ) 4289 if ((alignment() & Qt3::AlignJustify) == Qt3::AlignJustify )
4316 flush |= QTextFormatter::isBreakable( str, i ); 4290 flush |= QTextFormatter::isBreakable( str, i );
4317 // we flush when the string is getting too long 4291 // we flush when the string is getting too long
4318 flush |= ( i - paintStart >= 256 ); 4292 flush |= ( i - paintStart >= 256 );
4319 // we flush when the selection state changes 4293 // we flush when the selection state changes
4320 if ( drawSelections ) { 4294 if ( drawSelections ) {
4321 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin(); 4295 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin();
4322 it != mSelections->end(); ++it ) 4296 it != mSelections->end(); ++it )
4323 selectionStateChanged |=( (*it).start == i || (*it).start == i+1 || (*it).end == i+1 ); 4297 selectionStateChanged |=( (*it).start == i || (*it).start == i+1 || (*it).end == i+1 );
4324 flush |= selectionStateChanged; 4298 flush |= selectionStateChanged;
4325 } 4299 }
4326 } 4300 }
4327 4301
4328 // init a new line 4302 // init a new line
4329 if ( chr->lineStart ) { 4303 if ( chr->lineStart ) {
4330 if (fullWidthStyle && drawSelections && selection >= 0) 4304 if (fullWidthStyle && drawSelections && selection >= 0)
4331 painter.fillRect( xend, y, fullSelectionWidth - xend, h, 4305 painter.fillRect( xend, y, fullSelectionWidth - xend, h,
4332 (selection == QTextDocument::Standard || !hasdoc) ? 4306 (selection == QTextDocument::Standard || !hasdoc) ?
4333 cg.color( QColorGroup::Highlight ) : 4307 cg.color( QColorGroup::Highlight ) :
4334 document()->selectionColor( selection ) ); 4308 document()->selectionColor( selection ) );
4335 ++line; 4309 ++line;
4336 paintStart = i; 4310 paintStart = i;
4337 lineInfo( line, y, h, baseLine ); 4311 lineInfo( line, y, h, baseLine );
4338 if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave 4312 if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave
4339 break; 4313 break;
4340 } 4314 }
4341 4315
4342 // if this is the first line and we are a list item, draw the the bullet label 4316 // if this is the first line and we are a list item, draw the the bullet label
4343 if ( line == 0 && isListItem() ) 4317 if ( line == 0 && isListItem() )
4344 drawLabel( &painter, chr->x, y, 0, 0, baseLine, cg ); 4318 drawLabel( &painter, chr->x, y, 0, 0, baseLine, cg );
4345 } 4319 }
4346 4320
4347 // check for cursor mark 4321 // check for cursor mark
4348 if ( cursor && this == cursor->paragraph() && i == cursor->index() ) { 4322 if ( cursor && this == cursor->paragraph() && i == cursor->index() ) {
4349 QTextStringChar *c = i == 0 ? chr : chr - 1; 4323 QTextStringChar *c = i == 0 ? chr : chr - 1;
4350 cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(), 4324 cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(),
4351 1, c->format()->height() ); 4325 1, c->format()->height() );
4352 } 4326 }
4353 4327
4354 // check if we are in a selection and store which one it is 4328 // check if we are in a selection and store which one it is
4355 selection = -1; 4329 selection = -1;
4356 if ( drawSelections ) { 4330 if ( drawSelections ) {
4357 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin(); 4331 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin();
4358 it != mSelections->end(); ++it ) 4332 it != mSelections->end(); ++it )
4359 if ( (*it).start <= i && i < (*it).end + ( (*it).end == length()-1 && n && n->hasSelection(it.key()) ) ? 1:0 4333 if ( (*it).start <= i && i < (*it).end + ( (*it).end == length()-1 && n && n->hasSelection(it.key()) ) ? 1:0
4360 // exclude the standard selection from printing 4334 // exclude the standard selection from printing
4361 && (it.key() != QTextDocument::Standard || !is_printer( &painter) ) ) { 4335 && (it.key() != QTextDocument::Standard || !is_printer( &painter) ) ) {
4362 selection = it.key(); 4336 selection = it.key();
4363 break; 4337 break;
4364 } 4338 }
4365 } 4339 }
4366 4340
4367 if ( flush ) { // something changed, draw what we have so far 4341 if ( flush ) { // something changed, draw what we have so far
4368 if ( chr->rightToLeft ) { 4342 if ( chr->rightToLeft ) {
4369 xstart = chr->x; 4343 xstart = chr->x;
4370 xend = at( paintStart )->x + str->width( paintStart ); 4344 xend = at( paintStart )->x + str->width( paintStart );
4371 } else { 4345 } else {
4372 xstart = at( paintStart )->x; 4346 xstart = at( paintStart )->x;
4373 if ( !selectionStateChanged && i < length() - 1 && !str->at( i + 1 ).lineStart ) 4347 if ( !selectionStateChanged && i < length() - 1 && !str->at( i + 1 ).lineStart )
4374 xend = str->at( i + 1 ).x; 4348 xend = str->at( i + 1 ).x;
4375 else 4349 else
4376 xend = chr->x + str->width( i ); 4350 xend = chr->x + str->width( i );
4377 } 4351 }
4378 4352
4379 if ( (clipx == -1 || clipw == -1) || (xend >= clipx && xstart <= clipx + clipw) ) { 4353 if ( (clipx == -1 || clipw == -1) || (xend >= clipx && xstart <= clipx + clipw) ) {
4380 if ( !chr->isCustom() ) 4354 if ( !chr->isCustom() )
4381 drawString( painter, qstr, paintStart, i - paintStart + 1, xstart, y, 4355 drawString( painter, qstr, paintStart, i - paintStart + 1, xstart, y,
4382 baseLine, xend-xstart, h, selection, 4356 baseLine, xend-xstart, h, selection,
4383 chr, cg, chr->rightToLeft ); 4357 chr, cg, chr->rightToLeft );
4384 else if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline ) 4358 else if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline )
4385 chr->customItem()->draw( &painter, chr->x, y, 4359 chr->customItem()->draw( &painter, chr->x, y,
4386 clipx == -1 ? clipx : (clipx - r.x()), 4360 clipx == -1 ? clipx : (clipx - r.x()),
4387 clipy == -1 ? clipy : (clipy - r.y()), 4361 clipy == -1 ? clipy : (clipy - r.y()),
4388 clipw, cliph, cg, selection >= 0 ); 4362 clipw, cliph, cg, selection >= 0 );
4389 } 4363 }
4390 paintStart = i+1; 4364 paintStart = i+1;
4391 } 4365 }
4392 4366
4393 } 4367 }
4394 4368
4395 if (fullWidthStyle && drawSelections && selection >= 0 && next() && next()->mSelections) 4369 if (fullWidthStyle && drawSelections && selection >= 0 && next() && next()->mSelections)
4396 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = next()->mSelections->begin(); 4370 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = next()->mSelections->begin();
4397 it != next()->mSelections->end(); ++it ) 4371 it != next()->mSelections->end(); ++it )
4398 if (((*it).start) == 0) { 4372 if (((*it).start) == 0) {
4399 painter.fillRect( xend, y, fullSelectionWidth - xend, h, 4373 painter.fillRect( xend, y, fullSelectionWidth - xend, h,
4400 (selection == QTextDocument::Standard || !hasdoc) ? 4374 (selection == QTextDocument::Standard || !hasdoc) ?
4401 cg.color( QColorGroup::Highlight ) : 4375 cg.color( QColorGroup::Highlight ) :
4402 document()->selectionColor( selection ) ); 4376 document()->selectionColor( selection ) );
4403 break; 4377 break;
4404 } 4378 }
4405 4379
4406 // time to draw the cursor 4380 // time to draw the cursor
4407 const int cursor_extent = 4; 4381 const int cursor_extent = 4;
4408 if ( !cursorRect.isNull() && cursor && 4382 if ( !cursorRect.isNull() && cursor &&
4409 ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) { 4383 ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) {
4410 painter.fillRect( cursorRect, cg.color( QColorGroup::Text ) ); 4384 painter.fillRect( cursorRect, cg.color( QColorGroup::Text ) );
4411 painter.save(); 4385 painter.save();
4412 if ( string()->isBidi() ) { 4386 if ( string()->isBidi() ) {
4413 if ( at( cursor->index() )->rightToLeft ) { 4387 if ( at( cursor->index() )->rightToLeft ) {
4414 painter.setPen( Qt::black ); 4388 painter.setPen( Qt::black );
4415 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4389 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4416 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4390 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4417 } else { 4391 } else {
4418 painter.setPen( Qt::black ); 4392 painter.setPen( Qt::black );
4419 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4393 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4420 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 ); 4394 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4421 } 4395 }
4422 } 4396 }
4423 painter.restore(); 4397 painter.restore();
4424 } 4398 }
4425} 4399}
4426 4400
4427//#define BIDI_DEBUG 4401//#define BIDI_DEBUG
4428 4402
4429void QTextParagraph::drawString( QPainter &painter, const QString &s, int start, int len, int xstart, 4403void QTextParagraph::drawString( QPainter &painter, const QString &s, int start, int len, int xstart,
4430 int y, int baseLine, int w, int h, int selection, 4404 int y, int baseLine, int w, int h, int selection,
4431 QTextStringChar *formatChar, const QColorGroup& cg, 4405 QTextStringChar *formatChar, const QColorGroup& cg,
4432 bool rightToLeft ) 4406 bool rightToLeft )
4433{ 4407{
4434 int i = start + len - 1; 4408 int i = start + len - 1;
4435 bool plainText = hasdoc ? document()->textFormat() == Qt::PlainText : FALSE; 4409 bool plainText = hasdoc ? document()->textFormat() == Qt::PlainText : FALSE;
4436 QTextFormat* format = formatChar->format(); 4410 QTextFormat* format = formatChar->format();
4437 QString str( s ); 4411 QString str( s );
4438 if ( str[ (int)str.length() - 1 ].unicode() == 0xad ) 4412 if ( str[ (int)str.length() - 1 ].unicode() == 0xad )
4439 str.remove( str.length() - 1, 1 ); 4413 str.remove( str.length() - 1, 1 );
4440 if ( !plainText || hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() ) 4414 if ( !plainText || hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() )
4441 painter.setPen( QPen( format->color() ) ); 4415 painter.setPen( QPen( format->color() ) );
4442 else 4416 else
4443 painter.setPen( cg.text() ); 4417 painter.setPen( cg.text() );
4444 painter.setFont( format->font() ); 4418 painter.setFont( format->font() );
4445 4419
4446 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) { 4420 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) {
4447 if ( format->useLinkColor() ) { 4421 if ( format->useLinkColor() ) {
4448 if ( document()->linkColor.isValid() ) 4422 if ( document()->linkColor.isValid() )
4449 painter.setPen( document()->linkColor ); 4423 painter.setPen( document()->linkColor );
4450 else 4424 else
4451 painter.setPen( QPen( Qt::blue ) ); 4425 painter.setPen( QPen( Qt::blue ) );
4452 } 4426 }
4453 if ( document()->underlineLinks() ) { 4427 if ( document()->underlineLinks() ) {
4454 QFont fn = format->font(); 4428 QFont fn = format->font();
4455 fn.setUnderline( TRUE ); 4429 fn.setUnderline( TRUE );
4456 painter.setFont( fn ); 4430 painter.setFont( fn );
4457 } 4431 }
4458 } 4432 }
4459 4433
4460 if ( selection >= 0 ) { 4434 if ( selection >= 0 ) {
4461 if ( !hasdoc || document()->invertSelectionText( selection ) ) 4435 if ( !hasdoc || document()->invertSelectionText( selection ) )
4462 painter.setPen( cg.color( QColorGroup::HighlightedText ) ); 4436 painter.setPen( cg.color( QColorGroup::HighlightedText ) );
4463 painter.fillRect( xstart, y, w, h, 4437 painter.fillRect( xstart, y, w, h,
4464 (selection == QTextDocument::Standard || !hasdoc) ? 4438 (selection == QTextDocument::Standard || !hasdoc) ?
4465 cg.color( QColorGroup::Highlight ) : document()->selectionColor( selection ) ); 4439 cg.color( QColorGroup::Highlight ) : document()->selectionColor( selection ) );
4466 } 4440 }
4467 4441
4468 if ( str[ start ] != '\t' && str[ start ].unicode() != 0xad ) { 4442 if ( str[ start ] != '\t' && str[ start ].unicode() != 0xad ) {
4469 if ( format->vAlign() == QTextFormat::AlignNormal ) { 4443 if ( format->vAlign() == QTextFormat::AlignNormal ) {
4470 painter.drawText( xstart, y + baseLine, str.mid( start ), len ); 4444 painter.drawText( xstart, y + baseLine, str.mid( start ), len );
4471#ifdef BIDI_DEBUG 4445#ifdef BIDI_DEBUG
4472 painter.save(); 4446 painter.save();
4473 painter.setPen ( Qt::red ); 4447 painter.setPen ( Qt::red );
4474 painter.drawLine( xstart, y, xstart, y + baseLine ); 4448 painter.drawLine( xstart, y, xstart, y + baseLine );
4475 painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 ); 4449 painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 );
4476 int w = 0; 4450 int w = 0;
4477 int i = 0; 4451 int i = 0;
4478 while( i < len ) 4452 while( i < len )
4479 w += painter.fontMetrics().charWidth( str, start + i++ ); 4453 w += painter.fontMetrics().charWidth( str, start + i++ );
4480 painter.setPen ( Qt::blue ); 4454 painter.setPen ( Qt::blue );
4481 painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine ); 4455 painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine );
4482 painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 ); 4456 painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 );
4483 painter.restore(); 4457 painter.restore();
4484#endif 4458#endif
4485 } else if ( format->vAlign() == QTextFormat::AlignSuperScript ) { 4459 } else if ( format->vAlign() == QTextFormat::AlignSuperScript ) {
4486 QFont f( painter.font() ); 4460 QFont f( painter.font() );
4487 if ( format->fontSizesInPixels() ) 4461 if ( format->fontSizesInPixels() )
4488 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 4462 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
4489 else 4463 else
4490 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 4464 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
4491 painter.setFont( f ); 4465 painter.setFont( f );
4492 painter.drawText( xstart, y + baseLine - ( painter.fontMetrics().height() / 2 ), 4466 painter.drawText( xstart, y + baseLine - ( painter.fontMetrics().height() / 2 ),
4493 str.mid( start ), len ); 4467 str.mid( start ), len );
4494 } else if ( format->vAlign() == QTextFormat::AlignSubScript ) { 4468 } else if ( format->vAlign() == QTextFormat::AlignSubScript ) {
4495 QFont f( painter.font() ); 4469 QFont f( painter.font() );
4496 if ( format->fontSizesInPixels() ) 4470 if ( format->fontSizesInPixels() )
4497 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 4471 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
4498 else 4472 else
4499 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 4473 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
4500 painter.setFont( f ); 4474 painter.setFont( f );
4501 painter.drawText( xstart, y + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len ); 4475 painter.drawText( xstart, y + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len );
4502 } 4476 }
4503 } 4477 }
4504 if ( i + 1 < length() && at( i + 1 )->lineStart && at( i )->c.unicode() == 0xad ) { 4478 if ( i + 1 < length() && at( i + 1 )->lineStart && at( i )->c.unicode() == 0xad ) {
4505 painter.drawText( xstart + w, y + baseLine, "\xad" ); 4479 painter.drawText( xstart + w, y + baseLine, "\xad" );
4506 } 4480 }
4507 if ( format->isMisspelled() ) { 4481 if ( format->isMisspelled() ) {
4508 painter.save(); 4482 painter.save();
4509 painter.setPen( QPen( Qt::red, 1, Qt::DotLine ) ); 4483 painter.setPen( QPen( Qt::red, 1, Qt::DotLine ) );
4510 painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 ); 4484 painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 );
4511 painter.restore(); 4485 painter.restore();
4512 } 4486 }
4513 4487
4514 i -= len; 4488 i -= len;
4515 4489
4516 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() && 4490 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() &&
4517 document()->focusIndicator.parag == this && 4491 document()->focusIndicator.parag == this &&
4518 ( document()->focusIndicator.start >= i && 4492 ( document()->focusIndicator.start >= i &&
4519 document()->focusIndicator.start + document()->focusIndicator.len <= i + len || 4493 document()->focusIndicator.start + document()->focusIndicator.len <= i + len ||
4520 document()->focusIndicator.start <= i && 4494 document()->focusIndicator.start <= i &&
4521 document()->focusIndicator.start + document()->focusIndicator.len >= i + len ) ) { 4495 document()->focusIndicator.start + document()->focusIndicator.len >= i + len ) ) {
4522 painter.drawWinFocusRect( QRect( xstart, y, w, h ) ); 4496 painter.drawWinFocusRect( QRect( xstart, y, w, h ) );
4523 } 4497 }
4524 4498
4525} 4499}
4526 4500
4527void QTextParagraph::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ) 4501void QTextParagraph::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg )
4528{ 4502{
4529 QRect r ( x, y, w, h ); 4503 QRect r ( x, y, w, h );
4530 QStyleSheetItem::ListStyle s = listStyle(); 4504 QStyleSheetItem::ListStyle s = listStyle();
4531 4505
4532 p->save(); 4506 p->save();
4533 QTextFormat *format = at( 0 )->format(); 4507 QTextFormat *format = at( 0 )->format();
4534 if ( format ) { 4508 if ( format ) {
4535 p->setPen( format->color() ); 4509 p->setPen( format->color() );
4536 p->setFont( format->font() ); 4510 p->setFont( format->font() );
4537 } 4511 }
4538 QFontMetrics fm( p->fontMetrics() ); 4512 QFontMetrics fm( p->fontMetrics() );
4539 int size = fm.lineSpacing() / 3; 4513 int size = fm.lineSpacing() / 3;
4540 4514
4541 switch ( s ) { 4515 switch ( s ) {
4542 case QStyleSheetItem::ListDecimal: 4516 case QStyleSheetItem::ListDecimal:
4543 case QStyleSheetItem::ListLowerAlpha: 4517 case QStyleSheetItem::ListLowerAlpha:
4544 case QStyleSheetItem::ListUpperAlpha: 4518 case QStyleSheetItem::ListUpperAlpha:
4545 { 4519 {
4546 if ( list_val == -1 ) { // uninitialised list value, calcluate the right one 4520 if ( list_val == -1 ) { // uninitialised list value, calcluate the right one
4547 int depth = listDepth(); 4521 int depth = listDepth();
4548 list_val--; 4522 list_val--;
4549 // ### evil, square and expensive. This needs to be done when formatting, not when painting 4523 // ### evil, square and expensive. This needs to be done when formatting, not when painting
4550 QTextParagraph* s = prev(); 4524 QTextParagraph* s = prev();
4551 int depth_s; 4525 int depth_s;
4552 while ( s && (depth_s = s->listDepth()) >= depth ) { 4526 while ( s && (depth_s = s->listDepth()) >= depth ) {
4553 if ( depth_s == depth && s->isListItem() ) 4527 if ( depth_s == depth && s->isListItem() )
4554 list_val--; 4528 list_val--;
4555 s = s->prev(); 4529 s = s->prev();
4556 } 4530 }
4557 } 4531 }
4558 4532
4559 int n = list_val; 4533 int n = list_val;
4560 if ( n < -1 ) 4534 if ( n < -1 )
4561 n = -n - 1; 4535 n = -n - 1;
4562 QString l; 4536 QString l;
4563 switch ( s ) { 4537 switch ( s ) {
4564 case QStyleSheetItem::ListLowerAlpha: 4538 case QStyleSheetItem::ListLowerAlpha:
4565 if ( n < 27 ) { 4539 if ( n < 27 ) {
4566 l = QChar( ('a' + (char) (n-1))); 4540 l = QChar( ('a' + (char) (n-1)));
4567 break; 4541 break;
4568 } 4542 }
4569 case QStyleSheetItem::ListUpperAlpha: 4543 case QStyleSheetItem::ListUpperAlpha:
4570 if ( n < 27 ) { 4544 if ( n < 27 ) {
4571 l = QChar( ('A' + (char) (n-1))); 4545 l = QChar( ('A' + (char) (n-1)));
4572 break; 4546 break;
4573 } 4547 }
4574 break; 4548 break;
4575 default: //QStyleSheetItem::ListDecimal: 4549 default: //QStyleSheetItem::ListDecimal:
4576 l.setNum( n ); 4550 l.setNum( n );
4577 break; 4551 break;
4578 } 4552 }
4579 l += QString::fromLatin1(". "); 4553 l += QString::fromLatin1(". ");
4580 p->drawText( r.right() - fm.width( l ), r.top() + base, l ); 4554 p->drawText( r.right() - fm.width( l ), r.top() + base, l );
4581 } 4555 }
4582 break; 4556 break;
4583 case QStyleSheetItem::ListSquare: 4557 case QStyleSheetItem::ListSquare:
4584 { 4558 {
4585 QRect er( r.right() - size * 2, r.top() + fm.height() / 2 - size / 2, size, size ); 4559 QRect er( r.right() - size * 2, r.top() + fm.height() / 2 - size / 2, size, size );
4586 p->fillRect( er , cg.brush( QColorGroup::Text ) ); 4560 p->fillRect( er , cg.brush( QColorGroup::Text ) );
4587 } 4561 }
4588 break; 4562 break;
4589 case QStyleSheetItem::ListCircle: 4563 case QStyleSheetItem::ListCircle:
4590 { 4564 {
4591 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size); 4565 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size);
4592 p->drawEllipse( er ); 4566 p->drawEllipse( er );
4593 } 4567 }
4594 break; 4568 break;
4595 case QStyleSheetItem::ListDisc: 4569 case QStyleSheetItem::ListDisc:
4596 default: 4570 default:
4597 { 4571 {
4598 p->setBrush( cg.brush( QColorGroup::Text )); 4572 p->setBrush( cg.brush( QColorGroup::Text ));
4599 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size); 4573 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size);
4600 p->drawEllipse( er ); 4574 p->drawEllipse( er );
4601 p->setBrush( Qt::NoBrush ); 4575 p->setBrush( Qt::NoBrush );
4602 } 4576 }
4603 break; 4577 break;
4604 } 4578 }
4605 4579
4606 p->restore(); 4580 p->restore();
4607} 4581}
4608 4582
4609void QTextParagraph::readStyleInformation( QDataStream& stream ) 4583void QTextParagraph::readStyleInformation( QDataStream& stream )
4610{ 4584{
4611 int int_align, int_lstyle; 4585 int int_align, int_lstyle;
4612 uchar uchar_litem, uchar_rtext, uchar_dir; 4586 uchar uchar_litem, uchar_rtext, uchar_dir;
4613 stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm 4587 stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm
4614 >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir; 4588 >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir;
4615 align = int_align; lstyle = (QStyleSheetItem::ListStyle) int_lstyle; 4589 align = int_align; lstyle = (QStyleSheetItem::ListStyle) int_lstyle;
4616 litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (QChar::Direction)uchar_dir ); 4590 litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (QChar::Direction)uchar_dir );
4617 QTextParagraph* s = prev() ? prev() : this; 4591 QTextParagraph* s = prev() ? prev() : this;
4618 while ( s ) { 4592 while ( s ) {
4619 s->invalidate( 0 ); 4593 s->invalidate( 0 );
4620 s = s->next(); 4594 s = s->next();
4621 } 4595 }
4622} 4596}
4623 4597
4624void QTextParagraph::writeStyleInformation( QDataStream& stream ) const 4598void QTextParagraph::writeStyleInformation( QDataStream& stream ) const
4625{ 4599{
4626 stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction(); 4600 stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction();
4627} 4601}
4628 4602
4629 4603
4630 4604
4631void QTextParagraph::setListDepth( int depth ) { 4605void QTextParagraph::setListDepth( int depth ) {
4632 if ( !hasdoc || depth == ldepth ) 4606 if ( !hasdoc || depth == ldepth )
4633 return; 4607 return;
4634 ldepth = depth; 4608 ldepth = depth;
4635 QTextParagraph* s = prev() ? prev() : this; 4609 QTextParagraph* s = prev() ? prev() : this;
4636 while ( s ) { 4610 while ( s ) {
4637 s->invalidate( 0 ); 4611 s->invalidate( 0 );
4638 s = s->next(); 4612 s = s->next();
4639 } 4613 }
4640} 4614}
4641 4615
4642int *QTextParagraph::tabArray() const 4616int *QTextParagraph::tabArray() const
4643{ 4617{
4644 int *ta = tArray; 4618 int *ta = tArray;
4645 if ( !ta && hasdoc ) 4619 if ( !ta && hasdoc )
4646 ta = document()->tabArray(); 4620 ta = document()->tabArray();
4647 return ta; 4621 return ta;
4648} 4622}
4649 4623
4650int QTextParagraph::nextTab( int, int x ) 4624int QTextParagraph::nextTab( int, int x )
4651{ 4625{
4652 int *ta = tArray; 4626 int *ta = tArray;
4653 if ( hasdoc ) { 4627 if ( hasdoc ) {
4654 if ( !ta ) 4628 if ( !ta )
4655 ta = document()->tabArray(); 4629 ta = document()->tabArray();
4656 tabStopWidth = document()->tabStopWidth(); 4630 tabStopWidth = document()->tabStopWidth();
4657 } 4631 }
4658 if ( ta ) { 4632 if ( ta ) {
4659 int i = 0; 4633 int i = 0;
4660 while ( ta[ i ] ) { 4634 while ( ta[ i ] ) {
4661 if ( ta[ i ] >= x ) 4635 if ( ta[ i ] >= x )
4662 return tArray[ i ]; 4636 return tArray[ i ];
4663 ++i; 4637 ++i;
4664 } 4638 }
4665 return tArray[ 0 ]; 4639 return tArray[ 0 ];
4666 } else { 4640 } else {
4667 int d; 4641 int d;
4668 if ( tabStopWidth != 0 ) 4642 if ( tabStopWidth != 0 )
4669 d = x / tabStopWidth; 4643 d = x / tabStopWidth;
4670 else 4644 else
4671 return x; 4645 return x;
4672 return tabStopWidth * ( d + 1 ); 4646 return tabStopWidth * ( d + 1 );
4673 } 4647 }
4674} 4648}
4675 4649
4676void QTextParagraph::adjustToPainter( QPainter *p ) 4650void QTextParagraph::adjustToPainter( QPainter *p )
4677{ 4651{
4678 for ( int i = 0; i < length(); ++i ) { 4652 for ( int i = 0; i < length(); ++i ) {
4679 if ( at( i )->isCustom() ) 4653 if ( at( i )->isCustom() )
4680 at( i )->customItem()->adjustToPainter( p ); 4654 at( i )->customItem()->adjustToPainter( p );
4681 } 4655 }
4682} 4656}
4683 4657
4684QTextFormatCollection *QTextParagraph::formatCollection() const 4658QTextFormatCollection *QTextParagraph::formatCollection() const
4685{ 4659{
4686 if ( hasdoc ) 4660 if ( hasdoc )
4687 return document()->formatCollection(); 4661 return document()->formatCollection();
4688 if ( !qFormatCollection ) { 4662 if ( !qFormatCollection ) {
4689 qFormatCollection = new QTextFormatCollection; 4663 qFormatCollection = new QTextFormatCollection;
4690 static QSingleCleanupHandler<QTextFormatCollection> qtfCleanup; 4664 static QSingleCleanupHandler<QTextFormatCollection> qtfCleanup;
4691 qtfCleanup.set( &qFormatCollection ); 4665 qtfCleanup.set( &qFormatCollection );
4692 } 4666 }
4693 return qFormatCollection; 4667 return qFormatCollection;
4694} 4668}
4695 4669
4696QString QTextParagraph::richText() const 4670QString QTextParagraph::richText() const
4697{ 4671{
4698 QString s; 4672 QString s;
4699 QTextStringChar *formatChar = 0; 4673 QTextStringChar *formatChar = 0;
4700 QString spaces; 4674 QString spaces;
4701 bool doStart = richTextExportStart && richTextExportStart->paragraph() == this; 4675 bool doStart = richTextExportStart && richTextExportStart->paragraph() == this;
4702 bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this; 4676 bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this;
4703 int i; 4677 int i;
4704 for ( i = 0; i < length()-1; ++i ) { 4678 for ( i = 0; i < length()-1; ++i ) {
4705 if ( doStart && i && richTextExportStart->index() == i ) 4679 if ( doStart && i && richTextExportStart->index() == i )
4706 s += "<selstart/>"; 4680 s += "<selstart/>";
4707 if ( doEnd && richTextExportEnd->index() == i ) 4681 if ( doEnd && richTextExportEnd->index() == i )
4708 s += "<selend/>"; 4682 s += "<selend/>";
4709 QTextStringChar *c = &str->at( i ); 4683 QTextStringChar *c = &str->at( i );
4710 if ( c->isAnchor() && !c->anchorName().isEmpty() ) { 4684 if ( c->isAnchor() && !c->anchorName().isEmpty() ) {
4711 if ( c->anchorName().contains( '#' ) ) { 4685 if ( c->anchorName().contains( '#' ) ) {
4712 QStringList l = QStringList::split( '#', c->anchorName() ); 4686 QStringList l = QStringList::split( '#', c->anchorName() );
4713 for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) 4687 for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it )
4714 s += "<a name=\"" + *it + "\"></a>"; 4688 s += "<a name=\"" + *it + "\"></a>";
4715 } else { 4689 } else {
4716 s += "<a name=\"" + c->anchorName() + "\"></a>"; 4690 s += "<a name=\"" + c->anchorName() + "\"></a>";
4717 } 4691 }
4718 } 4692 }
4719 if ( !formatChar ) { 4693 if ( !formatChar ) {
4720 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), 4694 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(),
4721 0, QString::null, c->anchorHref() ); 4695 0, QString::null, c->anchorHref() );
4722 formatChar = c; 4696 formatChar = c;
4723 } else if ( ( formatChar->format()->key() != c->format()->key() ) || 4697 } else if ( ( formatChar->format()->key() != c->format()->key() ) ||
4724 (c->anchorHref() != formatChar->anchorHref() ) ) { 4698 (c->anchorHref() != formatChar->anchorHref() ) ) {
4725 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(), 4699 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(),
4726 formatChar->format() , formatChar->anchorHref(), c->anchorHref() ); 4700 formatChar->format() , formatChar->anchorHref(), c->anchorHref() );
4727 formatChar = c; 4701 formatChar = c;
4728 } 4702 }
4729 if ( c->c == '<' ) 4703 if ( c->c == '<' )
4730 s += "&lt;"; 4704 s += "&lt;";
4731 else if ( c->c == '>' ) 4705 else if ( c->c == '>' )
4732 s += "&gt;"; 4706 s += "&gt;";
4733 else if ( c->isCustom() ) 4707 else if ( c->isCustom() )
4734 s += c->customItem()->richText(); 4708 s += c->customItem()->richText();
4735 else if ( c->c == '\n' || c->c == QChar_linesep ) 4709 else if ( c->c == '\n' || c->c == QChar_linesep )
4736 s += "<br />"; // space on purpose for compatibility with Netscape, Lynx & Co. 4710 s += "<br />"; // space on purpose for compatibility with Netscape, Lynx & Co.
4737 else 4711 else
4738 s += c->c; 4712 s += c->c;
4739 } 4713 }
4740 if ( doEnd && richTextExportEnd->index() == i ) 4714 if ( doEnd && richTextExportEnd->index() == i )
4741 s += "<selend/>"; 4715 s += "<selend/>";
4742 if ( formatChar ) 4716 if ( formatChar )
4743 s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() ); 4717 s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() );
4744 return s; 4718 return s;
4745} 4719}
4746 4720
4747void QTextParagraph::addCommand( QTextCommand *cmd ) 4721void QTextParagraph::addCommand( QTextCommand *cmd )
4748{ 4722{
4749 if ( !hasdoc ) 4723 if ( !hasdoc )
4750 pseudoDocument()->commandHistory->addCommand( cmd ); 4724 pseudoDocument()->commandHistory->addCommand( cmd );
4751 else 4725 else
4752 document()->commands()->addCommand( cmd ); 4726 document()->commands()->addCommand( cmd );
4753} 4727}
4754 4728
4755QTextCursor *QTextParagraph::undo( QTextCursor *c ) 4729QTextCursor *QTextParagraph::undo( QTextCursor *c )
4756{ 4730{
4757 if ( !hasdoc ) 4731 if ( !hasdoc )
4758 return pseudoDocument()->commandHistory->undo( c ); 4732 return pseudoDocument()->commandHistory->undo( c );
4759 return document()->commands()->undo( c ); 4733 return document()->commands()->undo( c );
4760} 4734}
4761 4735
4762QTextCursor *QTextParagraph::redo( QTextCursor *c ) 4736QTextCursor *QTextParagraph::redo( QTextCursor *c )
4763{ 4737{
4764 if ( !hasdoc ) 4738 if ( !hasdoc )
4765 return pseudoDocument()->commandHistory->redo( c ); 4739 return pseudoDocument()->commandHistory->redo( c );
4766 return document()->commands()->redo( c ); 4740 return document()->commands()->redo( c );
4767} 4741}
4768 4742
4769int QTextParagraph::topMargin() const 4743int QTextParagraph::topMargin() const
4770{ 4744{
4771 int m = 0; 4745 int m = 0;
4772 if ( rtext ) { 4746 if ( rtext ) {
4773 m = isListItem() ? (document()->li_tm/QMAX(1,listDepth())) : document()->par_tm; 4747 m = isListItem() ? (document()->li_tm/QMAX(1,listDepth())) : document()->par_tm;
4774 if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) ) 4748 if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) )
4775 m = QMAX( m, document()->list_tm ); 4749 m = QMAX( m, document()->list_tm );
4776 } 4750 }
4777 m += utm; 4751 m += utm;
4778 return scale( m, QTextFormat::painter() ); 4752 return scale( m, QTextFormat::painter() );
4779} 4753}
4780 4754
4781int QTextParagraph::bottomMargin() const 4755int QTextParagraph::bottomMargin() const
4782{ 4756{
4783 int m = 0; 4757 int m = 0;
4784 if ( rtext ) { 4758 if ( rtext ) {
4785 m = isListItem() ? (document()->li_bm/QMAX(1,listDepth())) : document()->par_bm; 4759 m = isListItem() ? (document()->li_bm/QMAX(1,listDepth())) : document()->par_bm;
4786 if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) ) 4760 if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) )
4787 m = QMAX( m, document()->list_bm ); 4761 m = QMAX( m, document()->list_bm );
4788 } 4762 }
4789 m += ubm; 4763 m += ubm;
4790 return scale( m, QTextFormat::painter() ); 4764 return scale( m, QTextFormat::painter() );
4791} 4765}
4792 4766
4793int QTextParagraph::leftMargin() const 4767int QTextParagraph::leftMargin() const
4794{ 4768{
4795 int m = ulm; 4769 int m = ulm;
4796 if ( listDepth() ) 4770 if ( listDepth() )
4797 m += listDepth() * document()->list_lm; 4771 m += listDepth() * document()->list_lm;
4798 return scale( m, QTextFormat::painter() ); 4772 return scale( m, QTextFormat::painter() );
4799} 4773}
4800 4774
4801int QTextParagraph::firstLineMargin() const 4775int QTextParagraph::firstLineMargin() const
4802{ 4776{
4803 int m = uflm; 4777 int m = uflm;
4804 return scale( m, QTextFormat::painter() ); 4778 return scale( m, QTextFormat::painter() );
4805} 4779}
4806 4780
4807int QTextParagraph::rightMargin() const 4781int QTextParagraph::rightMargin() const
4808{ 4782{
4809 int m = urm; 4783 int m = urm;
4810 return scale( m, QTextFormat::painter() ); 4784 return scale( m, QTextFormat::painter() );
4811} 4785}
4812 4786
4813int QTextParagraph::lineSpacing() const 4787int QTextParagraph::lineSpacing() const
4814{ 4788{
4815 int l = ulinespacing; 4789 int l = ulinespacing;
4816 l = scale( l, QTextFormat::painter() ); 4790 l = scale( l, QTextFormat::painter() );
4817 return l; 4791 return l;
4818} 4792}
4819 4793
4820void QTextParagraph::copyParagData( QTextParagraph *parag ) 4794void QTextParagraph::copyParagData( QTextParagraph *parag )
4821{ 4795{
4822 rtext = parag->rtext; 4796 rtext = parag->rtext;
4823 lstyle = parag->lstyle; 4797 lstyle = parag->lstyle;
4824 ldepth = parag->ldepth; 4798 ldepth = parag->ldepth;
4825 litem = parag->litem; 4799 litem = parag->litem;
4826 align = parag->align; 4800 align = parag->align;
4827 utm = parag->utm; 4801 utm = parag->utm;
4828 ubm = parag->ubm; 4802 ubm = parag->ubm;
4829 urm = parag->urm; 4803 urm = parag->urm;
4830 ulm = parag->ulm; 4804 ulm = parag->ulm;
4831 uflm = parag->uflm; 4805 uflm = parag->uflm;
4832 ulinespacing = parag->ulinespacing; 4806 ulinespacing = parag->ulinespacing;
4833 QColor *c = parag->backgroundColor(); 4807 QColor *c = parag->backgroundColor();
4834 if ( c ) 4808 if ( c )
4835 setBackgroundColor( *c ); 4809 setBackgroundColor( *c );
4836 str->setDirection( parag->str->direction() ); 4810 str->setDirection( parag->str->direction() );
4837} 4811}
4838 4812
4839void QTextParagraph::show() 4813void QTextParagraph::show()
4840{ 4814{
4841 if ( visible || !hasdoc ) 4815 if ( visible || !hasdoc )
4842 return; 4816 return;
4843 visible = TRUE; 4817 visible = TRUE;
4844} 4818}
4845 4819
4846void QTextParagraph::hide() 4820void QTextParagraph::hide()
4847{ 4821{
4848 if ( !visible || !hasdoc ) 4822 if ( !visible || !hasdoc )
4849 return; 4823 return;
4850 visible = FALSE; 4824 visible = FALSE;
4851} 4825}
4852 4826
4853void QTextParagraph::setDirection( QChar::Direction d ) 4827void QTextParagraph::setDirection( QChar::Direction d )
4854{ 4828{
4855 if ( str && str->direction() != d ) { 4829 if ( str && str->direction() != d ) {
4856 str->setDirection( d ); 4830 str->setDirection( d );
4857 invalidate( 0 ); 4831 invalidate( 0 );
4858 } 4832 }
4859} 4833}
4860 4834
4861QChar::Direction QTextParagraph::direction() const 4835QChar::Direction QTextParagraph::direction() const
4862{ 4836{
4863 return (str ? str->direction() : QChar::DirON ); 4837 return (str ? str->direction() : QChar::DirON );
4864} 4838}
4865 4839
4866void QTextParagraph::setChanged( bool b, bool recursive ) 4840void QTextParagraph::setChanged( bool b, bool recursive )
4867{ 4841{
4868 changed = b; 4842 changed = b;
4869 if ( recursive ) { 4843 if ( recursive ) {
4870 if ( document() && document()->parentParagraph() ) 4844 if ( document() && document()->parentParagraph() )
4871 document()->parentParagraph()->setChanged( b, recursive ); 4845 document()->parentParagraph()->setChanged( b, recursive );
4872 } 4846 }
4873} 4847}
4874 4848
4875// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4849// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4876 4850
4877 4851
4878QTextPreProcessor::QTextPreProcessor() 4852QTextPreProcessor::QTextPreProcessor()
4879{ 4853{
4880} 4854}
4881 4855
4882// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4856// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4883 4857
4884QTextFormatter::QTextFormatter() 4858QTextFormatter::QTextFormatter()
4885 : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE ) 4859 : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE )
4886{ 4860{
4887} 4861}
4888 4862
4889QTextLineStart *QTextFormatter::formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, 4863QTextLineStart *QTextFormatter::formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line,
4890 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) 4864 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space )
4891{ 4865{
4892#ifndef QT_NO_COMPLEXTEXT 4866#ifndef QT_NO_COMPLEXTEXT
4893 if( string->isBidi() ) 4867 if( string->isBidi() )
4894 return bidiReorderLine( parag, string, line, startChar, lastChar, align, space ); 4868 return bidiReorderLine( parag, string, line, startChar, lastChar, align, space );
4895#endif 4869#endif
4896 int start = (startChar - &string->at(0)); 4870 int start = (startChar - &string->at(0));
4897 int last = (lastChar - &string->at(0) ); 4871 int last = (lastChar - &string->at(0) );
4898 // do alignment Auto == Left in this case 4872 // do alignment Auto == Left in this case
4899 if ( align & Qt::AlignHCenter || align & Qt::AlignRight ) { 4873 if ( align & Qt::AlignHCenter || align & Qt::AlignRight ) {
4900 if ( align & Qt::AlignHCenter ) 4874 if ( align & Qt::AlignHCenter )
4901 space /= 2; 4875 space /= 2;
4902 for ( int j = start; j <= last; ++j ) 4876 for ( int j = start; j <= last; ++j )
4903 string->at( j ).x += space; 4877 string->at( j ).x += space;
4904 } else if ( align & Qt3::AlignJustify ) { 4878 } else if ( align & Qt3::AlignJustify ) {
4905 int numSpaces = 0; 4879 int numSpaces = 0;
4906 // End at "last-1", the last space ends up with a width of 0 4880 // End at "last-1", the last space ends up with a width of 0
4907 for ( int j = last-1; j >= start; --j ) { 4881 for ( int j = last-1; j >= start; --j ) {
4908 // Start at last tab, if any. 4882 // Start at last tab, if any.
4909 if ( string->at( j ).c == '\t' ) { 4883 if ( string->at( j ).c == '\t' ) {
4910 start = j+1; 4884 start = j+1;
4911 break; 4885 break;
4912 } 4886 }
4913 if( isBreakable( string, j ) ) { 4887 if( isBreakable( string, j ) ) {
4914 numSpaces++; 4888 numSpaces++;
4915 } 4889 }
4916 } 4890 }
4917 int toAdd = 0; 4891 int toAdd = 0;
4918 for ( int k = start + 1; k <= last; ++k ) { 4892 for ( int k = start + 1; k <= last; ++k ) {
4919 if( isBreakable( string, k ) && numSpaces ) { 4893 if( isBreakable( string, k ) && numSpaces ) {
4920 int s = space / numSpaces; 4894 int s = space / numSpaces;
4921 toAdd += s; 4895 toAdd += s;
4922 space -= s; 4896 space -= s;
4923 numSpaces--; 4897 numSpaces--;
4924 } 4898 }
4925 string->at( k ).x += toAdd; 4899 string->at( k ).x += toAdd;
4926 } 4900 }
4927 } 4901 }
4928 4902
4929 if ( last >= 0 && last < string->length() ) 4903 if ( last >= 0 && last < string->length() )
4930 line->w = string->at( last ).x + string->width( last ); 4904 line->w = string->at( last ).x + string->width( last );
4931 else 4905 else
4932 line->w = 0; 4906 line->w = 0;
4933 4907
4934 return new QTextLineStart(); 4908 return new QTextLineStart();
4935} 4909}
4936 4910
4937#ifndef QT_NO_COMPLEXTEXT 4911#ifndef QT_NO_COMPLEXTEXT
4938 4912
4939#ifdef BIDI_DEBUG 4913#ifdef BIDI_DEBUG
4940#include <iostream> 4914#include <iostream>
4941#endif 4915#endif
4942 4916
4943// collects one line of the paragraph and transforms it to visual order 4917// collects one line of the paragraph and transforms it to visual order
4944QTextLineStart *QTextFormatter::bidiReorderLine( QTextParagraph * /*parag*/, QTextString *text, QTextLineStart *line, 4918QTextLineStart *QTextFormatter::bidiReorderLine( QTextParagraph * /*parag*/, QTextString *text, QTextLineStart *line,
4945 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) 4919 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space )
4946{ 4920{
4947 int start = (startChar - &text->at(0)); 4921 int start = (startChar - &text->at(0));
4948 int last = (lastChar - &text->at(0) ); 4922 int last = (lastChar - &text->at(0) );
4949 4923
4950 QBidiControl *control = new QBidiControl( line->context(), line->status ); 4924 QBidiControl *control = new QBidiControl( line->context(), line->status );
4951 QString str; 4925 QString str;
4952 str.setUnicode( 0, last - start + 1 ); 4926 str.setUnicode( 0, last - start + 1 );
4953 // fill string with logically ordered chars. 4927 // fill string with logically ordered chars.
4954 QTextStringChar *ch = startChar; 4928 QTextStringChar *ch = startChar;
4955 QChar *qch = (QChar *)str.unicode(); 4929 QChar *qch = (QChar *)str.unicode();
4956 while ( ch <= lastChar ) { 4930 while ( ch <= lastChar ) {
4957 *qch = ch->c; 4931 *qch = ch->c;
4958 qch++; 4932 qch++;
4959 ch++; 4933 ch++;
4960 } 4934 }
4961 int x = startChar->x; 4935 int x = startChar->x;
4962 4936
4963 QPtrList<QTextRun> *runs; 4937 QPtrList<QTextRun> *runs;
4964 runs = QComplexText::bidiReorderLine(control, str, 0, last - start + 1, 4938 runs = QComplexText::bidiReorderLine(control, str, 0, last - start + 1,
4965 (text->isRightToLeft() ? QChar::DirR : QChar::DirL) ); 4939 (text->isRightToLeft() ? QChar::DirR : QChar::DirL) );
4966 4940
4967 // now construct the reordered string out of the runs... 4941 // now construct the reordered string out of the runs...
4968 4942
4969 int numSpaces = 0; 4943 int numSpaces = 0;
4970 // set the correct alignment. This is a bit messy.... 4944 // set the correct alignment. This is a bit messy....
4971 if( align == Qt3::AlignAuto ) { 4945 if( align == Qt3::AlignAuto ) {
4972 // align according to directionality of the paragraph... 4946 // align according to directionality of the paragraph...
4973 if ( text->isRightToLeft() ) 4947 if ( text->isRightToLeft() )
4974 align = Qt::AlignRight; 4948 align = Qt::AlignRight;
4975 } 4949 }
4976 4950
4977 if ( align & Qt::AlignHCenter ) 4951 if ( align & Qt::AlignHCenter )
4978 x += space/2; 4952 x += space/2;
4979 else if ( align & Qt::AlignRight ) 4953 else if ( align & Qt::AlignRight )
4980 x += space; 4954 x += space;
4981 else if ( align & Qt3::AlignJustify ) { 4955 else if ( align & Qt3::AlignJustify ) {
4982 // End at "last-1", the last space ends up with a width of 0 4956 // End at "last-1", the last space ends up with a width of 0
4983 for ( int j = last-1; j >= start; --j ) { 4957 for ( int j = last-1; j >= start; --j ) {
4984 // Start at last tab, if any. 4958 // Start at last tab, if any.
4985 if ( text->at( j ).c == '\t' ) { 4959 if ( text->at( j ).c == '\t' ) {
4986 start = j+1; 4960 start = j+1;
4987 break; 4961 break;
4988 } 4962 }
4989 if( isBreakable( text, j ) ) { 4963 if( isBreakable( text, j ) ) {
4990 numSpaces++; 4964 numSpaces++;
4991 } 4965 }
4992 } 4966 }
4993 } 4967 }
4994 int toAdd = 0; 4968 int toAdd = 0;
4995 bool first = TRUE; 4969 bool first = TRUE;
4996 QTextRun *r = runs->first(); 4970 QTextRun *r = runs->first();
4997 int xmax = -0xffffff; 4971 int xmax = -0xffffff;
4998 while ( r ) { 4972 while ( r ) {
4999 if(r->level %2) { 4973 if(r->level %2) {
5000 // odd level, need to reverse the string 4974 // odd level, need to reverse the string
5001 int pos = r->stop + start; 4975 int pos = r->stop + start;
5002 while(pos >= r->start + start) { 4976 while(pos >= r->start + start) {
5003 QTextStringChar *c = &text->at(pos); 4977 QTextStringChar *c = &text->at(pos);
5004 if( numSpaces && !first && isBreakable( text, pos ) ) { 4978 if( numSpaces && !first && isBreakable( text, pos ) ) {
5005 int s = space / numSpaces; 4979 int s = space / numSpaces;
5006 toAdd += s; 4980 toAdd += s;
5007 space -= s; 4981 space -= s;
5008 numSpaces--; 4982 numSpaces--;
5009 } else if ( first ) { 4983 } else if ( first ) {
5010 first = FALSE; 4984 first = FALSE;
5011 if ( c->c == ' ' ) 4985 if ( c->c == ' ' )
5012 x -= c->format()->width( ' ' ); 4986 x -= c->format()->width( ' ' );
5013 } 4987 }
5014 c->x = x + toAdd; 4988 c->x = x + toAdd;
5015 c->rightToLeft = TRUE; 4989 c->rightToLeft = TRUE;
5016 c->startOfRun = FALSE; 4990 c->startOfRun = FALSE;
5017 int ww = 0; 4991 int ww = 0;
5018 if ( c->c.unicode() >= 32 || c->c == '\t' || c->c == '\n' || c->isCustom() ) { 4992 if ( c->c.unicode() >= 32 || c->c == '\t' || c->c == '\n' || c->isCustom() ) {
5019 ww = text->width( pos ); 4993 ww = text->width( pos );
5020 } else { 4994 } else {
5021 ww = c->format()->width( ' ' ); 4995 ww = c->format()->width( ' ' );
5022 } 4996 }
5023 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww; 4997 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww;
5024 x += ww; 4998 x += ww;
5025 pos--; 4999 pos--;
5026 } 5000 }
5027 } else { 5001 } else {
5028 int pos = r->start + start; 5002 int pos = r->start + start;
5029 while(pos <= r->stop + start) { 5003 while(pos <= r->stop + start) {
5030 QTextStringChar* c = &text->at(pos); 5004 QTextStringChar* c = &text->at(pos);
5031 if( numSpaces && !first && isBreakable( text, pos ) ) { 5005 if( numSpaces && !first && isBreakable( text, pos ) ) {
5032 int s = space / numSpaces; 5006 int s = space / numSpaces;
5033 toAdd += s; 5007 toAdd += s;
5034 space -= s; 5008 space -= s;
5035 numSpaces--; 5009 numSpaces--;
5036 } else if ( first ) { 5010 } else if ( first ) {
5037 first = FALSE; 5011 first = FALSE;
5038 if ( c->c == ' ' ) 5012 if ( c->c == ' ' )
5039 x -= c->format()->width( ' ' ); 5013 x -= c->format()->width( ' ' );
5040 } 5014 }
5041 c->x = x + toAdd; 5015 c->x = x + toAdd;
5042 c->rightToLeft = FALSE; 5016 c->rightToLeft = FALSE;
5043 c->startOfRun = FALSE; 5017 c->startOfRun = FALSE;
5044 int ww = 0; 5018 int ww = 0;
5045 if ( c->c.unicode() >= 32 || c->c == '\t' || c->isCustom() ) { 5019 if ( c->c.unicode() >= 32 || c->c == '\t' || c->isCustom() ) {
5046 ww = text->width( pos ); 5020 ww = text->width( pos );
5047 } else { 5021 } else {
5048 ww = c->format()->width( ' ' ); 5022 ww = c->format()->width( ' ' );
5049 } 5023 }
5050 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww; 5024 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww;
5051 x += ww; 5025 x += ww;
5052 pos++; 5026 pos++;
5053 } 5027 }
5054 } 5028 }
5055 text->at( r->start + start ).startOfRun = TRUE; 5029 text->at( r->start + start ).startOfRun = TRUE;
5056 r = runs->next(); 5030 r = runs->next();
5057 } 5031 }
5058 5032
5059 line->w = xmax + 10; 5033 line->w = xmax + 10;
5060 QTextLineStart *ls = new QTextLineStart( control->context, control->status ); 5034 QTextLineStart *ls = new QTextLineStart( control->context, control->status );
5061 delete control; 5035 delete control;
5062 delete runs; 5036 delete runs;
5063 return ls; 5037 return ls;
5064} 5038}
5065#endif 5039#endif
5066 5040
5067bool QTextFormatter::isBreakable( QTextString *string, int pos ) 5041bool QTextFormatter::isBreakable( QTextString *string, int pos )
5068{ 5042{
5069 const QChar &c = string->at( pos ).c; 5043 const QChar &c = string->at( pos ).c;
5070 char ch = c.latin1(); 5044 char ch = c.latin1();
5071 if ( c == QChar_linesep ) 5045 if ( c == QChar_linesep )
5072 return TRUE; 5046 return TRUE;
5073 if ( c.isSpace() && ch != '\n' && c.unicode() != 0x00a0U ) 5047 if ( c.isSpace() && ch != '\n' && c.unicode() != 0x00a0U )
5074 return TRUE; 5048 return TRUE;
5075 if ( c.unicode() == 0xad ) // soft hyphen 5049 if ( c.unicode() == 0xad ) // soft hyphen
5076 return TRUE; 5050 return TRUE;
5077 if ( !ch ) { 5051 if ( !ch ) {
5078 // not latin1, need to do more sophisticated checks for other scripts 5052 // not latin1, need to do more sophisticated checks for other scripts
5079 uchar row = c.row(); 5053 uchar row = c.row();
5080 if ( row == 0x0e ) { 5054 if ( row == 0x0e ) {
5081 // 0e00 - 0e7f == Thai 5055 // 0e00 - 0e7f == Thai
5082 if ( c.cell() < 0x80 ) { 5056 if ( c.cell() < 0x80 ) {
5083#ifdef HAVE_THAI_BREAKS 5057#ifdef HAVE_THAI_BREAKS
5084 // check for thai 5058 // check for thai
5085 if( string != cachedString ) { 5059 if( string != cachedString ) {
5086 // build up string of thai chars 5060 // build up string of thai chars
5087 QTextCodec *thaiCodec = QTextCodec::codecForMib(2259); 5061 QTextCodec *thaiCodec = QTextCodec::codecForMib(2259);
5088 if ( !thaiCache ) 5062 if ( !thaiCache )
5089 thaiCache = new QCString; 5063 thaiCache = new QCString;
5090 if ( !thaiIt ) 5064 if ( !thaiIt )
5091 thaiIt = ThBreakIterator::createWordInstance(); 5065 thaiIt = ThBreakIterator::createWordInstance();
5092 *thaiCache = thaiCodec->fromUnicode( s->string() ); 5066 *thaiCache = thaiCodec->fromUnicode( s->string() );
5093 } 5067 }
5094 thaiIt->setText(thaiCache->data()); 5068 thaiIt->setText(thaiCache->data());
5095 for(int i = thaiIt->first(); i != thaiIt->DONE; i = thaiIt->next() ) { 5069 for(int i = thaiIt->first(); i != thaiIt->DONE; i = thaiIt->next() ) {
5096 if( i == pos ) 5070 if( i == pos )
5097 return TRUE; 5071 return TRUE;
5098 if( i > pos ) 5072 if( i > pos )
5099 return FALSE; 5073 return FALSE;
5100 } 5074 }
5101 return FALSE; 5075 return FALSE;
5102#else 5076#else
5103 // if we don't have a thai line breaking lib, allow 5077 // if we don't have a thai line breaking lib, allow
5104 // breaks everywhere except directly before punctuation. 5078 // breaks everywhere except directly before punctuation.
5105 return TRUE; 5079 return TRUE;
5106#endif 5080#endif
5107 } else 5081 } else
5108 return FALSE; 5082 return FALSE;
5109 } 5083 }
5110 if ( row < 0x11 ) // no asian font 5084 if ( row < 0x11 ) // no asian font
5111 return FALSE; 5085 return FALSE;
5112 if ( row > 0x2d && row < 0xfb || row == 0x11 ) 5086 if ( row > 0x2d && row < 0xfb || row == 0x11 )
5113 // asian line breaking. Everywhere allowed except directly 5087 // asian line breaking. Everywhere allowed except directly
5114 // in front of a punctuation character. 5088 // in front of a punctuation character.
5115 return TRUE; 5089 return TRUE;
5116 } 5090 }
5117 return FALSE; 5091 return FALSE;
5118} 5092}
5119 5093
5120void QTextFormatter::insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls ) 5094void QTextFormatter::insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls )
5121{ 5095{
5122 if ( index > 0 ) { // we can assume that only first line starts are insrted multiple times 5096 if ( index > 0 ) { // we can assume that only first line starts are insrted multiple times
5123 parag->lineStartList().insert( index, ls ); 5097 parag->lineStartList().insert( index, ls );
5124 return; 5098 return;
5125 } 5099 }
5126 QMap<int, QTextLineStart*>::Iterator it; 5100 QMap<int, QTextLineStart*>::Iterator it;
5127 if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) { 5101 if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) {
5128 parag->lineStartList().insert( index, ls ); 5102 parag->lineStartList().insert( index, ls );
5129 } else { 5103 } else {
5130 delete *it; 5104 delete *it;
5131 parag->lineStartList().remove( it ); 5105 parag->lineStartList().remove( it );
5132 parag->lineStartList().insert( index, ls ); 5106 parag->lineStartList().insert( index, ls );
5133 } 5107 }
5134} 5108}
5135 5109
5136 5110
5137/* Standard pagebreak algorithm using QTextFlow::adjustFlow. Returns 5111/* Standard pagebreak algorithm using QTextFlow::adjustFlow. Returns
5138 the shift of the paragraphs bottom line. 5112 the shift of the paragraphs bottom line.
5139 */ 5113 */
5140int QTextFormatter::formatVertically( QTextDocument* doc, QTextParagraph* parag ) 5114int QTextFormatter::formatVertically( QTextDocument* doc, QTextParagraph* parag )
5141{ 5115{
5142 int oldHeight = parag->rect().height(); 5116 int oldHeight = parag->rect().height();
5143 QMap<int, QTextLineStart*>& lineStarts = parag->lineStartList(); 5117 QMap<int, QTextLineStart*>& lineStarts = parag->lineStartList();
5144 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin(); 5118 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin();
5145 int h = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0; 5119 int h = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0;
5146 for ( ; it != lineStarts.end() ; ++it ) { 5120 for ( ; it != lineStarts.end() ; ++it ) {
5147 QTextLineStart * ls = it.data(); 5121 QTextLineStart * ls = it.data();
5148 ls->y = h; 5122 ls->y = h;
5149 QTextStringChar *c = &parag->string()->at(it.key()); 5123 QTextStringChar *c = &parag->string()->at(it.key());
5150 if ( c && c->customItem() && c->customItem()->ownLine() ) { 5124 if ( c && c->customItem() && c->customItem()->ownLine() ) {
5151 int h = c->customItem()->height; 5125 int h = c->customItem()->height;
5152 c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() ); 5126 c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() );
5153 int delta = c->customItem()->height - h; 5127 int delta = c->customItem()->height - h;
5154 ls->h += delta; 5128 ls->h += delta;
5155 if ( delta ) 5129 if ( delta )
5156 parag->setMovedDown( TRUE ); 5130 parag->setMovedDown( TRUE );
5157 } else { 5131 } else {
5158 int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h ); 5132 int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h );
5159 ls->y += shift; 5133 ls->y += shift;
5160 if ( shift ) 5134 if ( shift )
5161 parag->setMovedDown( TRUE ); 5135 parag->setMovedDown( TRUE );
5162 } 5136 }
5163 h = ls->y + ls->h; 5137 h = ls->y + ls->h;
5164 } 5138 }
5165 int m = parag->bottomMargin(); 5139 int m = parag->bottomMargin();
5166 if ( !parag->next() ) 5140 if ( !parag->next() )
5167 m = 0; 5141 m = 0;
5168 else 5142 else
5169 m = QMAX(m, parag->next()->topMargin() ) / 2; 5143 m = QMAX(m, parag->next()->topMargin() ) / 2;
5170 h += m; 5144 h += m;
5171 parag->setHeight( h ); 5145 parag->setHeight( h );
5172 return h - oldHeight; 5146 return h - oldHeight;
5173} 5147}
5174 5148
5175// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5149// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5176 5150
5177QTextFormatterBreakInWords::QTextFormatterBreakInWords() 5151QTextFormatterBreakInWords::QTextFormatterBreakInWords()
5178{ 5152{
5179} 5153}
5180 5154
5181#define SPACE(s) doc?(s>0?s:0):s 5155#define SPACE(s) doc?(s>0?s:0):s
5182 5156
5183int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParagraph *parag, 5157int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParagraph *parag,
5184 int start, const QMap<int, QTextLineStart*> & ) 5158 int start, const QMap<int, QTextLineStart*> & )
5185{ 5159{
5186 QTextStringChar *c = 0; 5160 QTextStringChar *c = 0;
5187 QTextStringChar *firstChar = 0; 5161 QTextStringChar *firstChar = 0;
5188 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; 5162 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0;
5189 int x = left + ( doc ? parag->firstLineMargin() : 0 ); 5163 int x = left + ( doc ? parag->firstLineMargin() : 0 );
5190 int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 ); 5164 int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 );
5191 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; 5165 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0;
5192 int h = y; 5166 int h = y;
5193 int len = parag->length(); 5167 int len = parag->length();
5194 if ( doc ) 5168 if ( doc )
5195 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 ); 5169 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 );
5196 int rm = parag->rightMargin(); 5170 int rm = parag->rightMargin();
5197 int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5171 int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5198 bool fullWidth = TRUE; 5172 bool fullWidth = TRUE;
5199 int minw = 0; 5173 int minw = 0;
5200 int wused = 0; 5174 int wused = 0;
5201 bool wrapEnabled = isWrapEnabled( parag ); 5175 bool wrapEnabled = isWrapEnabled( parag );
5202 5176
5203 start = 0; //######### what is the point with start?! (Matthias) 5177 start = 0; //######### what is the point with start?! (Matthias)
5204 if ( start == 0 ) 5178 if ( start == 0 )
5205 c = &parag->string()->at( 0 ); 5179 c = &parag->string()->at( 0 );
5206 5180
5207 int i = start; 5181 int i = start;
5208 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); 5182 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
5209 insertLineStart( parag, 0, lineStart ); 5183 insertLineStart( parag, 0, lineStart );
5210 5184
5211 QPainter *painter = QTextFormat::painter(); 5185 QPainter *painter = QTextFormat::painter();
5212 5186
5213 int col = 0; 5187 int col = 0;
5214 int ww = 0; 5188 int ww = 0;
5215 QChar lastChr; 5189 QChar lastChr;
5216 for ( ; i < len; ++i, ++col ) { 5190 for ( ; i < len; ++i, ++col ) {
5217 if ( c ) 5191 if ( c )
5218 lastChr = c->c; 5192 lastChr = c->c;
5219 c = &parag->string()->at( i ); 5193 c = &parag->string()->at( i );
5220 c->rightToLeft = FALSE; 5194 c->rightToLeft = FALSE;
5221 // ### the lines below should not be needed 5195 // ### the lines below should not be needed
5222 if ( painter ) 5196 if ( painter )
5223 c->format()->setPainter( painter ); 5197 c->format()->setPainter( painter );
5224 if ( i > 0 ) { 5198 if ( i > 0 ) {
5225 c->lineStart = 0; 5199 c->lineStart = 0;
5226 } else { 5200 } else {
5227 c->lineStart = 1; 5201 c->lineStart = 1;
5228 firstChar = c; 5202 firstChar = c;
5229 } 5203 }
5230 if ( c->c.unicode() >= 32 || c->isCustom() ) { 5204 if ( c->c.unicode() >= 32 || c->isCustom() ) {
5231 ww = parag->string()->width( i ); 5205 ww = parag->string()->width( i );
5232 } else if ( c->c == '\t' ) { 5206 } else if ( c->c == '\t' ) {
5233 int nx = parag->nextTab( i, x - left ) + left; 5207 int nx = parag->nextTab( i, x - left ) + left;
5234 if ( nx < x ) 5208 if ( nx < x )
5235 ww = w - x; 5209 ww = w - x;
5236 else 5210 else
5237 ww = nx - x; 5211 ww = nx - x;
5238 } else { 5212 } else {
5239 ww = c->format()->width( ' ' ); 5213 ww = c->format()->width( ' ' );
5240 } 5214 }
5241 5215
5242 if ( c->isCustom() && c->customItem()->ownLine() ) { 5216 if ( c->isCustom() && c->customItem()->ownLine() ) {
5243 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5217 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5244 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5218 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5245 c->customItem()->resize( w - x ); 5219 c->customItem()->resize( w - x );
5246 w = dw; 5220 w = dw;
5247 y += h; 5221 y += h;
5248 h = c->height(); 5222 h = c->height();
5249 lineStart = new QTextLineStart( y, h, h ); 5223 lineStart = new QTextLineStart( y, h, h );
5250 insertLineStart( parag, i, lineStart ); 5224 insertLineStart( parag, i, lineStart );
5251 c->lineStart = 1; 5225 c->lineStart = 1;
5252 firstChar = c; 5226 firstChar = c;
5253 x = 0xffffff; 5227 x = 0xffffff;
5254 continue; 5228 continue;
5255 } 5229 }
5256 5230
5257 if ( wrapEnabled && 5231 if ( wrapEnabled &&
5258 ( wrapAtColumn() == -1 && x + ww > w || 5232 ( wrapAtColumn() == -1 && x + ww > w ||
5259 wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) { 5233 wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) {
5260 x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5234 x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5261 w = dw; 5235 w = dw;
5262 y += h; 5236 y += h;
5263 h = c->height(); 5237 h = c->height();
5264 lineStart = formatLine( parag, parag->string(), lineStart, firstChar, SPACE(c-1) ); 5238 lineStart = formatLine( parag, parag->string(), lineStart, firstChar, SPACE(c-1) );
5265 lineStart->y = y; 5239 lineStart->y = y;
5266 insertLineStart( parag, i, lineStart ); 5240 insertLineStart( parag, i, lineStart );
5267 lineStart->baseLine = c->ascent(); 5241 lineStart->baseLine = c->ascent();
5268 lineStart->h = c->height(); 5242 lineStart->h = c->height();
5269 c->lineStart = 1; 5243 c->lineStart = 1;
5270 firstChar = c; 5244 firstChar = c;
5271 col = 0; 5245 col = 0;
5272 if ( wrapAtColumn() != -1 ) 5246 if ( wrapAtColumn() != -1 )
5273 minw = QMAX( minw, w ); 5247 minw = QMAX( minw, w );
5274 } else if ( lineStart ) { 5248 } else if ( lineStart ) {
5275 lineStart->baseLine = QMAX( lineStart->baseLine, c->ascent() ); 5249 lineStart->baseLine = QMAX( lineStart->baseLine, c->ascent() );
5276 h = QMAX( h, c->height() ); 5250 h = QMAX( h, c->height() );
5277 lineStart->h = h; 5251 lineStart->h = h;
5278 } 5252 }
5279 5253
5280 c->x = x; 5254 c->x = x;
5281 x += ww; 5255 x += ww;
5282 wused = QMAX( wused, x ); 5256 wused = QMAX( wused, x );
5283 } 5257 }
5284 5258
5285 int m = parag->bottomMargin(); 5259 int m = parag->bottomMargin();
5286 if ( !parag->next() ) 5260 if ( !parag->next() )
5287 m = 0; 5261 m = 0;
5288 else 5262 else
5289 m = QMAX(m, parag->next()->topMargin() ) / 2; 5263 m = QMAX(m, parag->next()->topMargin() ) / 2;
5290 parag->setFullWidth( fullWidth ); 5264 parag->setFullWidth( fullWidth );
5291 y += h + m; 5265 y += h + m;
5292 if ( doc ) 5266 if ( doc )
5293 minw += doc->rightMargin(); 5267 minw += doc->rightMargin();
5294 if ( !wrapEnabled ) 5268 if ( !wrapEnabled )
5295 minw = QMAX(minw, wused); 5269 minw = QMAX(minw, wused);
5296 5270
5297 thisminw = minw; 5271 thisminw = minw;
5298 thiswused = wused; 5272 thiswused = wused;
5299 return y; 5273 return y;
5300} 5274}
5301 5275
5302// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5276// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5303 5277
5304QTextFormatterBreakWords::QTextFormatterBreakWords() 5278QTextFormatterBreakWords::QTextFormatterBreakWords()
5305{ 5279{
5306} 5280}
5307 5281
5308#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \ 5282#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \
5309 int yflow = lineStart->y + parag->rect().y();\ 5283 int yflow = lineStart->y + parag->rect().y();\
5310 int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \ 5284 int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \
5311 lineStart->y += shift;\ 5285 lineStart->y += shift;\
5312 y += shift;\ 5286 y += shift;\
5313 }}while(FALSE) 5287 }}while(FALSE)
5314 5288
5315int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParagraph *parag, 5289int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParagraph *parag,
5316 int start, const QMap<int, QTextLineStart*> & ) 5290 int start, const QMap<int, QTextLineStart*> & )
5317{ 5291{
5318 QTextStringChar *c = 0; 5292 QTextStringChar *c = 0;
5319 QTextStringChar *firstChar = 0; 5293 QTextStringChar *firstChar = 0;
5320 QTextString *string = parag->string(); 5294 QTextString *string = parag->string();
5321 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; 5295 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0;
5322 int x = left + ( doc ? parag->firstLineMargin() : 0 ); 5296 int x = left + ( doc ? parag->firstLineMargin() : 0 );
5323 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0; 5297 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0;
5324 int h = y; 5298 int h = y;
5325 int len = parag->length(); 5299 int len = parag->length();
5326 if ( doc ) 5300 if ( doc )
5327 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 ); 5301 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 );
5328 int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 ); 5302 int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 );
5329 5303
5330 int curLeft = x; 5304 int curLeft = x;
5331 int rm = parag->rightMargin(); 5305 int rm = parag->rightMargin();
5332 int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0; 5306 int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0;
5333 int w = dw - rdiff; 5307 int w = dw - rdiff;
5334 bool fullWidth = TRUE; 5308 bool fullWidth = TRUE;
5335 int marg = left + rdiff; 5309 int marg = left + rdiff;
5336 int minw = 0; 5310 int minw = 0;
5337 int wused = 0; 5311 int wused = 0;
5338 int tminw = marg; 5312 int tminw = marg;
5339 int linespacing = doc ? parag->lineSpacing() : 0; 5313 int linespacing = doc ? parag->lineSpacing() : 0;
5340 bool wrapEnabled = isWrapEnabled( parag ); 5314 bool wrapEnabled = isWrapEnabled( parag );
5341 5315
5342 start = 0; 5316 start = 0;
5343 if ( start == 0 ) 5317 if ( start == 0 )
5344 c = &parag->string()->at( 0 ); 5318 c = &parag->string()->at( 0 );
5345 5319
5346 int i = start; 5320 int i = start;
5347 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 ); 5321 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
5348 insertLineStart( parag, 0, lineStart ); 5322 insertLineStart( parag, 0, lineStart );
5349 int lastBreak = -1; 5323 int lastBreak = -1;
5350 int tmpBaseLine = 0, tmph = 0; 5324 int tmpBaseLine = 0, tmph = 0;
5351 bool lastWasNonInlineCustom = FALSE; 5325 bool lastWasNonInlineCustom = FALSE;
5352 5326
5353 int align = parag->alignment(); 5327 int align = parag->alignment();
5354 if ( align == Qt3::AlignAuto && doc && doc->alignment() != Qt3::AlignAuto ) 5328 if ( align == Qt3::AlignAuto && doc && doc->alignment() != Qt3::AlignAuto )
5355 align = doc->alignment(); 5329 align = doc->alignment();
5356 5330
5357 align &= Qt3::AlignHorizontal_Mask; 5331 align &= Qt3::AlignHorizontal_Mask;
5358 5332
5359 QPainter *painter = QTextFormat::painter(); 5333 QPainter *painter = QTextFormat::painter();
5360 int col = 0; 5334 int col = 0;
5361 int ww = 0; 5335 int ww = 0;
5362 QChar lastChr; 5336 QChar lastChr;
5363 for ( ; i < len; ++i, ++col ) { 5337 for ( ; i < len; ++i, ++col ) {
5364 if ( c ) 5338 if ( c )
5365 lastChr = c->c; 5339 lastChr = c->c;
5366 // ### next line should not be needed 5340 // ### next line should not be needed
5367 if ( c && painter ) 5341 if ( painter )
5368 c->format()->setPainter( painter ); 5342 c->format()->setPainter( painter );
5369 c = &string->at( i ); 5343 c = &string->at( i );
5370 c->rightToLeft = FALSE; 5344 c->rightToLeft = FALSE;
5371 if ( i > 0 && (x > curLeft || ww == 0) || lastWasNonInlineCustom ) { 5345 if ( i > 0 && (x > curLeft || ww == 0) || lastWasNonInlineCustom ) {
5372 c->lineStart = 0; 5346 c->lineStart = 0;
5373 } else { 5347 } else {
5374 c->lineStart = 1; 5348 c->lineStart = 1;
5375 firstChar = c; 5349 firstChar = c;
5376 } 5350 }
5377 5351
5378 if ( c->isCustom() && c->customItem()->placement() != QTextCustomItem::PlaceInline ) 5352 if ( c->isCustom() && c->customItem()->placement() != QTextCustomItem::PlaceInline )
5379 lastWasNonInlineCustom = TRUE; 5353 lastWasNonInlineCustom = TRUE;
5380 else 5354 else
5381 lastWasNonInlineCustom = FALSE; 5355 lastWasNonInlineCustom = FALSE;
5382 5356
5383 if ( c->c.unicode() >= 32 || c->isCustom() ) { 5357 if ( c->c.unicode() >= 32 || c->isCustom() ) {
5384 ww = string->width( i ); 5358 ww = string->width( i );
5385 } else if ( c->c == '\t' ) { 5359 } else if ( c->c == '\t' ) {
5386 int nx = parag->nextTab( i, x - left ) + left; 5360 int nx = parag->nextTab( i, x - left ) + left;
5387 if ( nx < x ) 5361 if ( nx < x )
5388 ww = w - x; 5362 ww = w - x;
5389 else 5363 else
5390 ww = nx - x; 5364 ww = nx - x;
5391 } else { 5365 } else {
5392 ww = c->format()->width( ' ' ); 5366 ww = c->format()->width( ' ' );
5393 } 5367 }
5394 5368
5395 // last character ("invisible" space) has no width 5369 // last character ("invisible" space) has no width
5396 if ( i == len - 1 ) 5370 if ( i == len - 1 )
5397 ww = 0; 5371 ww = 0;
5398 5372
5399 QTextCustomItem* ci = c->customItem(); 5373 QTextCustomItem* ci = c->customItem();
5400 if ( c->isCustom() && ci->ownLine() ) { 5374 if ( c->isCustom() && ci->ownLine() ) {
5401 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5375 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5402 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5376 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5403 QTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); 5377 QTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) );
5404 ci->resize( w - x); 5378 ci->resize( w - x);
5405 if ( ci->width < w - x ) { 5379 if ( ci->width < w - x ) {
5406 if ( align & Qt::AlignHCenter ) 5380 if ( align & Qt::AlignHCenter )
5407 x = ( w - ci->width ) / 2; 5381 x = ( w - ci->width ) / 2;
5408 else if ( align & Qt::AlignRight ) { 5382 else if ( align & Qt::AlignRight ) {
5409 x = w - ci->width; 5383 x = w - ci->width;
5410 } 5384 }
5411 } 5385 }
5412 c->x = x; 5386 c->x = x;
5413 curLeft = x; 5387 curLeft = x;
5414 if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) { 5388 if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) {
5415 y += QMAX( h, QMAX( tmph, linespacing ) ); 5389 y += QMAX( h, QMAX( tmph, linespacing ) );
5416 tmph = c->height(); 5390 tmph = c->height();
5417 h = tmph; 5391 h = tmph;
5418 lineStart = lineStart2; 5392 lineStart = lineStart2;
5419 lineStart->y = y; 5393 lineStart->y = y;
5420 insertLineStart( parag, i, lineStart ); 5394 insertLineStart( parag, i, lineStart );
5421 c->lineStart = 1; 5395 c->lineStart = 1;
5422 firstChar = c; 5396 firstChar = c;
5423 } else { 5397 } else {
5424 tmph = c->height(); 5398 tmph = c->height();
5425 h = tmph; 5399 h = tmph;
5426 delete lineStart2; 5400 delete lineStart2;
5427 } 5401 }
5428 lineStart->h = h; 5402 lineStart->h = h;
5429 lineStart->baseLine = h; 5403 lineStart->baseLine = h;
5430 tmpBaseLine = lineStart->baseLine; 5404 tmpBaseLine = lineStart->baseLine;
5431 lastBreak = -2; 5405 lastBreak = -2;
5432 x = 0xffffff; 5406 x = 0xffffff;
5433 minw = QMAX( minw, tminw ); 5407 minw = QMAX( minw, tminw );
5434 5408
5435 int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 ); 5409 int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 );
5436 if ( tw < QWIDGETSIZE_MAX ) 5410 if ( tw < QWIDGETSIZE_MAX )
5437 tminw = tw; 5411 tminw = tw;
5438 else 5412 else
5439 tminw = marg; 5413 tminw = marg;
5440 wused = QMAX( wused, ci->width ); 5414 wused = QMAX( wused, ci->width );
5441 continue; 5415 continue;
5442 } else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) { 5416 } else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) {
5443 int tw = ci->minimumWidth(); 5417 int tw = ci->minimumWidth();
5444 if ( tw < QWIDGETSIZE_MAX ) 5418 if ( tw < QWIDGETSIZE_MAX )
5445 minw = QMAX( minw, tw ); 5419 minw = QMAX( minw, tw );
5446 } 5420 }
5447 5421
5448 bool lastWasOwnLineCustomItem = lastBreak == -2; 5422 bool lastWasOwnLineCustomItem = lastBreak == -2;
5449 bool hadBreakableChar = lastBreak != -1; 5423 bool hadBreakableChar = lastBreak != -1;
5450 bool lastWasHardBreak = lastChr == QChar_linesep; 5424 bool lastWasHardBreak = lastChr == QChar_linesep;
5451 5425
5452 // we break if 5426 // we break if
5453 // 1. the last character was a hard break (QChar_linesep) or 5427 // 1. the last character was a hard break (QChar_linesep) or
5454 // 2. the last charater was a own-line custom item (eg. table or ruler) or 5428 // 2. the last charater was a own-line custom item (eg. table or ruler) or
5455 // 3. wrapping was enabled, it was not a space and following 5429 // 3. wrapping was enabled, it was not a space and following
5456 // condition is true: We either had a breakable character 5430 // condition is true: We either had a breakable character
5457 // previously or we ar allowed to break in words and - either 5431 // previously or we ar allowed to break in words and - either
5458 // we break at w pixels and the current char would exceed that 5432 // we break at w pixels and the current char would exceed that
5459 // or - we break at a column and the current character would 5433 // or - we break at a column and the current character would
5460 // exceed that. 5434 // exceed that.
5461 if ( lastWasHardBreak || lastWasOwnLineCustomItem || 5435 if ( lastWasHardBreak || lastWasOwnLineCustomItem ||
5462 ( wrapEnabled && 5436 ( wrapEnabled &&
5463 ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) && 5437 ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) &&
5464 ( (wrapAtColumn() == -1 && x + ww > w) || 5438 ( (wrapAtColumn() == -1 && x + ww > w) ||
5465 (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) ) 5439 (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) )
5466 ) 5440 )
5467 ) { 5441 ) {
5468 if ( wrapAtColumn() != -1 ) 5442 if ( wrapAtColumn() != -1 )
5469 minw = QMAX( minw, x + ww ); 5443 minw = QMAX( minw, x + ww );
5470 // if a break was forced (no breakable char, hard break or own line custom item), break immediately.... 5444 // if a break was forced (no breakable char, hard break or own line custom item), break immediately....
5471 if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) { 5445 if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) {
5472 if ( lineStart ) { 5446 if ( lineStart ) {
5473 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5447 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5474 h = QMAX( h, tmph ); 5448 h = QMAX( h, tmph );
5475 lineStart->h = h; 5449 lineStart->h = h;
5476 DO_FLOW( lineStart ); 5450 DO_FLOW( lineStart );
5477 } 5451 }
5478 lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) ); 5452 lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) );
5479 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5453 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5480 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5454 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5481 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling 5455 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling
5482 int nx = parag->nextTab( i, x - left ) + left; 5456 int nx = parag->nextTab( i, x - left ) + left;
5483 if ( nx < x ) 5457 if ( nx < x )
5484 ww = w - x; 5458 ww = w - x;
5485 else 5459 else
5486 ww = nx - x; 5460 ww = nx - x;
5487 } 5461 }
5488 curLeft = x; 5462 curLeft = x;
5489 y += QMAX( h, linespacing ); 5463 y += QMAX( h, linespacing );
5490 tmph = c->height(); 5464 tmph = c->height();
5491 h = 0; 5465 h = 0;
5492 lineStart->y = y; 5466 lineStart->y = y;
5493 insertLineStart( parag, i, lineStart ); 5467 insertLineStart( parag, i, lineStart );
5494 lineStart->baseLine = c->ascent(); 5468 lineStart->baseLine = c->ascent();
5495 lineStart->h = c->height(); 5469 lineStart->h = c->height();
5496 c->lineStart = 1; 5470 c->lineStart = 1;
5497 firstChar = c; 5471 firstChar = c;
5498 tmpBaseLine = lineStart->baseLine; 5472 tmpBaseLine = lineStart->baseLine;
5499 lastBreak = -1; 5473 lastBreak = -1;
5500 col = 0; 5474 col = 0;
5501 } else { // ... otherwise if we had a breakable char, break there 5475 } else { // ... otherwise if we had a breakable char, break there
5502 DO_FLOW( lineStart ); 5476 DO_FLOW( lineStart );
5503 i = lastBreak; 5477 i = lastBreak;
5504 lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i ).x) ); 5478 lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i ).x) );
5505 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5479 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5506 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5480 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5507 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling 5481 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling
5508 int nx = parag->nextTab( i, x - left ) + left; 5482 int nx = parag->nextTab( i, x - left ) + left;
5509 if ( nx < x ) 5483 if ( nx < x )
5510 ww = w - x; 5484 ww = w - x;
5511 else 5485 else
5512 ww = nx - x; 5486 ww = nx - x;
5513 } 5487 }
5514 curLeft = x; 5488 curLeft = x;
5515 y += QMAX( h, linespacing ); 5489 y += QMAX( h, linespacing );
5516 tmph = c->height(); 5490 tmph = c->height();
5517 h = tmph; 5491 h = tmph;
5518 lineStart->y = y; 5492 lineStart->y = y;
5519 insertLineStart( parag, i + 1, lineStart ); 5493 insertLineStart( parag, i + 1, lineStart );
5520 lineStart->baseLine = c->ascent(); 5494 lineStart->baseLine = c->ascent();
5521 lineStart->h = c->height(); 5495 lineStart->h = c->height();
5522 c->lineStart = 1; 5496 c->lineStart = 1;
5523 firstChar = c; 5497 firstChar = c;
5524 tmpBaseLine = lineStart->baseLine; 5498 tmpBaseLine = lineStart->baseLine;
5525 lastBreak = -1; 5499 lastBreak = -1;
5526 col = 0; 5500 col = 0;
5527 tminw = marg; 5501 tminw = marg;
5528 continue; 5502 continue;
5529 } 5503 }
5530 } else if ( lineStart && isBreakable( string, i ) ) { 5504 } else if ( lineStart && isBreakable( string, i ) ) {
5531 if ( len <= 2 || i < len - 1 ) { 5505 if ( len <= 2 || i < len - 1 ) {
5532 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); 5506 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() );
5533 tmph = QMAX( tmph, c->height() ); 5507 tmph = QMAX( tmph, c->height() );
5534 } 5508 }
5535 minw = QMAX( minw, tminw ); 5509 minw = QMAX( minw, tminw );
5536 tminw = marg + ww; 5510 tminw = marg + ww;
5537 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5511 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5538 h = QMAX( h, tmph ); 5512 h = QMAX( h, tmph );
5539 lineStart->h = h; 5513 lineStart->h = h;
5540 if ( i < len - 2 || c->c != ' ' ) 5514 if ( i < len - 2 || c->c != ' ' )
5541 lastBreak = i; 5515 lastBreak = i;
5542 } else { 5516 } else {
5543 tminw += ww; 5517 tminw += ww;
5544 int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height()- c->ascent() ); 5518 int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height()- c->ascent() );
5545 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); 5519 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() );
5546 tmph = tmpBaseLine + belowBaseLine; 5520 tmph = tmpBaseLine + belowBaseLine;
5547 } 5521 }
5548 5522
5549 c->x = x; 5523 c->x = x;
5550 x += ww; 5524 x += ww;
5551 wused = QMAX( wused, x ); 5525 wused = QMAX( wused, x );
5552 } 5526 }
5553 5527
5554 // ### hack. The last char in the paragraph is always invisible, 5528 // ### hack. The last char in the paragraph is always invisible,
5555 // ### and somehow sometimes has a wrong format. It changes 5529 // ### and somehow sometimes has a wrong format. It changes
5556 // ### between // layouting and printing. This corrects some 5530 // ### between // layouting and printing. This corrects some
5557 // ### layouting errors in BiDi mode due to this. 5531 // ### layouting errors in BiDi mode due to this.
5558 if ( len > 1 && !c->isAnchor() ) { 5532 if ( len > 1 && !c->isAnchor() ) {
5559 c->format()->removeRef(); 5533 c->format()->removeRef();
5560 c->setFormat( string->at( len - 2 ).format() ); 5534 c->setFormat( string->at( len - 2 ).format() );
5561 c->format()->addRef(); 5535 c->format()->addRef();
5562 } 5536 }
5563 5537
5564 if ( lineStart ) { 5538 if ( lineStart ) {
5565 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5539 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5566 h = QMAX( h, tmph ); 5540 h = QMAX( h, tmph );
5567 lineStart->h = h; 5541 lineStart->h = h;
5568 // last line in a paragraph is not justified 5542 // last line in a paragraph is not justified
5569 if ( align == Qt3::AlignJustify || lastChr == QChar_linesep ) 5543 if ( align == Qt3::AlignJustify || lastChr == QChar_linesep )
5570 align = Qt3::AlignAuto; 5544 align = Qt3::AlignAuto;
5571 DO_FLOW( lineStart ); 5545 DO_FLOW( lineStart );
5572 lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) ); 5546 lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) );
5573 delete lineStart; 5547 delete lineStart;
5574 } 5548 }
5575 5549
5576 minw = QMAX( minw, tminw ); 5550 minw = QMAX( minw, tminw );
5577 if ( doc ) 5551 if ( doc )
5578 minw += doc->rightMargin(); 5552 minw += doc->rightMargin();
5579 5553
5580 int m = parag->bottomMargin(); 5554 int m = parag->bottomMargin();
5581 if ( !parag->next() ) 5555 if ( !parag->next() )
5582 m = 0; 5556 m = 0;
5583 else 5557 else
5584 m = QMAX(m, parag->next()->topMargin() ) / 2; 5558 m = QMAX(m, parag->next()->topMargin() ) / 2;
5585 parag->setFullWidth( fullWidth ); 5559 parag->setFullWidth( fullWidth );
5586 y += QMAX( h, linespacing ) + m; 5560 y += QMAX( h, linespacing ) + m;
5587 5561
5588 wused += rm; 5562 wused += rm;
5589 if ( !wrapEnabled || wrapAtColumn() != -1 ) 5563 if ( !wrapEnabled || wrapAtColumn() != -1 )
5590 minw = QMAX(minw, wused); 5564 minw = QMAX(minw, wused);
5591 5565
5592 // This is the case where we are breaking wherever we darn well please 5566 // This is the case where we are breaking wherever we darn well please
5593 // in cases like that, the minw should not be the length of the entire 5567 // in cases like that, the minw should not be the length of the entire
5594 // word, because we necessarily want to show the word on the whole line. 5568 // word, because we necessarily want to show the word on the whole line.
5595 // example: word wrap in iconview 5569 // example: word wrap in iconview
5596 if ( allowBreakInWords() && minw > wused ) 5570 if ( allowBreakInWords() && minw > wused )
5597 minw = wused; 5571 minw = wused;
5598 5572
5599 thisminw = minw; 5573 thisminw = minw;
5600 thiswused = wused; 5574 thiswused = wused;
5601 return y; 5575 return y;
5602} 5576}
5603 5577
5604// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5578// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5605 5579
5606QTextIndent::QTextIndent() 5580QTextIndent::QTextIndent()
5607{ 5581{
5608} 5582}
5609 5583
5610// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5584// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5611 5585
5612QTextFormatCollection::QTextFormatCollection() 5586QTextFormatCollection::QTextFormatCollection()
5613 : cKey( 307 ) 5587 : cKey( 307 )
5614{ 5588{
5615 defFormat = new QTextFormat( QApplication::font(), 5589 defFormat = new QTextFormat( QApplication::font(),
5616 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) ); 5590 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) );
5617 lastFormat = cres = 0; 5591 lastFormat = cres = 0;
5618 cflags = -1; 5592 cflags = -1;
5619 cKey.setAutoDelete( TRUE ); 5593 cKey.setAutoDelete( TRUE );
5620 cachedFormat = 0; 5594 cachedFormat = 0;
5621} 5595}
5622 5596
5623QTextFormatCollection::~QTextFormatCollection() 5597QTextFormatCollection::~QTextFormatCollection()
5624{ 5598{
5625 delete defFormat; 5599 delete defFormat;
5626} 5600}
5627 5601
5628QTextFormat *QTextFormatCollection::format( QTextFormat *f ) 5602QTextFormat *QTextFormatCollection::format( QTextFormat *f )
5629{ 5603{
5630 if ( f->parent() == this || f == defFormat ) { 5604 if ( f->parent() == this || f == defFormat ) {
5631 lastFormat = f; 5605 lastFormat = f;
5632 lastFormat->addRef(); 5606 lastFormat->addRef();
5633 return lastFormat; 5607 return lastFormat;
5634 } 5608 }
5635 5609
5636 if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) { 5610 if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) {
5637 lastFormat->addRef(); 5611 lastFormat->addRef();
5638 return lastFormat; 5612 return lastFormat;
5639 } 5613 }
5640 5614
5641 QTextFormat *fm = cKey.find( f->key() ); 5615 QTextFormat *fm = cKey.find( f->key() );
5642 if ( fm ) { 5616 if ( fm ) {
5643 lastFormat = fm; 5617 lastFormat = fm;
5644 lastFormat->addRef(); 5618 lastFormat->addRef();
5645 return lastFormat; 5619 return lastFormat;
5646 } 5620 }
5647 5621
5648 if ( f->key() == defFormat->key() ) 5622 if ( f->key() == defFormat->key() )
5649 return defFormat; 5623 return defFormat;
5650 5624
5651 lastFormat = createFormat( *f ); 5625 lastFormat = createFormat( *f );
5652 lastFormat->collection = this; 5626 lastFormat->collection = this;
5653 cKey.insert( lastFormat->key(), lastFormat ); 5627 cKey.insert( lastFormat->key(), lastFormat );
5654 return lastFormat; 5628 return lastFormat;
5655} 5629}
5656 5630
5657QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, int flags ) 5631QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, int flags )
5658{ 5632{
5659 if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) { 5633 if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) {
5660 cres->addRef(); 5634 cres->addRef();
5661 return cres; 5635 return cres;
5662 } 5636 }
5663 5637
5664 cres = createFormat( *of ); 5638 cres = createFormat( *of );
5665 kof = of->key(); 5639 kof = of->key();
5666 knf = nf->key(); 5640 knf = nf->key();
5667 cflags = flags; 5641 cflags = flags;
5668 if ( flags & QTextFormat::Bold ) 5642 if ( flags & QTextFormat::Bold )
5669 cres->fn.setBold( nf->fn.bold() ); 5643 cres->fn.setBold( nf->fn.bold() );
5670 if ( flags & QTextFormat::Italic ) 5644 if ( flags & QTextFormat::Italic )
5671 cres->fn.setItalic( nf->fn.italic() ); 5645 cres->fn.setItalic( nf->fn.italic() );
5672 if ( flags & QTextFormat::Underline ) 5646 if ( flags & QTextFormat::Underline )
5673 cres->fn.setUnderline( nf->fn.underline() ); 5647 cres->fn.setUnderline( nf->fn.underline() );
5674 if ( flags & QTextFormat::StrikeOut ) 5648 if ( flags & QTextFormat::StrikeOut )
5675 cres->fn.setStrikeOut( nf->fn.strikeOut() ); 5649 cres->fn.setStrikeOut( nf->fn.strikeOut() );
5676 if ( flags & QTextFormat::Family ) 5650 if ( flags & QTextFormat::Family )
5677 cres->fn.setFamily( nf->fn.family() ); 5651 cres->fn.setFamily( nf->fn.family() );
5678 if ( flags & QTextFormat::Size ) { 5652 if ( flags & QTextFormat::Size ) {
5679 if ( of->usePixelSizes ) 5653 if ( of->usePixelSizes )
5680 cres->fn.setPixelSize( nf->fn.pixelSize() ); 5654 cres->fn.setPixelSize( nf->fn.pixelSize() );
5681 else 5655 else
5682 cres->fn.setPointSize( nf->fn.pointSize() ); 5656 cres->fn.setPointSize( nf->fn.pointSize() );
5683 } 5657 }
5684 if ( flags & QTextFormat::Color ) 5658 if ( flags & QTextFormat::Color )
5685 cres->col = nf->col; 5659 cres->col = nf->col;
5686 if ( flags & QTextFormat::Misspelled ) 5660 if ( flags & QTextFormat::Misspelled )
5687 cres->missp = nf->missp; 5661 cres->missp = nf->missp;
5688 if ( flags & QTextFormat::VAlign ) 5662 if ( flags & QTextFormat::VAlign )
5689 cres->ha = nf->ha; 5663 cres->ha = nf->ha;
5690 cres->update(); 5664 cres->update();
5691 5665
5692 QTextFormat *fm = cKey.find( cres->key() ); 5666 QTextFormat *fm = cKey.find( cres->key() );
5693 if ( !fm ) { 5667 if ( !fm ) {
5694 cres->collection = this; 5668 cres->collection = this;
5695 cKey.insert( cres->key(), cres ); 5669 cKey.insert( cres->key(), cres );
5696 } else { 5670 } else {
5697 delete cres; 5671 delete cres;
5698 cres = fm; 5672 cres = fm;
5699 cres->addRef(); 5673 cres->addRef();
5700 } 5674 }
5701 5675
5702 return cres; 5676 return cres;
5703} 5677}
5704 5678
5705QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c ) 5679QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c )
5706{ 5680{
5707 if ( cachedFormat && cfont == f && ccol == c ) { 5681 if ( cachedFormat && cfont == f && ccol == c ) {
5708 cachedFormat->addRef(); 5682 cachedFormat->addRef();
5709 return cachedFormat; 5683 return cachedFormat;
5710 } 5684 }
5711 5685
5712 QString key = QTextFormat::getKey( f, c, FALSE, QTextFormat::AlignNormal ); 5686 QString key = QTextFormat::getKey( f, c, FALSE, QTextFormat::AlignNormal );
5713 cachedFormat = cKey.find( key ); 5687 cachedFormat = cKey.find( key );
5714 cfont = f; 5688 cfont = f;
5715 ccol = c; 5689 ccol = c;
5716 5690
5717 if ( cachedFormat ) { 5691 if ( cachedFormat ) {
5718 cachedFormat->addRef(); 5692 cachedFormat->addRef();
5719 return cachedFormat; 5693 return cachedFormat;
5720 } 5694 }
5721 5695
5722 if ( key == defFormat->key() ) 5696 if ( key == defFormat->key() )
5723 return defFormat; 5697 return defFormat;
5724 5698
5725 cachedFormat = createFormat( f, c ); 5699 cachedFormat = createFormat( f, c );
5726 cachedFormat->collection = this; 5700 cachedFormat->collection = this;
5727 cKey.insert( cachedFormat->key(), cachedFormat ); 5701 cKey.insert( cachedFormat->key(), cachedFormat );
5728 if ( cachedFormat->key() != key ) 5702 if ( cachedFormat->key() != key )
5729 owarn << "ASSERT: keys for format not identical: '" << cachedFormat->key().latin1() << " '" << key.latin1() << "'" << oendl; 5703 owarn << "ASSERT: keys for format not identical: '" << cachedFormat->key().latin1() << " '" << key.latin1() << "'" << oendl;
5730 return cachedFormat; 5704 return cachedFormat;
5731} 5705}
5732 5706
5733void QTextFormatCollection::remove( QTextFormat *f ) 5707void QTextFormatCollection::remove( QTextFormat *f )
5734{ 5708{
5735 if ( lastFormat == f ) 5709 if ( lastFormat == f )
5736 lastFormat = 0; 5710 lastFormat = 0;
5737 if ( cres == f ) 5711 if ( cres == f )
5738 cres = 0; 5712 cres = 0;
5739 if ( cachedFormat == f ) 5713 if ( cachedFormat == f )
5740 cachedFormat = 0; 5714 cachedFormat = 0;
5741 cKey.remove( f->key() ); 5715 cKey.remove( f->key() );
5742} 5716}
5743 5717
5744#define UPDATE( up, lo, rest ) \ 5718#define UPDATE( up, lo, rest ) \
5745 if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \ 5719 if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \
5746 fm->fn.set##up##rest( font.lo##rest() ) 5720 fm->fn.set##up##rest( font.lo##rest() )
5747 5721
5748void QTextFormatCollection::updateDefaultFormat( const QFont &font, const QColor &color, QStyleSheet *sheet ) 5722void QTextFormatCollection::updateDefaultFormat( const QFont &font, const QColor &color, QStyleSheet *sheet )
5749{ 5723{
5750 QDictIterator<QTextFormat> it( cKey ); 5724 QDictIterator<QTextFormat> it( cKey );
5751 QTextFormat *fm; 5725 QTextFormat *fm;
5752 bool usePixels = font.pointSize() == -1; 5726 bool usePixels = font.pointSize() == -1;
5753 bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() : 5727 bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() :
5754 font.pointSize() != defFormat->fn.pointSize(); 5728 font.pointSize() != defFormat->fn.pointSize();
5755 int base = usePixels ? font.pixelSize() : font.pointSize(); 5729 int base = usePixels ? font.pixelSize() : font.pointSize();
5756 while ( ( fm = it.current() ) ) { 5730 while ( ( fm = it.current() ) ) {
5757 ++it; 5731 ++it;
5758 UPDATE( F, f, amily ); 5732 UPDATE( F, f, amily );
5759 UPDATE( W, w, eight ); 5733 UPDATE( W, w, eight );
5760 UPDATE( B, b, old ); 5734 UPDATE( B, b, old );
5761 UPDATE( I, i, talic ); 5735 UPDATE( I, i, talic );
5762 UPDATE( U, u, nderline ); 5736 UPDATE( U, u, nderline );
5763 if ( changeSize ) { 5737 if ( changeSize ) {
5764 fm->stdSize = base; 5738 fm->stdSize = base;
5765 fm->usePixelSizes = usePixels; 5739 fm->usePixelSizes = usePixels;
5766 if ( usePixels ) 5740 if ( usePixels )
5767 fm->fn.setPixelSize( fm->stdSize ); 5741 fm->fn.setPixelSize( fm->stdSize );
5768 else 5742 else
5769 fm->fn.setPointSize( fm->stdSize ); 5743 fm->fn.setPointSize( fm->stdSize );
5770 sheet->scaleFont( fm->fn, fm->logicalFontSize ); 5744 sheet->scaleFont( fm->fn, fm->logicalFontSize );
5771 } 5745 }
5772 if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col ) 5746 if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col )
5773 fm->col = color; 5747 fm->col = color;
5774 fm->update(); 5748 fm->update();
5775 } 5749 }
5776 5750
5777 defFormat->fn = font; 5751 defFormat->fn = font;
5778 defFormat->col = color; 5752 defFormat->col = color;
5779 defFormat->update(); 5753 defFormat->update();
5780 defFormat->stdSize = base; 5754 defFormat->stdSize = base;
5781 defFormat->usePixelSizes = usePixels; 5755 defFormat->usePixelSizes = usePixels;
5782 5756
5783 updateKeys(); 5757 updateKeys();
5784} 5758}
5785 5759
5786// the keys in cKey have changed, rebuild the hashtable 5760// the keys in cKey have changed, rebuild the hashtable
5787void QTextFormatCollection::updateKeys() 5761void QTextFormatCollection::updateKeys()
5788{ 5762{
5789 if ( cKey.isEmpty() ) 5763 if ( cKey.isEmpty() )
5790 return; 5764 return;
5791 cKey.setAutoDelete( FALSE ); 5765 cKey.setAutoDelete( FALSE );
5792 QTextFormat** formats = new QTextFormat*[ cKey.count() + 1 ]; 5766 QTextFormat** formats = new QTextFormat*[ cKey.count() + 1 ];
5793 QTextFormat **f = formats; 5767 QTextFormat **f = formats;
5794 QDictIterator<QTextFormat> it( cKey ); 5768 QDictIterator<QTextFormat> it( cKey );
5795 while ( ( *f = it.current() ) ) { 5769 while ( ( *f = it.current() ) ) {
5796 ++it; 5770 ++it;
5797 ++f; 5771 ++f;
5798 } 5772 }
5799 cKey.clear(); 5773 cKey.clear();
5800 for ( f = formats; *f; f++ ) 5774 for ( f = formats; *f; f++ )
5801 cKey.insert( (*f)->key(), *f ); 5775 cKey.insert( (*f)->key(), *f );
5802 cKey.setAutoDelete( TRUE ); 5776 cKey.setAutoDelete( TRUE );
5803 delete [] formats; 5777 delete [] formats;
5804} 5778}
5805 5779
5806 5780
5807 5781
5808// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5782// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5809 5783
5810void QTextFormat::setBold( bool b ) 5784void QTextFormat::setBold( bool b )
5811{ 5785{
5812 if ( b == fn.bold() ) 5786 if ( b == fn.bold() )
5813 return; 5787 return;
5814 fn.setBold( b ); 5788 fn.setBold( b );
5815 update(); 5789 update();
5816} 5790}
5817 5791
5818void QTextFormat::setMisspelled( bool b ) 5792void QTextFormat::setMisspelled( bool b )
5819{ 5793{
5820 if ( b == (bool)missp ) 5794 if ( b == (bool)missp )
5821 return; 5795 return;
5822 missp = b; 5796 missp = b;
5823 update(); 5797 update();
5824} 5798}
5825 5799
5826void QTextFormat::setVAlign( VerticalAlignment a ) 5800void QTextFormat::setVAlign( VerticalAlignment a )
5827{ 5801{
5828 if ( a == ha ) 5802 if ( a == ha )
5829 return; 5803 return;
5830 ha = a; 5804 ha = a;
5831 update(); 5805 update();
5832} 5806}
5833 5807
5834void QTextFormat::setItalic( bool b ) 5808void QTextFormat::setItalic( bool b )
5835{ 5809{
5836 if ( b == fn.italic() ) 5810 if ( b == fn.italic() )
5837 return; 5811 return;
5838 fn.setItalic( b ); 5812 fn.setItalic( b );
5839 update(); 5813 update();
5840} 5814}
5841 5815
5842void QTextFormat::setUnderline( bool b ) 5816void QTextFormat::setUnderline( bool b )
5843{ 5817{
5844 if ( b == fn.underline() ) 5818 if ( b == fn.underline() )
5845 return; 5819 return;
5846 fn.setUnderline( b ); 5820 fn.setUnderline( b );
5847 update(); 5821 update();
5848} 5822}
5849 5823
5850void QTextFormat::setStrikeOut( bool b ) 5824void QTextFormat::setStrikeOut( bool b )
5851{ 5825{
5852 if ( b == fn.strikeOut() ) 5826 if ( b == fn.strikeOut() )
5853 return; 5827 return;
5854 fn.setStrikeOut( b ); 5828 fn.setStrikeOut( b );
5855 update(); 5829 update();
5856} 5830}
5857 5831
5858void QTextFormat::setFamily( const QString &f ) 5832void QTextFormat::setFamily( const QString &f )
5859{ 5833{
5860 if ( f == fn.family() ) 5834 if ( f == fn.family() )
5861 return; 5835 return;
5862 fn.setFamily( f ); 5836 fn.setFamily( f );
5863 update(); 5837 update();
5864} 5838}
5865 5839
5866void QTextFormat::setPointSize( int s ) 5840void QTextFormat::setPointSize( int s )
5867{ 5841{
5868 if ( s == fn.pointSize() ) 5842 if ( s == fn.pointSize() )
5869 return; 5843 return;
5870 fn.setPointSize( s ); 5844 fn.setPointSize( s );
5871 usePixelSizes = FALSE; 5845 usePixelSizes = FALSE;
5872 update(); 5846 update();
5873} 5847}
5874 5848
5875void QTextFormat::setFont( const QFont &f ) 5849void QTextFormat::setFont( const QFont &f )
5876{ 5850{
5877 if ( f == fn && !k.isEmpty() ) 5851 if ( f == fn && !k.isEmpty() )
5878 return; 5852 return;
5879 fn = f; 5853 fn = f;
5880 update(); 5854 update();
5881} 5855}
5882 5856
5883void QTextFormat::setColor( const QColor &c ) 5857void QTextFormat::setColor( const QColor &c )
5884{ 5858{
5885 if ( c == col ) 5859 if ( c == col )
5886 return; 5860 return;
5887 col = c; 5861 col = c;
5888 update(); 5862 update();
5889} 5863}
5890 5864
5891QString QTextFormat::makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f, 5865QString QTextFormat::makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f,
5892 const QString& oldAnchorHref, const QString& anchorHref ) const 5866 const QString& oldAnchorHref, const QString& anchorHref ) const
5893{ 5867{
5894 QString tag; 5868 QString tag;
5895 if ( f ) 5869 if ( f )
5896 tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref ); 5870 tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref );
5897 5871
5898 if ( !anchorHref.isEmpty() ) 5872 if ( !anchorHref.isEmpty() )
5899 tag += "<a href=\"" + anchorHref + "\">"; 5873 tag += "<a href=\"" + anchorHref + "\">";
5900 5874
5901 if ( font() != defaultFormat->font() 5875 if ( font() != defaultFormat->font()
5902 || vAlign() != defaultFormat->vAlign() 5876 || vAlign() != defaultFormat->vAlign()
5903 || color().rgb() != defaultFormat->color().rgb() ) { 5877 || color().rgb() != defaultFormat->color().rgb() ) {
5904 QString s; 5878 QString s;
5905 if ( font().family() != defaultFormat->font().family() ) 5879 if ( font().family() != defaultFormat->font().family() )
5906 s += QString(!!s?";":"") + "font-family:" + fn.family(); 5880 s += QString(!!s?";":"") + "font-family:" + fn.family();
5907 if ( font().italic() && font().italic() != defaultFormat->font().italic() ) 5881 if ( font().italic() && font().italic() != defaultFormat->font().italic() )
5908 s += QString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal"); 5882 s += QString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal");
5909 if ( font().pointSize() != defaultFormat->font().pointSize() ) 5883 if ( font().pointSize() != defaultFormat->font().pointSize() )
5910 s += QString(!!s?";":"") + "font-size:" + QString::number( fn.pointSize() ) + "pt"; 5884 s += QString(!!s?";":"") + "font-size:" + QString::number( fn.pointSize() ) + "pt";
5911 if ( font().weight() != defaultFormat->font().weight() ) 5885 if ( font().weight() != defaultFormat->font().weight() )
5912 s += QString(!!s?";":"") + "font-weight:" + QString::number( fn.weight() * 8 ); 5886 s += QString(!!s?";":"") + "font-weight:" + QString::number( fn.weight() * 8 );
5913 if ( font().underline() != defaultFormat->font().underline() ) 5887 if ( font().underline() != defaultFormat->font().underline() )
5914 s += QString(!!s?";":"") + "text-decoration:" + ( font().underline() ? "underline" : "none"); 5888 s += QString(!!s?";":"") + "text-decoration:" + ( font().underline() ? "underline" : "none");
5915 if ( vAlign() != defaultFormat->vAlign() ) { 5889 if ( vAlign() != defaultFormat->vAlign() ) {
5916 s += QString(!!s?";":"") + "vertical-align:"; 5890 s += QString(!!s?";":"") + "vertical-align:";
5917 if ( vAlign() == QTextFormat::AlignSuperScript ) 5891 if ( vAlign() == QTextFormat::AlignSuperScript )
5918 s += "super"; 5892 s += "super";
5919 else if ( vAlign() == QTextFormat::AlignSubScript ) 5893 else if ( vAlign() == QTextFormat::AlignSubScript )
5920 s += "sub"; 5894 s += "sub";
5921 else 5895 else
5922 s += "normal"; 5896 s += "normal";
5923 } 5897 }
5924 if ( color().rgb() != defaultFormat->color().rgb() ) 5898 if ( color().rgb() != defaultFormat->color().rgb() )
5925 s += QString(!!s?";":"") + "color:" + col.name(); 5899 s += QString(!!s?";":"") + "color:" + col.name();
5926 if ( !s.isEmpty() ) 5900 if ( !s.isEmpty() )
5927 tag += "<span style=\"" + s + "\">"; 5901 tag += "<span style=\"" + s + "\">";
5928 } 5902 }
5929 5903
5930 return tag; 5904 return tag;
5931} 5905}
5932 5906
5933QString QTextFormat::makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const 5907QString QTextFormat::makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const
5934{ 5908{
5935 QString tag; 5909 QString tag;
5936 if ( font().family() != defaultFormat->font().family() 5910 if ( font().family() != defaultFormat->font().family()
5937 || font().pointSize() != defaultFormat->font().pointSize() 5911 || font().pointSize() != defaultFormat->font().pointSize()
5938 || font().weight() != defaultFormat->font().weight() 5912 || font().weight() != defaultFormat->font().weight()
5939 || font().italic() != defaultFormat->font().italic() 5913 || font().italic() != defaultFormat->font().italic()
5940 || font().underline() != defaultFormat->font().underline() 5914 || font().underline() != defaultFormat->font().underline()
5941 || font().strikeOut() != defaultFormat->font().strikeOut() 5915 || font().strikeOut() != defaultFormat->font().strikeOut()
5942 || vAlign() != defaultFormat->vAlign() 5916 || vAlign() != defaultFormat->vAlign()
5943 || color().rgb() != defaultFormat->color().rgb() ) 5917 || color().rgb() != defaultFormat->color().rgb() )
5944 tag += "</span>"; 5918 tag += "</span>";
5945 if ( !anchorHref.isEmpty() ) 5919 if ( !anchorHref.isEmpty() )
5946 tag += "</a>"; 5920 tag += "</a>";
5947 return tag; 5921 return tag;
5948} 5922}
5949 5923
5950QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const 5924QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const
5951{ 5925{
5952 QTextFormat format(*this); 5926 QTextFormat format(*this);
5953 if (!style ) 5927 if (!style )
5954 return format; 5928 return format;
5955 5929
5956 if ( !style->isAnchor() && style->color().isValid() ) { 5930 if ( !style->isAnchor() && style->color().isValid() ) {
5957 // the style is not an anchor and defines a color. 5931 // the style is not an anchor and defines a color.
5958 // It might be used inside an anchor and it should 5932 // It might be used inside an anchor and it should
5959 // override the link color. 5933 // override the link color.
5960 format.linkColor = FALSE; 5934 format.linkColor = FALSE;
5961 } 5935 }
5962 switch ( style->verticalAlignment() ) { 5936 switch ( style->verticalAlignment() ) {
5963 case QStyleSheetItem::VAlignBaseline: 5937 case QStyleSheetItem::VAlignBaseline:
5964 format.setVAlign( QTextFormat::AlignNormal ); 5938 format.setVAlign( QTextFormat::AlignNormal );
5965 break; 5939 break;
5966 case QStyleSheetItem::VAlignSuper: 5940 case QStyleSheetItem::VAlignSuper:
5967 format.setVAlign( QTextFormat::AlignSuperScript ); 5941 format.setVAlign( QTextFormat::AlignSuperScript );
5968 break; 5942 break;
5969 case QStyleSheetItem::VAlignSub: 5943 case QStyleSheetItem::VAlignSub:
5970 format.setVAlign( QTextFormat::AlignSubScript ); 5944 format.setVAlign( QTextFormat::AlignSubScript );
5971 break; 5945 break;
5972 } 5946 }
5973 5947
5974 if ( style->fontWeight() != QStyleSheetItem::Undefined ) 5948 if ( style->fontWeight() != QStyleSheetItem::Undefined )
5975 format.fn.setWeight( style->fontWeight() ); 5949 format.fn.setWeight( style->fontWeight() );
5976 if ( style->fontSize() != QStyleSheetItem::Undefined ) { 5950 if ( style->fontSize() != QStyleSheetItem::Undefined ) {
5977 format.fn.setPointSize( style->fontSize() ); 5951 format.fn.setPointSize( style->fontSize() );
5978 } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) { 5952 } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) {
5979 format.logicalFontSize = style->logicalFontSize(); 5953 format.logicalFontSize = style->logicalFontSize();
5980 if ( format.usePixelSizes ) 5954 if ( format.usePixelSizes )
5981 format.fn.setPixelSize( format.stdSize ); 5955 format.fn.setPixelSize( format.stdSize );
5982 else 5956 else
5983 format.fn.setPointSize( format.stdSize ); 5957 format.fn.setPointSize( format.stdSize );
5984 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 5958 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
5985 } else if ( style->logicalFontSizeStep() ) { 5959 } else if ( style->logicalFontSizeStep() ) {
5986 format.logicalFontSize += style->logicalFontSizeStep(); 5960 format.logicalFontSize += style->logicalFontSizeStep();
5987 if ( format.usePixelSizes ) 5961 if ( format.usePixelSizes )
5988 format.fn.setPixelSize( format.stdSize ); 5962 format.fn.setPixelSize( format.stdSize );
5989 else 5963 else
5990 format.fn.setPointSize( format.stdSize ); 5964 format.fn.setPointSize( format.stdSize );
5991 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 5965 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
5992 } 5966 }
5993 if ( !style->fontFamily().isEmpty() ) 5967 if ( !style->fontFamily().isEmpty() )
5994 format.fn.setFamily( style->fontFamily() ); 5968 format.fn.setFamily( style->fontFamily() );
5995 if ( style->color().isValid() ) 5969 if ( style->color().isValid() )
5996 format.col = style->color(); 5970 format.col = style->color();
5997 if ( style->definesFontItalic() ) 5971 if ( style->definesFontItalic() )
5998 format.fn.setItalic( style->fontItalic() ); 5972 format.fn.setItalic( style->fontItalic() );
5999 if ( style->definesFontUnderline() ) 5973 if ( style->definesFontUnderline() )
6000 format.fn.setUnderline( style->fontUnderline() ); 5974 format.fn.setUnderline( style->fontUnderline() );
6001 if ( style->definesFontStrikeOut() ) 5975 if ( style->definesFontStrikeOut() )
6002 format.fn.setStrikeOut( style->fontStrikeOut() ); 5976 format.fn.setStrikeOut( style->fontStrikeOut() );
6003 5977
6004 5978
6005 if ( style->name() == "font") { 5979 if ( style->name() == "font") {
6006 if ( attr.contains("color") ) { 5980 if ( attr.contains("color") ) {
6007 QString s = attr["color"]; 5981 QString s = attr["color"];
6008 if ( !s.isEmpty() ) { 5982 if ( !s.isEmpty() ) {
6009 format.col.setNamedColor( s ); 5983 format.col.setNamedColor( s );
6010 format.linkColor = FALSE; 5984 format.linkColor = FALSE;
6011 } 5985 }
6012 } 5986 }
6013 if ( attr.contains("face") ) { 5987 if ( attr.contains("face") ) {
6014 QString a = attr["face"]; 5988 QString a = attr["face"];
6015 QString family = QTextDocument::section( a, ",", 0, 0 ); 5989 QString family = QTextDocument::section( a, ",", 0, 0 );
6016 if ( !!family ) 5990 if ( !!family )
6017 format.fn.setFamily( family ); 5991 format.fn.setFamily( family );
6018 } 5992 }
6019 if ( attr.contains("size") ) { 5993 if ( attr.contains("size") ) {
6020 QString a = attr["size"]; 5994 QString a = attr["size"];
6021 int n = a.toInt(); 5995 int n = a.toInt();
6022 if ( a[0] == '+' || a[0] == '-' ) 5996 if ( a[0] == '+' || a[0] == '-' )
6023 n += format.logicalFontSize; 5997 n += format.logicalFontSize;
6024 format.logicalFontSize = n; 5998 format.logicalFontSize = n;
6025 if ( format.usePixelSizes ) 5999 if ( format.usePixelSizes )
6026 format.fn.setPixelSize( format.stdSize ); 6000 format.fn.setPixelSize( format.stdSize );
6027 else 6001 else
6028 format.fn.setPointSize( format.stdSize ); 6002 format.fn.setPointSize( format.stdSize );
6029 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 6003 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
6030 } 6004 }
6031 } 6005 }
6032 if ( attr.contains("style" ) ) { 6006 if ( attr.contains("style" ) ) {
6033 QString a = attr["style"]; 6007 QString a = attr["style"];
6034 for ( int s = 0; s < a.contains(';')+1; s++ ) { 6008 for ( int s = 0; s < a.contains(';')+1; s++ ) {
6035 QString style = QTextDocument::section( a, ";", s, s ); 6009 QString style = QTextDocument::section( a, ";", s, s );
6036 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) { 6010 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) {
6037 format.logicalFontSize = 0; 6011 format.logicalFontSize = 0;
6038 format.setPointSize( int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toInt() ) ); 6012 format.setPointSize( int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toInt() ) );
6039 } if ( style.startsWith("font-style:" ) ) { 6013 } if ( style.startsWith("font-style:" ) ) {
6040 QString s = style.mid( 11 ).stripWhiteSpace(); 6014 QString s = style.mid( 11 ).stripWhiteSpace();
6041 if ( s == "normal" ) 6015 if ( s == "normal" )
6042 format.fn.setItalic( FALSE ); 6016 format.fn.setItalic( FALSE );
6043 else if ( s == "italic" || s == "oblique" ) 6017 else if ( s == "italic" || s == "oblique" )
6044 format.fn.setItalic( TRUE ); 6018 format.fn.setItalic( TRUE );
6045 } else if ( style.startsWith("font-weight:" ) ) { 6019 } else if ( style.startsWith("font-weight:" ) ) {
6046 QString s = style.mid( 12 ); 6020 QString s = style.mid( 12 );
6047 bool ok = TRUE; 6021 bool ok = TRUE;
6048 int n = s.toInt( &ok ); 6022 int n = s.toInt( &ok );
6049 if ( ok ) 6023 if ( ok )
6050 format.fn.setWeight( n/8 ); 6024 format.fn.setWeight( n/8 );
6051 } else if ( style.startsWith("font-family:" ) ) { 6025 } else if ( style.startsWith("font-family:" ) ) {
6052 format.fn.setFamily( QTextDocument::section(style.mid(12),",",0,0).stripWhiteSpace() ); 6026 format.fn.setFamily( QTextDocument::section(style.mid(12),",",0,0).stripWhiteSpace() );
6053 } else if ( style.startsWith("text-decoration:" ) ) { 6027 } else if ( style.startsWith("text-decoration:" ) ) {
6054 QString s = style.mid( 16 ).stripWhiteSpace(); 6028 QString s = style.mid( 16 ).stripWhiteSpace();
6055 format.fn.setUnderline( s == "underline" ); 6029 format.fn.setUnderline( s == "underline" );
6056 } else if ( style.startsWith("vertical-align:" ) ) { 6030 } else if ( style.startsWith("vertical-align:" ) ) {
6057 QString s = style.mid( 15 ).stripWhiteSpace(); 6031 QString s = style.mid( 15 ).stripWhiteSpace();
6058 if ( s == "sub" ) 6032 if ( s == "sub" )
6059 format.setVAlign( QTextFormat::AlignSubScript ); 6033 format.setVAlign( QTextFormat::AlignSubScript );
6060 else if ( s == "super" ) 6034 else if ( s == "super" )
6061 format.setVAlign( QTextFormat::AlignSuperScript ); 6035 format.setVAlign( QTextFormat::AlignSuperScript );
6062 else 6036 else
6063 format.setVAlign( QTextFormat::AlignNormal ); 6037 format.setVAlign( QTextFormat::AlignNormal );
6064 } else if ( style.startsWith("color:" ) ) { 6038 } else if ( style.startsWith("color:" ) ) {
6065 format.col.setNamedColor( style.mid(6) ); 6039 format.col.setNamedColor( style.mid(6) );
6066 format.linkColor = FALSE; 6040 format.linkColor = FALSE;
6067 } 6041 }
6068 } 6042 }
6069 } 6043 }
6070 6044
6071 format.update(); 6045 format.update();
6072 return format; 6046 return format;
6073} 6047}
6074 6048
6075struct QPixmapInt 6049struct QPixmapInt
6076{ 6050{
6077 QPixmapInt() : ref( 0 ) {} 6051 QPixmapInt() : ref( 0 ) {}
6078 QPixmap pm; 6052 QPixmap pm;
6079 int ref; 6053 int ref;
6080}; 6054};
6081 6055
6082static QMap<QString, QPixmapInt> *pixmap_map = 0; 6056static QMap<QString, QPixmapInt> *pixmap_map = 0;
6083 6057
6084QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, 6058QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context,
6085 QMimeSourceFactory &factory ) 6059 QMimeSourceFactory &factory )
6086 : QTextCustomItem( p ), reg( 0 ) 6060 : QTextCustomItem( p ), reg( 0 )
6087{ 6061{
6088 width = height = 0; 6062 width = height = 0;
6089 if ( attr.contains("width") ) 6063 if ( attr.contains("width") )
6090 width = attr["width"].toInt(); 6064 width = attr["width"].toInt();
6091 if ( attr.contains("height") ) 6065 if ( attr.contains("height") )
6092 height = attr["height"].toInt(); 6066 height = attr["height"].toInt();
6093 6067
6094 QString imageName = attr["src"]; 6068 QString imageName = attr["src"];
6095 6069
6096 if (!imageName) 6070 if (!imageName)
6097 imageName = attr["source"]; 6071 imageName = attr["source"];
6098 6072
6099 if ( !imageName.isEmpty() ) { 6073 if ( !imageName.isEmpty() ) {
6100 imgId = QString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory ); 6074 imgId = QString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory );
6101 if ( !pixmap_map ) 6075 if ( !pixmap_map )
6102 pixmap_map = new QMap<QString, QPixmapInt>; 6076 pixmap_map = new QMap<QString, QPixmapInt>;
6103 if ( pixmap_map->contains( imgId ) ) { 6077 if ( pixmap_map->contains( imgId ) ) {
6104 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6078 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6105 pm = pmi.pm; 6079 pm = pmi.pm;
6106 pmi.ref++; 6080 pmi.ref++;
6107 width = pm.width(); 6081 width = pm.width();
6108 height = pm.height(); 6082 height = pm.height();
6109 } else { 6083 } else {
6110 QImage img; 6084 QImage img;
6111 const QMimeSource* m = 6085 const QMimeSource* m =
6112 factory.data( imageName, context ); 6086 factory.data( imageName, context );
6113 if ( !m ) { 6087 if ( !m ) {
6114 owarn << "QTextImage: no mimesource for " << imageName.latin1() << "" << oendl; 6088 owarn << "QTextImage: no mimesource for " << imageName.latin1() << "" << oendl;
6115 } 6089 }
6116 else { 6090 else {
6117 if ( !QImageDrag::decode( m, img ) ) { 6091 if ( !QImageDrag::decode( m, img ) ) {
6118 owarn << "QTextImage: cannot decode " << imageName.latin1() << "" << oendl; 6092 owarn << "QTextImage: cannot decode " << imageName.latin1() << "" << oendl;
6119 } 6093 }
6120 } 6094 }
6121 6095
6122 if ( !img.isNull() ) { 6096 if ( !img.isNull() ) {
6123 if ( width == 0 ) { 6097 if ( width == 0 ) {
6124 width = img.width(); 6098 width = img.width();
6125 if ( height != 0 ) { 6099 if ( height != 0 ) {
6126 width = img.width() * height / img.height(); 6100 width = img.width() * height / img.height();
6127 } 6101 }
6128 } 6102 }
6129 if ( height == 0 ) { 6103 if ( height == 0 ) {
6130 height = img.height(); 6104 height = img.height();
6131 if ( width != img.width() ) { 6105 if ( width != img.width() ) {
6132 height = img.height() * width / img.width(); 6106 height = img.height() * width / img.width();
6133 } 6107 }
6134 } 6108 }
6135 if ( img.width() != width || img.height() != height ){ 6109 if ( img.width() != width || img.height() != height ){
6136#ifndef QT_NO_IMAGE_SMOOTHSCALE 6110#ifndef QT_NO_IMAGE_SMOOTHSCALE
6137 img = img.smoothScale(width, height); 6111 img = img.smoothScale(width, height);
6138#endif 6112#endif
6139 width = img.width(); 6113 width = img.width();
6140 height = img.height(); 6114 height = img.height();
6141 } 6115 }
6142 pm.convertFromImage( img ); 6116 pm.convertFromImage( img );
6143 } 6117 }
6144 if ( !pm.isNull() ) { 6118 if ( !pm.isNull() ) {
6145 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6119 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6146 pmi.pm = pm; 6120 pmi.pm = pm;
6147 pmi.ref++; 6121 pmi.ref++;
6148 } 6122 }
6149 } 6123 }
6150 if ( pm.mask() ) { 6124 if ( pm.mask() ) {
6151 QRegion mask( *pm.mask() ); 6125 QRegion mask( *pm.mask() );
6152 QRegion all( 0, 0, pm.width(), pm.height() ); 6126 QRegion all( 0, 0, pm.width(), pm.height() );
6153 reg = new QRegion( all.subtract( mask ) ); 6127 reg = new QRegion( all.subtract( mask ) );
6154 } 6128 }
6155 } 6129 }
6156 6130
6157 if ( pm.isNull() && (width*height)==0 ) 6131 if ( pm.isNull() && (width*height)==0 )
6158 width = height = 50; 6132 width = height = 50;
6159 6133
6160 place = PlaceInline; 6134 place = PlaceInline;
6161 if ( attr["align"] == "left" ) 6135 if ( attr["align"] == "left" )
6162 place = PlaceLeft; 6136 place = PlaceLeft;
6163 else if ( attr["align"] == "right" ) 6137 else if ( attr["align"] == "right" )
6164 place = PlaceRight; 6138 place = PlaceRight;
6165 6139
6166 tmpwidth = width; 6140 tmpwidth = width;
6167 tmpheight = height; 6141 tmpheight = height;
6168 6142
6169 attributes = attr; 6143 attributes = attr;
6170} 6144}
6171 6145
6172QTextImage::~QTextImage() 6146QTextImage::~QTextImage()
6173{ 6147{
6174 delete reg; 6148 delete reg;
6175 if ( pixmap_map && pixmap_map->contains( imgId ) ) { 6149 if ( pixmap_map && pixmap_map->contains( imgId ) ) {
6176 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6150 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6177 pmi.ref--; 6151 pmi.ref--;
6178 if ( !pmi.ref ) { 6152 if ( !pmi.ref ) {
6179 pixmap_map->remove( imgId ); 6153 pixmap_map->remove( imgId );
6180 if ( pixmap_map->isEmpty() ) { 6154 if ( pixmap_map->isEmpty() ) {
6181 delete pixmap_map; 6155 delete pixmap_map;
6182 pixmap_map = 0; 6156 pixmap_map = 0;
6183 } 6157 }
6184 } 6158 }
6185 } 6159 }
6186} 6160}
6187 6161
6188QString QTextImage::richText() const 6162QString QTextImage::richText() const
6189{ 6163{
6190 QString s; 6164 QString s;
6191 s += "<img "; 6165 s += "<img ";
6192 QMap<QString, QString>::ConstIterator it = attributes.begin(); 6166 QMap<QString, QString>::ConstIterator it = attributes.begin();
6193 for ( ; it != attributes.end(); ++it ) 6167 for ( ; it != attributes.end(); ++it )
6194 s += it.key() + "=" + *it + " "; 6168 s += it.key() + "=" + *it + " ";
6195 s += ">"; 6169 s += ">";
6196 return s; 6170 return s;
6197} 6171}
6198 6172
6199void QTextImage::adjustToPainter( QPainter* p ) 6173void QTextImage::adjustToPainter( QPainter* p )
6200{ 6174{
6201 width = scale( tmpwidth, p ); 6175 width = scale( tmpwidth, p );
6202 height = scale( tmpheight, p ); 6176 height = scale( tmpheight, p );
6203} 6177}
6204 6178
6205#if !defined(Q_WS_X11) 6179#if !defined(Q_WS_X11)
6206#include <qbitmap.h> 6180#include <qbitmap.h>
6207#include "qcleanuphandler.h" 6181#include "qcleanuphandler.h"
6208static QPixmap *qrt_selection = 0; 6182static QPixmap *qrt_selection = 0;
6209static QSingleCleanupHandler<QPixmap> qrt_cleanup_pixmap; 6183static QSingleCleanupHandler<QPixmap> qrt_cleanup_pixmap;
6210static void qrt_createSelectionPixmap( const QColorGroup &cg ) 6184static void qrt_createSelectionPixmap( const QColorGroup &cg )
6211{ 6185{
6212 qrt_selection = new QPixmap( 2, 2 ); 6186 qrt_selection = new QPixmap( 2, 2 );
6213 qrt_cleanup_pixmap.set( &qrt_selection ); 6187 qrt_cleanup_pixmap.set( &qrt_selection );
6214 qrt_selection->fill( Qt::color0 ); 6188 qrt_selection->fill( Qt::color0 );
6215 QBitmap m( 2, 2 ); 6189 QBitmap m( 2, 2 );
6216 m.fill( Qt::color1 ); 6190 m.fill( Qt::color1 );
6217 QPainter p( &m ); 6191 QPainter p( &m );
6218 p.setPen( Qt::color0 ); 6192 p.setPen( Qt::color0 );
6219 for ( int j = 0; j < 2; ++j ) { 6193 for ( int j = 0; j < 2; ++j ) {
6220 p.drawPoint( j % 2, j ); 6194 p.drawPoint( j % 2, j );
6221 } 6195 }
6222 p.end(); 6196 p.end();
6223 qrt_selection->setMask( m ); 6197 qrt_selection->setMask( m );
6224 qrt_selection->fill( cg.highlight() ); 6198 qrt_selection->fill( cg.highlight() );
6225} 6199}
6226#endif 6200#endif
6227 6201
6228void QTextImage::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) 6202void QTextImage::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected )
6229{ 6203{
6230 if ( placement() != PlaceInline ) { 6204 if ( placement() != PlaceInline ) {
6231 x = xpos; 6205 x = xpos;
6232 y = ypos; 6206 y = ypos;
6233 } 6207 }
6234 6208
6235 if ( pm.isNull() ) { 6209 if ( pm.isNull() ) {
6236 p->fillRect( x , y, width, height, cg.dark() ); 6210 p->fillRect( x , y, width, height, cg.dark() );
6237 return; 6211 return;
6238 } 6212 }
6239 6213
6240 if ( is_printer( p ) ) { 6214 if ( is_printer( p ) ) {
6241 p->drawPixmap( x, y, pm ); 6215 p->drawPixmap( x, y, pm );
6242 return; 6216 return;
6243 } 6217 }
6244 6218
6245 if ( placement() != PlaceInline && !QRect( xpos, ypos, width, height ).intersects( QRect( cx, cy, cw, ch ) ) ) 6219 if ( placement() != PlaceInline && !QRect( xpos, ypos, width, height ).intersects( QRect( cx, cy, cw, ch ) ) )
6246 return; 6220 return;
6247 6221
6248 if ( placement() == PlaceInline ) 6222 if ( placement() == PlaceInline )
6249 p->drawPixmap( x , y, pm ); 6223 p->drawPixmap( x , y, pm );
6250 else 6224 else
6251 p->drawPixmap( cx , cy, pm, cx - x, cy - y, cw, ch ); 6225 p->drawPixmap( cx , cy, pm, cx - x, cy - y, cw, ch );
6252 6226
6253 if ( selected && placement() == PlaceInline && is_printer( p ) ) { 6227 if ( selected && placement() == PlaceInline && is_printer( p ) ) {
6254#if defined(Q_WS_X11) 6228#if defined(Q_WS_X11)
6255 p->fillRect( QRect( QPoint( x, y ), pm.size() ), QBrush( cg.highlight(), QBrush::Dense4Pattern) ); 6229 p->fillRect( QRect( QPoint( x, y ), pm.size() ), QBrush( cg.highlight(), QBrush::Dense4Pattern) );
6256#else // in WIN32 Dense4Pattern doesn't work correctly (transparency problem), so work around it 6230#else // in WIN32 Dense4Pattern doesn't work correctly (transparency problem), so work around it
6257 if ( !qrt_selection ) 6231 if ( !qrt_selection )
6258 qrt_createSelectionPixmap( cg ); 6232 qrt_createSelectionPixmap( cg );
6259 p->drawTiledPixmap( x, y, pm.width(), pm.height(), *qrt_selection ); 6233 p->drawTiledPixmap( x, y, pm.width(), pm.height(), *qrt_selection );
6260#endif 6234#endif
6261 } 6235 }
6262} 6236}
6263 6237
6264void QTextHorizontalLine::adjustToPainter( QPainter* p ) 6238void QTextHorizontalLine::adjustToPainter( QPainter* p )
6265{ 6239{
6266 height = scale( tmpheight, p ); 6240 height = scale( tmpheight, p );
6267} 6241}
6268 6242
6269 6243
6270QTextHorizontalLine::QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr, 6244QTextHorizontalLine::QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr,
6271 const QString &, 6245 const QString &,
6272 QMimeSourceFactory & ) 6246 QMimeSourceFactory & )
6273 : QTextCustomItem( p ) 6247 : QTextCustomItem( p )
6274{ 6248{
6275 height = tmpheight = 8; 6249 height = tmpheight = 8;
6276 if ( attr.find( "color" ) != attr.end() ) 6250 if ( attr.find( "color" ) != attr.end() )
6277 color = QColor( *attr.find( "color" ) ); 6251 color = QColor( *attr.find( "color" ) );
6278} 6252}
6279 6253
6280QTextHorizontalLine::~QTextHorizontalLine() 6254QTextHorizontalLine::~QTextHorizontalLine()
6281{ 6255{
6282} 6256}
6283 6257
6284QString QTextHorizontalLine::richText() const 6258QString QTextHorizontalLine::richText() const
6285{ 6259{
6286 return "<hr>"; 6260 return "<hr>";
6287} 6261}
6288 6262
6289void QTextHorizontalLine::draw( QPainter* p, int x, int y, int , int , int , int , const QColorGroup& cg, bool selected ) 6263void QTextHorizontalLine::draw( QPainter* p, int x, int y, int , int , int , int , const QColorGroup& cg, bool selected )
6290{ 6264{
6291 QRect r( x, y, width, height); 6265 QRect r( x, y, width, height);
6292 if ( is_printer( p ) ) { 6266 if ( is_printer( p ) ) {
6293 QPen oldPen = p->pen(); 6267 QPen oldPen = p->pen();
6294 if ( !color.isValid() ) 6268 if ( !color.isValid() )
6295 p->setPen( QPen( cg.text(), height/8 ) ); 6269 p->setPen( QPen( cg.text(), height/8 ) );
6296 else 6270 else
6297 p->setPen( QPen( color, height/8 ) ); 6271 p->setPen( QPen( color, height/8 ) );
6298 p->drawLine( r.left()-1, y + height / 2, r.right() + 1, y + height / 2 ); 6272 p->drawLine( r.left()-1, y + height / 2, r.right() + 1, y + height / 2 );
6299 p->setPen( oldPen ); 6273 p->setPen( oldPen );
6300 } else { 6274 } else {
6301 QColorGroup g( cg ); 6275 QColorGroup g( cg );
6302 if ( color.isValid() ) 6276 if ( color.isValid() )
6303 g.setColor( QColorGroup::Dark, color ); 6277 g.setColor( QColorGroup::Dark, color );
6304 if ( selected ) 6278 if ( selected )
6305 p->fillRect( r.left(), y, r.right(), y + height, g.highlight() ); 6279 p->fillRect( r.left(), y, r.right(), y + height, g.highlight() );
6306 qDrawShadeLine( p, r.left() - 1, y + height / 2, r.right() + 1, y + height / 2, g, TRUE, height / 8 ); 6280 qDrawShadeLine( p, r.left() - 1, y + height / 2, r.right() + 1, y + height / 2, g, TRUE, height / 8 );
6307 } 6281 }
6308} 6282}
6309 6283
6310 6284
6311/*****************************************************************/ 6285/*****************************************************************/
6312// Small set of utility functions to make the parser a bit simpler 6286// Small set of utility functions to make the parser a bit simpler
6313// 6287//
6314 6288
6315bool QTextDocument::hasPrefix(const QChar* doc, int length, int pos, QChar c) 6289bool QTextDocument::hasPrefix(const QChar* doc, int length, int pos, QChar c)
6316{ 6290{
6317 if ( pos >= length ) 6291 if ( pos >= length )
6318 return FALSE; 6292 return FALSE;
6319 return doc[ pos ].lower() == c.lower(); 6293 return doc[ pos ].lower() == c.lower();
6320} 6294}
6321 6295
6322bool QTextDocument::hasPrefix( const QChar* doc, int length, int pos, const QString& s ) 6296bool QTextDocument::hasPrefix( const QChar* doc, int length, int pos, const QString& s )
6323{ 6297{
6324 if ( pos + (int) s.length() >= length ) 6298 if ( pos + (int) s.length() >= length )
6325 return FALSE; 6299 return FALSE;
6326 for ( int i = 0; i < (int)s.length(); i++ ) { 6300 for ( int i = 0; i < (int)s.length(); i++ ) {
6327 if ( doc[ pos + i ].lower() != s[ i ].lower() ) 6301 if ( doc[ pos + i ].lower() != s[ i ].lower() )
6328 return FALSE; 6302 return FALSE;
6329 } 6303 }
6330 return TRUE; 6304 return TRUE;
6331} 6305}
6332 6306
6333static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col ) 6307static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col )
6334{ 6308{
6335 for ( QTextTableCell* c = cells.first(); c; c = cells.next() ) { 6309 for ( QTextTableCell* c = cells.first(); c; c = cells.next() ) {
6336 if ( row >= c->row() && row < c->row() + c->rowspan() 6310 if ( row >= c->row() && row < c->row() + c->rowspan()
6337 && col >= c->column() && col < c->column() + c->colspan() ) 6311 && col >= c->column() && col < c->column() + c->colspan() )
6338 return TRUE; 6312 return TRUE;
6339 } 6313 }
6340 return FALSE; 6314 return FALSE;
6341} 6315}
6342 6316
6343QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, 6317QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt,
6344 const QChar* doc, int length, int& pos, QTextParagraph *curpar ) 6318 const QChar* doc, int length, int& pos, QTextParagraph *curpar )
6345{ 6319{
6346 6320
6347 QTextTable* table = new QTextTable( this, attr ); 6321 QTextTable* table = new QTextTable( this, attr );
6348 int row = -1; 6322 int row = -1;
6349 int col = -1; 6323 int col = -1;
6350 6324
6351 QString rowbgcolor; 6325 QString rowbgcolor;
6352 QString rowalign; 6326 QString rowalign;
6353 QString tablebgcolor = attr["bgcolor"]; 6327 QString tablebgcolor = attr["bgcolor"];
6354 6328
6355 QPtrList<QTextTableCell> multicells; 6329 QPtrList<QTextTableCell> multicells;
6356 6330
6357 QString tagname; 6331 QString tagname;
6358 (void) eatSpace(doc, length, pos); 6332 (void) eatSpace(doc, length, pos);
6359 while ( pos < length) { 6333 while ( pos < length) {
6360 if (hasPrefix(doc, length, pos, QChar('<')) ){ 6334 if (hasPrefix(doc, length, pos, QChar('<')) ){
6361 if (hasPrefix(doc, length, pos+1, QChar('/'))) { 6335 if (hasPrefix(doc, length, pos+1, QChar('/'))) {
6362 tagname = parseCloseTag( doc, length, pos ); 6336 tagname = parseCloseTag( doc, length, pos );
6363 if ( tagname == "table" ) { 6337 if ( tagname == "table" ) {
6364 return table; 6338 return table;
6365 } 6339 }
6366 } else { 6340 } else {
6367 QMap<QString, QString> attr2; 6341 QMap<QString, QString> attr2;
6368 bool emptyTag = FALSE; 6342 bool emptyTag = FALSE;
6369 tagname = parseOpenTag( doc, length, pos, attr2, emptyTag ); 6343 tagname = parseOpenTag( doc, length, pos, attr2, emptyTag );
6370 if ( tagname == "tr" ) { 6344 if ( tagname == "tr" ) {
6371 rowbgcolor = attr2["bgcolor"]; 6345 rowbgcolor = attr2["bgcolor"];
6372 rowalign = attr2["align"]; 6346 rowalign = attr2["align"];
6373 row++; 6347 row++;
6374 col = -1; 6348 col = -1;
6375 } 6349 }
6376 else if ( tagname == "td" || tagname == "th" ) { 6350 else if ( tagname == "td" || tagname == "th" ) {
6377 col++; 6351 col++;
6378 while ( qt_is_cell_in_use( multicells, row, col ) ) { 6352 while ( qt_is_cell_in_use( multicells, row, col ) ) {
6379 col++; 6353 col++;
6380 } 6354 }
6381 6355
6382 if ( row >= 0 && col >= 0 ) { 6356 if ( row >= 0 && col >= 0 ) {
6383 const QStyleSheetItem* s = sheet_->item(tagname); 6357 const QStyleSheetItem* s = sheet_->item(tagname);
6384 if ( !attr2.contains("bgcolor") ) { 6358 if ( !attr2.contains("bgcolor") ) {
6385 if (!rowbgcolor.isEmpty() ) 6359 if (!rowbgcolor.isEmpty() )
6386 attr2["bgcolor"] = rowbgcolor; 6360 attr2["bgcolor"] = rowbgcolor;
6387 else if (!tablebgcolor.isEmpty() ) 6361 else if (!tablebgcolor.isEmpty() )
6388 attr2["bgcolor"] = tablebgcolor; 6362 attr2["bgcolor"] = tablebgcolor;
6389 } 6363 }
6390 if ( !attr2.contains("align") ) { 6364 if ( !attr2.contains("align") ) {
6391 if (!rowalign.isEmpty() ) 6365 if (!rowalign.isEmpty() )
6392 attr2["align"] = rowalign; 6366 attr2["align"] = rowalign;
6393 } 6367 }
6394 6368
6395 // extract the cell contents 6369 // extract the cell contents
6396 int end = pos; 6370 int end = pos;
6397 while ( end < length 6371 while ( end < length
6398 && !hasPrefix( doc, length, end, "</td") 6372 && !hasPrefix( doc, length, end, "</td")
6399 && !hasPrefix( doc, length, end, "<td") 6373 && !hasPrefix( doc, length, end, "<td")
6400 && !hasPrefix( doc, length, end, "</th") 6374 && !hasPrefix( doc, length, end, "</th")
6401 && !hasPrefix( doc, length, end, "<th") 6375 && !hasPrefix( doc, length, end, "<th")
6402 && !hasPrefix( doc, length, end, "<td") 6376 && !hasPrefix( doc, length, end, "<td")
6403 && !hasPrefix( doc, length, end, "</tr") 6377 && !hasPrefix( doc, length, end, "</tr")
6404 && !hasPrefix( doc, length, end, "<tr") 6378 && !hasPrefix( doc, length, end, "<tr")
6405 && !hasPrefix( doc, length, end, "</table") ) { 6379 && !hasPrefix( doc, length, end, "</table") ) {
6406 if ( hasPrefix( doc, length, end, "<table" ) ) { // nested table 6380 if ( hasPrefix( doc, length, end, "<table" ) ) { // nested table
6407 int nested = 1; 6381 int nested = 1;
6408 ++end; 6382 ++end;
6409 while ( end < length && nested != 0 ) { 6383 while ( end < length && nested != 0 ) {
6410 if ( hasPrefix( doc, length, end, "</table" ) ) 6384 if ( hasPrefix( doc, length, end, "</table" ) )
6411 nested--; 6385 nested--;
6412 if ( hasPrefix( doc, length, end, "<table" ) ) 6386 if ( hasPrefix( doc, length, end, "<table" ) )
6413 nested++; 6387 nested++;
6414 end++; 6388 end++;
6415 } 6389 }
6416 } 6390 }
6417 end++; 6391 end++;
6418 } 6392 }
6419 QTextTableCell* cell = new QTextTableCell( table, row, col, 6393 QTextTableCell* cell = new QTextTableCell( table, row, col,
6420 attr2, s, fmt.makeTextFormat( s, attr2, scaleFontsFactor ), 6394 attr2, s, fmt.makeTextFormat( s, attr2, scaleFontsFactor ),
6421 contxt, *factory_, sheet_, 6395 contxt, *factory_, sheet_,
6422 QString( doc, length).mid( pos, end - pos ) ); 6396 QString( doc, length).mid( pos, end - pos ) );
6423 cell->richText()->parentPar = curpar; 6397 cell->richText()->parentPar = curpar;
6424 if ( cell->colspan() > 1 || cell->rowspan() > 1 ) 6398 if ( cell->colspan() > 1 || cell->rowspan() > 1 )
6425 multicells.append( cell ); 6399 multicells.append( cell );
6426 col += cell->colspan()-1; 6400 col += cell->colspan()-1;
6427 pos = end; 6401 pos = end;
6428 } 6402 }
6429 } 6403 }
6430 } 6404 }
6431 6405
6432 } else { 6406 } else {
6433 ++pos; 6407 ++pos;
6434 } 6408 }
6435 } 6409 }
6436 return table; 6410 return table;
6437} 6411}
6438 6412
6439bool QTextDocument::eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp ) 6413bool QTextDocument::eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp )
6440{ 6414{
6441 int old_pos = pos; 6415 int old_pos = pos;
6442 while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != QChar::nbsp ) ) ) 6416 while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != QChar::nbsp ) ) )
6443 pos++; 6417 pos++;
6444 return old_pos < pos; 6418 return old_pos < pos;
6445} 6419}
6446 6420
6447bool QTextDocument::eat(const QChar* doc, int length, int& pos, QChar c) 6421bool QTextDocument::eat(const QChar* doc, int length, int& pos, QChar c)
6448{ 6422{
6449 bool ok = pos < length && doc[pos] == c; 6423 bool ok = pos < length && doc[pos] == c;
6450 if ( ok ) 6424 if ( ok )
6451 pos++; 6425 pos++;
6452 return ok; 6426 return ok;
6453} 6427}
6454/*****************************************************************/ 6428/*****************************************************************/
6455 6429
6456struct Entity { 6430struct Entity {
6457 const char * name; 6431 const char * name;
6458 Q_UINT16 code; 6432 Q_UINT16 code;
6459}; 6433};
6460 6434
6461static const Entity entitylist [] = { 6435static const Entity entitylist [] = {
6462 { "AElig", 0x00c6 }, 6436 { "AElig", 0x00c6 },
6463 { "Aacute", 0x00c1 }, 6437 { "Aacute", 0x00c1 },
6464 { "Acirc", 0x00c2 }, 6438 { "Acirc", 0x00c2 },
6465 { "Agrave", 0x00c0 }, 6439 { "Agrave", 0x00c0 },
6466 { "Alpha", 0x0391 }, 6440 { "Alpha", 0x0391 },
6467 { "AMP", 38 }, 6441 { "AMP", 38 },
6468 { "Aring", 0x00c5 }, 6442 { "Aring", 0x00c5 },
6469 { "Atilde", 0x00c3 }, 6443 { "Atilde", 0x00c3 },
6470 { "Auml", 0x00c4 }, 6444 { "Auml", 0x00c4 },
6471 { "Beta", 0x0392 }, 6445 { "Beta", 0x0392 },
6472 { "Ccedil", 0x00c7 }, 6446 { "Ccedil", 0x00c7 },
6473 { "Chi", 0x03a7 }, 6447 { "Chi", 0x03a7 },
6474 { "Dagger", 0x2021 }, 6448 { "Dagger", 0x2021 },
6475 { "Delta", 0x0394 }, 6449 { "Delta", 0x0394 },
6476 { "ETH", 0x00d0 }, 6450 { "ETH", 0x00d0 },
6477 { "Eacute", 0x00c9 }, 6451 { "Eacute", 0x00c9 },
6478 { "Ecirc", 0x00ca }, 6452 { "Ecirc", 0x00ca },
6479 { "Egrave", 0x00c8 }, 6453 { "Egrave", 0x00c8 },
6480 { "Epsilon", 0x0395 }, 6454 { "Epsilon", 0x0395 },
6481 { "Eta", 0x0397 }, 6455 { "Eta", 0x0397 },
6482 { "Euml", 0x00cb }, 6456 { "Euml", 0x00cb },
6483 { "Gamma", 0x0393 }, 6457 { "Gamma", 0x0393 },
6484 { "GT", 62 }, 6458 { "GT", 62 },
6485 { "Iacute", 0x00cd }, 6459 { "Iacute", 0x00cd },
6486 { "Icirc", 0x00ce }, 6460 { "Icirc", 0x00ce },
6487 { "Igrave", 0x00cc }, 6461 { "Igrave", 0x00cc },
6488 { "Iota", 0x0399 }, 6462 { "Iota", 0x0399 },
6489 { "Iuml", 0x00cf }, 6463 { "Iuml", 0x00cf },
6490 { "Kappa", 0x039a }, 6464 { "Kappa", 0x039a },
6491 { "Lambda", 0x039b }, 6465 { "Lambda", 0x039b },
6492 { "LT", 60 }, 6466 { "LT", 60 },
6493 { "Mu", 0x039c }, 6467 { "Mu", 0x039c },
6494 { "Ntilde", 0x00d1 }, 6468 { "Ntilde", 0x00d1 },
6495 { "Nu", 0x039d }, 6469 { "Nu", 0x039d },
6496 { "OElig", 0x0152 }, 6470 { "OElig", 0x0152 },
6497 { "Oacute", 0x00d3 }, 6471 { "Oacute", 0x00d3 },
6498 { "Ocirc", 0x00d4 }, 6472 { "Ocirc", 0x00d4 },
6499 { "Ograve", 0x00d2 }, 6473 { "Ograve", 0x00d2 },
6500 { "Omega", 0x03a9 }, 6474 { "Omega", 0x03a9 },
6501 { "Omicron", 0x039f }, 6475 { "Omicron", 0x039f },
6502 { "Oslash", 0x00d8 }, 6476 { "Oslash", 0x00d8 },
6503 { "Otilde", 0x00d5 }, 6477 { "Otilde", 0x00d5 },
6504 { "Ouml", 0x00d6 }, 6478 { "Ouml", 0x00d6 },
6505 { "Phi", 0x03a6 }, 6479 { "Phi", 0x03a6 },
6506 { "Pi", 0x03a0 }, 6480 { "Pi", 0x03a0 },
6507 { "Prime", 0x2033 }, 6481 { "Prime", 0x2033 },
6508 { "Psi", 0x03a8 }, 6482 { "Psi", 0x03a8 },
6509 { "QUOT", 34 }, 6483 { "QUOT", 34 },
6510 { "Rho", 0x03a1 }, 6484 { "Rho", 0x03a1 },
6511 { "Scaron", 0x0160 }, 6485 { "Scaron", 0x0160 },
6512 { "Sigma", 0x03a3 }, 6486 { "Sigma", 0x03a3 },
6513 { "THORN", 0x00de }, 6487 { "THORN", 0x00de },
6514 { "Tau", 0x03a4 }, 6488 { "Tau", 0x03a4 },
6515 { "Theta", 0x0398 }, 6489 { "Theta", 0x0398 },
6516 { "Uacute", 0x00da }, 6490 { "Uacute", 0x00da },
6517 { "Ucirc", 0x00db }, 6491 { "Ucirc", 0x00db },
6518 { "Ugrave", 0x00d9 }, 6492 { "Ugrave", 0x00d9 },
6519 { "Upsilon", 0x03a5 }, 6493 { "Upsilon", 0x03a5 },
6520 { "Uuml", 0x00dc }, 6494 { "Uuml", 0x00dc },
6521 { "Xi", 0x039e }, 6495 { "Xi", 0x039e },
6522 { "Yacute", 0x00dd }, 6496 { "Yacute", 0x00dd },
6523 { "Yuml", 0x0178 }, 6497 { "Yuml", 0x0178 },
6524 { "Zeta", 0x0396 }, 6498 { "Zeta", 0x0396 },
6525 { "aacute", 0x00e1 }, 6499 { "aacute", 0x00e1 },
6526 { "acirc", 0x00e2 }, 6500 { "acirc", 0x00e2 },
6527 { "acute", 0x00b4 }, 6501 { "acute", 0x00b4 },
6528 { "aelig", 0x00e6 }, 6502 { "aelig", 0x00e6 },
6529 { "agrave", 0x00e0 }, 6503 { "agrave", 0x00e0 },
6530 { "alefsym", 0x2135 }, 6504 { "alefsym", 0x2135 },
6531 { "alpha", 0x03b1 }, 6505 { "alpha", 0x03b1 },
6532 { "amp", 38 }, 6506 { "amp", 38 },
6533 { "and", 0x22a5 }, 6507 { "and", 0x22a5 },
6534 { "ang", 0x2220 }, 6508 { "ang", 0x2220 },
6535 { "apos", 0x0027 }, 6509 { "apos", 0x0027 },
6536 { "aring", 0x00e5 }, 6510 { "aring", 0x00e5 },
6537 { "asymp", 0x2248 }, 6511 { "asymp", 0x2248 },
6538 { "atilde", 0x00e3 }, 6512 { "atilde", 0x00e3 },
6539 { "auml", 0x00e4 }, 6513 { "auml", 0x00e4 },
6540 { "bdquo", 0x201e }, 6514 { "bdquo", 0x201e },
6541 { "beta", 0x03b2 }, 6515 { "beta", 0x03b2 },
6542 { "brvbar", 0x00a6 }, 6516 { "brvbar", 0x00a6 },
6543 { "bull", 0x2022 }, 6517 { "bull", 0x2022 },
6544 { "cap", 0x2229 }, 6518 { "cap", 0x2229 },
6545 { "ccedil", 0x00e7 }, 6519 { "ccedil", 0x00e7 },
6546 { "cedil", 0x00b8 }, 6520 { "cedil", 0x00b8 },
6547 { "cent", 0x00a2 }, 6521 { "cent", 0x00a2 },
6548 { "chi", 0x03c7 }, 6522 { "chi", 0x03c7 },
6549 { "circ", 0x02c6 }, 6523 { "circ", 0x02c6 },
6550 { "clubs", 0x2663 }, 6524 { "clubs", 0x2663 },
6551 { "cong", 0x2245 }, 6525 { "cong", 0x2245 },
6552 { "copy", 0x00a9 }, 6526 { "copy", 0x00a9 },
6553 { "crarr", 0x21b5 }, 6527 { "crarr", 0x21b5 },
6554 { "cup", 0x222a }, 6528 { "cup", 0x222a },
6555 { "curren", 0x00a4 }, 6529 { "curren", 0x00a4 },
6556 { "dArr", 0x21d3 }, 6530 { "dArr", 0x21d3 },
6557 { "dagger", 0x2020 }, 6531 { "dagger", 0x2020 },
6558 { "darr", 0x2193 }, 6532 { "darr", 0x2193 },
6559 { "deg", 0x00b0 }, 6533 { "deg", 0x00b0 },
6560 { "delta", 0x03b4 }, 6534 { "delta", 0x03b4 },
6561 { "diams", 0x2666 }, 6535 { "diams", 0x2666 },
6562 { "divide", 0x00f7 }, 6536 { "divide", 0x00f7 },
6563 { "eacute", 0x00e9 }, 6537 { "eacute", 0x00e9 },
6564 { "ecirc", 0x00ea }, 6538 { "ecirc", 0x00ea },
6565 { "egrave", 0x00e8 }, 6539 { "egrave", 0x00e8 },
6566 { "empty", 0x2205 }, 6540 { "empty", 0x2205 },
6567 { "emsp", 0x2003 }, 6541 { "emsp", 0x2003 },
6568 { "ensp", 0x2002 }, 6542 { "ensp", 0x2002 },
6569 { "epsilon", 0x03b5 }, 6543 { "epsilon", 0x03b5 },
6570 { "equiv", 0x2261 }, 6544 { "equiv", 0x2261 },
6571 { "eta", 0x03b7 }, 6545 { "eta", 0x03b7 },
6572 { "eth", 0x00f0 }, 6546 { "eth", 0x00f0 },
6573 { "euml", 0x00eb }, 6547 { "euml", 0x00eb },
6574 { "euro", 0x20ac }, 6548 { "euro", 0x20ac },
6575 { "exist", 0x2203 }, 6549 { "exist", 0x2203 },
6576 { "fnof", 0x0192 }, 6550 { "fnof", 0x0192 },
6577 { "forall", 0x2200 }, 6551 { "forall", 0x2200 },
6578 { "frac12", 0x00bd }, 6552 { "frac12", 0x00bd },
6579 { "frac14", 0x00bc }, 6553 { "frac14", 0x00bc },
6580 { "frac34", 0x00be }, 6554 { "frac34", 0x00be },
6581 { "frasl", 0x2044 }, 6555 { "frasl", 0x2044 },
6582 { "gamma", 0x03b3 }, 6556 { "gamma", 0x03b3 },
6583 { "ge", 0x2265 }, 6557 { "ge", 0x2265 },
6584 { "gt", 62 }, 6558 { "gt", 62 },
6585 { "hArr", 0x21d4 }, 6559 { "hArr", 0x21d4 },
6586 { "harr", 0x2194 }, 6560 { "harr", 0x2194 },
6587 { "hearts", 0x2665 }, 6561 { "hearts", 0x2665 },
6588 { "hellip", 0x2026 }, 6562 { "hellip", 0x2026 },
6589 { "iacute", 0x00ed }, 6563 { "iacute", 0x00ed },
6590 { "icirc", 0x00ee }, 6564 { "icirc", 0x00ee },
6591 { "iexcl", 0x00a1 }, 6565 { "iexcl", 0x00a1 },
6592 { "igrave", 0x00ec }, 6566 { "igrave", 0x00ec },
6593 { "image", 0x2111 }, 6567 { "image", 0x2111 },
6594 { "infin", 0x221e }, 6568 { "infin", 0x221e },
6595 { "int", 0x222b }, 6569 { "int", 0x222b },
6596 { "iota", 0x03b9 }, 6570 { "iota", 0x03b9 },
6597 { "iquest", 0x00bf }, 6571 { "iquest", 0x00bf },
6598 { "isin", 0x2208 }, 6572 { "isin", 0x2208 },
6599 { "iuml", 0x00ef }, 6573 { "iuml", 0x00ef },
6600 { "kappa", 0x03ba }, 6574 { "kappa", 0x03ba },
6601 { "lArr", 0x21d0 }, 6575 { "lArr", 0x21d0 },
6602 { "lambda", 0x03bb }, 6576 { "lambda", 0x03bb },
6603 { "lang", 0x2329 }, 6577 { "lang", 0x2329 },
6604 { "laquo", 0x00ab }, 6578 { "laquo", 0x00ab },
6605 { "larr", 0x2190 }, 6579 { "larr", 0x2190 },
6606 { "lceil", 0x2308 }, 6580 { "lceil", 0x2308 },
6607 { "ldquo", 0x201c }, 6581 { "ldquo", 0x201c },
6608 { "le", 0x2264 }, 6582 { "le", 0x2264 },
6609 { "lfloor", 0x230a }, 6583 { "lfloor", 0x230a },
6610 { "lowast", 0x2217 }, 6584 { "lowast", 0x2217 },
6611 { "loz", 0x25ca }, 6585 { "loz", 0x25ca },
6612 { "lrm", 0x200e }, 6586 { "lrm", 0x200e },
6613 { "lsaquo", 0x2039 }, 6587 { "lsaquo", 0x2039 },
6614 { "lsquo", 0x2018 }, 6588 { "lsquo", 0x2018 },
6615 { "lt", 60 }, 6589 { "lt", 60 },
6616 { "macr", 0x00af }, 6590 { "macr", 0x00af },
6617 { "mdash", 0x2014 }, 6591 { "mdash", 0x2014 },
6618 { "micro", 0x00b5 }, 6592 { "micro", 0x00b5 },
6619 { "middot", 0x00b7 }, 6593 { "middot", 0x00b7 },
6620 { "minus", 0x2212 }, 6594 { "minus", 0x2212 },
6621 { "mu", 0x03bc }, 6595 { "mu", 0x03bc },
6622 { "nabla", 0x2207 }, 6596 { "nabla", 0x2207 },
6623 { "nbsp", 0x00a0 }, 6597 { "nbsp", 0x00a0 },
6624 { "ndash", 0x2013 }, 6598 { "ndash", 0x2013 },
6625 { "ne", 0x2260 }, 6599 { "ne", 0x2260 },
6626 { "ni", 0x220b }, 6600 { "ni", 0x220b },
6627 { "not", 0x00ac }, 6601 { "not", 0x00ac },
6628 { "notin", 0x2209 }, 6602 { "notin", 0x2209 },
6629 { "nsub", 0x2284 }, 6603 { "nsub", 0x2284 },
6630 { "ntilde", 0x00f1 }, 6604 { "ntilde", 0x00f1 },
6631 { "nu", 0x03bd }, 6605 { "nu", 0x03bd },
6632 { "oacute", 0x00f3 }, 6606 { "oacute", 0x00f3 },
6633 { "ocirc", 0x00f4 }, 6607 { "ocirc", 0x00f4 },
6634 { "oelig", 0x0153 }, 6608 { "oelig", 0x0153 },
6635 { "ograve", 0x00f2 }, 6609 { "ograve", 0x00f2 },
6636 { "oline", 0x203e }, 6610 { "oline", 0x203e },
6637 { "omega", 0x03c9 }, 6611 { "omega", 0x03c9 },
6638 { "omicron", 0x03bf }, 6612 { "omicron", 0x03bf },
6639 { "oplus", 0x2295 }, 6613 { "oplus", 0x2295 },
6640 { "or", 0x22a6 }, 6614 { "or", 0x22a6 },
6641 { "ordf", 0x00aa }, 6615 { "ordf", 0x00aa },
6642 { "ordm", 0x00ba }, 6616 { "ordm", 0x00ba },
6643 { "oslash", 0x00f8 }, 6617 { "oslash", 0x00f8 },
6644 { "otilde", 0x00f5 }, 6618 { "otilde", 0x00f5 },
6645 { "otimes", 0x2297 }, 6619 { "otimes", 0x2297 },
6646 { "ouml", 0x00f6 }, 6620 { "ouml", 0x00f6 },
6647 { "para", 0x00b6 }, 6621 { "para", 0x00b6 },
6648 { "part", 0x2202 }, 6622 { "part", 0x2202 },
6649 { "percnt", 0x0025 }, 6623 { "percnt", 0x0025 },
6650 { "permil", 0x2030 }, 6624 { "permil", 0x2030 },
6651 { "perp", 0x22a5 }, 6625 { "perp", 0x22a5 },
6652 { "phi", 0x03c6 }, 6626 { "phi", 0x03c6 },
6653 { "pi", 0x03c0 }, 6627 { "pi", 0x03c0 },
6654 { "piv", 0x03d6 }, 6628 { "piv", 0x03d6 },
6655 { "plusmn", 0x00b1 }, 6629 { "plusmn", 0x00b1 },
6656 { "pound", 0x00a3 }, 6630 { "pound", 0x00a3 },
6657 { "prime", 0x2032 }, 6631 { "prime", 0x2032 },
6658 { "prod", 0x220f }, 6632 { "prod", 0x220f },
6659 { "prop", 0x221d }, 6633 { "prop", 0x221d },
6660 { "psi", 0x03c8 }, 6634 { "psi", 0x03c8 },
6661 { "quot", 34 }, 6635 { "quot", 34 },
6662 { "rArr", 0x21d2 }, 6636 { "rArr", 0x21d2 },
6663 { "radic", 0x221a }, 6637 { "radic", 0x221a },
6664 { "rang", 0x232a }, 6638 { "rang", 0x232a },
6665 { "raquo", 0x00bb }, 6639 { "raquo", 0x00bb },
6666 { "rarr", 0x2192 }, 6640 { "rarr", 0x2192 },
6667 { "rceil", 0x2309 }, 6641 { "rceil", 0x2309 },
6668 { "rdquo", 0x201d }, 6642 { "rdquo", 0x201d },
6669 { "real", 0x211c }, 6643 { "real", 0x211c },
6670 { "reg", 0x00ae }, 6644 { "reg", 0x00ae },
6671 { "rfloor", 0x230b }, 6645 { "rfloor", 0x230b },
6672 { "rho", 0x03c1 }, 6646 { "rho", 0x03c1 },
6673 { "rlm", 0x200f }, 6647 { "rlm", 0x200f },
6674 { "rsaquo", 0x203a }, 6648 { "rsaquo", 0x203a },
6675 { "rsquo", 0x2019 }, 6649 { "rsquo", 0x2019 },
6676 { "sbquo", 0x201a }, 6650 { "sbquo", 0x201a },
6677 { "scaron", 0x0161 }, 6651 { "scaron", 0x0161 },
6678 { "sdot", 0x22c5 }, 6652 { "sdot", 0x22c5 },
6679 { "sect", 0x00a7 }, 6653 { "sect", 0x00a7 },
6680 { "shy", 0x00ad }, 6654 { "shy", 0x00ad },
6681 { "sigma", 0x03c3 }, 6655 { "sigma", 0x03c3 },
6682 { "sigmaf", 0x03c2 }, 6656 { "sigmaf", 0x03c2 },
6683 { "sim", 0x223c }, 6657 { "sim", 0x223c },
6684 { "spades", 0x2660 }, 6658 { "spades", 0x2660 },
6685 { "sub", 0x2282 }, 6659 { "sub", 0x2282 },
6686 { "sube", 0x2286 }, 6660 { "sube", 0x2286 },
6687 { "sum", 0x2211 }, 6661 { "sum", 0x2211 },
6688 { "sup1", 0x00b9 }, 6662 { "sup1", 0x00b9 },
6689 { "sup2", 0x00b2 }, 6663 { "sup2", 0x00b2 },
6690 { "sup3", 0x00b3 }, 6664 { "sup3", 0x00b3 },
6691 { "sup", 0x2283 }, 6665 { "sup", 0x2283 },
6692 { "supe", 0x2287 }, 6666 { "supe", 0x2287 },
6693 { "szlig", 0x00df }, 6667 { "szlig", 0x00df },
6694 { "tau", 0x03c4 }, 6668 { "tau", 0x03c4 },
6695 { "there4", 0x2234 }, 6669 { "there4", 0x2234 },
6696 { "theta", 0x03b8 }, 6670 { "theta", 0x03b8 },
6697 { "thetasym", 0x03d1 }, 6671 { "thetasym", 0x03d1 },
6698 { "thinsp", 0x2009 }, 6672 { "thinsp", 0x2009 },
6699 { "thorn", 0x00fe }, 6673 { "thorn", 0x00fe },
6700 { "tilde", 0x02dc }, 6674 { "tilde", 0x02dc },
6701 { "times", 0x00d7 }, 6675 { "times", 0x00d7 },
6702 { "trade", 0x2122 }, 6676 { "trade", 0x2122 },
6703 { "uArr", 0x21d1 }, 6677 { "uArr", 0x21d1 },
6704 { "uacute", 0x00fa }, 6678 { "uacute", 0x00fa },
6705 { "uarr", 0x2191 }, 6679 { "uarr", 0x2191 },
6706 { "ucirc", 0x00fb }, 6680 { "ucirc", 0x00fb },
6707 { "ugrave", 0x00f9 }, 6681 { "ugrave", 0x00f9 },
6708 { "uml", 0x00a8 }, 6682 { "uml", 0x00a8 },
6709 { "upsih", 0x03d2 }, 6683 { "upsih", 0x03d2 },
6710 { "upsilon", 0x03c5 }, 6684 { "upsilon", 0x03c5 },
6711 { "uuml", 0x00fc }, 6685 { "uuml", 0x00fc },
6712 { "weierp", 0x2118 }, 6686 { "weierp", 0x2118 },
6713 { "xi", 0x03be }, 6687 { "xi", 0x03be },
6714 { "yacute", 0x00fd }, 6688 { "yacute", 0x00fd },
6715 { "yen", 0x00a5 }, 6689 { "yen", 0x00a5 },
6716 { "yuml", 0x00ff }, 6690 { "yuml", 0x00ff },
6717 { "zeta", 0x03b6 }, 6691 { "zeta", 0x03b6 },
6718 { "zwj", 0x200d }, 6692 { "zwj", 0x200d },
6719 { "zwnj", 0x200c }, 6693 { "zwnj", 0x200c },
6720 { "", 0x0000 } 6694 { "", 0x0000 }
6721}; 6695};
6722 6696
6723 6697
6724 6698
6725 6699
6726 6700
6727static QMap<QCString, QChar> *html_map = 0; 6701static QMap<QCString, QChar> *html_map = 0;
6728static void qt_cleanup_html_map() 6702static void qt_cleanup_html_map()
6729{ 6703{
6730 delete html_map; 6704 delete html_map;
6731 html_map = 0; 6705 html_map = 0;
6732} 6706}
6733 6707
6734static QMap<QCString, QChar> *htmlMap() 6708static QMap<QCString, QChar> *htmlMap()
6735{ 6709{
6736 if ( !html_map ) { 6710 if ( !html_map ) {
6737 html_map = new QMap<QCString, QChar>; 6711 html_map = new QMap<QCString, QChar>;
6738 qAddPostRoutine( qt_cleanup_html_map ); 6712 qAddPostRoutine( qt_cleanup_html_map );
6739 6713
6740 const Entity *ent = entitylist; 6714 const Entity *ent = entitylist;
6741 while( ent->code ) { 6715 while( ent->code ) {
6742 html_map->insert( ent->name, QChar(ent->code) ); 6716 html_map->insert( ent->name, QChar(ent->code) );
6743 ent++; 6717 ent++;
6744 } 6718 }
6745 } 6719 }
6746 return html_map; 6720 return html_map;
6747} 6721}
6748 6722
6749QChar QTextDocument::parseHTMLSpecialChar(const QChar* doc, int length, int& pos) 6723QChar QTextDocument::parseHTMLSpecialChar(const QChar* doc, int length, int& pos)
6750{ 6724{
6751 QCString s; 6725 QCString s;
6752 pos++; 6726 pos++;
6753 int recoverpos = pos; 6727 int recoverpos = pos;
6754 while ( pos < length && doc[pos] != ';' && !doc[pos].isSpace() && pos < recoverpos + 6) { 6728 while ( pos < length && doc[pos] != ';' && !doc[pos].isSpace() && pos < recoverpos + 6) {
6755 s += doc[pos]; 6729 s += doc[pos];
6756 pos++; 6730 pos++;
6757 } 6731 }
6758 if (doc[pos] != ';' && !doc[pos].isSpace() ) { 6732 if (doc[pos] != ';' && !doc[pos].isSpace() ) {
6759 pos = recoverpos; 6733 pos = recoverpos;
6760 return '&'; 6734 return '&';
6761 } 6735 }
6762 pos++; 6736 pos++;
6763 6737
6764 if ( s.length() > 1 && s[0] == '#') { 6738 if ( s.length() > 1 && s[0] == '#') {
6765 int num = s.mid(1).toInt(); 6739 int num = s.mid(1).toInt();
6766 if ( num == 151 ) // ### hack for designer manual 6740 if ( num == 151 ) // ### hack for designer manual
6767 return '-'; 6741 return '-';
6768 return num; 6742 return num;
6769 } 6743 }
6770 6744
6771 QMap<QCString, QChar>::Iterator it = htmlMap()->find(s); 6745 QMap<QCString, QChar>::Iterator it = htmlMap()->find(s);
6772 if ( it != htmlMap()->end() ) { 6746 if ( it != htmlMap()->end() ) {
6773 return *it; 6747 return *it;
6774 } 6748 }
6775 6749
6776 pos = recoverpos; 6750 pos = recoverpos;
6777 return '&'; 6751 return '&';
6778} 6752}
6779 6753
6780QString QTextDocument::parseWord(const QChar* doc, int length, int& pos, bool lower) 6754QString QTextDocument::parseWord(const QChar* doc, int length, int& pos, bool lower)
6781{ 6755{
6782 QString s; 6756 QString s;
6783 6757
6784 if (doc[pos] == '"') { 6758 if (doc[pos] == '"') {
6785 pos++; 6759 pos++;
6786 while ( pos < length && doc[pos] != '"' ) { 6760 while ( pos < length && doc[pos] != '"' ) {
6787 s += doc[pos]; 6761 s += doc[pos];
6788 pos++; 6762 pos++;
6789 } 6763 }
6790 eat(doc, length, pos, '"'); 6764 eat(doc, length, pos, '"');
6791 } else { 6765 } else {
6792 static QString term = QString::fromLatin1("/>"); 6766 static QString term = QString::fromLatin1("/>");
6793 while( pos < length && 6767 while( pos < length &&
6794 (doc[pos] != '>' && !hasPrefix( doc, length, pos, term)) 6768 (doc[pos] != '>' && !hasPrefix( doc, length, pos, term))
6795 && doc[pos] != '<' 6769 && doc[pos] != '<'
6796 && doc[pos] != '=' 6770 && doc[pos] != '='
6797 && !doc[pos].isSpace()) 6771 && !doc[pos].isSpace())
6798 { 6772 {
6799 if ( doc[pos] == '&') 6773 if ( doc[pos] == '&')
6800 s += parseHTMLSpecialChar( doc, length, pos ); 6774 s += parseHTMLSpecialChar( doc, length, pos );
6801 else { 6775 else {
6802 s += doc[pos]; 6776 s += doc[pos];
6803 pos++; 6777 pos++;
6804 } 6778 }
6805 } 6779 }
6806 if (lower) 6780 if (lower)
6807 s = s.lower(); 6781 s = s.lower();
6808 } 6782 }
6809 return s; 6783 return s;
6810} 6784}
6811 6785
6812QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm ) 6786QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm )
6813{ 6787{
6814 if ( pos >= length ) 6788 if ( pos >= length )
6815 return QChar::null; 6789 return QChar::null;
6816 6790
6817 QChar c = doc[pos++]; 6791 QChar c = doc[pos++];
6818 6792
6819 if (c == '<' ) 6793 if (c == '<' )
6820 return QChar::null; 6794 return QChar::null;
6821 6795
6822 if ( c.isSpace() && c != QChar::nbsp ) { 6796 if ( c.isSpace() && c != QChar::nbsp ) {
6823 if ( wsm == QStyleSheetItem::WhiteSpacePre ) { 6797 if ( wsm == QStyleSheetItem::WhiteSpacePre ) {
6824 if ( c == '\n' ) 6798 if ( c == '\n' )
6825 return QChar_linesep; 6799 return QChar_linesep;
6826 else 6800 else
6827 return c; 6801 return c;
6828 } else { // non-pre mode: collapse whitespace except nbsp 6802 } else { // non-pre mode: collapse whitespace except nbsp
6829 while ( pos< length && 6803 while ( pos< length &&
6830 doc[pos].isSpace() && doc[pos] != QChar::nbsp ) 6804 doc[pos].isSpace() && doc[pos] != QChar::nbsp )
6831 pos++; 6805 pos++;
6832 if ( wsm == QStyleSheetItem::WhiteSpaceNoWrap ) 6806 if ( wsm == QStyleSheetItem::WhiteSpaceNoWrap )
6833 return QChar::nbsp; 6807 return QChar::nbsp;
6834 else 6808 else
6835 return ' '; 6809 return ' ';
6836 } 6810 }
6837 } 6811 }
6838 else if ( c == '&' ) 6812 else if ( c == '&' )
6839 return parseHTMLSpecialChar( doc, length, --pos ); 6813 return parseHTMLSpecialChar( doc, length, --pos );
6840 else 6814 else
6841 return c; 6815 return c;
6842} 6816}
6843 6817
6844QString QTextDocument::parseOpenTag(const QChar* doc, int length, int& pos, 6818QString QTextDocument::parseOpenTag(const QChar* doc, int length, int& pos,
6845 QMap<QString, QString> &attr, bool& emptyTag) 6819 QMap<QString, QString> &attr, bool& emptyTag)
6846{ 6820{
6847 emptyTag = FALSE; 6821 emptyTag = FALSE;
6848 pos++; 6822 pos++;
6849 if ( hasPrefix(doc, length, pos, '!') ) { 6823 if ( hasPrefix(doc, length, pos, '!') ) {
6850 if ( hasPrefix( doc, length, pos+1, "--")) { 6824 if ( hasPrefix( doc, length, pos+1, "--")) {
6851 pos += 3; 6825 pos += 3;
6852 // eat comments 6826 // eat comments
6853 QString pref = QString::fromLatin1("-->"); 6827 QString pref = QString::fromLatin1("-->");
6854 while ( !hasPrefix(doc, length, pos, pref ) && pos < length ) 6828 while ( !hasPrefix(doc, length, pos, pref ) && pos < length )
6855 pos++; 6829 pos++;
6856 if ( hasPrefix(doc, length, pos, pref ) ) { 6830 if ( hasPrefix(doc, length, pos, pref ) ) {
6857 pos += 3; 6831 pos += 3;
6858 eatSpace(doc, length, pos, TRUE); 6832 eatSpace(doc, length, pos, TRUE);
6859 } 6833 }
6860 emptyTag = TRUE; 6834 emptyTag = TRUE;
6861 return QString::null; 6835 return QString::null;
6862 } 6836 }
6863 else { 6837 else {
6864 // eat strange internal tags 6838 // eat strange internal tags
6865 while ( !hasPrefix(doc, length, pos, '>') && pos < length ) 6839 while ( !hasPrefix(doc, length, pos, '>') && pos < length )
6866 pos++; 6840 pos++;
6867 if ( hasPrefix(doc, length, pos, '>') ) { 6841 if ( hasPrefix(doc, length, pos, '>') ) {
6868 pos++; 6842 pos++;
6869 eatSpace(doc, length, pos, TRUE); 6843 eatSpace(doc, length, pos, TRUE);
6870 } 6844 }
6871 return QString::null; 6845 return QString::null;
6872 } 6846 }
6873 } 6847 }
6874 6848
6875 QString tag = parseWord(doc, length, pos ); 6849 QString tag = parseWord(doc, length, pos );
6876 eatSpace(doc, length, pos, TRUE); 6850 eatSpace(doc, length, pos, TRUE);
6877 static QString term = QString::fromLatin1("/>"); 6851 static QString term = QString::fromLatin1("/>");
6878 static QString s_TRUE = QString::fromLatin1("TRUE"); 6852 static QString s_TRUE = QString::fromLatin1("TRUE");
6879 6853
6880 while (doc[pos] != '>' && ! (emptyTag = hasPrefix(doc, length, pos, term) )) { 6854 while (doc[pos] != '>' && ! (emptyTag = hasPrefix(doc, length, pos, term) )) {
6881 QString key = parseWord(doc, length, pos ); 6855 QString key = parseWord(doc, length, pos );
6882 eatSpace(doc, length, pos, TRUE); 6856 eatSpace(doc, length, pos, TRUE);
6883 if ( key.isEmpty()) { 6857 if ( key.isEmpty()) {
6884 // error recovery 6858 // error recovery
6885 while ( pos < length && doc[pos] != '>' ) 6859 while ( pos < length && doc[pos] != '>' )
6886 pos++; 6860 pos++;
6887 break; 6861 break;
6888 } 6862 }
6889 QString value; 6863 QString value;
6890 if (hasPrefix(doc, length, pos, '=') ){ 6864 if (hasPrefix(doc, length, pos, '=') ){
6891 pos++; 6865 pos++;
6892 eatSpace(doc, length, pos); 6866 eatSpace(doc, length, pos);
6893 value = parseWord(doc, length, pos, FALSE); 6867 value = parseWord(doc, length, pos, FALSE);
6894 } 6868 }
6895 else 6869 else
6896 value = s_TRUE; 6870 value = s_TRUE;
6897 attr.insert(key.lower(), value ); 6871 attr.insert(key.lower(), value );
6898 eatSpace(doc, length, pos, TRUE); 6872 eatSpace(doc, length, pos, TRUE);
6899 } 6873 }
6900 6874
6901 if (emptyTag) { 6875 if (emptyTag) {
6902 eat(doc, length, pos, '/'); 6876 eat(doc, length, pos, '/');
6903 eat(doc, length, pos, '>'); 6877 eat(doc, length, pos, '>');