summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/apps/opie-write/qcleanuphandler.h12
-rw-r--r--noncore/apps/opie-write/qcomplextext.cpp3
-rw-r--r--noncore/apps/opie-write/qrichtext.cpp4311
-rw-r--r--noncore/apps/opie-write/qrichtext_p.cpp303
-rw-r--r--noncore/apps/opie-write/qrichtext_p.h576
-rw-r--r--noncore/apps/opie-write/qstylesheet.cpp1230
-rw-r--r--noncore/apps/opie-write/qstylesheet.h16
-rw-r--r--noncore/apps/opie-write/qt3namespace.h1
-rw-r--r--noncore/apps/opie-write/qtextedit.cpp1495
-rw-r--r--noncore/apps/opie-write/qtextedit.h30
10 files changed, 3833 insertions, 4144 deletions
diff --git a/noncore/apps/opie-write/qcleanuphandler.h b/noncore/apps/opie-write/qcleanuphandler.h
index 5c5bf16..2d6eb7c 100644
--- a/noncore/apps/opie-write/qcleanuphandler.h
+++ b/noncore/apps/opie-write/qcleanuphandler.h
@@ -12,128 +12,116 @@
12** LICENSE.QPL included in the packaging of this file. 12** LICENSE.QPL included in the packaging of this file.
13** 13**
14** This file may be distributed and/or modified under the terms of the 14** This file may be distributed and/or modified under the terms of the
15** GNU General Public License version 2 as published by the Free Software 15** GNU General Public License version 2 as published by the Free Software
16** Foundation and appearing in the file LICENSE.GPL included in the 16** Foundation and appearing in the file LICENSE.GPL included in the
17** packaging of this file. 17** packaging of this file.
18** 18**
19** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition 19** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
20** licenses may use this file in accordance with the Qt Commercial License 20** licenses may use this file in accordance with the Qt Commercial License
21** Agreement provided with the Software. 21** Agreement provided with the Software.
22** 22**
23** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 23** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 24** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25** 25**
26** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for 26** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
27** information about Qt Commercial License Agreements. 27** information about Qt Commercial License Agreements.
28** See http://www.trolltech.com/qpl/ for QPL licensing information. 28** See http://www.trolltech.com/qpl/ for QPL licensing information.
29** See http://www.trolltech.com/gpl/ for GPL licensing information. 29** See http://www.trolltech.com/gpl/ for GPL licensing information.
30** 30**
31** Contact info@trolltech.com if any conditions of this licensing are 31** Contact info@trolltech.com if any conditions of this licensing are
32** not clear to you. 32** not clear to you.
33** 33**
34**********************************************************************/ 34**********************************************************************/
35 35
36#ifndef QCLEANUPHANDLER_H 36#ifndef QCLEANUPHANDLER_H
37#define QCLEANUPHANDLER_H 37#define QCLEANUPHANDLER_H
38 38
39#ifndef QT_H 39#ifndef QT_H
40#include <qlist.h> 40#include <qlist.h>
41#endif // QT_H 41#endif // QT_H
42 42
43template<class Type> 43template<class Type>
44#ifdef Q_NO_TEMPLATE_EXPORT
45class QCleanupHandler 44class QCleanupHandler
46#else
47class Q_EXPORT QCleanupHandler
48#endif
49{ 45{
50public: 46public:
51 QCleanupHandler() : cleanupObjects( 0 ) {} 47 QCleanupHandler() : cleanupObjects( 0 ) {}
52 ~QCleanupHandler() { clear(); } 48 ~QCleanupHandler() { clear(); }
53 49
54 Type* add( Type **object ) { 50 Type* add( Type **object ) {
55 if ( !cleanupObjects ) 51 if ( !cleanupObjects )
56 cleanupObjects = new QPtrList<Type*>; 52 cleanupObjects = new QPtrList<Type*>;
57 cleanupObjects->insert( 0, object ); 53 cleanupObjects->insert( 0, object );
58 return *object; 54 return *object;
59 } 55 }
60 56
61 void remove( Type **object ) { 57 void remove( Type **object ) {
62 if ( !cleanupObjects ) 58 if ( !cleanupObjects )
63 return; 59 return;
64 if ( cleanupObjects->findRef( object ) >= 0 ) 60 if ( cleanupObjects->findRef( object ) >= 0 )
65 (void) cleanupObjects->take(); 61 (void) cleanupObjects->take();
66 } 62 }
67 63
68 bool isEmpty() const { 64 bool isEmpty() const {
69 return cleanupObjects ? cleanupObjects->isEmpty() : TRUE; 65 return cleanupObjects ? cleanupObjects->isEmpty() : TRUE;
70 } 66 }
71 67
72 void clear() { 68 void clear() {
73 if ( !cleanupObjects ) 69 if ( !cleanupObjects )
74 return; 70 return;
75 QPtrListIterator<Type*> it( *cleanupObjects ); 71 QPtrListIterator<Type*> it( *cleanupObjects );
76 Type **object; 72 Type **object;
77 while ( ( object = it.current() ) ) { 73 while ( ( object = it.current() ) ) {
78 delete *object; 74 delete *object;
79 *object = 0; 75 *object = 0;
80 cleanupObjects->remove( object ); 76 cleanupObjects->remove( object );
81 } 77 }
82 delete cleanupObjects; 78 delete cleanupObjects;
83 cleanupObjects = 0; 79 cleanupObjects = 0;
84 } 80 }
85 81
86private: 82private:
87 QPtrList<Type*> *cleanupObjects; 83 QPtrList<Type*> *cleanupObjects;
88}; 84};
89 85
90template<class Type> 86template<class Type>
91#ifdef Q_NO_TEMPLATE_EXPORT
92class QSingleCleanupHandler 87class QSingleCleanupHandler
93#else
94class Q_EXPORT QSingleCleanupHandler
95#endif
96{ 88{
97public: 89public:
98 QSingleCleanupHandler() : object( 0 ) {} 90 QSingleCleanupHandler() : object( 0 ) {}
99 ~QSingleCleanupHandler() { 91 ~QSingleCleanupHandler() {
100 if ( object ) { 92 if ( object ) {
101 delete *object; 93 delete *object;
102 *object = 0; 94 *object = 0;
103 } 95 }
104 } 96 }
105 Type* set( Type **o ) { 97 Type* set( Type **o ) {
106 object = o; 98 object = o;
107 return *object; 99 return *object;
108 } 100 }
109 void reset() { object = 0; } 101 void reset() { object = 0; }
110private: 102private:
111 Type **object; 103 Type **object;
112}; 104};
113 105
114template<class Type> 106template<class Type>
115#ifdef Q_NO_TEMPLATE_EXPORT
116class QSharedCleanupHandler 107class QSharedCleanupHandler
117#else
118class Q_EXPORT QSharedCleanupHandler
119#endif
120{ 108{
121public: 109public:
122 QSharedCleanupHandler() : object( 0 ) {} 110 QSharedCleanupHandler() : object( 0 ) {}
123 ~QSharedCleanupHandler() { 111 ~QSharedCleanupHandler() {
124 if ( object ) { 112 if ( object ) {
125 if ( (*object)->deref() ) 113 if ( (*object)->deref() )
126 delete *object; 114 delete *object;
127 *object = 0; 115 *object = 0;
128 } 116 }
129 } 117 }
130 Type* set( Type **o ) { 118 Type* set( Type **o ) {
131 object = o; 119 object = o;
132 return *object; 120 return *object;
133 } 121 }
134 void reset() { object = 0; } 122 void reset() { object = 0; }
135private: 123private:
136 Type **object; 124 Type **object;
137}; 125};
138 126
139#endif //QCLEANUPHANDLER_H 127#endif //QCLEANUPHANDLER_H
diff --git a/noncore/apps/opie-write/qcomplextext.cpp b/noncore/apps/opie-write/qcomplextext.cpp
index 0fa6c2e..e8b94da 100644
--- a/noncore/apps/opie-write/qcomplextext.cpp
+++ b/noncore/apps/opie-write/qcomplextext.cpp
@@ -37,67 +37,64 @@
37 37
38#include "qcomplextext_p.h" 38#include "qcomplextext_p.h"
39 39
40#include "qrichtext_p.h" 40#include "qrichtext_p.h"
41#include "qfontmetrics.h" 41#include "qfontmetrics.h"
42#include "qrect.h" 42#include "qrect.h"
43 43
44#include <stdlib.h> 44#include <stdlib.h>
45 45
46using namespace Qt3; 46using namespace Qt3;
47 47
48// ----------------------------------------------------- 48// -----------------------------------------------------
49 49
50/* a small helper class used internally to resolve Bidi embedding levels. 50/* a small helper class used internally to resolve Bidi embedding levels.
51 Each line of text caches the embedding level at the start of the line for faster 51 Each line of text caches the embedding level at the start of the line for faster
52 relayouting 52 relayouting
53*/ 53*/
54QBidiContext::QBidiContext( uchar l, QChar::Direction e, QBidiContext *p, bool o ) 54QBidiContext::QBidiContext( uchar l, QChar::Direction e, QBidiContext *p, bool o )
55 : level(l) , override(o), dir(e) 55 : level(l) , override(o), dir(e)
56{ 56{
57 if ( p ) 57 if ( p )
58 p->ref(); 58 p->ref();
59 parent = p; 59 parent = p;
60 count = 0; 60 count = 0;
61} 61}
62 62
63QBidiContext::~QBidiContext() 63QBidiContext::~QBidiContext()
64{ 64{
65 if( parent && parent->deref() ) 65 if( parent && parent->deref() )
66 delete parent; 66 delete parent;
67} 67}
68 68
69static QChar *shapeBuffer = 0;
70static int shapeBufSize = 0;
71
72/* 69/*
73 Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on 70 Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on
74 arabic). 71 arabic).
75 72
76 Each unicode char has a joining class (right, dual (left&right), center (joincausing) or transparent). 73 Each unicode char has a joining class (right, dual (left&right), center (joincausing) or transparent).
77 transparent joining is not encoded in QChar::joining(), but applies to all combining marks and format marks. 74 transparent joining is not encoded in QChar::joining(), but applies to all combining marks and format marks.
78 75
79 Right join-causing: dual + center 76 Right join-causing: dual + center
80 Left join-causing: dual + right + center 77 Left join-causing: dual + right + center
81 78
82 Rules are as follows (for a string already in visual order, as we have it here): 79 Rules are as follows (for a string already in visual order, as we have it here):
83 80
84 R1 Transparent characters do not affect joining behaviour. 81 R1 Transparent characters do not affect joining behaviour.
85 R2 A right joining character, that has a right join-causing char on the right will get form XRight 82 R2 A right joining character, that has a right join-causing char on the right will get form XRight
86 (R3 A left joining character, that has a left join-causing char on the left will get form XLeft) 83 (R3 A left joining character, that has a left join-causing char on the left will get form XLeft)
87 Note: the above rule is meaningless, as there are no pure left joining characters defined in Unicode 84 Note: the above rule is meaningless, as there are no pure left joining characters defined in Unicode
88 R4 A dual joining character, that has a left join-causing char on the left and a right join-causing char on 85 R4 A dual joining character, that has a left join-causing char on the left and a right join-causing char on
89 the right will get form XMedial 86 the right will get form XMedial
90 R5 A dual joining character, that has a right join causing char on the right, and no left join causing char on the left 87 R5 A dual joining character, that has a right join causing char on the right, and no left join causing char on the left
91 will get form XRight 88 will get form XRight
92 R6 A dual joining character, that has a left join causing char on the left, and no right join causing char on the right 89 R6 A dual joining character, that has a left join causing char on the left, and no right join causing char on the right
93 will get form XLeft 90 will get form XLeft
94 R7 Otherwise the character will get form XIsolated 91 R7 Otherwise the character will get form XIsolated
95 92
96 Additionally we have to do the minimal ligature support for lam-alef ligatures: 93 Additionally we have to do the minimal ligature support for lam-alef ligatures:
97 94
98 L1 Transparent characters do not affect ligature behaviour. 95 L1 Transparent characters do not affect ligature behaviour.
99 L2 Any sequence of Alef(XRight) + Lam(XMedial) will form the ligature Alef.Lam(XLeft) 96 L2 Any sequence of Alef(XRight) + Lam(XMedial) will form the ligature Alef.Lam(XLeft)
100 L3 Any sequence of Alef(XRight) + Lam(XLeft) will form the ligature Alef.Lam(XIsolated) 97 L3 Any sequence of Alef(XRight) + Lam(XLeft) will form the ligature Alef.Lam(XIsolated)
101 98
102 The two functions defined in this class do shaping in visual and logical order. For logical order just replace right with 99 The two functions defined in this class do shaping in visual and logical order. For logical order just replace right with
103 previous and left with next in the above rules ;-) 100 previous and left with next in the above rules ;-)
diff --git a/noncore/apps/opie-write/qrichtext.cpp b/noncore/apps/opie-write/qrichtext.cpp
index 7901000..3b044c3 100644
--- a/noncore/apps/opie-write/qrichtext.cpp
+++ b/noncore/apps/opie-write/qrichtext.cpp
@@ -12,106 +12,97 @@
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#include "qstringlist.h" 40#include "qstringlist.h"
41#include "qfont.h" 41#include "qfont.h"
42#include "qtextstream.h" 42#include "qtextstream.h"
43#include "qfile.h" 43#include "qfile.h"
44#include "qregexp.h"
45#include "qapplication.h" 44#include "qapplication.h"
46#include "qclipboard.h"
47#include "qmap.h" 45#include "qmap.h"
48#include "qfileinfo.h" 46#include "qfileinfo.h"
49#include "qstylesheet.h" 47#include "qstylesheet.h"
50#include "qmime.h" 48#include "qmime.h"
51#include "qregexp.h"
52#include "qimage.h" 49#include "qimage.h"
53#include "qdragobject.h" 50#include "qdragobject.h"
54#include "qpaintdevicemetrics.h" 51#include "qpaintdevicemetrics.h"
55#include "qpainter.h" 52#include "qpainter.h"
56#include "qdrawutil.h" 53#include "qdrawutil.h"
57#include "qcursor.h" 54#include "qcursor.h"
58#include "qstack.h" 55#include "qstack.h"
59#include "qstyle.h" 56#include "qstyle.h"
60#include "qcomplextext_p.h" 57#include "qcomplextext_p.h"
61#include "qcleanuphandler.h" 58#include "qcleanuphandler.h"
62 59
63#include <stdlib.h> 60#include <stdlib.h>
64 61
65using namespace Qt3; 62using namespace Qt3;
66 63
67//#define PARSER_DEBUG 64static QTextCursor* richTextExportStart = 0;
68//#define DEBUG_COLLECTION// ---> also in qrichtext_p.h 65static QTextCursor* richTextExportEnd = 0;
69//#define DEBUG_TABLE_RENDERING
70 66
71static QTextFormatCollection *qFormatCollection = 0; 67static QTextFormatCollection *qFormatCollection = 0;
72 68
73const int QStyleSheetItem_WhiteSpaceNoCompression = 3; // ### belongs in QStyleSheetItem, fix 3.1
74const int QStyleSheetItem_WhiteSpaceNormalWithNewlines = 4; // ### belongs in QStyleSheetItem, fix 3.1
75
76const int border_tolerance = 2; 69const int border_tolerance = 2;
77 70
78#if defined(PARSER_DEBUG)
79static QString debug_indent;
80#endif
81
82#ifdef Q_WS_WIN 71#ifdef Q_WS_WIN
83#include "qt_windows.h" 72#include "qt_windows.h"
84#endif 73#endif
85 74
75#define QChar_linesep QChar(0x2028U)
76
86static inline bool is_printer( QPainter *p ) 77static inline bool is_printer( QPainter *p )
87{ 78{
88 if ( !p || !p->device() ) 79 if ( !p || !p->device() )
89 return FALSE; 80 return FALSE;
90 return p->device()->devType() == QInternal::Printer; 81 return p->device()->devType() == QInternal::Printer;
91} 82}
92 83
93static inline int scale( int value, QPainter *painter ) 84static inline int scale( int value, QPainter *painter )
94{ 85{
95 if ( is_printer( painter ) ) { 86 if ( is_printer( painter ) ) {
96 QPaintDeviceMetrics metrics( painter->device() ); 87 QPaintDeviceMetrics metrics( painter->device() );
97#if defined(Q_WS_X11) 88#if defined(Q_WS_X11)
98 value = value * metrics.logicalDpiY() / QPaintDevice::x11AppDpiY(); 89 value = value * metrics.logicalDpiY() / QPaintDevice::x11AppDpiY();
99#elif defined (Q_WS_WIN) 90#elif defined (Q_WS_WIN)
100 HDC hdc = GetDC( 0 ); 91 HDC hdc = GetDC( 0 );
101 int gdc = GetDeviceCaps( hdc, LOGPIXELSY ); 92 int gdc = GetDeviceCaps( hdc, LOGPIXELSY );
102 if ( gdc ) 93 if ( gdc )
103 value = value * metrics.logicalDpiY() / gdc; 94 value = value * metrics.logicalDpiY() / gdc;
104 ReleaseDC( 0, hdc ); 95 ReleaseDC( 0, hdc );
105#elif defined (Q_WS_MAC) 96#elif defined (Q_WS_MAC)
106 value = value * metrics.logicalDpiY() / 75; // ##### FIXME 97 value = value * metrics.logicalDpiY() / 75; // ##### FIXME
107#elif defined (Q_WS_QWS) 98#elif defined (Q_WS_QWS)
108 value = value * metrics.logicalDpiY() / 75; 99 value = value * metrics.logicalDpiY() / 75;
109#endif 100#endif
110 } 101 }
111 return value; 102 return value;
112} 103}
113 104
114// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 105// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
115 106
116void QTextCommandHistory::addCommand( QTextCommand *cmd ) 107void QTextCommandHistory::addCommand( QTextCommand *cmd )
117{ 108{
@@ -148,3090 +139,3125 @@ QTextCursor *QTextCommandHistory::undo( QTextCursor *c )
148 return 0; 139 return 0;
149} 140}
150 141
151QTextCursor *QTextCommandHistory::redo( QTextCursor *c ) 142QTextCursor *QTextCommandHistory::redo( QTextCursor *c )
152{ 143{
153 if ( current > -1 ) { 144 if ( current > -1 ) {
154 if ( current < (int)history.count() - 1 ) { 145 if ( current < (int)history.count() - 1 ) {
155 ++current; 146 ++current;
156 return history.at( current )->execute( c ); 147 return history.at( current )->execute( c );
157 } 148 }
158 } else { 149 } else {
159 if ( history.count() > 0 ) { 150 if ( history.count() > 0 ) {
160 ++current; 151 ++current;
161 return history.at( current )->execute( c ); 152 return history.at( current )->execute( c );
162 } 153 }
163 } 154 }
164 return 0; 155 return 0;
165} 156}
166 157
167bool QTextCommandHistory::isUndoAvailable() 158bool QTextCommandHistory::isUndoAvailable()
168{ 159{
169 return current > -1; 160 return current > -1;
170} 161}
171 162
172bool QTextCommandHistory::isRedoAvailable() 163bool QTextCommandHistory::isRedoAvailable()
173{ 164{
174 return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0; 165 return current > -1 && current < (int)history.count() - 1 || current == -1 && history.count() > 0;
175} 166}
176 167
177// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 168// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
178 169
179QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, 170QTextDeleteCommand::QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str,
180 const QValueList< QPtrVector<QStyleSheetItem> > &os, 171 const QByteArray& oldStyleInfo )
181 const QValueList<QStyleSheetItem::ListStyle> &ols, 172 : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), styleInformation( oldStyleInfo )
182 const QMemArray<int> &oas)
183 : QTextCommand( d ), id( i ), index( idx ), parag( 0 ), text( str ), oldStyles( os ), oldListStyles( ols ), oldAligns( oas )
184{ 173{
185 for ( int j = 0; j < (int)text.size(); ++j ) { 174 for ( int j = 0; j < (int)text.size(); ++j ) {
186 if ( text[ j ].format() ) 175 if ( text[ j ].format() )
187 text[ j ].format()->addRef(); 176 text[ j ].format()->addRef();
188 } 177 }
189} 178}
190 179
191QTextDeleteCommand::QTextDeleteCommand( QTextParag *p, int idx, const QMemArray<QTextStringChar> &str ) 180QTextDeleteCommand::QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str )
192 : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str ) 181 : QTextCommand( 0 ), id( -1 ), index( idx ), parag( p ), text( str )
193{ 182{
194 for ( int i = 0; i < (int)text.size(); ++i ) { 183 for ( int i = 0; i < (int)text.size(); ++i ) {
195 if ( text[ i ].format() ) 184 if ( text[ i ].format() )
196 text[ i ].format()->addRef(); 185 text[ i ].format()->addRef();
197 } 186 }
198} 187}
199 188
200QTextDeleteCommand::~QTextDeleteCommand() 189QTextDeleteCommand::~QTextDeleteCommand()
201{ 190{
202 for ( int i = 0; i < (int)text.size(); ++i ) { 191 for ( int i = 0; i < (int)text.size(); ++i ) {
203 if ( text[ i ].format() ) 192 if ( text[ i ].format() )
204 text[ i ].format()->removeRef(); 193 text[ i ].format()->removeRef();
205 } 194 }
206 text.resize( 0 ); 195 text.resize( 0 );
207} 196}
208 197
209QTextCursor *QTextDeleteCommand::execute( QTextCursor *c ) 198QTextCursor *QTextDeleteCommand::execute( QTextCursor *c )
210{ 199{
211 QTextParag *s = doc ? doc->paragAt( id ) : parag; 200 QTextParagraph *s = doc ? doc->paragAt( id ) : parag;
212 if ( !s ) { 201 if ( !s ) {
213 qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParag()->paragId() ); 202 qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() );
214 return 0; 203 return 0;
215 } 204 }
216 205
217 cursor.setParag( s ); 206 cursor.setParagraph( s );
218 cursor.setIndex( index ); 207 cursor.setIndex( index );
219 int len = text.size(); 208 int len = text.size();
220 if ( c ) 209 if ( c )
221 *c = cursor; 210 *c = cursor;
222 if ( doc ) { 211 if ( doc ) {
223 doc->setSelectionStart( QTextDocument::Temp, &cursor ); 212 doc->setSelectionStart( QTextDocument::Temp, cursor );
224 for ( int i = 0; i < len; ++i ) 213 for ( int i = 0; i < len; ++i )
225 cursor.gotoNextLetter(); 214 cursor.gotoNextLetter();
226 doc->setSelectionEnd( QTextDocument::Temp, &cursor ); 215 doc->setSelectionEnd( QTextDocument::Temp, cursor );
227 doc->removeSelectedText( QTextDocument::Temp, &cursor ); 216 doc->removeSelectedText( QTextDocument::Temp, &cursor );
228 if ( c ) 217 if ( c )
229 *c = cursor; 218 *c = cursor;
230 } else { 219 } else {
231 s->remove( index, len ); 220 s->remove( index, len );
232 } 221 }
233 222
234 return c; 223 return c;
235} 224}
236 225
237QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c ) 226QTextCursor *QTextDeleteCommand::unexecute( QTextCursor *c )
238{ 227{
239 QTextParag *s = doc ? doc->paragAt( id ) : parag; 228 QTextParagraph *s = doc ? doc->paragAt( id ) : parag;
240 if ( !s ) { 229 if ( !s ) {
241 qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParag()->paragId() ); 230 qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParagraph()->paragId() );
242 return 0; 231 return 0;
243 } 232 }
244 233
245 cursor.setParag( s ); 234 cursor.setParagraph( s );
246 cursor.setIndex( index ); 235 cursor.setIndex( index );
247 QString str = QTextString::toString( text ); 236 QString str = QTextString::toString( text );
248 cursor.insert( str, TRUE, &text ); 237 cursor.insert( str, TRUE, &text );
249 cursor.setParag( s ); 238 cursor.setParagraph( s );
250 cursor.setIndex( index ); 239 cursor.setIndex( index );
251 if ( c ) { 240 if ( c ) {
252 c->setParag( s ); 241 c->setParagraph( s );
253 c->setIndex( index ); 242 c->setIndex( index );
254 for ( int i = 0; i < (int)text.size(); ++i ) 243 for ( int i = 0; i < (int)text.size(); ++i )
255 c->gotoNextLetter(); 244 c->gotoNextLetter();
256 } 245 }
257 246
258 QValueList< QPtrVector<QStyleSheetItem> >::Iterator it = oldStyles.begin(); 247 if ( !styleInformation.isEmpty() ) {
259 QValueList<QStyleSheetItem::ListStyle>::Iterator lit = oldListStyles.begin(); 248 QDataStream styleStream( styleInformation, IO_ReadOnly );
260 int i = 0; 249 int num;
261 QTextParag *p = s; 250 styleStream >> num;
262 bool end = FALSE; 251 QTextParagraph *p = s;
263 while ( p ) { 252 while ( num-- && p ) {
264 if ( it != oldStyles.end() ) 253 p->readStyleInformation( styleStream );
265 p->setStyleSheetItems( *it ); 254 p = p->next();
266 else 255 }
267 end = TRUE;
268 if ( lit != oldListStyles.end() )
269 p->setListStyle( *lit );
270 else
271 end = TRUE;
272 if ( i < (int)oldAligns.size() )
273 p->setAlignment( oldAligns.at( i ) );
274 else
275 end = TRUE;
276 if ( end )
277 break;
278 p = p->next();
279 ++it;
280 ++lit;
281 ++i;
282 } 256 }
283 257 s = cursor.paragraph();
284 s = cursor.parag();
285 while ( s ) { 258 while ( s ) {
286 s->format(); 259 s->format();
287 s->setChanged( TRUE ); 260 s->setChanged( TRUE );
288 if ( s == c->parag() ) 261 if ( s == c->paragraph() )
289 break; 262 break;
290 s = s->next(); 263 s = s->next();
291 } 264 }
292 265
293 return &cursor; 266 return &cursor;
294} 267}
295 268
296QTextFormatCommand::QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, 269QTextFormatCommand::QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx,
297 const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl ) 270 const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl )
298 : QTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl ) 271 : QTextCommand( d ), startId( sid ), startIndex( sidx ), endId( eid ), endIndex( eidx ), format( f ), oldFormats( old ), flags( fl )
299{ 272{
300 format = d->formatCollection()->format( f ); 273 format = d->formatCollection()->format( f );
301 for ( int j = 0; j < (int)oldFormats.size(); ++j ) { 274 for ( int j = 0; j < (int)oldFormats.size(); ++j ) {
302 if ( oldFormats[ j ].format() ) 275 if ( oldFormats[ j ].format() )
303 oldFormats[ j ].format()->addRef(); 276 oldFormats[ j ].format()->addRef();
304 } 277 }
305} 278}
306 279
307QTextFormatCommand::~QTextFormatCommand() 280QTextFormatCommand::~QTextFormatCommand()
308{ 281{
309 format->removeRef(); 282 format->removeRef();
310 for ( int j = 0; j < (int)oldFormats.size(); ++j ) { 283 for ( int j = 0; j < (int)oldFormats.size(); ++j ) {
311 if ( oldFormats[ j ].format() ) 284 if ( oldFormats[ j ].format() )
312 oldFormats[ j ].format()->removeRef(); 285 oldFormats[ j ].format()->removeRef();
313 } 286 }
314} 287}
315 288
316QTextCursor *QTextFormatCommand::execute( QTextCursor *c ) 289QTextCursor *QTextFormatCommand::execute( QTextCursor *c )
317{ 290{
318 QTextParag *sp = doc->paragAt( startId ); 291 QTextParagraph *sp = doc->paragAt( startId );
319 QTextParag *ep = doc->paragAt( endId ); 292 QTextParagraph *ep = doc->paragAt( endId );
320 if ( !sp || !ep ) 293 if ( !sp || !ep )
321 return c; 294 return c;
322 295
323 QTextCursor start( doc ); 296 QTextCursor start( doc );
324 start.setParag( sp ); 297 start.setParagraph( sp );
325 start.setIndex( startIndex ); 298 start.setIndex( startIndex );
326 QTextCursor end( doc ); 299 QTextCursor end( doc );
327 end.setParag( ep ); 300 end.setParagraph( ep );
328 end.setIndex( endIndex ); 301 end.setIndex( endIndex );
329 302
330 doc->setSelectionStart( QTextDocument::Temp, &start ); 303 doc->setSelectionStart( QTextDocument::Temp, start );
331 doc->setSelectionEnd( QTextDocument::Temp, &end ); 304 doc->setSelectionEnd( QTextDocument::Temp, end );
332 doc->setFormat( QTextDocument::Temp, format, flags ); 305 doc->setFormat( QTextDocument::Temp, format, flags );
333 doc->removeSelection( QTextDocument::Temp ); 306 doc->removeSelection( QTextDocument::Temp );
334 if ( endIndex == ep->length() ) 307 if ( endIndex == ep->length() )
335 end.gotoLeft(); 308 end.gotoLeft();
336 *c = end; 309 *c = end;
337 return c; 310 return c;
338} 311}
339 312
340QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c ) 313QTextCursor *QTextFormatCommand::unexecute( QTextCursor *c )
341{ 314{
342 QTextParag *sp = doc->paragAt( startId ); 315 QTextParagraph *sp = doc->paragAt( startId );
343 QTextParag *ep = doc->paragAt( endId ); 316 QTextParagraph *ep = doc->paragAt( endId );
344 if ( !sp || !ep ) 317 if ( !sp || !ep )
345 return 0; 318 return 0;
346 319
347 int idx = startIndex; 320 int idx = startIndex;
348 int fIndex = 0; 321 int fIndex = 0;
349 for ( ;; ) { 322 for ( ;; ) {
350 if ( oldFormats.at( fIndex ).c == '\n' ) { 323 if ( oldFormats.at( fIndex ).c == '\n' ) {
351 if ( idx > 0 ) { 324 if ( idx > 0 ) {
352 if ( idx < sp->length() && fIndex > 0 ) 325 if ( idx < sp->length() && fIndex > 0 )
353 sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() ); 326 sp->setFormat( idx, 1, oldFormats.at( fIndex - 1 ).format() );
354 if ( sp == ep ) 327 if ( sp == ep )
355 break; 328 break;
356 sp = sp->next(); 329 sp = sp->next();
357 idx = 0; 330 idx = 0;
358 } 331 }
359 fIndex++; 332 fIndex++;
360 } 333 }
361 if ( oldFormats.at( fIndex ).format() ) 334 if ( oldFormats.at( fIndex ).format() )
362 sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() ); 335 sp->setFormat( idx, 1, oldFormats.at( fIndex ).format() );
363 idx++; 336 idx++;
364 fIndex++; 337 fIndex++;
365 if ( fIndex >= (int)oldFormats.size() ) 338 if ( fIndex >= (int)oldFormats.size() )
366 break; 339 break;
367 if ( idx >= sp->length() ) { 340 if ( idx >= sp->length() ) {
368 if ( sp == ep ) 341 if ( sp == ep )
369 break; 342 break;
370 sp = sp->next(); 343 sp = sp->next();
371 idx = 0; 344 idx = 0;
372 } 345 }
373 } 346 }
374 347
375 QTextCursor end( doc ); 348 QTextCursor end( doc );
376 end.setParag( ep ); 349 end.setParagraph( ep );
377 end.setIndex( endIndex ); 350 end.setIndex( endIndex );
378 if ( endIndex == ep->length() ) 351 if ( endIndex == ep->length() )
379 end.gotoLeft(); 352 end.gotoLeft();
380 *c = end; 353 *c = end;
381 return c; 354 return c;
382} 355}
383 356
384QTextAlignmentCommand::QTextAlignmentCommand( QTextDocument *d, int fParag, int lParag, int na, const QMemArray<int> &oa ) 357QTextStyleCommand::QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange )
385 : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), newAlign( na ), oldAligns( oa ) 358 : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), before( beforeChange )
386{ 359{
360 after = readStyleInformation( d, fParag, lParag );
387} 361}
388 362
389QTextCursor *QTextAlignmentCommand::execute( QTextCursor *c ) 363
364QByteArray QTextStyleCommand::readStyleInformation( QTextDocument* doc, int fParag, int lParag )
390{ 365{
391 QTextParag *p = doc->paragAt( firstParag ); 366 QByteArray style;
367 QTextParagraph *p = doc->paragAt( fParag );
392 if ( !p ) 368 if ( !p )
393 return c; 369 return style;
394 while ( p ) { 370 QDataStream styleStream( style, IO_WriteOnly );
395 p->setAlignment( newAlign ); 371 int num = lParag - fParag + 1;
396 if ( p->paragId() == lastParag ) 372 styleStream << num;
397 break; 373 while ( num -- && p ) {
374 p->writeStyleInformation( styleStream );
398 p = p->next(); 375 p = p->next();
399 } 376 }
400 return c; 377 return style;
401} 378}
402 379
403QTextCursor *QTextAlignmentCommand::unexecute( QTextCursor *c ) 380void QTextStyleCommand::writeStyleInformation( QTextDocument* doc, int fParag, const QByteArray& style )
404{ 381{
405 QTextParag *p = doc->paragAt( firstParag ); 382 QTextParagraph *p = doc->paragAt( fParag );
406 if ( !p ) 383 if ( !p )
407 return c; 384 return;
408 int i = 0; 385 QDataStream styleStream( style, IO_ReadOnly );
409 while ( p ) { 386 int num;
410 if ( i < (int)oldAligns.size() ) 387 styleStream >> num;
411 p->setAlignment( oldAligns.at( i ) ); 388 while ( num-- && p ) {
412 if ( p->paragId() == lastParag ) 389 p->readStyleInformation( styleStream );
413 break;
414 p = p->next(); 390 p = p->next();
415 ++i;
416 } 391 }
417 return c;
418}
419
420QTextParagTypeCommand::QTextParagTypeCommand( QTextDocument *d, int fParag, int lParag, bool l,
421 QStyleSheetItem::ListStyle s, const QValueList< QPtrVector<QStyleSheetItem> > &os,
422 const QValueList<QStyleSheetItem::ListStyle> &ols )
423 : QTextCommand( d ), firstParag( fParag ), lastParag( lParag ), list( l ), listStyle( s ), oldStyles( os ), oldListStyles( ols )
424{
425} 392}
426 393
427QTextCursor *QTextParagTypeCommand::execute( QTextCursor *c ) 394QTextCursor *QTextStyleCommand::execute( QTextCursor *c )
428{ 395{
429 QTextParag *p = doc->paragAt( firstParag ); 396 writeStyleInformation( doc, firstParag, after );
430 if ( !p )
431 return c;
432 while ( p ) {
433 p->setList( list, (int)listStyle );
434 if ( p->paragId() == lastParag )
435 break;
436 p = p->next();
437 }
438 return c; 397 return c;
439} 398}
440 399
441QTextCursor *QTextParagTypeCommand::unexecute( QTextCursor *c ) 400QTextCursor *QTextStyleCommand::unexecute( QTextCursor *c )
442{ 401{
443 QTextParag *p = doc->paragAt( firstParag ); 402 writeStyleInformation( doc, firstParag, before );
444 if ( !p )
445 return c;
446 QValueList< QPtrVector<QStyleSheetItem> >::Iterator it = oldStyles.begin();
447 QValueList<QStyleSheetItem::ListStyle>::Iterator lit = oldListStyles.begin();
448 while ( p ) {
449 if ( it != oldStyles.end() )
450 p->setStyleSheetItems( *it );
451 if ( lit != oldListStyles.end() )
452 p->setListStyle( *lit );
453 if ( p->paragId() == lastParag )
454 break;
455 p = p->next();
456 ++it;
457 ++lit;
458 }
459 return c; 403 return c;
460} 404}
461 405
462// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 406// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
463 407
464QTextCursor::QTextCursor( QTextDocument *d ) 408QTextCursor::QTextCursor( QTextDocument *d )
465 : doc( d ), ox( 0 ), oy( 0 ) 409 : idx( 0 ), tmpIndex( -1 ), ox( 0 ), oy( 0 ),
466{ 410 valid( TRUE )
467 nested = FALSE;
468 idx = 0;
469 string = doc ? doc->firstParag() : 0;
470 tmpIndex = -1;
471 valid = TRUE;
472}
473
474QTextCursor::QTextCursor()
475{ 411{
412 para = d ? d->firstParagraph() : 0;
476} 413}
477 414
478QTextCursor::QTextCursor( const QTextCursor &c ) 415QTextCursor::QTextCursor( const QTextCursor &c )
479{ 416{
480 doc = c.doc;
481 ox = c.ox; 417 ox = c.ox;
482 oy = c.oy; 418 oy = c.oy;
483 nested = c.nested;
484 idx = c.idx; 419 idx = c.idx;
485 string = c.string; 420 para = c.para;
486 tmpIndex = c.tmpIndex; 421 tmpIndex = c.tmpIndex;
487 indices = c.indices; 422 indices = c.indices;
488 parags = c.parags; 423 paras = c.paras;
489 xOffsets = c.xOffsets; 424 xOffsets = c.xOffsets;
490 yOffsets = c.yOffsets; 425 yOffsets = c.yOffsets;
491 valid = c.valid; 426 valid = c.valid;
492} 427}
493 428
494QTextCursor &QTextCursor::operator=( const QTextCursor &c ) 429QTextCursor &QTextCursor::operator=( const QTextCursor &c )
495{ 430{
496 doc = c.doc;
497 ox = c.ox; 431 ox = c.ox;
498 oy = c.oy; 432 oy = c.oy;
499 nested = c.nested;
500 idx = c.idx; 433 idx = c.idx;
501 string = c.string; 434 para = c.para;
502 tmpIndex = c.tmpIndex; 435 tmpIndex = c.tmpIndex;
503 indices = c.indices; 436 indices = c.indices;
504 parags = c.parags; 437 paras = c.paras;
505 xOffsets = c.xOffsets; 438 xOffsets = c.xOffsets;
506 yOffsets = c.yOffsets; 439 yOffsets = c.yOffsets;
507 valid = c.valid; 440 valid = c.valid;
508 441
509 return *this; 442 return *this;
510} 443}
511 444
512bool QTextCursor::operator==( const QTextCursor &c ) const 445bool QTextCursor::operator==( const QTextCursor &c ) const
513{ 446{
514 return doc == c.doc && string == c.string && idx == c.idx; 447 return para == c.para && idx == c.idx;
515} 448}
516 449
517int QTextCursor::totalOffsetX() const 450int QTextCursor::totalOffsetX() const
518{ 451{
519 if ( !nested )
520 return 0;
521 QValueStack<int>::ConstIterator xit = xOffsets.begin();
522 int xoff = ox; 452 int xoff = ox;
523 for ( ; xit != xOffsets.end(); ++xit ) 453 for ( QValueStack<int>::ConstIterator xit = xOffsets.begin(); xit != xOffsets.end(); ++xit )
524 xoff += *xit; 454 xoff += *xit;
525 return xoff; 455 return xoff;
526} 456}
527 457
528int QTextCursor::totalOffsetY() const 458int QTextCursor::totalOffsetY() const
529{ 459{
530 if ( !nested )
531 return 0;
532 QValueStack<int>::ConstIterator yit = yOffsets.begin();
533 int yoff = oy; 460 int yoff = oy;
534 for ( ; yit != yOffsets.end(); ++yit ) 461 for ( QValueStack<int>::ConstIterator yit = yOffsets.begin(); yit != yOffsets.end(); ++yit )
535 yoff += *yit; 462 yoff += *yit;
536 return yoff; 463 return yoff;
537} 464}
538 465
539void QTextCursor::gotoIntoNested( const QPoint &globalPos ) 466void QTextCursor::gotoIntoNested( const QPoint &globalPos )
540{ 467{
541 if ( !doc ) 468 if ( !para )
542 return; 469 return;
543 push(); 470 push();
544 ox = 0; 471 ox = 0;
545 int bl, y; 472 int bl, y;
546 string->lineHeightOfChar( idx, &bl, &y ); 473 para->lineHeightOfChar( idx, &bl, &y );
547 oy = y + string->rect().y(); 474 oy = y + para->rect().y();
548 nested = TRUE;
549 QPoint p( globalPos.x() - offsetX(), globalPos.y() - offsetY() ); 475 QPoint p( globalPos.x() - offsetX(), globalPos.y() - offsetY() );
550 Q_ASSERT( string->at( idx )->isCustom() ); 476 Q_ASSERT( para->at( idx )->isCustom() );
551 ox = string->at( idx )->x; 477 ox = para->at( idx )->x;
552 string->at( idx )->customItem()->enterAt( this, doc, string, idx, ox, oy, p ); 478
479 QTextDocument* doc = document();
480 para->at( idx )->customItem()->enterAt( this, doc, para, idx, ox, oy, p );
553} 481}
554 482
555void QTextCursor::invalidateNested() 483void QTextCursor::invalidateNested()
556{ 484{
557 if ( nested ) { 485 QValueStack<QTextParagraph*>::Iterator it = paras.begin();
558 QValueStack<QTextParag*>::Iterator it = parags.begin(); 486 QValueStack<int>::Iterator it2 = indices.begin();
559 QValueStack<int>::Iterator it2 = indices.begin(); 487 for ( ; it != paras.end(); ++it, ++it2 ) {
560 for ( ; it != parags.end(); ++it, ++it2 ) { 488 if ( *it == para )
561 if ( *it == string ) 489 continue;
562 continue; 490 (*it)->invalidate( 0 );
563 (*it)->invalidate( 0 ); 491 if ( (*it)->at( *it2 )->isCustom() )
564 if ( (*it)->at( *it2 )->isCustom() ) 492 (*it)->at( *it2 )->customItem()->invalidate();
565 (*it)->at( *it2 )->customItem()->invalidate();
566 }
567 } 493 }
568} 494}
569 495
570void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting ) 496void QTextCursor::insert( const QString &str, bool checkNewLine, QMemArray<QTextStringChar> *formatting )
571{ 497{
572 tmpIndex = -1; 498 tmpIndex = -1;
573 bool justInsert = TRUE; 499 bool justInsert = TRUE;
574 QString s( str ); 500 QString s( str );
575#if defined(Q_WS_WIN) 501#if defined(Q_WS_WIN)
576 if ( checkNewLine ) 502 if ( checkNewLine ) {
577 s = s.replace( QRegExp( "\\r" ), "" ); 503 int i = 0;
504 while ( ( i = s.find( '\r', i ) ) != -1 )
505 s.remove( i ,1 );
506 }
578#endif 507#endif
579 if ( checkNewLine ) 508 if ( checkNewLine )
580 justInsert = s.find( '\n' ) == -1; 509 justInsert = s.find( '\n' ) == -1;
581 if ( justInsert ) { 510 if ( justInsert ) { // we ignore new lines and insert all in the current para at the current index
582 string->insert( idx, s ); 511 para->insert( idx, s.unicode(), s.length() );
583 if ( formatting ) { 512 if ( formatting ) {
584 for ( int i = 0; i < (int)s.length(); ++i ) { 513 for ( int i = 0; i < (int)s.length(); ++i ) {
585 if ( formatting->at( i ).format() ) { 514 if ( formatting->at( i ).format() ) {
586 formatting->at( i ).format()->addRef(); 515 formatting->at( i ).format()->addRef();
587 string->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE ); 516 para->string()->setFormat( idx + i, formatting->at( i ).format(), TRUE );
588 } 517 }
589 } 518 }
590 } 519 }
591 idx += s.length(); 520 idx += s.length();
592 } else { 521 } else { // we split at new lines
593 QStringList lst = QStringList::split( '\n', s, TRUE ); 522 int start = -1;
594 QStringList::Iterator it = lst.begin(); 523 int end;
595 int y = string->rect().y() + string->rect().height(); 524 int y = para->rect().y() + para->rect().height();
596 int lastIndex = 0; 525 int lastIndex = 0;
597 QTextFormat *lastFormat = 0; 526 do {
598 for ( ; it != lst.end(); ) { 527 end = s.find( '\n', start + 1 ); // find line break
599 if ( it != lst.begin() ) { 528 if ( end == -1 ) // didn't find one, so end of line is end of string
600 splitAndInsertEmptyParag( FALSE, TRUE ); 529 end = s.length();
601 string->setEndState( -1 ); 530 int len = (start == -1 ? end : end - start - 1);
602 string->prev()->format( -1, FALSE ); 531 if ( len > 0 ) // insert the line
603 if ( lastFormat && formatting && string->prev() ) { 532 para->insert( idx, s.unicode() + start + 1, len );
604 lastFormat->addRef();
605 string->prev()->string()->setFormat( string->prev()->length() - 1, lastFormat, TRUE );
606 }
607 }
608 lastFormat = 0;
609 QString s = *it;
610 ++it;
611 if ( !s.isEmpty() )
612 string->insert( idx, s );
613 else 533 else
614 string->invalidate( 0 ); 534 para->invalidate( 0 );
615 if ( formatting ) { 535 if ( formatting ) { // set formats to the chars of the line
616 int len = s.length();
617 for ( int i = 0; i < len; ++i ) { 536 for ( int i = 0; i < len; ++i ) {
618 if ( formatting->at( i + lastIndex ).format() ) { 537 if ( formatting->at( i + lastIndex ).format() ) {
619 formatting->at( i + lastIndex ).format()->addRef(); 538 formatting->at( i + lastIndex ).format()->addRef();
620 string->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE ); 539 para->string()->setFormat( i + idx, formatting->at( i + lastIndex ).format(), TRUE );
621 } 540 }
622 } 541 }
623 if ( it != lst.end() )
624 lastFormat = formatting->at( len + lastIndex ).format();
625 ++len;
626 lastIndex += len; 542 lastIndex += len;
627 } 543 }
544 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
546 if ( s[end] == '\n' ) { // if at the end was a line break, break the line
547 splitAndInsertEmptyParagraph( FALSE, TRUE );
548 para->setEndState( -1 );
549 para->prev()->format( -1, FALSE );
550 lastIndex++;
551 }
628 552
629 idx += s.length(); 553 } while ( end < (int)s.length() );
630 } 554
631 string->format( -1, FALSE ); 555 para->format( -1, FALSE );
632 int dy = string->rect().y() + string->rect().height() - y; 556 int dy = para->rect().y() + para->rect().height() - y;
633 QTextParag *p = string; 557 QTextParagraph *p = para;
634 p->setParagId( p->prev()->paragId() + 1 ); 558 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 );
635 p = p->next(); 559 p = p->next();
636 while ( p ) { 560 while ( p ) {
637 p->setParagId( p->prev()->paragId() + 1 ); 561 p->setParagId( p->prev()->paragId() + 1 );
638 p->move( dy ); 562 p->move( dy );
639 p->invalidate( 0 ); 563 p->invalidate( 0 );
640 p->setEndState( -1 ); 564 p->setEndState( -1 );
641 p = p->next(); 565 p = p->next();
642 } 566 }
643 } 567 }
644 568
645 int h = string->rect().height(); 569 int h = para->rect().height();
646 string->format( -1, TRUE ); 570 para->format( -1, TRUE );
647 if ( h != string->rect().height() ) 571 if ( h != para->rect().height() )
648 invalidateNested(); 572 invalidateNested();
649 else if ( doc && doc->parent() ) 573 else if ( para->document() && para->document()->parent() )
650 doc->nextDoubleBuffered = TRUE; 574 para->document()->nextDoubleBuffered = TRUE;
651} 575}
652 576
653void QTextCursor::gotoLeft() 577void QTextCursor::gotoLeft()
654{ 578{
655 if ( string->string()->isRightToLeft() ) 579 if ( para->string()->isRightToLeft() )
656 gotoNextLetter(); 580 gotoNextLetter();
657 else 581 else
658 gotoPreviousLetter(); 582 gotoPreviousLetter();
659} 583}
660 584
661void QTextCursor::gotoPreviousLetter() 585void QTextCursor::gotoPreviousLetter()
662{ 586{
663 tmpIndex = -1; 587 tmpIndex = -1;
664 588
665 if ( idx > 0 ) { 589 if ( idx > 0 ) {
666 idx--; 590 idx--;
667 } else if ( string->prev() ) { 591 const QTextStringChar *tsc = para->at( idx );
668 QTextParag *s = string->prev(); 592 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() )
669 while ( s && !s->isVisible() ) 593 processNesting( EnterEnd );
670 s = s->prev(); 594 } else if ( para->prev() ) {
671 if ( s ) { 595 para = para->prev();
672 string = s; 596 while ( !para->isVisible() && para->prev() )
673 idx = string->length() - 1; 597 para = para->prev();
674 } 598 idx = para->length() - 1;
675 } else { 599 } else if ( nestedDepth() ) {
676 if ( nested ) { 600 pop();
601 processNesting( Prev );
602 if ( idx == -1 ) {
677 pop(); 603 pop();
678 processNesting( Prev ); 604 if ( idx > 0 ) {
679 if ( idx == -1 ) { 605 idx--;
680 pop(); 606 } else if ( para->prev() ) {
681 if ( idx > 0 ) { 607 para = para->prev();
682 idx--; 608 idx = para->length() - 1;
683 } else if ( string->prev() ) {
684 string = string->prev();
685 idx = string->length() - 1;
686 }
687 } 609 }
688 } 610 }
689 } 611 }
690
691 const QTextStringChar *tsc = string->at( idx );
692 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) {
693 processNesting( EnterEnd );
694 }
695} 612}
696 613
697void QTextCursor::push() 614void QTextCursor::push()
698{ 615{
699 indices.push( idx ); 616 indices.push( idx );
700 parags.push( string ); 617 paras.push( para );
701 xOffsets.push( ox ); 618 xOffsets.push( ox );
702 yOffsets.push( oy ); 619 yOffsets.push( oy );
703 nestedStack.push( nested );
704} 620}
705 621
706void QTextCursor::pop() 622void QTextCursor::pop()
707{ 623{
708 if ( !doc ) 624 if ( indices.isEmpty() )
709 return; 625 return;
710 idx = indices.pop(); 626 idx = indices.pop();
711 string = parags.pop(); 627 para = paras.pop();
712 ox = xOffsets.pop(); 628 ox = xOffsets.pop();
713 oy = yOffsets.pop(); 629 oy = yOffsets.pop();
714 if ( doc->parent() )
715 doc = doc->parent();
716 nested = nestedStack.pop();
717} 630}
718 631
719void QTextCursor::restoreState() 632void QTextCursor::restoreState()
720{ 633{
721 while ( !indices.isEmpty() ) 634 while ( !indices.isEmpty() )
722 pop(); 635 pop();
723} 636}
724 637
725bool QTextCursor::place( const QPoint &p, QTextParag *s, bool link ) 638bool QTextCursor::place( const QPoint &p, QTextParagraph *s, bool link )
726{ 639{
727 QPoint pos( p ); 640 QPoint pos( p );
728 QRect r; 641 QRect r;
729 QTextParag *str = s; 642 QTextParagraph *str = s;
730 if ( pos.y() < s->rect().y() ) 643 if ( pos.y() < s->rect().y() )
731 pos.setY( s->rect().y() ); 644 pos.setY( s->rect().y() );
732 while ( s ) { 645 while ( s ) {
733 r = s->rect(); 646 r = s->rect();
734 r.setWidth( doc ? doc->width() : QWIDGETSIZE_MAX ); 647 r.setWidth( document() ? document()->width() : QWIDGETSIZE_MAX );
735 if ( s->isVisible() ) 648 if ( s->isVisible() )
736 str = s; 649 str = s;
737 if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() || !s->next() ) 650 if ( pos.y() >= r.y() && pos.y() <= r.y() + r.height() || !s->next() )
738 break; 651 break;
739 s = s->next(); 652 s = s->next();
740 } 653 }
741 654
742 if ( !s || !str ) 655 if ( !s || !str )
743 return FALSE; 656 return FALSE;
744 657
745 s = str; 658 s = str;
746 659
747 setParag( s, FALSE ); 660 setParagraph( s );
748 int y = s->rect().y(); 661 int y = s->rect().y();
749 int lines = s->lines(); 662 int lines = s->lines();
750 QTextStringChar *chr = 0; 663 QTextStringChar *chr = 0;
751 int index = 0; 664 int index = 0;
752 int i = 0; 665 int i = 0;
753 int cy = 0; 666 int cy = 0;
754 int ch = 0; 667 int ch = 0;
755 for ( ; i < lines; ++i ) { 668 for ( ; i < lines; ++i ) {
756 chr = s->lineStartOfLine( i, &index ); 669 chr = s->lineStartOfLine( i, &index );
757 cy = s->lineY( i ); 670 cy = s->lineY( i );
758 ch = s->lineHeight( i ); 671 ch = s->lineHeight( i );
759 if ( !chr ) 672 if ( !chr )
760 return FALSE; 673 return FALSE;
761 if ( pos.y() >= y + cy && pos.y() <= y + cy + ch ) 674 if ( pos.y() <= y + cy + ch )
762 break; 675 break;
763 } 676 }
764 int nextLine; 677 int nextLine;
765 if ( i < lines - 1 ) 678 if ( i < lines - 1 )
766 s->lineStartOfLine( i+1, &nextLine ); 679 s->lineStartOfLine( i+1, &nextLine );
767 else 680 else
768 nextLine = s->length(); 681 nextLine = s->length();
769 i = index; 682 i = index;
770 int x = s->rect().x(); 683 int x = s->rect().x();
771 if ( pos.x() < x ) 684 if ( pos.x() < x )
772 pos.setX( x + 1 ); 685 pos.setX( x + 1 );
773 int cw; 686 int cw;
774 int curpos = s->length()-1; 687 int curpos = s->length()-1;
775 int dist = 10000000; 688 int dist = 10000000;
776 bool inCustom = FALSE; 689 bool inCustom = FALSE;
777 while ( i < nextLine ) { 690 while ( i < nextLine ) {
778 chr = s->at(i); 691 chr = s->at(i);
779 int cpos = x + chr->x; 692 int cpos = x + chr->x;
780 cw = s->string()->width( i ); 693 cw = s->string()->width( i );
781 if ( chr->isCustom() && chr->customItem()->isNested() ) { 694 if ( chr->isCustom() && chr->customItem()->isNested() ) {
782 if ( pos.x() >= cpos && pos.x() <= cpos + cw && 695 if ( pos.x() >= cpos && pos.x() <= cpos + cw &&
783 pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) { 696 pos.y() >= y + cy && pos.y() <= y + cy + chr->height() ) {
784 inCustom = TRUE; 697 inCustom = TRUE;
785 curpos = i; 698 curpos = i;
786 break; 699 break;
787 } 700 }
788 } else { 701 } else {
789 if( chr->rightToLeft ) 702 if( chr->rightToLeft )
790 cpos += cw; 703 cpos += cw;
791 int d = cpos - pos.x(); 704 int d = cpos - pos.x();
792 bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft; 705 bool dm = d < 0 ? !chr->rightToLeft : chr->rightToLeft;
793 if ( QABS( d ) < dist || (dist == d && dm == TRUE ) ) { 706 if ( QABS( d ) < dist || (dist == d && dm == TRUE ) ) {
794 dist = QABS( d ); 707 dist = QABS( d );
795 if ( !link || pos.x() >= x + chr->x ) 708 if ( !link || pos.x() >= x + chr->x )
796 curpos = i; 709 curpos = i;
797 } 710 }
798 } 711 }
799 i++; 712 i++;
800 } 713 }
801 setIndex( curpos, FALSE ); 714 setIndex( curpos );
802 715
803 if ( inCustom && doc && parag()->at( curpos )->isCustom() && parag()->at( curpos )->customItem()->isNested() ) { 716 if ( inCustom && para->document() && para->at( curpos )->isCustom() && para->at( curpos )->customItem()->isNested() ) {
804 QTextDocument *oldDoc = doc; 717 QTextDocument *oldDoc = para->document();
805 gotoIntoNested( pos ); 718 gotoIntoNested( pos );
806 if ( oldDoc == doc ) 719 if ( oldDoc == para->document() )
807 return TRUE; 720 return TRUE;
808 QPoint p( pos.x() - offsetX(), pos.y() - offsetY() ); 721 QPoint p( pos.x() - offsetX(), pos.y() - offsetY() );
809 if ( !place( p, document()->firstParag(), link ) ) 722 if ( !place( p, document()->firstParagraph(), link ) )
810 pop(); 723 pop();
811 } 724 }
812 return TRUE; 725 return TRUE;
813} 726}
814 727
815void QTextCursor::processNesting( Operation op ) 728void QTextCursor::processNesting( Operation op )
816{ 729{
817 if ( !doc ) 730 if ( !para->document() )
818 return; 731 return;
732 QTextDocument* doc = para->document();
819 push(); 733 push();
820 ox = string->at( idx )->x; 734 ox = para->at( idx )->x;
821 int bl, y; 735 int bl, y;
822 string->lineHeightOfChar( idx, &bl, &y ); 736 para->lineHeightOfChar( idx, &bl, &y );
823 oy = y + string->rect().y(); 737 oy = y + para->rect().y();
824 nested = TRUE;
825 bool ok = FALSE; 738 bool ok = FALSE;
826 739
827 switch ( op ) { 740 switch ( op ) {
828 case EnterBegin: 741 case EnterBegin:
829 ok = string->at( idx )->customItem()->enter( this, doc, string, idx, ox, oy ); 742 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy );
830 break; 743 break;
831 case EnterEnd: 744 case EnterEnd:
832 ok = string->at( idx )->customItem()->enter( this, doc, string, idx, ox, oy, TRUE ); 745 ok = para->at( idx )->customItem()->enter( this, doc, para, idx, ox, oy, TRUE );
833 break; 746 break;
834 case Next: 747 case Next:
835 ok = string->at( idx )->customItem()->next( this, doc, string, idx, ox, oy ); 748 ok = para->at( idx )->customItem()->next( this, doc, para, idx, ox, oy );
836 break; 749 break;
837 case Prev: 750 case Prev:
838 ok = string->at( idx )->customItem()->prev( this, doc, string, idx, ox, oy ); 751 ok = para->at( idx )->customItem()->prev( this, doc, para, idx, ox, oy );
839 break; 752 break;
840 case Down: 753 case Down:
841 ok = string->at( idx )->customItem()->down( this, doc, string, idx, ox, oy ); 754 ok = para->at( idx )->customItem()->down( this, doc, para, idx, ox, oy );
842 break; 755 break;
843 case Up: 756 case Up:
844 ok = string->at( idx )->customItem()->up( this, doc, string, idx, ox, oy ); 757 ok = para->at( idx )->customItem()->up( this, doc, para, idx, ox, oy );
845 break; 758 break;
846 } 759 }
847 if ( !ok ) 760 if ( !ok )
848 pop(); 761 pop();
849} 762}
850 763
851void QTextCursor::gotoRight() 764void QTextCursor::gotoRight()
852{ 765{
853 if ( string->string()->isRightToLeft() ) 766 if ( para->string()->isRightToLeft() )
854 gotoPreviousLetter(); 767 gotoPreviousLetter();
855 else 768 else
856 gotoNextLetter(); 769 gotoNextLetter();
857} 770}
858 771
859void QTextCursor::gotoNextLetter() 772void QTextCursor::gotoNextLetter()
860{ 773{
861 tmpIndex = -1; 774 tmpIndex = -1;
862 775
863 const QTextStringChar *tsc = string->at( idx ); 776 const QTextStringChar *tsc = para->at( idx );
864 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) { 777 if ( tsc && tsc->isCustom() && tsc->customItem()->isNested() ) {
865 processNesting( EnterBegin ); 778 processNesting( EnterBegin );
866 return; 779 return;
867 } 780 }
868 781
869 if ( idx < string->length() - 1 ) { 782 if ( idx < para->length() - 1 ) {
870 idx++; 783 idx++;
871 } else if ( string->next() ) { 784 } else if ( para->next() ) {
872 QTextParag *s = string->next(); 785 para = para->next();
873 while ( s && !s->isVisible() ) 786 while ( !para->isVisible() && para->next() )
874 s = s->next(); 787 para = para->next();
875 if ( s ) { 788 idx = 0;
876 string = s; 789 } else if ( nestedDepth() ) {
877 idx = 0; 790 pop();
878 } 791 processNesting( Next );
879 } else { 792 if ( idx == -1 ) {
880 if ( nested ) {
881 pop(); 793 pop();
882 processNesting( Next ); 794 if ( idx < para->length() - 1 ) {
883 if ( idx == -1 ) { 795 idx++;
884 pop(); 796 } else if ( para->next() ) {
885 if ( idx < string->length() - 1 ) { 797 para = para->next();
886 idx++; 798 idx = 0;
887 } else if ( string->next() ) {
888 string = string->next();
889 idx = 0;
890 }
891 } 799 }
892 } 800 }
893 } 801 }
894} 802}
895 803
896void QTextCursor::gotoUp() 804void QTextCursor::gotoUp()
897{ 805{
898 int indexOfLineStart; 806 int indexOfLineStart;
899 int line; 807 int line;
900 QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); 808 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
901 if ( !c ) 809 if ( !c )
902 return; 810 return;
903 811
904 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); 812 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart );
905 if ( indexOfLineStart == 0 ) { 813 if ( indexOfLineStart == 0 ) {
906 if ( !string->prev() ) { 814 if ( !para->prev() ) {
907 if ( !nested ) 815 if ( !nestedDepth() )
908 return; 816 return;
909 pop(); 817 pop();
910 processNesting( Up ); 818 processNesting( Up );
911 if ( idx == -1 ) { 819 if ( idx == -1 ) {
912 pop(); 820 pop();
913 if ( !string->prev() ) 821 if ( !para->prev() )
914 return; 822 return;
915 idx = tmpIndex = 0; 823 idx = tmpIndex = 0;
916 } else { 824 } else {
917 tmpIndex = -1; 825 tmpIndex = -1;
918 return; 826 return;
919 } 827 }
920 } 828 }
921 QTextParag *s = string->prev(); 829 QTextParagraph *p = para->prev();
922 while ( s && !s->isVisible() ) 830 while ( p && !p->isVisible() )
923 s = s->prev(); 831 p = p->prev();
924 if ( s ) 832 if ( p )
925 string = s; 833 para = p;
926 int lastLine = string->lines() - 1; 834 int lastLine = para->lines() - 1;
927 if ( !string->lineStartOfLine( lastLine, &indexOfLineStart ) ) 835 if ( !para->lineStartOfLine( lastLine, &indexOfLineStart ) )
928 return; 836 return;
929 if ( indexOfLineStart + tmpIndex < string->length() ) 837 if ( indexOfLineStart + tmpIndex < para->length() )
930 idx = indexOfLineStart + tmpIndex; 838 idx = indexOfLineStart + tmpIndex;
931 else 839 else
932 idx = string->length() - 1; 840 idx = para->length() - 1;
933 } else { 841 } else {
934 --line; 842 --line;
935 int oldIndexOfLineStart = indexOfLineStart; 843 int oldIndexOfLineStart = indexOfLineStart;
936 if ( !string->lineStartOfLine( line, &indexOfLineStart ) ) 844 if ( !para->lineStartOfLine( line, &indexOfLineStart ) )
937 return; 845 return;
938 if ( indexOfLineStart + tmpIndex < oldIndexOfLineStart ) 846 if ( indexOfLineStart + tmpIndex < oldIndexOfLineStart )
939 idx = indexOfLineStart + tmpIndex; 847 idx = indexOfLineStart + tmpIndex;
940 else 848 else
941 idx = oldIndexOfLineStart - 1; 849 idx = oldIndexOfLineStart - 1;
942 } 850 }
943} 851}
944 852
945void QTextCursor::gotoDown() 853void QTextCursor::gotoDown()
946{ 854{
947 int indexOfLineStart; 855 int indexOfLineStart;
948 int line; 856 int line;
949 QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); 857 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
950 if ( !c ) 858 if ( !c )
951 return; 859 return;
952 860
953 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart ); 861 tmpIndex = QMAX( tmpIndex, idx - indexOfLineStart );
954 if ( line == string->lines() - 1 ) { 862 if ( line == para->lines() - 1 ) {
955 if ( !string->next() ) { 863 if ( !para->next() ) {
956 if ( !nested ) 864 if ( !nestedDepth() )
957 return; 865 return;
958 pop(); 866 pop();
959 processNesting( Down ); 867 processNesting( Down );
960 if ( idx == -1 ) { 868 if ( idx == -1 ) {
961 pop(); 869 pop();
962 if ( !string->next() ) 870 if ( !para->next() )
963 return; 871 return;
964 idx = tmpIndex = 0; 872 idx = tmpIndex = 0;
965 } else { 873 } else {
966 tmpIndex = -1; 874 tmpIndex = -1;
967 return; 875 return;
968 } 876 }
969 } 877 }
970 QTextParag *s = string->next(); 878 QTextParagraph *s = para->next();
971 while ( s && !s->isVisible() ) 879 while ( s && !s->isVisible() )
972 s = s->next(); 880 s = s->next();
973 if ( s ) 881 if ( s )
974 string = s; 882 para = s;
975 if ( !string->lineStartOfLine( 0, &indexOfLineStart ) ) 883 if ( !para->lineStartOfLine( 0, &indexOfLineStart ) )
976 return; 884 return;
977 int end; 885 int end;
978 if ( string->lines() == 1 ) 886 if ( para->lines() == 1 )
979 end = string->length(); 887 end = para->length();
980 else 888 else
981 string->lineStartOfLine( 1, &end ); 889 para->lineStartOfLine( 1, &end );
982 if ( indexOfLineStart + tmpIndex < end ) 890 if ( indexOfLineStart + tmpIndex < end )
983 idx = indexOfLineStart + tmpIndex; 891 idx = indexOfLineStart + tmpIndex;
984 else 892 else
985 idx = end - 1; 893 idx = end - 1;
986 } else { 894 } else {
987 ++line; 895 ++line;
988 int end; 896 int end;
989 if ( line == string->lines() - 1 ) 897 if ( line == para->lines() - 1 )
990 end = string->length(); 898 end = para->length();
991 else 899 else
992 string->lineStartOfLine( line + 1, &end ); 900 para->lineStartOfLine( line + 1, &end );
993 if ( !string->lineStartOfLine( line, &indexOfLineStart ) ) 901 if ( !para->lineStartOfLine( line, &indexOfLineStart ) )
994 return; 902 return;
995 if ( indexOfLineStart + tmpIndex < end ) 903 if ( indexOfLineStart + tmpIndex < end )
996 idx = indexOfLineStart + tmpIndex; 904 idx = indexOfLineStart + tmpIndex;
997 else 905 else
998 idx = end - 1; 906 idx = end - 1;
999 } 907 }
1000} 908}
1001 909
1002void QTextCursor::gotoLineEnd() 910void QTextCursor::gotoLineEnd()
1003{ 911{
1004 tmpIndex = -1; 912 tmpIndex = -1;
1005 int indexOfLineStart; 913 int indexOfLineStart;
1006 int line; 914 int line;
1007 QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); 915 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
1008 if ( !c ) 916 if ( !c )
1009 return; 917 return;
1010 918
1011 if ( line == string->lines() - 1 ) { 919 if ( line == para->lines() - 1 ) {
1012 idx = string->length() - 1; 920 idx = para->length() - 1;
1013 } else { 921 } else {
1014 c = string->lineStartOfLine( ++line, &indexOfLineStart ); 922 c = para->lineStartOfLine( ++line, &indexOfLineStart );
1015 indexOfLineStart--; 923 indexOfLineStart--;
1016 idx = indexOfLineStart; 924 idx = indexOfLineStart;
1017 } 925 }
1018} 926}
1019 927
1020void QTextCursor::gotoLineStart() 928void QTextCursor::gotoLineStart()
1021{ 929{
1022 tmpIndex = -1; 930 tmpIndex = -1;
1023 int indexOfLineStart; 931 int indexOfLineStart;
1024 int line; 932 int line;
1025 QTextStringChar *c = string->lineStartOfChar( idx, &indexOfLineStart, &line ); 933 QTextStringChar *c = para->lineStartOfChar( idx, &indexOfLineStart, &line );
1026 if ( !c ) 934 if ( !c )
1027 return; 935 return;
1028 936
1029 idx = indexOfLineStart; 937 idx = indexOfLineStart;
1030} 938}
1031 939
1032void QTextCursor::gotoHome() 940void QTextCursor::gotoHome()
1033{ 941{
1034 tmpIndex = -1; 942 if ( topParagraph()->document() )
1035 if ( doc ) 943 gotoPosition( topParagraph()->document()->firstParagraph() );
1036 string = doc->firstParag(); 944 else
1037 idx = 0; 945 gotoLineStart();
1038} 946}
1039 947
1040void QTextCursor::gotoEnd() 948void QTextCursor::gotoEnd()
1041{ 949{
1042 if ( doc && !doc->lastParag()->isValid() ) 950 if ( topParagraph()->document() && topParagraph()->document()->lastParagraph()->isValid() )
1043 return; 951 gotoPosition( topParagraph()->document()->lastParagraph(),
1044 952 topParagraph()->document()->lastParagraph()->length() - 1);
1045 tmpIndex = -1; 953 else
1046 if ( doc ) 954 gotoLineEnd();
1047 string = doc->lastParag();
1048 idx = string->length() - 1;
1049} 955}
1050 956
1051void QTextCursor::gotoPageUp( int visibleHeight ) 957void QTextCursor::gotoPageUp( int visibleHeight )
1052{ 958{
1053 tmpIndex = -1; 959 int targetY = globalY() - visibleHeight;
1054 QTextParag *s = string; 960 QTextParagraph* old; int index;
1055 int h = visibleHeight; 961 do {
1056 int y = s->rect().y(); 962 old = para; index = idx;
1057 while ( s ) { 963 gotoUp();
1058 if ( y - s->rect().y() >= h ) 964 } while ( (old != para || index != idx) && globalY() > targetY );
1059 break;
1060 s = s->prev();
1061 }
1062
1063 if ( !s && doc )
1064 s = doc->firstParag();
1065
1066 string = s;
1067 idx = 0;
1068} 965}
1069 966
1070void QTextCursor::gotoPageDown( int visibleHeight ) 967void QTextCursor::gotoPageDown( int visibleHeight )
1071{ 968{
1072 tmpIndex = -1; 969 int targetY = globalY() + visibleHeight;
1073 QTextParag *s = string; 970 QTextParagraph* old; int index;
1074 int h = visibleHeight; 971 do {
1075 int y = s->rect().y(); 972 old = para; index = idx;
1076 while ( s ) { 973 gotoDown();
1077 if ( s->rect().y() - y >= h ) 974 } while ( (old != para || index != idx) && globalY() < targetY );
1078 break;
1079 s = s->next();
1080 }
1081
1082 if ( !s && doc ) {
1083 s = doc->lastParag();
1084 string = s;
1085 idx = string->length() - 1;
1086 return;
1087 }
1088
1089 if ( !s->isValid() )
1090 return;
1091
1092 string = s;
1093 idx = 0;
1094} 975}
1095 976
1096void QTextCursor::gotoWordRight() 977void QTextCursor::gotoWordRight()
1097{ 978{
1098 if ( string->string()->isRightToLeft() ) 979 if ( para->string()->isRightToLeft() )
1099 gotoPreviousWord(); 980 gotoPreviousWord();
1100 else 981 else
1101 gotoNextWord(); 982 gotoNextWord();
1102} 983}
1103 984
1104void QTextCursor::gotoWordLeft() 985void QTextCursor::gotoWordLeft()
1105{ 986{
1106 if ( string->string()->isRightToLeft() ) 987 if ( para->string()->isRightToLeft() )
1107 gotoNextWord(); 988 gotoNextWord();
1108 else 989 else
1109 gotoPreviousWord(); 990 gotoPreviousWord();
1110} 991}
1111 992
1112void QTextCursor::gotoPreviousWord() 993void QTextCursor::gotoPreviousWord()
1113{ 994{
1114 gotoPreviousLetter(); 995 gotoPreviousLetter();
1115 tmpIndex = -1; 996 tmpIndex = -1;
1116 QTextString *s = string->string(); 997 QTextString *s = para->string();
1117 bool allowSame = FALSE; 998 bool allowSame = FALSE;
1118 if ( idx == ((int)s->length()-1) ) 999 if ( idx == ((int)s->length()-1) )
1119 return; 1000 return;
1120 for ( int i = idx; i >= 0; --i ) { 1001 for ( int i = idx; i >= 0; --i ) {
1121 if ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1002 if ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1122 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) { 1003 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) {
1123 if ( !allowSame ) 1004 if ( !allowSame )
1124 continue; 1005 continue;
1125 idx = i + 1; 1006 idx = i + 1;
1126 return; 1007 return;
1127 } 1008 }
1128 if ( !allowSame && !( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1009 if ( !allowSame && !( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1129 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) ) 1010 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) )
1130 allowSame = TRUE; 1011 allowSame = TRUE;
1131 } 1012 }
1132 idx = 0; 1013 idx = 0;
1133} 1014}
1134 1015
1135void QTextCursor::gotoNextWord() 1016void QTextCursor::gotoNextWord()
1136{ 1017{
1137 tmpIndex = -1; 1018 tmpIndex = -1;
1138 QTextString *s = string->string(); 1019 QTextString *s = para->string();
1139 bool allowSame = FALSE; 1020 bool allowSame = FALSE;
1140 for ( int i = idx; i < (int)s->length(); ++i ) { 1021 for ( int i = idx; i < (int)s->length(); ++i ) {
1141 if ( ! (s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1022 if ( ! (s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1142 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';') ) { 1023 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';') ) {
1143 if ( !allowSame ) 1024 if ( !allowSame )
1144 continue; 1025 continue;
1145 idx = i; 1026 idx = i;
1146 return; 1027 return;
1147 } 1028 }
1148 if ( !allowSame && ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' || 1029 if ( !allowSame && ( s->at( i ).c.isSpace() || s->at( i ).c == '\t' || s->at( i ).c == '.' ||
1149 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) ) 1030 s->at( i ).c == ',' || s->at( i ).c == ':' || s->at( i ).c == ';' ) )
1150 allowSame = TRUE; 1031 allowSame = TRUE;
1151 1032
1152 } 1033 }
1153 1034
1154 if ( idx < ((int)s->length()-1) ) { 1035 if ( idx < ((int)s->length()-1) ) {
1155 gotoLineEnd(); 1036 gotoLineEnd();
1156 } else if ( string->next() ) { 1037 } else if ( para->next() ) {
1157 QTextParag *s = string->next(); 1038 QTextParagraph *p = para->next();
1158 while ( s && !s->isVisible() ) 1039 while ( p && !p->isVisible() )
1159 s = s->next(); 1040 p = p->next();
1160 if ( s ) { 1041 if ( s ) {
1161 string = s; 1042 para = p;
1162 idx = 0; 1043 idx = 0;
1163 } 1044 }
1164 } else { 1045 } else {
1165 gotoLineEnd(); 1046 gotoLineEnd();
1166 } 1047 }
1167} 1048}
1168 1049
1169bool QTextCursor::atParagStart() 1050bool QTextCursor::atParagStart()
1170{ 1051{
1171 return idx == 0; 1052 return idx == 0;
1172} 1053}
1173 1054
1174bool QTextCursor::atParagEnd() 1055bool QTextCursor::atParagEnd()
1175{ 1056{
1176 return idx == string->length() - 1; 1057 return idx == para->length() - 1;
1177} 1058}
1178 1059
1179void QTextCursor::splitAndInsertEmptyParag( bool ind, bool updateIds ) 1060void QTextCursor::splitAndInsertEmptyParagraph( bool ind, bool updateIds )
1180{ 1061{
1181 if ( !doc ) 1062 if ( !para->document() )
1182 return; 1063 return;
1183 tmpIndex = -1; 1064 tmpIndex = -1;
1184 QTextFormat *f = 0; 1065 QTextFormat *f = 0;
1185 if ( doc->useFormatCollection() ) { 1066 if ( para->document()->useFormatCollection() ) {
1186 f = string->at( idx )->format(); 1067 f = para->at( idx )->format();
1187 if ( idx == string->length() - 1 && idx > 0 ) 1068 if ( idx == para->length() - 1 && idx > 0 )
1188 f = string->at( idx - 1 )->format(); 1069 f = para->at( idx - 1 )->format();
1189 if ( f->isMisspelled() ) { 1070 if ( f->isMisspelled() ) {
1190 f->removeRef(); 1071 f->removeRef();
1191 f = doc->formatCollection()->format( f->font(), f->color() ); 1072 f = para->document()->formatCollection()->format( f->font(), f->color() );
1192 } 1073 }
1193 } 1074 }
1194 1075
1195 if ( atParagEnd() ) { 1076 if ( atParagEnd() ) {
1196 QTextParag *n = string->next(); 1077 QTextParagraph *n = para->next();
1197 QTextParag *s = doc->createParag( doc, string, n, updateIds ); 1078 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds );
1198 if ( f ) 1079 if ( f )
1199 s->setFormat( 0, 1, f, TRUE ); 1080 s->setFormat( 0, 1, f, TRUE );
1200 s->copyParagData( string ); 1081 s->copyParagData( para );
1201 if ( ind ) { 1082 if ( ind ) {
1202 int oi, ni; 1083 int oi, ni;
1203 s->indent( &oi, &ni ); 1084 s->indent( &oi, &ni );
1204 string = s; 1085 para = s;
1205 idx = ni; 1086 idx = ni;
1206 } else { 1087 } else {
1207 string = s; 1088 para = s;
1208 idx = 0; 1089 idx = 0;
1209 } 1090 }
1210 } else if ( atParagStart() ) { 1091 } else if ( atParagStart() ) {
1211 QTextParag *p = string->prev(); 1092 QTextParagraph *p = para->prev();
1212 QTextParag *s = doc->createParag( doc, p, string, updateIds ); 1093 QTextParagraph *s = para->document()->createParagraph( para->document(), p, para, updateIds );
1213 if ( f ) 1094 if ( f )
1214 s->setFormat( 0, 1, f, TRUE ); 1095 s->setFormat( 0, 1, f, TRUE );
1215 s->copyParagData( string ); 1096 s->copyParagData( para );
1216 if ( ind ) { 1097 if ( ind ) {
1217 s->indent(); 1098 s->indent();
1218 s->format(); 1099 s->format();
1219 indent(); 1100 indent();
1220 string->format(); 1101 para->format();
1221 } 1102 }
1222 } else { 1103 } else {
1223 QString str = string->string()->toString().mid( idx, 0xFFFFFF ); 1104 QString str = para->string()->toString().mid( idx, 0xFFFFFF );
1224 QTextParag *n = string->next(); 1105 QTextParagraph *n = para->next();
1225 QTextParag *s = doc->createParag( doc, string, n, updateIds ); 1106 QTextParagraph *s = para->document()->createParagraph( para->document(), para, n, updateIds );
1226 s->copyParagData( string ); 1107 s->copyParagData( para );
1227 s->remove( 0, 1 ); 1108 s->remove( 0, 1 );
1228 s->append( str, TRUE ); 1109 s->append( str, TRUE );
1229 for ( uint i = 0; i < str.length(); ++i ) { 1110 for ( uint i = 0; i < str.length(); ++i ) {
1230 s->setFormat( i, 1, string->at( idx + i )->format(), TRUE ); 1111 QTextStringChar* tsc = para->at( idx + i );
1231 if ( string->at( idx + i )->isCustom() ) { 1112 s->setFormat( i, 1, tsc->format(), TRUE );
1232 QTextCustomItem * item = string->at( idx + i )->customItem(); 1113 if ( tsc->isCustom() ) {
1114 QTextCustomItem * item = tsc->customItem();
1233 s->at( i )->setCustomItem( item ); 1115 s->at( i )->setCustomItem( item );
1234 string->at( idx + i )->loseCustomItem(); 1116 tsc->loseCustomItem();
1235 } 1117 }
1118 if ( tsc->isAnchor() )
1119 s->at( i )->setAnchor( tsc->anchorName(),
1120 tsc->anchorHref() );
1236 } 1121 }
1237 string->truncate( idx ); 1122 para->truncate( idx );
1238 if ( ind ) { 1123 if ( ind ) {
1239 int oi, ni; 1124 int oi, ni;
1240 s->indent( &oi, &ni ); 1125 s->indent( &oi, &ni );
1241 string = s; 1126 para = s;
1242 idx = ni; 1127 idx = ni;
1243 } else { 1128 } else {
1244 string = s; 1129 para = s;
1245 idx = 0; 1130 idx = 0;
1246 } 1131 }
1247 } 1132 }
1248 1133
1249 invalidateNested(); 1134 invalidateNested();
1250} 1135}
1251 1136
1252bool QTextCursor::remove() 1137bool QTextCursor::remove()
1253{ 1138{
1254 tmpIndex = -1; 1139 tmpIndex = -1;
1255 if ( !atParagEnd() ) { 1140 if ( !atParagEnd() ) {
1256 string->remove( idx, 1 ); 1141 para->remove( idx, 1 );
1257 int h = string->rect().height(); 1142 int h = para->rect().height();
1258 string->format( -1, TRUE ); 1143 para->format( -1, TRUE );
1259 if ( h != string->rect().height() ) 1144 if ( h != para->rect().height() )
1260 invalidateNested(); 1145 invalidateNested();
1261 else if ( doc && doc->parent() ) 1146 else if ( para->document() && para->document()->parent() )
1262 doc->nextDoubleBuffered = TRUE; 1147 para->document()->nextDoubleBuffered = TRUE;
1263 return FALSE; 1148 return FALSE;
1264 } else if ( string->next() ) { 1149 } else if ( para->next() ) {
1265 if ( string->length() == 1 ) { 1150 para->join( para->next() );
1266 string->next()->setPrev( string->prev() );
1267 if ( string->prev() )
1268 string->prev()->setNext( string->next() );
1269 QTextParag *p = string->next();
1270 delete string;
1271 string = p;
1272 string->invalidate( 0 );
1273 QTextParag *s = string;
1274 while ( s ) {
1275 s->id = s->p ? s->p->id + 1 : 0;
1276 s->state = -1;
1277 s->needPreProcess = TRUE;
1278 s->changed = TRUE;
1279 s = s->n;
1280 }
1281 string->format();
1282 } else {
1283 string->join( string->next() );
1284 }
1285 invalidateNested(); 1151 invalidateNested();
1286 return TRUE; 1152 return TRUE;
1287 } 1153 }
1288 return FALSE; 1154 return FALSE;
1289} 1155}
1290 1156
1291void QTextCursor::killLine()
1292{
1293 if ( atParagEnd() )
1294 return;
1295 string->remove( idx, string->length() - idx - 1 );
1296 int h = string->rect().height();
1297 string->format( -1, TRUE );
1298 if ( h != string->rect().height() )
1299 invalidateNested();
1300 else if ( doc && doc->parent() )
1301 doc->nextDoubleBuffered = TRUE;
1302}
1303
1304void QTextCursor::indent() 1157void QTextCursor::indent()
1305{ 1158{
1306 int oi = 0, ni = 0; 1159 int oi = 0, ni = 0;
1307 string->indent( &oi, &ni ); 1160 para->indent( &oi, &ni );
1308 if ( oi == ni ) 1161 if ( oi == ni )
1309 return; 1162 return;
1310 1163
1311 if ( idx >= oi ) 1164 if ( idx >= oi )
1312 idx += ni - oi; 1165 idx += ni - oi;
1313 else 1166 else
1314 idx = ni; 1167 idx = ni;
1315} 1168}
1316 1169
1317void QTextCursor::setDocument( QTextDocument *d )
1318{
1319 doc = d;
1320 string = d->firstParag();
1321 idx = 0;
1322 nested = FALSE;
1323 restoreState();
1324 tmpIndex = -1;
1325}
1326
1327// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1170// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1328 1171
1329QTextDocument::QTextDocument( QTextDocument *p ) 1172QTextDocument::QTextDocument( QTextDocument *p )
1330 : par( p ), parParag( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) 1173 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 )
1331{ 1174{
1332 fCollection = new QTextFormatCollection; 1175 fCollection = new QTextFormatCollection;
1333 init(); 1176 init();
1334} 1177}
1335 1178
1336QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f ) 1179QTextDocument::QTextDocument( QTextDocument *p, QTextFormatCollection *f )
1337 : par( p ), parParag( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 ) 1180 : par( p ), parentPar( 0 ), tc( 0 ), tArray( 0 ), tStopWidth( 0 )
1338{ 1181{
1339 fCollection = f; 1182 fCollection = f;
1340 init(); 1183 init();
1341} 1184}
1342 1185
1343void QTextDocument::init() 1186void QTextDocument::init()
1344{ 1187{
1345#if defined(PARSER_DEBUG)
1346 qDebug( debug_indent + "new QTextDocument (%p)", this );
1347#endif
1348 oTextValid = TRUE; 1188 oTextValid = TRUE;
1349 mightHaveCustomItems = FALSE; 1189 mightHaveCustomItems = FALSE;
1350 if ( par ) 1190 if ( par )
1351 par->insertChild( this ); 1191 par->insertChild( this );
1352 pProcessor = 0; 1192 pProcessor = 0;
1353 useFC = TRUE; 1193 useFC = TRUE;
1354 pFormatter = 0; 1194 pFormatter = 0;
1355 indenter = 0; 1195 indenter = 0;
1356 fParag = 0; 1196 fParag = 0;
1357 txtFormat = Qt::AutoText; 1197 txtFormat = Qt::AutoText;
1358 preferRichText = FALSE; 1198 preferRichText = FALSE;
1359 pages = FALSE; 1199 pages = FALSE;
1360 focusIndicator.parag = 0; 1200 focusIndicator.parag = 0;
1361 minw = 0; 1201 minw = 0;
1362 wused = 0; 1202 wused = 0;
1363 minwParag = curParag = 0; 1203 minwParag = curParag = 0;
1364 align = AlignAuto; 1204 align = AlignAuto;
1365 nSelections = 1; 1205 nSelections = 1;
1366 addMargs = FALSE;
1367 1206
1368 sheet_ = QStyleSheet::defaultSheet(); 1207 setStyleSheet( QStyleSheet::defaultSheet() );
1369 factory_ = QMimeSourceFactory::defaultFactory(); 1208 factory_ = QMimeSourceFactory::defaultFactory();
1370 contxt = QString::null; 1209 contxt = QString::null;
1371 fCollection->setStyleSheet( sheet_ );
1372 1210
1373 underlLinks = par ? par->underlLinks : TRUE; 1211 underlLinks = par ? par->underlLinks : TRUE;
1374 backBrush = 0; 1212 backBrush = 0;
1375 buf_pixmap = 0; 1213 buf_pixmap = 0;
1376 nextDoubleBuffered = FALSE; 1214 nextDoubleBuffered = FALSE;
1377 1215
1378 if ( par ) 1216 if ( par )
1379 withoutDoubleBuffer = par->withoutDoubleBuffer; 1217 withoutDoubleBuffer = par->withoutDoubleBuffer;
1380 else 1218 else
1381 withoutDoubleBuffer = FALSE; 1219 withoutDoubleBuffer = FALSE;
1382 1220
1383 lParag = fParag = createParag( this, 0, 0 ); 1221 lParag = fParag = createParagraph( this, 0, 0 );
1384 tmpCursor = 0;
1385 1222
1386 cx = 0; 1223 cx = 0;
1387 cy = 2; 1224 cy = 2;
1388 if ( par ) 1225 if ( par )
1389 cx = cy = 0; 1226 cx = cy = 0;
1390 cw = 600; 1227 cw = 600;
1391 vw = 0; 1228 vw = 0;
1392 flow_ = new QTextFlow; 1229 flow_ = new QTextFlow;
1393 flow_->setWidth( cw ); 1230 flow_->setWidth( cw );
1394 1231
1395 leftmargin = rightmargin = 4; 1232 leftmargin = rightmargin = 4;
1233 scaleFontsFactor = 1;
1234
1396 1235
1397 selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight ); 1236 selectionColors[ Standard ] = QApplication::palette().color( QPalette::Active, QColorGroup::Highlight );
1398 selectionText[ Standard ] = TRUE; 1237 selectionText[ Standard ] = TRUE;
1399 commandHistory = new QTextCommandHistory( 100 ); 1238 commandHistory = new QTextCommandHistory( 100 );
1400 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8; 1239 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8;
1401} 1240}
1402 1241
1403QTextDocument::~QTextDocument() 1242QTextDocument::~QTextDocument()
1404{ 1243{
1405 if ( par ) 1244 if ( par )
1406 par->removeChild( this ); 1245 par->removeChild( this );
1407 clear(); 1246 clear();
1408 delete commandHistory; 1247 delete commandHistory;
1409 delete flow_; 1248 delete flow_;
1410 if ( !par ) 1249 if ( !par )
1411 delete pFormatter; 1250 delete pFormatter;
1412 delete fCollection; 1251 delete fCollection;
1413 delete pProcessor; 1252 delete pProcessor;
1414 delete buf_pixmap; 1253 delete buf_pixmap;
1415 delete indenter; 1254 delete indenter;
1416 delete backBrush; 1255 delete backBrush;
1417 if ( tArray ) 1256 if ( tArray )
1418 delete [] tArray; 1257 delete [] tArray;
1419} 1258}
1420 1259
1421void QTextDocument::clear( bool createEmptyParag ) 1260void QTextDocument::clear( bool createEmptyParag )
1422{ 1261{
1423 if ( flow_ ) 1262 if ( flow_ )
1424 flow_->clear(); 1263 flow_->clear();
1425 while ( fParag ) { 1264 while ( fParag ) {
1426 QTextParag *p = fParag->next(); 1265 QTextParagraph *p = fParag->next();
1427 delete fParag; 1266 delete fParag;
1428 fParag = p; 1267 fParag = p;
1429 } 1268 }
1430 fParag = lParag = 0; 1269 fParag = lParag = 0;
1431 if ( createEmptyParag ) 1270 if ( createEmptyParag )
1432 fParag = lParag = createParag( this ); 1271 fParag = lParag = createParagraph( this );
1433 selections.clear(); 1272 selections.clear();
1273 oText = QString::null;
1274 oTextValid = TRUE;
1434} 1275}
1435 1276
1436int QTextDocument::widthUsed() const 1277int QTextDocument::widthUsed() const
1437{ 1278{
1438 return wused + border_tolerance; 1279 return wused + border_tolerance;
1439} 1280}
1440 1281
1441int QTextDocument::height() const 1282int QTextDocument::height() const
1442{ 1283{
1443 int h = 0; 1284 int h = 0;
1444 if ( lParag ) 1285 if ( lParag )
1445 h = lParag->rect().top() + lParag->rect().height() + 1; 1286 h = lParag->rect().top() + lParag->rect().height() + 1;
1446 int fh = flow_->boundingRect().bottom(); 1287 int fh = flow_->boundingRect().bottom();
1447 return QMAX( h, fh ); 1288 return QMAX( h, fh );
1448} 1289}
1449 1290
1450 1291
1451 1292
1452QTextParag *QTextDocument::createParag( QTextDocument *d, QTextParag *pr, QTextParag *nx, bool updateIds ) 1293QTextParagraph *QTextDocument::createParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds )
1453{ 1294{
1454 return new QTextParag( d, pr, nx, updateIds ); 1295 return new QTextParagraph( d, pr, nx, updateIds );
1455} 1296}
1456 1297
1457bool QTextDocument::setMinimumWidth( int needed, int used, QTextParag *p ) 1298bool QTextDocument::setMinimumWidth( int needed, int used, QTextParagraph *p )
1458{ 1299{
1459 if ( needed == -1 ) { 1300 if ( needed == -1 ) {
1460 minw = 0; 1301 minw = 0;
1461 wused = 0; 1302 wused = 0;
1462 p = 0; 1303 p = 0;
1463 } 1304 }
1464 if ( p == minwParag ) { 1305 if ( p == minwParag ) {
1465 minw = needed; 1306 minw = needed;
1466 emit minimumWidthChanged( minw ); 1307 emit minimumWidthChanged( minw );
1467 } else if ( needed > minw ) { 1308 } else if ( needed > minw ) {
1468 minw = needed; 1309 minw = needed;
1469 minwParag = p; 1310 minwParag = p;
1470 emit minimumWidthChanged( minw ); 1311 emit minimumWidthChanged( minw );
1471 } 1312 }
1472 wused = QMAX( wused, used ); 1313 wused = QMAX( wused, used );
1473 wused = QMAX( wused, minw ); 1314 wused = QMAX( wused, minw );
1474 cw = QMAX( minw, cw ); 1315 cw = QMAX( minw, cw );
1475 return TRUE; 1316 return TRUE;
1476} 1317}
1477 1318
1478void QTextDocument::setPlainText( const QString &text ) 1319void QTextDocument::setPlainText( const QString &text )
1479{ 1320{
1480 clear(); 1321 clear();
1481 preferRichText = FALSE; 1322 preferRichText = FALSE;
1482 oTextValid = TRUE; 1323 oTextValid = TRUE;
1483 oText = text; 1324 oText = text;
1484 1325
1485 int lastNl = 0; 1326 int lastNl = 0;
1486 int nl = text.find( '\n' ); 1327 int nl = text.find( '\n' );
1487 if ( nl == -1 ) { 1328 if ( nl == -1 ) {
1488 lParag = createParag( this, lParag, 0 ); 1329 lParag = createParagraph( this, lParag, 0 );
1489 if ( !fParag ) 1330 if ( !fParag )
1490 fParag = lParag; 1331 fParag = lParag;
1491 QString s = text; 1332 QString s = text;
1492 if ( !s.isEmpty() ) { 1333 if ( !s.isEmpty() ) {
1493 if ( s[ (int)s.length() - 1 ] == '\r' ) 1334 if ( s[ (int)s.length() - 1 ] == '\r' )
1494 s.remove( s.length() - 1, 1 ); 1335 s.remove( s.length() - 1, 1 );
1495 lParag->append( s ); 1336 lParag->append( s );
1496 } 1337 }
1497 } else { 1338 } else {
1498 for (;;) { 1339 for (;;) {
1499 lParag = createParag( this, lParag, 0 ); 1340 lParag = createParagraph( this, lParag, 0 );
1500 if ( !fParag ) 1341 if ( !fParag )
1501 fParag = lParag; 1342 fParag = lParag;
1502 QString s = text.mid( lastNl, nl - lastNl ); 1343 QString s = text.mid( lastNl, nl - lastNl );
1503 if ( !s.isEmpty() ) { 1344 if ( !s.isEmpty() ) {
1504 if ( s[ (int)s.length() - 1 ] == '\r' ) 1345 if ( s[ (int)s.length() - 1 ] == '\r' )
1505 s.remove( s.length() - 1, 1 ); 1346 s.remove( s.length() - 1, 1 );
1506 lParag->append( s ); 1347 lParag->append( s );
1507 } 1348 }
1508 if ( nl == 0xffffff ) 1349 if ( nl == 0xffffff )
1509 break; 1350 break;
1510 lastNl = nl + 1; 1351 lastNl = nl + 1;
1511 nl = text.find( '\n', nl + 1 ); 1352 nl = text.find( '\n', nl + 1 );
1512 if ( nl == -1 ) 1353 if ( nl == -1 )
1513 nl = 0xffffff; 1354 nl = 0xffffff;
1514 } 1355 }
1515 } 1356 }
1516 if ( !lParag ) 1357 if ( !lParag )
1517 lParag = fParag = createParag( this, 0, 0 ); 1358 lParag = fParag = createParagraph( this, 0, 0 );
1518} 1359}
1519 1360
1520struct Q_EXPORT QTextDocumentTag { 1361struct Q_EXPORT QTextDocumentTag {
1521 QTextDocumentTag(){} 1362 QTextDocumentTag(){}
1522 QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f ) 1363 QTextDocumentTag( const QString&n, const QStyleSheetItem* s, const QTextFormat& f )
1523 :name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) { 1364 :name(n),style(s), format(f), alignment(Qt3::AlignAuto), direction(QChar::DirON),liststyle(QStyleSheetItem::ListDisc) {
1524 wsm = QStyleSheetItem::WhiteSpaceNormal; 1365 wsm = QStyleSheetItem::WhiteSpaceNormal;
1525 } 1366 }
1526 QString name; 1367 QString name;
1527 const QStyleSheetItem* style; 1368 const QStyleSheetItem* style;
1528 QString anchorHref; 1369 QString anchorHref;
1529 QStyleSheetItem::WhiteSpaceMode wsm; 1370 QStyleSheetItem::WhiteSpaceMode wsm;
1530 QTextFormat format; 1371 QTextFormat format;
1531 int alignment : 16; 1372 int alignment : 16;
1532 int direction : 5; 1373 int direction : 5;
1533 QStyleSheetItem::ListStyle liststyle; 1374 QStyleSheetItem::ListStyle liststyle;
1534 1375
1535 QTextDocumentTag( const QTextDocumentTag& t ) { 1376 QTextDocumentTag( const QTextDocumentTag& t ) {
1536 name = t.name; 1377 name = t.name;
1537 style = t.style; 1378 style = t.style;
1538 anchorHref = t.anchorHref; 1379 anchorHref = t.anchorHref;
1539 wsm = t.wsm; 1380 wsm = t.wsm;
1540 format = t.format; 1381 format = t.format;
1541 alignment = t.alignment; 1382 alignment = t.alignment;
1542 direction = t.direction; 1383 direction = t.direction;
1543 liststyle = t.liststyle; 1384 liststyle = t.liststyle;
1544 } 1385 }
1545 QTextDocumentTag& operator=(const QTextDocumentTag& t) { 1386 QTextDocumentTag& operator=(const QTextDocumentTag& t) {
1546 name = t.name; 1387 name = t.name;
1547 style = t.style; 1388 style = t.style;
1548 anchorHref = t.anchorHref; 1389 anchorHref = t.anchorHref;
1549 wsm = t.wsm; 1390 wsm = t.wsm;
1550 format = t.format; 1391 format = t.format;
1551 alignment = t.alignment; 1392 alignment = t.alignment;
1552 direction = t.direction; 1393 direction = t.direction;
1553 liststyle = t.liststyle; 1394 liststyle = t.liststyle;
1554 return *this; 1395 return *this;
1555 } 1396 }
1556 1397
1557#if defined(Q_FULL_TEMPLATE_INSTANTIATION) 1398#if defined(Q_FULL_TEMPLATE_INSTANTIATION)
1558 bool operator==( const QTextDocumentTag& ) const { return FALSE; } 1399 bool operator==( const QTextDocumentTag& ) const { return FALSE; }
1559#endif 1400#endif
1560}; 1401};
1561 1402
1562#define NEWPAR do{ if ( !hasNewPar ) curpar = createParag( this, curpar ); \ 1403
1563 if ( curpar->isBr ) curpar->isBr = FALSE; \ 1404#define NEWPAR do{ if ( !hasNewPar) { \
1405 if ( !textEditMode && curpar && curpar->length()>1 && curpar->at( curpar->length()-2)->c == QChar_linesep ) \
1406 curpar->remove( curpar->length()-2, 1 ); \
1407 curpar = createParagraph( this, curpar, curpar->next() ); styles.append( vec ); vec = 0;} \
1564 hasNewPar = TRUE; \ 1408 hasNewPar = TRUE; \
1565 curpar->setAlignment( curtag.alignment ); \ 1409 curpar->rtext = TRUE; \
1566 curpar->setDirection( (QChar::Direction)curtag.direction ); \ 1410 curpar->align = curtag.alignment; \
1411 curpar->lstyle = curtag.liststyle; \
1412 curpar->litem = ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ); \
1413 curpar->str->setDirection( (QChar::Direction)curtag.direction ); \
1567 space = TRUE; \ 1414 space = TRUE; \
1568 QPtrVector<QStyleSheetItem> vec( (uint)tags.count() + 1); \ 1415 delete vec; vec = new QPtrVector<QStyleSheetItem>( (uint)tags.count() + 1); \
1569 int i = 0; \ 1416 int i = 0; \
1570 for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \ 1417 for ( QValueStack<QTextDocumentTag>::Iterator it = tags.begin(); it != tags.end(); ++it ) \
1571 vec.insert( i++, (*it).style ); \ 1418 vec->insert( i++, (*it).style ); \
1572 vec.insert( i, curtag.style ); \ 1419 vec->insert( i, curtag.style ); \
1573 curpar->setStyleSheetItems( vec ); }while(FALSE) 1420 }while(FALSE)
1574 1421
1575 1422
1576void QTextDocument::setRichText( const QString &text, const QString &context ) 1423void QTextDocument::setRichText( const QString &text, const QString &context )
1577{ 1424{
1578 setTextFormat( Qt::RichText );
1579 if ( !context.isEmpty() ) 1425 if ( !context.isEmpty() )
1580 setContext( context ); 1426 setContext( context );
1581 clear(); 1427 clear();
1582 fParag = lParag = createParag( this ); 1428 fParag = lParag = createParagraph( this );
1429 oTextValid = TRUE;
1430 oText = text;
1583 setRichTextInternal( text ); 1431 setRichTextInternal( text );
1432 fParag->rtext = TRUE;
1584} 1433}
1585 1434
1586static QStyleSheetItem::ListStyle chooseListStyle( const QStyleSheetItem *nstyle, 1435void QTextDocument::setRichTextInternal( const QString &text, QTextCursor* cursor )
1587 const QMap<QString, QString> &attr,
1588 QStyleSheetItem::ListStyle curListStyle )
1589{
1590 if ( nstyle->name() == "ol" || nstyle->name() == "ul" ) {
1591 curListStyle = nstyle->listStyle();
1592 QMap<QString, QString>::ConstIterator it = attr.find( "type" );
1593 if ( it != attr.end() ) {
1594 QString sl = *it;
1595 if ( sl == "1" ) {
1596 curListStyle = QStyleSheetItem::ListDecimal;
1597 } else if ( sl == "a" ) {
1598 curListStyle = QStyleSheetItem::ListLowerAlpha;
1599 } else if ( sl == "A" ) {
1600 curListStyle = QStyleSheetItem::ListUpperAlpha;
1601 } else {
1602 sl = sl.lower();
1603 if ( sl == "square" )
1604 curListStyle = QStyleSheetItem::ListSquare;
1605 else if ( sl == "disc" )
1606 curListStyle = QStyleSheetItem::ListDisc;
1607 else if ( sl == "circle" )
1608 curListStyle = QStyleSheetItem::ListCircle;
1609 }
1610 }
1611 }
1612 return curListStyle;
1613}
1614
1615void QTextDocument::setRichTextInternal( const QString &text )
1616{ 1436{
1617 oTextValid = TRUE; 1437 QTextParagraph* curpar = lParag;
1618 oText = text;
1619 QTextParag* curpar = lParag;
1620 int pos = 0; 1438 int pos = 0;
1621 QValueStack<QTextDocumentTag> tags; 1439 QValueStack<QTextDocumentTag> tags;
1622 QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() ); 1440 QTextDocumentTag initag( "", sheet_->item(""), *formatCollection()->defaultFormat() );
1623 QTextDocumentTag curtag = initag; 1441 QTextDocumentTag curtag = initag;
1624 bool space = TRUE; 1442 bool space = TRUE;
1443 bool canMergeLi = FALSE;
1444
1445 bool textEditMode = FALSE;
1625 1446
1626 const QChar* doc = text.unicode(); 1447 const QChar* doc = text.unicode();
1627 int length = text.length(); 1448 int length = text.length();
1628 bool hasNewPar = curpar->length() <= 1; 1449 bool hasNewPar = curpar->length() <= 1;
1629 QString lastClose;
1630 QString anchorName; 1450 QString anchorName;
1451
1452 // style sheet handling for margin and line spacing calculation below
1453 QTextParagraph* stylesPar = curpar;
1454 QPtrVector<QStyleSheetItem>* vec = 0;
1455 QPtrList< QPtrVector<QStyleSheetItem> > styles;
1456 styles.setAutoDelete( TRUE );
1457
1458 if ( cursor ) {
1459 cursor->splitAndInsertEmptyParagraph();
1460 QTextCursor tmp = *cursor;
1461 tmp.gotoPreviousLetter();
1462 stylesPar = curpar = tmp.paragraph();
1463 hasNewPar = TRUE;
1464 textEditMode = TRUE;
1465 } else {
1466 NEWPAR;
1467 }
1468
1469 // set rtext spacing to FALSE for the initial paragraph.
1470 curpar->rtext = FALSE;
1471
1472 QString wellKnownTags = "br hr wsp table qt body meta title";
1473
1631 while ( pos < length ) { 1474 while ( pos < length ) {
1632 if ( hasPrefix(doc, length, pos, '<' ) ){ 1475 if ( hasPrefix(doc, length, pos, '<' ) ){
1633 if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) { 1476 if ( !hasPrefix( doc, length, pos+1, QChar('/') ) ) {
1634 // open tag 1477 // open tag
1635 QMap<QString, QString> attr; 1478 QMap<QString, QString> attr;
1636 bool emptyTag = FALSE; 1479 bool emptyTag = FALSE;
1637 QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag); 1480 QString tagname = parseOpenTag(doc, length, pos, attr, emptyTag);
1638 if ( tagname.isEmpty() ) 1481 if ( tagname.isEmpty() )
1639 continue; // nothing we could do with this, probably parse error 1482 continue; // nothing we could do with this, probably parse error
1640 1483
1641 if ( tagname == "title" ) {
1642 QString title;
1643 while ( pos < length ) {
1644 if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) &&
1645 parseCloseTag( doc, length, pos ) == "title" )
1646 break;
1647 title += doc[ pos ];
1648 ++pos;
1649 }
1650 attribs.replace( "title", title );
1651 }
1652
1653 const QStyleSheetItem* nstyle = sheet_->item(tagname); 1484 const QStyleSheetItem* nstyle = sheet_->item(tagname);
1654 1485
1655 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1656 // if ( tagname == "br" ) {
1657 // // our standard br emty-tag handling breaks
1658 // // inside list items, we would get another
1659 // // list item in this case. As workaround, fake
1660 // // a new paragraph instead
1661 // tagname = "p";
1662 // nstyle = sheet_->item( tagname );
1663 // }
1664 if ( nstyle )
1665 hasNewPar = FALSE; // we want empty paragraphs in this case
1666 }
1667
1668 if ( nstyle ) { 1486 if ( nstyle ) {
1669 // we might have to close some 'forgotten' tags 1487 // we might have to close some 'forgotten' tags
1670 while ( !nstyle->allowedInContext( curtag.style ) ) { 1488 while ( !nstyle->allowedInContext( curtag.style ) ) {
1671 QString msg; 1489 QString msg;
1672 msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)", 1490 msg.sprintf( "QText Warning: Document not valid ( '%s' not allowed in '%s' #%d)",
1673 tagname.ascii(), curtag.style->name().ascii(), pos); 1491 tagname.ascii(), curtag.style->name().ascii(), pos);
1674 sheet_->error( msg ); 1492 sheet_->error( msg );
1675 if ( tags.isEmpty() ) 1493 if ( tags.isEmpty() )
1676 break; 1494 break;
1677 curtag = tags.pop(); 1495 curtag = tags.pop();
1678 } 1496 }
1679 1497
1680 // special handling for p. We do not want to nest there for HTML compatibility 1498 /* special handling for p and li for HTML
1681 if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { 1499 compatibility. We do not want to embed blocks in
1500 p, and we do not want new blocks inside non-empty
1501 lis. Plus we want to merge empty lis sometimes. */
1502 if( nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) {
1503 canMergeLi = TRUE;
1504 } else if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) {
1682 while ( curtag.style->name() == "p" ) { 1505 while ( curtag.style->name() == "p" ) {
1683 if ( tags.isEmpty() ) 1506 if ( tags.isEmpty() )
1684 break; 1507 break;
1685 curtag = tags.pop(); 1508 curtag = tags.pop();
1686 } 1509 }
1687 }
1688 1510
1511 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1512 // we are in a li and a new block comes along
1513 if ( nstyle->name() == "ul" || nstyle->name() == "ol" )
1514 hasNewPar = FALSE; // we want an empty li (like most browsers)
1515 if ( !hasNewPar ) {
1516 /* do not add new blocks inside
1517 non-empty lis */
1518 while ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1519 if ( tags.isEmpty() )
1520 break;
1521 curtag = tags.pop();
1522 }
1523 } else if ( canMergeLi ) {
1524 /* we have an empty li and a block
1525 comes along, merge them */
1526 nstyle = curtag.style;
1527 }
1528 canMergeLi = FALSE;
1529 }
1530 }
1689 } 1531 }
1690 1532
1691 QTextCustomItem* custom = 0; 1533 QTextCustomItem* custom = 0;
1692 // some well-known empty tags 1534
1693 if ( tagname == "br" ) { 1535 // some well-known tags, some have a nstyle, some not
1694 emptyTag = TRUE; 1536 if ( wellKnownTags.find( tagname ) != -1 ) {
1695 hasNewPar = FALSE; 1537 if ( tagname == "br" ) {
1696 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1538 emptyTag = space = TRUE;
1697 // when linebreaking a list item, we do not 1539 int index = QMAX( curpar->length(),1) - 1;
1698 // actually want a new list item but just a 1540 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1699 // new line. Fake this by pushing a paragraph 1541 curpar->append( QChar_linesep );
1700 // onto the stack 1542 curpar->setFormat( index, 1, &format );
1701 tags.push( curtag ); 1543 } else if ( tagname == "hr" ) {
1702 curtag.name = tagname; 1544 emptyTag = space = TRUE;
1703 curtag.style = nstyle; 1545 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
1704 } 1546 NEWPAR;
1705 NEWPAR; 1547 } else if ( tagname == "table" ) {
1706 curpar->isBr = TRUE; 1548 emptyTag = space = TRUE;
1707 curpar->setAlignment( curtag.alignment ); 1549 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1708 } else if ( tagname == "hr" ) { 1550 curpar->setAlignment( curtag.alignment );
1709 emptyTag = TRUE; 1551 custom = parseTable( attr, format, doc, length, pos, curpar );
1710 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); 1552 } else if ( tagname == "qt" || tagname == "body" ) {
1711 NEWPAR; 1553 if ( attr.contains( "bgcolor" ) ) {
1712 } else if ( tagname == "table" ) { 1554 QBrush *b = new QBrush( QColor( attr["bgcolor"] ) );
1713 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr );
1714 curpar->setAlignment( curtag.alignment );
1715 custom = parseTable( attr, format, doc, length, pos, curpar );
1716 (void)eatSpace( doc, length, pos );
1717 emptyTag = TRUE;
1718 } else if ( tagname == "qt" ) {
1719 for ( QMap<QString, QString>::Iterator it = attr.begin(); it != attr.end(); ++it ) {
1720 if ( it.key() == "bgcolor" ) {
1721 QBrush *b = new QBrush( QColor( *it ) );
1722 setPaper( b ); 1555 setPaper( b );
1723 } else if ( it.key() == "background" ) { 1556 }
1557 if ( attr.contains( "background" ) ) {
1724 QImage img; 1558 QImage img;
1725 const QMimeSource* m = factory_->data( *it, contxt ); 1559 QString bg = attr["background"];
1560 const QMimeSource* m = factory_->data( bg, contxt );
1726 if ( !m ) { 1561 if ( !m ) {
1727 qWarning("QRichText: no mimesource for %s", (*it).latin1() ); 1562 qWarning("QRichText: no mimesource for %s", bg.latin1() );
1728 } else { 1563 } else {
1729 if ( !QImageDrag::decode( m, img ) ) { 1564 if ( !QImageDrag::decode( m, img ) ) {
1730 qWarning("QTextImage: cannot decode %s", (*it).latin1() ); 1565 qWarning("QTextImage: cannot decode %s", bg.latin1() );
1731 } 1566 }
1732 } 1567 }
1733 if ( !img.isNull() ) { 1568 if ( !img.isNull() ) {
1734 QPixmap pm; 1569 QPixmap pm;
1735 pm.convertFromImage( img ); 1570 pm.convertFromImage( img );
1736 QBrush *b = new QBrush( QColor(), pm ); 1571 QBrush *b = new QBrush( QColor(), pm );
1737 setPaper( b ); 1572 setPaper( b );
1738 } 1573 }
1739 } else if ( it.key() == "text" ) { 1574 }
1740 QColor c( *it ); 1575 if ( attr.contains( "text" ) ) {
1576 QColor c( attr["text"] );
1741 if ( formatCollection()->defaultFormat()->color() != c ) { 1577 if ( formatCollection()->defaultFormat()->color() != c ) {
1742 QDict<QTextFormat> formats = formatCollection()->dict(); 1578 QDict<QTextFormat> formats = formatCollection()->dict();
1743 QDictIterator<QTextFormat> it( formats ); 1579 QDictIterator<QTextFormat> it( formats );
1744 while ( it.current() ) { 1580 while ( it.current() ) {
1745 if ( it.current() == formatCollection()->defaultFormat() ) { 1581 if ( it.current() == formatCollection()->defaultFormat() ) {
1746 ++it; 1582 ++it;
1747 continue; 1583 continue;
1748 } 1584 }
1749 it.current()->setColor( c ); 1585 it.current()->setColor( c );
1750 ++it; 1586 ++it;
1751 } 1587 }
1752 formatCollection()->defaultFormat()->setColor( c ); 1588 formatCollection()->defaultFormat()->setColor( c );
1753 curtag.format.setColor( c ); 1589 curtag.format.setColor( c );
1754 } 1590 }
1755 } else if ( it.key() == "link" ) {
1756 linkColor = QColor( *it );
1757 } else if ( it.key() == "title" ) {
1758 attribs.replace( it.key(), *it );
1759 } 1591 }
1592 if ( attr.contains( "link" ) )
1593 linkColor = QColor( attr["link"] );
1594 if ( attr.contains( "title" ) )
1595 attribs.replace( "title", attr["title"] );
1596
1597 if ( textEditMode ) {
1598 if ( attr.contains("style" ) ) {
1599 QString a = attr["style"];
1600 for ( int s = 0; s < a.contains(';')+1; s++ ) {
1601 QString style = QTextDocument::section( a, ";", s, s );
1602 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) {
1603 scaleFontsFactor = double( formatCollection()->defaultFormat()->fn.pointSize() ) /
1604 style.mid( 10, style.length() - 12 ).toInt();
1605 }
1606 }
1607 }
1608 nstyle = 0; // ignore body in textEditMode
1609 }
1610 // end qt- and body-tag handling
1611 } else if ( tagname == "meta" ) {
1612 if ( attr["name"] == "qrichtext" && attr["content"] == "1" )
1613 textEditMode = TRUE;
1614 } else if ( tagname == "title" ) {
1615 QString title;
1616 while ( pos < length ) {
1617 if ( hasPrefix( doc, length, pos, QChar('<') ) && hasPrefix( doc, length, pos+1, QChar('/') ) &&
1618 parseCloseTag( doc, length, pos ) == "title" )
1619 break;
1620 title += doc[ pos ];
1621 ++pos;
1622 }
1623 attribs.replace( "title", title );
1760 } 1624 }
1761 } else { 1625 } // end of well-known tag handling
1626
1627 if ( !custom ) // try generic custom item
1762 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this ); 1628 custom = sheet_->tag( tagname, attr, contxt, *factory_ , emptyTag, this );
1763 }
1764 1629
1765 if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it 1630 if ( !nstyle && !custom ) // we have no clue what this tag could be, ignore it
1766 continue; 1631 continue;
1767 1632
1768 if ( custom ) { 1633 if ( custom ) {
1769 int index = curpar->length() - 1; 1634 int index = QMAX( curpar->length(),1) - 1;
1770 if ( index < 0 ) 1635 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1771 index = 0;
1772 QTextFormat format = curtag.format.makeTextFormat( nstyle, attr );
1773 curpar->append( QChar('*') ); 1636 curpar->append( QChar('*') );
1774 curpar->setFormat( index, 1, &format ); 1637 curpar->setFormat( index, 1, &format );
1775 curpar->at( index )->setCustomItem( custom ); 1638 curpar->at( index )->setCustomItem( custom );
1776 if ( !curtag.anchorHref.isEmpty() ) 1639 if ( !curtag.anchorHref.isEmpty() )
1777 curpar->at(index)->setAnchor( QString::null, curtag.anchorHref ); 1640 curpar->at(index)->setAnchor( QString::null, curtag.anchorHref );
1778 if ( !anchorName.isEmpty() ) { 1641 if ( !anchorName.isEmpty() ) {
1779 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); 1642 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
1780 anchorName = QString::null; 1643 anchorName = QString::null;
1781 } 1644 }
1782 registerCustomItem( custom, curpar ); 1645 registerCustomItem( custom, curpar );
1783 hasNewPar = FALSE; 1646 hasNewPar = FALSE;
1784 } else if ( !emptyTag ) { 1647 } else if ( !emptyTag ) {
1785 // ignore whitespace for inline elements if there was already one 1648 /* if we do nesting, push curtag on the stack,
1786 if ( nstyle->whiteSpaceMode() == QStyleSheetItem::WhiteSpaceNormal 1649 otherwise reinint curag. */
1787 && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) ) 1650 if ( curtag.style->name() != tagname || nstyle->selfNesting() ) {
1788 eatSpace( doc, length, pos );
1789
1790 // if we do nesting, push curtag on the stack,
1791 // otherwise reinint curag.
1792 if ( nstyle != curtag.style || nstyle->selfNesting() ) {
1793 tags.push( curtag ); 1651 tags.push( curtag );
1794 } else { 1652 } else {
1795 if ( !tags.isEmpty() ) 1653 if ( !tags.isEmpty() )
1796 curtag = tags.top(); 1654 curtag = tags.top();
1797 else 1655 else
1798 curtag = initag; 1656 curtag = initag;
1799 } 1657 }
1800 1658
1801 const QStyleSheetItem* ostyle = curtag.style;
1802
1803 curtag.name = tagname; 1659 curtag.name = tagname;
1804 curtag.style = nstyle; 1660 curtag.style = nstyle;
1805 curtag.name = tagname; 1661 curtag.name = tagname;
1806 curtag.style = nstyle; 1662 curtag.style = nstyle;
1807 if ( nstyle->whiteSpaceMode() != QStyleSheetItem::WhiteSpaceNormal ) 1663 if ( int(nstyle->whiteSpaceMode()) != QStyleSheetItem::Undefined )
1808 curtag.wsm = nstyle->whiteSpaceMode(); 1664 curtag.wsm = nstyle->whiteSpaceMode();
1809 curtag.liststyle = chooseListStyle( nstyle, attr, curtag.liststyle ); 1665
1810 curtag.format = curtag.format.makeTextFormat( nstyle, attr ); 1666 /* ignore whitespace for inline elements if there
1667 was already one*/
1668 if ( !textEditMode && curtag.wsm == QStyleSheetItem::WhiteSpaceNormal
1669 && ( space || nstyle->displayMode() != QStyleSheetItem::DisplayInline ) )
1670 eatSpace( doc, length, pos );
1671
1672 curtag.format = curtag.format.makeTextFormat( nstyle, attr, scaleFontsFactor );
1811 if ( nstyle->isAnchor() ) { 1673 if ( nstyle->isAnchor() ) {
1812 if ( !anchorName.isEmpty() ) 1674 if ( !anchorName.isEmpty() )
1813 anchorName += "#" + attr["name"]; 1675 anchorName += "#" + attr["name"];
1814 else 1676 else
1815 anchorName = attr["name"]; 1677 anchorName = attr["name"];
1816 curtag.anchorHref = attr["href"]; 1678 curtag.anchorHref = attr["href"];
1817 } 1679 }
1818 1680
1819 if ( nstyle->alignment() != QStyleSheetItem::Undefined ) 1681 if ( nstyle->alignment() != QStyleSheetItem::Undefined )
1820 curtag.alignment = nstyle->alignment(); 1682 curtag.alignment = nstyle->alignment();
1821 1683
1822 if ( ostyle->displayMode() == QStyleSheetItem::DisplayListItem && 1684 if ( (int) nstyle->listStyle() != QStyleSheetItem::Undefined )
1823 curpar->length() <= 1 1685 curtag.liststyle = nstyle->listStyle();
1824 && nstyle->displayMode() == QStyleSheetItem::DisplayBlock ) { 1686
1825 // do not do anything, we reuse the paragraph we have 1687 if ( nstyle->displayMode() == QStyleSheetItem::DisplayBlock
1826 } else if ( nstyle->displayMode() != QStyleSheetItem::DisplayInline && nstyle->displayMode() != QStyleSheetItem::DisplayNone ) { 1688 || nstyle->displayMode() == QStyleSheetItem::DisplayListItem ) {
1689
1690 if ( nstyle->name() == "ol" || nstyle->name() == "ul" || nstyle->name() == "li") {
1691 QString type = attr["type"];
1692 if ( !type.isEmpty() ) {
1693 if ( type == "1" ) {
1694 curtag.liststyle = QStyleSheetItem::ListDecimal;
1695 } else if ( type == "a" ) {
1696 curtag.liststyle = QStyleSheetItem::ListLowerAlpha;
1697 } else if ( type == "A" ) {
1698 curtag.liststyle = QStyleSheetItem::ListUpperAlpha;
1699 } else {
1700 type = type.lower();
1701 if ( type == "square" )
1702 curtag.liststyle = QStyleSheetItem::ListSquare;
1703 else if ( type == "disc" )
1704 curtag.liststyle = QStyleSheetItem::ListDisc;
1705 else if ( type == "circle" )
1706 curtag.liststyle = QStyleSheetItem::ListCircle;
1707 }
1708 }
1709 }
1710
1711
1712 /* Internally we treat ordered and bullet
1713 lists the same for margin calculations. In
1714 order to have fast pointer compares in the
1715 xMargin() functions we restrict ourselves to
1716 <ol>. Once we calculate the margins in the
1717 parser rathern than later, the unelegance of
1718 this approach goes awy
1719 */
1720 if ( nstyle->name() == "ul" )
1721 curtag.style = sheet_->item( "ol" );
1722
1723 if ( attr.contains( "align" ) ) {
1724 QString align = attr["align"];
1725 if ( align == "center" )
1726 curtag.alignment = Qt::AlignCenter;
1727 else if ( align == "right" )
1728 curtag.alignment = Qt::AlignRight;
1729 else if ( align == "justify" )
1730 curtag.alignment = Qt3::AlignJustify;
1731 }
1732 if ( attr.contains( "dir" ) ) {
1733 QString dir = attr["dir"];
1734 if ( dir == "rtl" )
1735 curtag.direction = QChar::DirR;
1736 else if ( dir == "ltr" )
1737 curtag.direction = QChar::DirL;
1738 }
1739
1827 NEWPAR; 1740 NEWPAR;
1828 }
1829 1741
1830 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1742 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1831 curpar->setListStyle( curtag.liststyle ); 1743 if ( attr.contains( "value " ) )
1832 if ( attr.find( "value" ) != attr.end() ) 1744 curpar->setListValue( attr["value"].toInt() );
1833 curpar->setListValue( (*attr.find( "value" )).toInt() ); 1745 }
1834 }
1835 1746
1836 if ( nstyle->displayMode() != QStyleSheetItem::DisplayInline ) 1747 if ( attr.contains( "style" ) ) {
1837 curpar->setFormat( &curtag.format ); 1748 QString a = attr["style"];
1838 1749 bool ok = TRUE;
1839 if ( attr.contains( "align" ) && 1750 for ( int s = 0; ok && s < a.contains(';')+1; s++ ) {
1840 ( curtag.name == "p" || 1751 QString style = QTextDocument::section( a, ";", s, s );
1841 curtag.name == "div" || 1752 if ( style.startsWith("margin-top:" ) && QTextDocument::endsWith(style, "px") )
1842 curtag.name == "li" || 1753 curpar->utm = 1+style.mid(11, style.length() - 13).toInt(&ok);
1843 curtag.name[ 0 ] == 'h' ) ) { 1754 else if ( style.startsWith("margin-bottom:" ) && QTextDocument::endsWith(style, "px") )
1844 QString align = attr["align"]; 1755 curpar->ubm = 1+style.mid(14, style.length() - 16).toInt(&ok);
1845 if ( align == "center" ) 1756 else if ( style.startsWith("margin-left:" ) && QTextDocument::endsWith(style, "px") )
1846 curtag.alignment = Qt::AlignCenter; 1757 curpar->ulm = 1+style.mid(12, style.length() - 14).toInt(&ok);
1847 else if ( align == "right" ) 1758 else if ( style.startsWith("margin-right:" ) && QTextDocument::endsWith(style, "px") )
1848 curtag.alignment = Qt::AlignRight; 1759 curpar->urm = 1+style.mid(13, style.length() - 15).toInt(&ok);
1849 else if ( align == "justify" ) 1760 else if ( style.startsWith("text-indent:" ) && QTextDocument::endsWith(style, "px") )
1850 curtag.alignment = Qt3::AlignJustify; 1761 curpar->uflm = 1+style.mid(12, style.length() - 14).toInt(&ok);
1851 } 1762 }
1852 if ( attr.contains( "dir" ) && 1763 if ( !ok ) // be pressmistic
1853 ( curtag.name == "p" || 1764 curpar->utm = curpar->ubm = curpar->urm = curpar->ulm = 0;
1854 curtag.name == "div" || 1765 }
1855 curtag.name == "li" ||
1856 curtag.name[ 0 ] == 'h' ) ) {
1857 QString dir = attr["dir"];
1858 if ( dir == "rtl" )
1859 curtag.direction = QChar::DirR;
1860 else if ( dir == "ltr" )
1861 curtag.direction = QChar::DirL;
1862 }
1863 if ( nstyle->displayMode() != QStyleSheetItem::DisplayInline ) {
1864 curpar->setAlignment( curtag.alignment );
1865 curpar->setDirection( (QChar::Direction)curtag.direction );
1866 } 1766 }
1867 } 1767 }
1868 } else { 1768 } else {
1869 QString tagname = parseCloseTag( doc, length, pos ); 1769 QString tagname = parseCloseTag( doc, length, pos );
1870 lastClose = tagname;
1871 if ( tagname.isEmpty() ) 1770 if ( tagname.isEmpty() )
1872 continue; // nothing we could do with this, probably parse error 1771 continue; // nothing we could do with this, probably parse error
1873 if ( !sheet_->item( tagname ) ) // ignore unknown tags 1772 if ( !sheet_->item( tagname ) ) // ignore unknown tags
1874 continue; 1773 continue;
1875 1774
1876
1877 // we close a block item. Since the text may continue, we need to have a new paragraph 1775 // we close a block item. Since the text may continue, we need to have a new paragraph
1878 bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock; 1776 bool needNewPar = curtag.style->displayMode() == QStyleSheetItem::DisplayBlock
1777 || curtag.style->displayMode() == QStyleSheetItem::DisplayListItem;
1879 1778
1880 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) {
1881 needNewPar = TRUE;
1882 hasNewPar = FALSE; // we want empty paragraphs in this case
1883 }
1884 1779
1885 // html slopiness: handle unbalanched tag closing 1780 // html slopiness: handle unbalanched tag closing
1886 while ( curtag.name != tagname ) { 1781 while ( curtag.name != tagname ) {
1887 QString msg; 1782 QString msg;
1888 msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)", 1783 msg.sprintf( "QText Warning: Document not valid ( '%s' not closed before '%s' #%d)",
1889 curtag.name.ascii(), tagname.ascii(), pos); 1784 curtag.name.ascii(), tagname.ascii(), pos);
1890 sheet_->error( msg ); 1785 sheet_->error( msg );
1891 if ( tags.isEmpty() ) 1786 if ( tags.isEmpty() )
1892 break; 1787 break;
1893 curtag = tags.pop(); 1788 curtag = tags.pop();
1894 } 1789 }
1895 1790
1896 1791
1897 // close the tag 1792 // close the tag
1898 if ( !tags.isEmpty() ) 1793 if ( !tags.isEmpty() )
1899 curtag = tags.pop(); 1794 curtag = tags.pop();
1900 else 1795 else
1901 curtag = initag; 1796 curtag = initag;
1902 1797
1903 if ( needNewPar ) { 1798 if ( needNewPar ) {
1904 if ( curtag.style->displayMode() == QStyleSheetItem::DisplayListItem ) { 1799 if ( textEditMode && tagname == "p" ) // preserve empty paragraphs
1905 tags.push( curtag ); 1800 hasNewPar = FALSE;
1906 curtag.name = "p";
1907 curtag.style = sheet_->item( curtag.name ); // a list item continues, use p for that
1908 }
1909 NEWPAR; 1801 NEWPAR;
1910 } 1802 }
1911 } 1803 }
1912 } else { 1804 } else {
1913 // normal contents 1805 // normal contents
1914 QString s; 1806 QString s;
1915 QChar c; 1807 QChar c;
1916 while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){ 1808 while ( pos < length && !hasPrefix(doc, length, pos, QChar('<') ) ){
1917 QStyleSheetItem::WhiteSpaceMode wsm = curtag.wsm; 1809 if ( textEditMode ) {
1918 if ( s.length() > 4096 ) 1810 // text edit mode: we handle all white space but ignore newlines
1919 wsm = (QStyleSheetItem::WhiteSpaceMode)QStyleSheetItem_WhiteSpaceNormalWithNewlines; 1811 c = parseChar( doc, length, pos, QStyleSheetItem::WhiteSpacePre );
1920 1812 if ( c == QChar_linesep )
1921 c = parseChar( doc, length, pos, wsm ); 1813 break;
1814 } else {
1815 int l = pos;
1816 c = parseChar( doc, length, pos, curtag.wsm );
1817
1818 // in white space pre mode: treat any space as non breakable
1819 if ( c == ' ' && curtag.wsm == QStyleSheetItem::WhiteSpacePre )
1820 c = QChar::nbsp;
1821
1822 if ( c == ' ' || c == QChar_linesep ) {
1823 /* avoid overlong paragraphs by forcing a new
1824 paragraph after 4096 characters. This case can
1825 occur when loading undiscovered plain text
1826 documents in rich text mode. Instead of hanging
1827 forever, we do the trick.
1828 */
1829 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && s.length() > 4096 ) do {
1830 if ( doc[l] == '\n' ) {
1831 hasNewPar = FALSE; // for a new paragraph ...
1832 NEWPAR;
1833 hasNewPar = FALSE; // ... and make it non-reusable
1834 c = '\n'; // make sure we break below
1835 break;
1836 }
1837 } while ( ++l < pos );
1838 }
1839 }
1922 1840
1923 if ( c == '\n' ) // happens only in whitespacepre-mode or with WhiteSpaceNormalWithNewlines. 1841 if ( c == '\n' )
1924 break; // we want a new line in this case 1842 break; // break on newlines, pre delievers a QChar_linesep
1925 1843
1926 bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && 1844 bool c_isSpace = c.isSpace() && c.unicode() != 0x00a0U && !textEditMode;
1927 curtag.wsm != QStyleSheetItem_WhiteSpaceNoCompression;
1928 1845
1929 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space ) 1846 if ( curtag.wsm == QStyleSheetItem::WhiteSpaceNormal && c_isSpace && space )
1930 continue; 1847 continue;
1931 if ( c == '\r' ) 1848 if ( c == '\r' )
1932 continue; 1849 continue;
1933 space = c_isSpace; 1850 space = c_isSpace;
1934 s += c; 1851 s += c;
1935 } 1852 }
1936 if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) { 1853 if ( !s.isEmpty() && curtag.style->displayMode() != QStyleSheetItem::DisplayNone ) {
1937 hasNewPar = FALSE; 1854 hasNewPar = FALSE;
1938 int index = curpar->length() - 1; 1855 int index = QMAX( curpar->length(),1) - 1;
1939 if ( index < 0 )
1940 index = 0;
1941 curpar->append( s ); 1856 curpar->append( s );
1942 QTextFormat* f = formatCollection()->format( &curtag.format ); 1857 QTextFormat* f = formatCollection()->format( &curtag.format );
1943 curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already 1858 curpar->setFormat( index, s.length(), f, FALSE ); // do not use collection because we have done that already
1944 f->ref += s.length() -1; // that what friends are for... 1859 f->ref += s.length() -1; // that what friends are for...
1945 if ( !curtag.anchorHref.isEmpty() ) { 1860 if ( !curtag.anchorHref.isEmpty() ) {
1946 for ( int i = 0; i < int(s.length()); i++ ) 1861 for ( int i = 0; i < int(s.length()); i++ )
1947 curpar->at(index + i)->setAnchor( QString::null, curtag.anchorHref ); 1862 curpar->at(index + i)->setAnchor( QString::null, curtag.anchorHref );
1948 } 1863 }
1949 if ( !anchorName.isEmpty() ) { 1864 if ( !anchorName.isEmpty() ) {
1950 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() ); 1865 curpar->at(index)->setAnchor( anchorName, curpar->at(index)->anchorHref() );
1951 anchorName = QString::null; 1866 anchorName = QString::null;
1952 } 1867 }
1953 } 1868 }
1954 if ( c == '\n' ) { // happens in WhiteSpacePre mode
1955 hasNewPar = FALSE;
1956 tags.push( curtag );
1957 NEWPAR;
1958 curtag = tags.pop();
1959 }
1960 } 1869 }
1961 } 1870 }
1962 1871 if ( hasNewPar && curpar != fParag && !cursor ) {
1963 if ( hasNewPar && curpar != fParag ) {
1964 // cleanup unused last paragraphs 1872 // cleanup unused last paragraphs
1965 curpar = curpar->p; 1873 curpar = curpar->p;
1966 delete curpar->n; 1874 delete curpar->n;
1967 } 1875 }
1968
1969 if ( !anchorName.isEmpty() ) { 1876 if ( !anchorName.isEmpty() ) {
1970 curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() ); 1877 curpar->at(curpar->length() - 1)->setAnchor( anchorName, curpar->at( curpar->length() - 1 )->anchorHref() );
1971 anchorName = QString::null; 1878 anchorName = QString::null;
1972 } 1879 }
1880
1881
1882 setRichTextMarginsInternal( styles, stylesPar );
1883
1884 if ( cursor ) {
1885 cursor->gotoPreviousLetter();
1886 cursor->remove();
1887 }
1888
1889}
1890
1891void QTextDocument::setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar )
1892{
1893 // margin and line spacing calculation
1894 QPtrVector<QStyleSheetItem>* prevStyle = 0;
1895 QPtrVector<QStyleSheetItem>* curStyle = styles.first();
1896 QPtrVector<QStyleSheetItem>* nextStyle = styles.next();
1897 while ( stylesPar ) {
1898 if ( !curStyle ) {
1899 stylesPar = stylesPar->next();
1900 prevStyle = curStyle;
1901 curStyle = nextStyle;
1902 nextStyle = styles.next();
1903 continue;
1904 }
1905
1906 int i, mar;
1907 QStyleSheetItem* mainStyle = curStyle->size() ? (*curStyle)[curStyle->size()-1] : 0;
1908 if ( mainStyle && mainStyle->displayMode() == QStyleSheetItem::DisplayListItem )
1909 stylesPar->setListItem( TRUE );
1910 int numLists = 0;
1911 for ( i = 0; i < (int)curStyle->size(); ++i ) {
1912 if ( (*curStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock
1913 && int((*curStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined )
1914 numLists++;
1915 }
1916 stylesPar->ldepth = numLists;
1917 if ( stylesPar->next() && nextStyle ) {
1918 // also set the depth of the next paragraph, required for the margin calculation
1919 numLists = 0;
1920 for ( i = 0; i < (int)nextStyle->size(); ++i ) {
1921 if ( (*nextStyle)[ i ]->displayMode() == QStyleSheetItem::DisplayBlock
1922 && int((*nextStyle)[ i ]->listStyle()) != QStyleSheetItem::Undefined )
1923 numLists++;
1924 }
1925 stylesPar->next()->ldepth = numLists;
1926 }
1927
1928 // do the top margin
1929 QStyleSheetItem* item = mainStyle;
1930 int m;
1931 if (stylesPar->utm > 0 ) {
1932 m = stylesPar->utm-1;
1933 stylesPar->utm = 0;
1934 } else {
1935 m = QMAX(0, item->margin( QStyleSheetItem::MarginTop ) );
1936 if ( item->displayMode() == QStyleSheetItem::DisplayListItem
1937 && stylesPar->ldepth )
1938 m /= stylesPar->ldepth;
1939 }
1940 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1941 item = (*curStyle)[ i ];
1942 if ( prevStyle && i < (int) prevStyle->size() &&
1943 ( item->displayMode() == QStyleSheetItem::DisplayBlock &&
1944 (*prevStyle)[ i ] == item ) )
1945 break;
1946 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags
1947 if ( int(item->listStyle()) != QStyleSheetItem::Undefined &&
1948 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) )
1949 continue;
1950 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginTop ) );
1951 m = QMAX( m, mar );
1952 }
1953 stylesPar->utm = m - stylesPar->topMargin();
1954
1955 // do the bottom margin
1956 item = mainStyle;
1957 if (stylesPar->ubm > 0 ) {
1958 m = stylesPar->ubm-1;
1959 stylesPar->ubm = 0;
1960 } else {
1961 m = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) );
1962 if ( item->displayMode() == QStyleSheetItem::DisplayListItem
1963 && stylesPar->ldepth )
1964 m /= stylesPar->ldepth;
1965 }
1966 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1967 item = (*curStyle)[ i ];
1968 if ( nextStyle && i < (int) nextStyle->size() &&
1969 ( item->displayMode() == QStyleSheetItem::DisplayBlock &&
1970 (*nextStyle)[ i ] == item ) )
1971 break;
1972 // emulate CSS2' standard 0 vertical margin for multiple ul or ol tags
1973 if ( int(item->listStyle()) != QStyleSheetItem::Undefined &&
1974 ( ( i> 0 && (*curStyle)[ i-1 ] == item ) || (*curStyle)[i+1] == item ) )
1975 continue;
1976 mar = QMAX(0, item->margin( QStyleSheetItem::MarginBottom ) );
1977 m = QMAX( m, mar );
1978 }
1979 stylesPar->ubm = m - stylesPar->bottomMargin();
1980
1981 // do the left margin, simplyfied
1982 item = mainStyle;
1983 if (stylesPar->ulm > 0 ) {
1984 m = stylesPar->ulm-1;
1985 stylesPar->ulm = 0;
1986 } else {
1987 m = QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) );
1988 }
1989 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
1990 item = (*curStyle)[ i ];
1991 m += QMAX( 0, item->margin( QStyleSheetItem::MarginLeft ) );
1992 }
1993 stylesPar->ulm = m - stylesPar->leftMargin();
1994
1995 // do the right margin, simplyfied
1996 item = mainStyle;
1997 if (stylesPar->urm > 0 ) {
1998 m = stylesPar->urm-1;
1999 stylesPar->urm = 0;
2000 } else {
2001 m = QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) );
2002 }
2003 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
2004 item = (*curStyle)[ i ];
2005 m += QMAX( 0, item->margin( QStyleSheetItem::MarginRight ) );
2006 }
2007 stylesPar->urm = m - stylesPar->rightMargin();
2008
2009 // do the first line margin, which really should be called text-indent
2010 item = mainStyle;
2011 if (stylesPar->uflm > 0 ) {
2012 m = stylesPar->uflm-1;
2013 stylesPar->uflm = 0;
2014 } else {
2015 m = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) );
2016 }
2017 for ( i = (int)curStyle->size() - 2 ; i >= 0; --i ) {
2018 item = (*curStyle)[ i ];
2019 mar = QMAX( 0, item->margin( QStyleSheetItem::MarginFirstLine ) );
2020 m = QMAX( m, mar );
2021 }
2022 stylesPar->uflm =m - stylesPar->firstLineMargin();
2023
2024 // do the bogus line "spacing", which really is just an extra margin
2025 item = mainStyle;
2026 for ( i = (int)curStyle->size() - 1 ; i >= 0; --i ) {
2027 item = (*curStyle)[ i ];
2028 if ( item->lineSpacing() != QStyleSheetItem::Undefined ) {
2029 stylesPar->ulinespacing = item->lineSpacing();
2030 if ( formatCollection() &&
2031 stylesPar->ulinespacing < formatCollection()->defaultFormat()->height() )
2032 stylesPar->ulinespacing += formatCollection()->defaultFormat()->height();
2033 break;
2034 }
2035 }
2036
2037 stylesPar = stylesPar->next();
2038 prevStyle = curStyle;
2039 curStyle = nextStyle;
2040 nextStyle = styles.next();
2041 }
1973} 2042}
1974 2043
1975void QTextDocument::setText( const QString &text, const QString &context ) 2044void QTextDocument::setText( const QString &text, const QString &context )
1976{ 2045{
1977 focusIndicator.parag = 0; 2046 focusIndicator.parag = 0;
1978 selections.clear(); 2047 selections.clear();
1979 if ( txtFormat == Qt::AutoText && QStyleSheet::mightBeRichText( text ) || 2048 if ( txtFormat == Qt::AutoText && QStyleSheet::mightBeRichText( text ) ||
1980 txtFormat == Qt::RichText ) 2049 txtFormat == Qt::RichText )
1981 setRichText( text, context ); 2050 setRichText( text, context );
1982 else 2051 else
1983 setPlainText( text ); 2052 setPlainText( text );
1984} 2053}
1985 2054
1986QString QTextDocument::plainText( QTextParag *p ) const 2055QString QTextDocument::plainText() const
1987{ 2056{
1988 if ( !p ) { 2057 QString buffer;
1989 QString buffer; 2058 QString s;
1990 QString s; 2059 QTextParagraph *p = fParag;
1991 QTextParag *p = fParag; 2060 while ( p ) {
1992 while ( p ) { 2061 if ( !p->mightHaveCustomItems ) {
1993 if ( !p->mightHaveCustomItems ) { 2062 s = p->string()->toString();
1994 s = p->string()->toString(); 2063 } else {
1995 } else { 2064 for ( int i = 0; i < p->length() - 1; ++i ) {
1996 for ( int i = 0; i < p->length() - 1; ++i ) { 2065 if ( p->at( i )->isCustom() ) {
1997 if ( p->at( i )->isCustom() ) { 2066 if ( p->at( i )->customItem()->isNested() ) {
1998 if ( p->at( i )->customItem()->isNested() ) { 2067 s += "\n";
1999 s += "\n"; 2068 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2000 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2069 QPtrList<QTextTableCell> cells = t->tableCells();
2001 QPtrList<QTextTableCell> cells = t->tableCells(); 2070 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2002 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2071 s += c->richText()->plainText() + "\n";
2003 s += c->richText()->plainText() + "\n"; 2072 s += "\n";
2004 s += "\n";
2005 }
2006 } else {
2007 s += p->at( i )->c;
2008 } 2073 }
2074 } else {
2075 s += p->at( i )->c;
2009 } 2076 }
2010 } 2077 }
2011 s.remove( s.length() - 1, 1 );
2012 if ( p->next() )
2013 s += "\n";
2014 buffer += s;
2015 p = p->next();
2016 } 2078 }
2017 return buffer; 2079 s.remove( s.length() - 1, 1 );
2018 } else { 2080 if ( p->next() )
2019 return p->string()->toString(); 2081 s += "\n";
2082 buffer += s;
2083 p = p->next();
2020 } 2084 }
2085 return buffer;
2021} 2086}
2022 2087
2023static QString align_to_string( const QString &tag, int a ) 2088static QString align_to_string( int a )
2024{ 2089{
2025 if ( tag == "p" || tag == "li" || ( tag[0] == 'h' && tag[1].isDigit() ) ) { 2090 if ( a & Qt::AlignRight )
2026 if ( a & Qt::AlignRight ) 2091 return " align=\"right\"";
2027 return " align=\"right\""; 2092 if ( a & Qt::AlignHCenter )
2028 if ( a & Qt::AlignCenter ) 2093 return " align=\"center\"";
2029 return " align=\"center\""; 2094 if ( a & Qt3::AlignJustify )
2030 if ( a & Qt3::AlignJustify ) 2095 return " align=\"justify\"";
2031 return " align=\"justify\""; 2096 return QString::null;
2032 }
2033 return "";
2034} 2097}
2035 2098
2036static QString direction_to_string( const QString &tag, int d ) 2099static QString direction_to_string( int d )
2037{ 2100{
2038 if ( d != QChar::DirON && 2101 if ( d != QChar::DirON )
2039 ( tag == "p" || tag == "div" || tag == "li" || ( tag[0] == 'h' && tag[1].isDigit() ) ) )
2040 return ( d == QChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" ); 2102 return ( d == QChar::DirL? " dir=\"ltr\"" : " dir=\"rtl\"" );
2041 return ""; 2103 return QString::null;
2042} 2104}
2043 2105
2044QString QTextDocument::richText( QTextParag *p ) const 2106static QString list_value_to_string( int v )
2045{ 2107{
2046 QString s,n; 2108 if ( v != -1 )
2047 if ( !p ) { 2109 return " listvalue=\"" + QString::number( v ) + "\"";
2048 p = fParag; 2110 return QString::null;
2049 QPtrVector<QStyleSheetItem> lastItems, items; 2111}
2050 while ( p ) { 2112
2051 items = p->styleSheetItems(); 2113static QString list_style_to_string( int v )
2052 if ( items.size() ) { 2114{
2053 QStyleSheetItem *item = items[ items.size() - 1 ]; 2115 switch( v ) {
2054 items.resize( items.size() - 1 ); 2116 case QStyleSheetItem::ListDecimal: return "\"1\"";
2055 if ( items.size() > lastItems.size() ) { 2117 case QStyleSheetItem::ListLowerAlpha: return "\"a\"";
2056 for ( int i = lastItems.size(); i < (int)items.size(); ++i ) { 2118 case QStyleSheetItem::ListUpperAlpha: return "\"A\"";
2057 n = items[i]->name(); 2119 case QStyleSheetItem::ListDisc: return "\"disc\"";
2058 if ( n.isEmpty() || n == "li" ) 2120 case QStyleSheetItem::ListSquare: return "\"square\"";
2059 continue; 2121 case QStyleSheetItem::ListCircle: return "\"circle\"";
2060 s += "<" + n + align_to_string( n, p->alignment() ) + ">"; 2122 default:
2061 } 2123 return QString::null;
2062 } else { 2124 }
2063 QString end; 2125}
2064 for ( int i = items.size(); i < (int)lastItems.size(); ++i ) { 2126
2065 n = lastItems[i]->name(); 2127static inline bool list_is_ordered( int v )
2066 if ( n.isEmpty() || n == "li" || n == "br" ) 2128{
2067 continue; 2129 return v == QStyleSheetItem::ListDecimal ||
2068 end.prepend( "</" + lastItems[ i ]->name() + ">" ); 2130 v == QStyleSheetItem::ListLowerAlpha ||
2069 } 2131 v == QStyleSheetItem::ListUpperAlpha;
2070 s += end; 2132}
2071 } 2133
2072 lastItems = items; 2134
2073 n = item->name(); 2135static QString margin_to_string( QStyleSheetItem* style, int t, int b, int l, int r, int fl )
2074 if ( n == "li" && p->listValue() != -1 ) { 2136{
2075 s += "<li value=\"" + QString::number( p->listValue() ) + "\">"; 2137 QString s;
2076 } else { 2138 if ( l > 0 )
2077 QString ps = p->richText(); 2139 s += QString(!!s?";":"") + "margin-left:" + QString::number(l+QMAX(0,style->margin(QStyleSheetItem::MarginLeft))) + "px";
2078 if ( ps.isEmpty() ) 2140 if ( r > 0 )
2079 s += "<br>"; // empty paragraph 2141 s += QString(!!s?";":"") + "margin-right:" + QString::number(r+QMAX(0,style->margin(QStyleSheetItem::MarginRight))) + "px";
2080 else if ( !n.isEmpty() ) { 2142 if ( t > 0 )
2081 s += "<" + n + align_to_string( n, p->alignment() ) 2143 s += QString(!!s?";":"") + "margin-top:" + QString::number(t+QMAX(0,style->margin(QStyleSheetItem::MarginTop))) + "px";
2082 + direction_to_string( n, p->direction() ) + ">" + ps; 2144 if ( b > 0 )
2083 if ( n != "li" && n != "br") 2145 s += QString(!!s?";":"") + "margin-bottom:" + QString::number(b+QMAX(0,style->margin(QStyleSheetItem::MarginBottom))) + "px";
2084 s += "</" + n + ">"; 2146 if ( fl > 0 )
2085 } else 2147 s += QString(!!s?";":"") + "text-indent:" + QString::number(fl+QMAX(0,style->margin(QStyleSheetItem::MarginFirstLine))) + "px";
2086 s += ps; 2148 if ( !!s )
2087 } 2149 return " style=\"" + s + "\"";
2088 } else { 2150 return QString::null;
2089 QString end; 2151}
2090 for ( int i = 0; i < (int)lastItems.size(); ++i ) { 2152
2091 QString n = lastItems[i]->name(); 2153QString QTextDocument::richText() const
2092 if ( n.isEmpty() || n == "li" || n == "br" ) 2154{
2093 continue; 2155 QString s = "";
2094 end.prepend( "</" + n + ">" ); 2156 if ( !par ) {
2095 } 2157 s += "<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body style=\"font-size:" ;
2096 s += end; 2158 s += QString::number( formatCollection()->defaultFormat()->font().pointSize() );
2097 QString ps = p->richText(); 2159 s += "pt;font-family:";
2098 if ( ps.isEmpty() ) 2160 s += formatCollection()->defaultFormat()->font().family();
2099 s += "<br>"; // empty paragraph 2161 s +="\">";
2100 else 2162 }
2101 s += "<p" + align_to_string( "p", p->alignment() ) + direction_to_string( "p", p->direction() ) 2163 QTextParagraph* p = fParag;
2102 + ">" + ps + "</p>"; 2164
2103 lastItems = items; 2165 QStyleSheetItem* item_p = styleSheet()->item("p");
2166 QStyleSheetItem* item_ul = styleSheet()->item("ul");
2167 QStyleSheetItem* item_ol = styleSheet()->item("ol");
2168 QStyleSheetItem* item_li = styleSheet()->item("li");
2169 if ( !item_p || !item_ul || !item_ol || !item_li ) {
2170 qWarning( "QTextEdit: cannot export HTML due to insufficient stylesheet (lack of p, ul, ol, or li)" );
2171 return QString::null;
2172 }
2173 int pastListDepth = 0;
2174 int listDepth = 0;
2175 int futureListDepth = 0;
2176 QMemArray<int> listStyles(10);
2177
2178 while ( p ) {
2179 listDepth = p->listDepth();
2180 if ( listDepth < pastListDepth ) {
2181 for ( int i = listDepth+1; i <= pastListDepth; i++ )
2182 s += list_is_ordered( listStyles[i] ) ? "</ol>" : "</ul>";
2183 s += '\n';
2184 } else if ( listDepth > pastListDepth ) {
2185 s += '\n';
2186 listStyles.resize( QMAX( (int)listStyles.size(), listDepth+1 ) );
2187 QString list_type;
2188 listStyles[listDepth] = p->listStyle();
2189 if ( !list_is_ordered( p->listStyle() ) || item_ol->listStyle() != p->listStyle() )
2190 list_type = " type=" + list_style_to_string( p->listStyle() );
2191 for ( int i = pastListDepth; i < listDepth; i++ ) {
2192 s += list_is_ordered( p->listStyle() ) ? "<ol" : "<ul" ;
2193 s += list_type + ">";
2104 } 2194 }
2105 if ( ( p = p->next() ) ) 2195 } else {
2106 s += '\n'; 2196 s += '\n';
2107 } 2197 }
2108 } else { 2198
2109 s = p->richText(); 2199 QString ps = p->richText();
2200
2201 // for the bottom margin we need to know whether we are at the end of a list
2202 futureListDepth = 0;
2203 if ( listDepth > 0 && p->next() )
2204 futureListDepth = p->next()->listDepth();
2205
2206 if ( richTextExportStart && richTextExportStart->paragraph() ==p &&
2207 richTextExportStart->index() == 0 )
2208 s += "<selstart/>";
2209
2210 if ( p->isListItem() ) {
2211 s += "<li";
2212 if ( p->listStyle() != listStyles[listDepth] )
2213 s += " type=" + list_style_to_string( p->listStyle() );
2214 s +=align_to_string( p->alignment() );
2215 s += margin_to_string( item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm );
2216 s += list_value_to_string( p->listValue() );
2217 s += direction_to_string( p->direction() );
2218 s +=">";
2219 s += ps;
2220 s += "</li>";
2221 } else {
2222 // normal paragraph item
2223 s += "<p";
2224 s += align_to_string( p->alignment() );
2225 s += margin_to_string( item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm );
2226 s +=direction_to_string( p->direction() );
2227 s += ">";
2228 s += ps;
2229 s += "</p>";
2230 }
2231 pastListDepth = listDepth;
2232 p = p->next();
2233 }
2234 while ( listDepth > 0 ) {
2235 s += list_is_ordered( listStyles[listDepth] ) ? "</ol>" : "</ul>";
2236 listDepth--;
2110 } 2237 }
2111 2238
2239 if ( !par )
2240 s += "\n</body></html>\n";
2241
2112 return s; 2242 return s;
2113} 2243}
2114 2244
2115QString QTextDocument::text() const 2245QString QTextDocument::text() const
2116{ 2246{
2117 if ( plainText().simplifyWhiteSpace().isEmpty() )
2118 return QString("");
2119 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) 2247 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText )
2120 return richText(); 2248 return richText();
2121 return plainText( 0 ); 2249 return plainText();
2122} 2250}
2123 2251
2124QString QTextDocument::text( int parag ) const 2252QString QTextDocument::text( int parag ) const
2125{ 2253{
2126 QTextParag *p = paragAt( parag ); 2254 QTextParagraph *p = paragAt( parag );
2127 if ( !p ) 2255 if ( !p )
2128 return QString::null; 2256 return QString::null;
2129 2257
2130 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText ) 2258 if ( txtFormat == Qt::AutoText && preferRichText || txtFormat == Qt::RichText )
2131 return richText( p ); 2259 return p->richText();
2132 else 2260 else
2133 return plainText( p ); 2261 return p->string()->toString();
2134} 2262}
2135 2263
2136void QTextDocument::invalidate() 2264void QTextDocument::invalidate()
2137{ 2265{
2138 QTextParag *s = fParag; 2266 QTextParagraph *s = fParag;
2139 while ( s ) { 2267 while ( s ) {
2140 s->invalidate( 0 ); 2268 s->invalidate( 0 );
2141 s = s->next(); 2269 s = s->next();
2142 } 2270 }
2143} 2271}
2144 2272
2145void QTextDocument::selectionStart( int id, int &paragId, int &index ) 2273void QTextDocument::selectionStart( int id, int &paragId, int &index )
2146{ 2274{
2147 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2275 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2148 if ( it == selections.end() ) 2276 if ( it == selections.end() )
2149 return; 2277 return;
2150 QTextDocumentSelection &sel = *it; 2278 QTextDocumentSelection &sel = *it;
2151 paragId = !sel.swapped ? sel.startCursor.parag()->paragId() : sel.endCursor.parag()->paragId(); 2279 paragId = !sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId();
2152 index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); 2280 index = !sel.swapped ? sel.startCursor.index() : sel.endCursor.index();
2153} 2281}
2154 2282
2155QTextCursor QTextDocument::selectionStartCursor( int id) 2283QTextCursor QTextDocument::selectionStartCursor( int id)
2156{ 2284{
2157 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2285 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2158 if ( it == selections.end() ) 2286 if ( it == selections.end() )
2159 return QTextCursor( this ); 2287 return QTextCursor( this );
2160 QTextDocumentSelection &sel = *it; 2288 QTextDocumentSelection &sel = *it;
2161 if ( sel.swapped ) 2289 if ( sel.swapped )
2162 return sel.endCursor; 2290 return sel.endCursor;
2163 return sel.startCursor; 2291 return sel.startCursor;
2164} 2292}
2165 2293
2166QTextCursor QTextDocument::selectionEndCursor( int id) 2294QTextCursor QTextDocument::selectionEndCursor( int id)
2167{ 2295{
2168 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2296 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2169 if ( it == selections.end() ) 2297 if ( it == selections.end() )
2170 return QTextCursor( this ); 2298 return QTextCursor( this );
2171 QTextDocumentSelection &sel = *it; 2299 QTextDocumentSelection &sel = *it;
2172 if ( !sel.swapped ) 2300 if ( !sel.swapped )
2173 return sel.endCursor; 2301 return sel.endCursor;
2174 return sel.startCursor; 2302 return sel.startCursor;
2175} 2303}
2176 2304
2177void QTextDocument::selectionEnd( int id, int &paragId, int &index ) 2305void QTextDocument::selectionEnd( int id, int &paragId, int &index )
2178{ 2306{
2179 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2307 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2180 if ( it == selections.end() ) 2308 if ( it == selections.end() )
2181 return; 2309 return;
2182 QTextDocumentSelection &sel = *it; 2310 QTextDocumentSelection &sel = *it;
2183 paragId = sel.swapped ? sel.startCursor.parag()->paragId() : sel.endCursor.parag()->paragId(); 2311 paragId = sel.swapped ? sel.startCursor.paragraph()->paragId() : sel.endCursor.paragraph()->paragId();
2184 index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index(); 2312 index = sel.swapped ? sel.startCursor.index() : sel.endCursor.index();
2185} 2313}
2186 2314
2187QTextParag *QTextDocument::selectionStart( int id )
2188{
2189 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2190 if ( it == selections.end() )
2191 return 0;
2192 QTextDocumentSelection &sel = *it;
2193 if ( sel.startCursor.parag()->paragId() < sel.endCursor.parag()->paragId() )
2194 return sel.startCursor.parag();
2195 return sel.endCursor.parag();
2196}
2197
2198QTextParag *QTextDocument::selectionEnd( int id )
2199{
2200 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2201 if ( it == selections.end() )
2202 return 0;
2203 QTextDocumentSelection &sel = *it;
2204 if ( sel.startCursor.parag()->paragId() > sel.endCursor.parag()->paragId() )
2205 return sel.startCursor.parag();
2206 return sel.endCursor.parag();
2207}
2208
2209void QTextDocument::addSelection( int id ) 2315void QTextDocument::addSelection( int id )
2210{ 2316{
2211 nSelections = QMAX( nSelections, id + 1 ); 2317 nSelections = QMAX( nSelections, id + 1 );
2212} 2318}
2213 2319
2214static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCursor &start, QTextCursor &end ) 2320static void setSelectionEndHelper( int id, QTextDocumentSelection &sel, QTextCursor &start, QTextCursor &end )
2215{ 2321{
2216 QTextCursor c1 = start; 2322 QTextCursor c1 = start;
2217 QTextCursor c2 = end; 2323 QTextCursor c2 = end;
2218 if ( sel.swapped ) { 2324 if ( sel.swapped ) {
2219 c1 = end; 2325 c1 = end;
2220 c2 = start; 2326 c2 = start;
2221 } 2327 }
2222 2328
2223 c1.parag()->removeSelection( id ); 2329 c1.paragraph()->removeSelection( id );
2224 c2.parag()->removeSelection( id ); 2330 c2.paragraph()->removeSelection( id );
2225 if ( c1.parag() != c2.parag() ) { 2331 if ( c1.paragraph() != c2.paragraph() ) {
2226 c1.parag()->setSelection( id, c1.index(), c1.parag()->length() - 1 ); 2332 c1.paragraph()->setSelection( id, c1.index(), c1.paragraph()->length() - 1 );
2227 c2.parag()->setSelection( id, 0, c2.index() ); 2333 c2.paragraph()->setSelection( id, 0, c2.index() );
2228 } else { 2334 } else {
2229 c1.parag()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) ); 2335 c1.paragraph()->setSelection( id, QMIN( c1.index(), c2.index() ), QMAX( c1.index(), c2.index() ) );
2230 } 2336 }
2231 2337
2232 sel.startCursor = start; 2338 sel.startCursor = start;
2233 sel.endCursor = end; 2339 sel.endCursor = end;
2234 if ( sel.startCursor.parag() == sel.endCursor.parag() ) 2340 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() )
2235 sel.swapped = sel.startCursor.index() > sel.endCursor.index(); 2341 sel.swapped = sel.startCursor.index() > sel.endCursor.index();
2236} 2342}
2237 2343
2238bool QTextDocument::setSelectionEnd( int id, QTextCursor *cursor ) 2344bool QTextDocument::setSelectionEnd( int id, const QTextCursor &cursor )
2239{ 2345{
2240 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2346 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2241 if ( it == selections.end() ) 2347 if ( it == selections.end() )
2242 return FALSE; 2348 return FALSE;
2243 QTextDocumentSelection &sel = *it; 2349 QTextDocumentSelection &sel = *it;
2244 2350
2245 QTextCursor start = sel.startCursor; 2351 QTextCursor start = sel.startCursor;
2246 QTextCursor end = *cursor; 2352 QTextCursor end = cursor;
2247 2353
2248 if ( start == end ) { 2354 if ( start == end ) {
2249 removeSelection( id ); 2355 removeSelection( id );
2250 setSelectionStart( id, cursor ); 2356 setSelectionStart( id, cursor );
2251 return TRUE; 2357 return TRUE;
2252 } 2358 }
2253 2359
2254 if ( sel.endCursor.parag() == end.parag() ) { 2360 if ( sel.endCursor.paragraph() == end.paragraph() ) {
2255 setSelectionEndHelper( id, sel, start, end ); 2361 setSelectionEndHelper( id, sel, start, end );
2256 return TRUE; 2362 return TRUE;
2257 } 2363 }
2258 2364
2259 bool inSelection = FALSE; 2365 bool inSelection = FALSE;
2260 QTextCursor c( this ); 2366 QTextCursor c( this );
2261 QTextCursor tmp = sel.startCursor; 2367 QTextCursor tmp = sel.startCursor;
2262 if ( sel.swapped ) 2368 if ( sel.swapped )
2263 tmp = sel.endCursor; 2369 tmp = sel.endCursor;
2264 tmp.restoreState(); 2370 tmp.restoreState();
2265 QTextCursor tmp2 = *cursor; 2371 QTextCursor tmp2 = cursor;
2266 tmp2.restoreState(); 2372 tmp2.restoreState();
2267 c.setParag( tmp.parag()->paragId() < tmp2.parag()->paragId() ? tmp.parag() : tmp2.parag() ); 2373 c.setParagraph( tmp.paragraph()->paragId() < tmp2.paragraph()->paragId() ? tmp.paragraph() : tmp2.paragraph() );
2268 QTextCursor old;
2269 bool hadStart = FALSE; 2374 bool hadStart = FALSE;
2270 bool hadEnd = FALSE; 2375 bool hadEnd = FALSE;
2271 bool hadStartParag = FALSE; 2376 bool hadStartParag = FALSE;
2272 bool hadEndParag = FALSE; 2377 bool hadEndParag = FALSE;
2273 bool hadOldStart = FALSE; 2378 bool hadOldStart = FALSE;
2274 bool hadOldEnd = FALSE; 2379 bool hadOldEnd = FALSE;
2275 bool leftSelection = FALSE; 2380 bool leftSelection = FALSE;
2276 sel.swapped = FALSE; 2381 sel.swapped = FALSE;
2277 for ( ;; ) { 2382 for ( ;; ) {
2278 if ( c == start ) 2383 if ( c == start )
2279 hadStart = TRUE; 2384 hadStart = TRUE;
2280 if ( c == end ) 2385 if ( c == end )
2281 hadEnd = TRUE; 2386 hadEnd = TRUE;
2282 if ( c.parag() == start.parag() ) 2387 if ( c.paragraph() == start.paragraph() )
2283 hadStartParag = TRUE; 2388 hadStartParag = TRUE;
2284 if ( c.parag() == end.parag() ) 2389 if ( c.paragraph() == end.paragraph() )
2285 hadEndParag = TRUE; 2390 hadEndParag = TRUE;
2286 if ( c == sel.startCursor ) 2391 if ( c == sel.startCursor )
2287 hadOldStart = TRUE; 2392 hadOldStart = TRUE;
2288 if ( c == sel.endCursor ) 2393 if ( c == sel.endCursor )
2289 hadOldEnd = TRUE; 2394 hadOldEnd = TRUE;
2290 2395
2291 if ( !sel.swapped && 2396 if ( !sel.swapped &&
2292 ( hadEnd && !hadStart || 2397 ( hadEnd && !hadStart ||
2293 hadEnd && hadStart && start.parag() == end.parag() && start.index() > end.index() ) ) 2398 hadEnd && hadStart && start.paragraph() == end.paragraph() && start.index() > end.index() ) )
2294 sel.swapped = TRUE; 2399 sel.swapped = TRUE;
2295 2400
2296 if ( c == end && hadStartParag || 2401 if ( c == end && hadStartParag ||
2297 c == start && hadEndParag ) { 2402 c == start && hadEndParag ) {
2298 QTextCursor tmp = c; 2403 QTextCursor tmp = c;
2299 tmp.restoreState(); 2404 tmp.restoreState();
2300 if ( tmp.parag() != c.parag() ) { 2405 if ( tmp.paragraph() != c.paragraph() ) {
2301 int sstart = tmp.parag()->selectionStart( id ); 2406 int sstart = tmp.paragraph()->selectionStart( id );
2302 tmp.parag()->removeSelection( id ); 2407 tmp.paragraph()->removeSelection( id );
2303 tmp.parag()->setSelection( id, sstart, tmp.index() ); 2408 tmp.paragraph()->setSelection( id, sstart, tmp.index() );
2304 } 2409 }
2305 } 2410 }
2306 2411
2307 if ( inSelection && 2412 if ( inSelection &&
2308 ( c == end && hadStart || c == start && hadEnd ) ) 2413 ( c == end && hadStart || c == start && hadEnd ) )
2309 leftSelection = TRUE; 2414 leftSelection = TRUE;
2310 else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) ) 2415 else if ( !leftSelection && !inSelection && ( hadStart || hadEnd ) )
2311 inSelection = TRUE; 2416 inSelection = TRUE;
2312 2417
2313 bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.parag()->hasSelection( id ) && c.atParagEnd(); 2418 bool noSelectionAnymore = hadOldStart && hadOldEnd && leftSelection && !inSelection && !c.paragraph()->hasSelection( id ) && c.atParagEnd();
2314 c.parag()->removeSelection( id ); 2419 c.paragraph()->removeSelection( id );
2315 if ( inSelection ) { 2420 if ( inSelection ) {
2316 if ( c.parag() == start.parag() && start.parag() == end.parag() ) { 2421 if ( c.paragraph() == start.paragraph() && start.paragraph() == end.paragraph() ) {
2317 c.parag()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) ); 2422 c.paragraph()->setSelection( id, QMIN( start.index(), end.index() ), QMAX( start.index(), end.index() ) );
2318 } else if ( c.parag() == start.parag() && !hadEndParag ) { 2423 } else if ( c.paragraph() == start.paragraph() && !hadEndParag ) {
2319 c.parag()->setSelection( id, start.index(), c.parag()->length() - 1 ); 2424 c.paragraph()->setSelection( id, start.index(), c.paragraph()->length() - 1 );
2320 } else if ( c.parag() == end.parag() && !hadStartParag ) { 2425 } else if ( c.paragraph() == end.paragraph() && !hadStartParag ) {
2321 c.parag()->setSelection( id, end.index(), c.parag()->length() - 1 ); 2426 c.paragraph()->setSelection( id, end.index(), c.paragraph()->length() - 1 );
2322 } else if ( c.parag() == end.parag() && hadEndParag ) { 2427 } else if ( c.paragraph() == end.paragraph() && hadEndParag ) {
2323 c.parag()->setSelection( id, 0, end.index() ); 2428 c.paragraph()->setSelection( id, 0, end.index() );
2324 } else if ( c.parag() == start.parag() && hadStartParag ) { 2429 } else if ( c.paragraph() == start.paragraph() && hadStartParag ) {
2325 c.parag()->setSelection( id, 0, start.index() ); 2430 c.paragraph()->setSelection( id, 0, start.index() );
2326 } else { 2431 } else {
2327 c.parag()->setSelection( id, 0, c.parag()->length() - 1 ); 2432 c.paragraph()->setSelection( id, 0, c.paragraph()->length() - 1 );
2328 } 2433 }
2329 } 2434 }
2330 2435
2331 if ( leftSelection ) 2436 if ( leftSelection )
2332 inSelection = FALSE; 2437 inSelection = FALSE;
2333 2438
2334 old = c; 2439 if ( noSelectionAnymore )
2335 c.gotoNextLetter();
2336 if ( old == c || noSelectionAnymore )
2337 break; 2440 break;
2441 // *ugle*hack optimization
2442 QTextParagraph *p = c.paragraph();
2443 if ( p->mightHaveCustomItems || p == start.paragraph() || p == end.paragraph() || p == lastParagraph() ) {
2444 c.gotoNextLetter();
2445 if ( p == lastParagraph() && c.atParagEnd() )
2446 break;
2447 } else {
2448 if ( p->document()->parent() )
2449 do {
2450 c.gotoNextLetter();
2451 } while ( c.paragraph() == p );
2452 else
2453 c.setParagraph( p->next() );
2454 }
2338 } 2455 }
2339 2456
2340 if ( !sel.swapped ) 2457 if ( !sel.swapped )
2341 sel.startCursor.parag()->setSelection( id, sel.startCursor.index(), sel.startCursor.parag()->length() - 1 ); 2458 sel.startCursor.paragraph()->setSelection( id, sel.startCursor.index(), sel.startCursor.paragraph()->length() - 1 );
2342 2459
2343 sel.startCursor = start; 2460 sel.startCursor = start;
2344 sel.endCursor = end; 2461 sel.endCursor = end;
2345 if ( sel.startCursor.parag() == sel.endCursor.parag() ) 2462 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() )
2346 sel.swapped = sel.startCursor.index() > sel.endCursor.index(); 2463 sel.swapped = sel.startCursor.index() > sel.endCursor.index();
2347 2464
2348 setSelectionEndHelper( id, sel, start, end ); 2465 setSelectionEndHelper( id, sel, start, end );
2349 2466
2350 return TRUE; 2467 return TRUE;
2351} 2468}
2352 2469
2353void QTextDocument::selectAll( int id ) 2470void QTextDocument::selectAll( int id )
2354{ 2471{
2355 removeSelection( id ); 2472 removeSelection( id );
2356 2473
2357 QTextDocumentSelection sel; 2474 QTextDocumentSelection sel;
2358 sel.swapped = FALSE; 2475 sel.swapped = FALSE;
2359 QTextCursor c( this ); 2476 QTextCursor c( this );
2360 2477
2361 c.setParag( fParag ); 2478 c.setParagraph( fParag );
2362 c.setIndex( 0 ); 2479 c.setIndex( 0 );
2363 sel.startCursor = c; 2480 sel.startCursor = c;
2364 2481
2365 c.setParag( lParag ); 2482 c.setParagraph( lParag );
2366 c.setIndex( lParag->length() - 1 ); 2483 c.setIndex( lParag->length() - 1 );
2367 sel.endCursor = c; 2484 sel.endCursor = c;
2368 2485
2369 QTextParag *p = fParag; 2486 selections.insert( id, sel );
2487
2488 QTextParagraph *p = fParag;
2370 while ( p ) { 2489 while ( p ) {
2371 p->setSelection( id, 0, p->length() - 1 ); 2490 p->setSelection( id, 0, p->length() - 1 );
2372 for ( int i = 0; i < (int)p->length(); ++i ) {
2373 if ( p->at( i )->isCustom() && p->at( i )->customItem()->isNested() ) {
2374 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2375 QPtrList<QTextTableCell> tableCells = t->tableCells();
2376 for ( QTextTableCell *c = tableCells.first(); c; c = tableCells.next() )
2377 c->richText()->selectAll( id );
2378 }
2379 }
2380 p = p->next(); 2491 p = p->next();
2381 } 2492 }
2382 2493
2383 selections.insert( id, sel ); 2494 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
2495 d->selectAll( id );
2384} 2496}
2385 2497
2386bool QTextDocument::removeSelection( int id ) 2498bool QTextDocument::removeSelection( int id )
2387{ 2499{
2388 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2500 if ( !selections.contains( id ) )
2389 if ( it == selections.end() )
2390 return FALSE; 2501 return FALSE;
2391 2502
2392 QTextDocumentSelection &sel = *it; 2503 QTextDocumentSelection &sel = selections[ id ];
2393
2394 if ( sel.startCursor == sel.endCursor ) {
2395 selections.remove( id );
2396 return TRUE;
2397 }
2398
2399 if ( !mightHaveCustomItems ) {
2400 QTextCursor start = sel.startCursor;
2401 QTextCursor end = sel.endCursor;
2402 if ( sel.swapped ) {
2403 start = sel.endCursor;
2404 end = sel.startCursor;
2405 }
2406 2504
2407 for ( QTextParag *p = start.parag(); p; p = p->next() ) { 2505 QTextCursor start = sel.swapped ? sel.endCursor : sel.startCursor;
2506 QTextCursor end = sel.swapped ? sel.startCursor : sel.endCursor;
2507 QTextParagraph* p = 0;
2508 while ( start != end ) {
2509 if ( p != start.paragraph() ) {
2510 p = start.paragraph();
2408 p->removeSelection( id ); 2511 p->removeSelection( id );
2409 if ( p == end.parag() )
2410 break;
2411 } 2512 }
2412 2513 start.gotoNextLetter();
2413 selections.remove( id );
2414 return TRUE;
2415 }
2416
2417 QTextCursor c( this );
2418 QTextCursor tmp = sel.startCursor;
2419 if ( sel.swapped )
2420 tmp = sel.endCursor;
2421 tmp.restoreState();
2422 c.setParag( tmp.parag() );
2423 QTextCursor old;
2424 bool hadStart = FALSE;
2425 bool hadEnd = FALSE;
2426 QTextParag *lastParag = 0;
2427 bool leftSelection = FALSE;
2428 bool inSelection = FALSE;
2429 sel.swapped = FALSE;
2430 for ( ;; ) {
2431 if ( c.parag() == sel.startCursor.parag() )
2432 hadStart = TRUE;
2433 if ( c.parag() == sel.endCursor.parag() )
2434 hadEnd = TRUE;
2435
2436 if ( inSelection &&
2437 ( c == sel.endCursor && hadStart || c == sel.startCursor && hadEnd ) )
2438 leftSelection = TRUE;
2439 else if ( !leftSelection && !inSelection && ( c.parag() == sel.startCursor.parag() || c.parag() == sel.endCursor.parag() ) )
2440 inSelection = TRUE;
2441
2442 bool noSelectionAnymore = leftSelection && !inSelection && !c.parag()->hasSelection( id ) && c.atParagEnd();
2443
2444 if ( lastParag != c.parag() )
2445 c.parag()->removeSelection( id );
2446
2447 old = c;
2448 lastParag = c.parag();
2449 c.gotoNextLetter();
2450 if ( old == c || noSelectionAnymore )
2451 break;
2452 } 2514 }
2453
2454 selections.remove( id ); 2515 selections.remove( id );
2455 return TRUE; 2516 return TRUE;
2456} 2517}
2457 2518
2458QString QTextDocument::selectedText( int id, bool withCustom ) const 2519QString QTextDocument::selectedText( int id, bool asRichText ) const
2459{ 2520{
2460 // ######## TODO: look at textFormat() and return rich text or plain text (like the text() method!)
2461 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id ); 2521 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id );
2462 if ( it == selections.end() ) 2522 if ( it == selections.end() )
2463 return QString::null; 2523 return QString::null;
2464 2524
2465 QTextDocumentSelection sel = *it; 2525 QTextDocumentSelection sel = *it;
2466 2526
2467 2527
2468 QTextCursor c1 = sel.startCursor; 2528 QTextCursor c1 = sel.startCursor;
2469 QTextCursor c2 = sel.endCursor; 2529 QTextCursor c2 = sel.endCursor;
2470 if ( sel.swapped ) { 2530 if ( sel.swapped ) {
2471 c2 = sel.startCursor; 2531 c2 = sel.startCursor;
2472 c1 = sel.endCursor; 2532 c1 = sel.endCursor;
2473 } 2533 }
2474 2534
2475 /* 3.0.3 improvement: Make it possible to get a reasonable 2535 /* 3.0.3 improvement: Make it possible to get a reasonable
2476 selection inside a table. This approach is very conservative: 2536 selection inside a table. This approach is very conservative:
2477 make sure that both cursors have the same depth level and point 2537 make sure that both cursors have the same depth level and point
2478 to paragraphs within the same text document. 2538 to paragraphs within the same text document.
2479 2539
2480 Meaning if you select text in two table cells, you will get the 2540 Meaning if you select text in two table cells, you will get the
2481 entire table. This is still far better than the 3.0.2, where 2541 entire table. This is still far better than the 3.0.2, where
2482 you always got the entire table. 2542 you always got the entire table.
2483 2543
2484 ### Fix this properly for 3.0.4. 2544 ### Fix this properly when refactoring
2485 */ 2545 */
2486 while ( c2.nestedDepth() > c1.nestedDepth() ) 2546 while ( c2.nestedDepth() > c1.nestedDepth() )
2487 c2.oneUp(); 2547 c2.oneUp();
2488 while ( c1.nestedDepth() > c2.nestedDepth() ) 2548 while ( c1.nestedDepth() > c2.nestedDepth() )
2489 c1.oneUp(); 2549 c1.oneUp();
2490 while ( c1.nestedDepth() && c2.nestedDepth() && 2550 while ( c1.nestedDepth() && c2.nestedDepth() &&
2491 c1.parag()->document() != c2.parag()->document() ) { 2551 c1.paragraph()->document() != c2.paragraph()->document() ) {
2492 c1.oneUp(); 2552 c1.oneUp();
2493 c2.oneUp(); 2553 c2.oneUp();
2494 } 2554 }
2495 // do not trust sel_swapped with tables. Fix this properly for 3.0.4 as well 2555 // do not trust sel_swapped with tables. Fix this properly when refactoring as well
2496 if ( c1.parag()->paragId() > c2.parag()->paragId() || 2556 if ( c1.paragraph()->paragId() > c2.paragraph()->paragId() ||
2497 (c1.parag() == c2.parag() && c1.index() > c2.index() ) ) { 2557 (c1.paragraph() == c2.paragraph() && c1.index() > c2.index() ) ) {
2498 QTextCursor tmp = c1; 2558 QTextCursor tmp = c1;
2499 c2 = c1; 2559 c2 = c1;
2500 c1 = tmp; 2560 c1 = tmp;
2501 } 2561 }
2502 2562
2503 // end selection 3.0.3 improvement 2563 // end selection 3.0.3 improvement
2504 2564
2565 if ( asRichText && !parent() ) {
2566 richTextExportStart = &c1;
2567 richTextExportEnd = &c2;
2505 2568
2506 if ( c1.parag() == c2.parag() ) { 2569 QString sel = richText();
2507 QString s; 2570 int from = sel.find( "<selstart/>" );
2508 QTextParag *p = c1.parag(); 2571 int to = sel.findRev( "<selend/>" );
2572 if ( from >= 0 && from <= to )
2573 sel = sel.mid( from, to - from );
2574 richTextExportStart = richTextExportEnd = 0;
2575 return sel;
2576 }
2577
2578 QString s;
2579 if ( c1.paragraph() == c2.paragraph() ) {
2580 QTextParagraph *p = c1.paragraph();
2509 int end = c2.index(); 2581 int end = c2.index();
2510 if ( p->at( QMAX( 0, end - 1 ) )->isCustom() ) 2582 if ( p->at( QMAX( 0, end - 1 ) )->isCustom() )
2511 ++end; 2583 ++end;
2512 if ( !withCustom || !p->mightHaveCustomItems ) { 2584 if ( !p->mightHaveCustomItems ) {
2513 s += p->string()->toString().mid( c1.index(), end - c1.index() ); 2585 s += p->string()->toString().mid( c1.index(), end - c1.index() );
2514 } else { 2586 } else {
2515 for ( int i = c1.index(); i < end; ++i ) { 2587 for ( int i = c1.index(); i < end; ++i ) {
2516 if ( p->at( i )->isCustom() ) { 2588 if ( p->at( i )->isCustom() ) {
2517 if ( p->at( i )->customItem()->isNested() ) { 2589 if ( p->at( i )->customItem()->isNested() ) {
2518 s += "\n"; 2590 s += "\n";
2519 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2591 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2520 QPtrList<QTextTableCell> cells = t->tableCells(); 2592 QPtrList<QTextTableCell> cells = t->tableCells();
2521 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2593 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2522 s += c->richText()->plainText() + "\n"; 2594 s += c->richText()->plainText() + "\n";
2523 s += "\n"; 2595 s += "\n";
2524 } 2596 }
2525 } else { 2597 } else {
2526 s += p->at( i )->c; 2598 s += p->at( i )->c;
2527 } 2599 }
2528 } 2600 }
2529 } 2601 }
2530 return s; 2602 } else {
2531 } 2603 QTextParagraph *p = c1.paragraph();
2532 2604 int start = c1.index();
2533 QString s; 2605 while ( p ) {
2534 QTextParag *p = c1.parag(); 2606 int end = p == c2.paragraph() ? c2.index() : p->length() - 1;
2535 int start = c1.index(); 2607 if ( p == c2.paragraph() && p->at( QMAX( 0, end - 1 ) )->isCustom() )
2536 while ( p ) { 2608 ++end;
2537 int end = p == c2.parag() ? c2.index() : p->length() - 1; 2609 if ( !p->mightHaveCustomItems ) {
2538 if ( p == c2.parag() && p->at( QMAX( 0, end - 1 ) )->isCustom() ) 2610 s += p->string()->toString().mid( start, end - start );
2539 ++end; 2611 if ( p != c2.paragraph() )
2540 if ( !withCustom || !p->mightHaveCustomItems ) { 2612 s += "\n";
2541 s += p->string()->toString().mid( start, end - start ); 2613 } else {
2542 if ( p != c2.parag() ) 2614 for ( int i = start; i < end; ++i ) {
2543 s += "\n"; 2615 if ( p->at( i )->isCustom() ) {
2544 } else { 2616 if ( p->at( i )->customItem()->isNested() ) {
2545 for ( int i = start; i < end; ++i ) { 2617 s += "\n";
2546 if ( p->at( i )->isCustom() ) { 2618 QTextTable *t = (QTextTable*)p->at( i )->customItem();
2547 if ( p->at( i )->customItem()->isNested() ) { 2619 QPtrList<QTextTableCell> cells = t->tableCells();
2548 s += "\n"; 2620 for ( QTextTableCell *c = cells.first(); c; c = cells.next() )
2549 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 2621 s += c->richText()->plainText() + "\n";
2550 QPtrList<QTextTableCell> cells = t->tableCells(); 2622 s += "\n";
2551 for ( QTextTableCell *c = cells.first(); c; c = cells.next() ) 2623 }
2552 s += c->richText()->plainText() + "\n"; 2624 } else {
2553 s += "\n"; 2625 s += p->at( i )->c;
2554 } 2626 }
2555 } else {
2556 s += p->at( i )->c;
2557 } 2627 }
2558 } 2628 }
2629 start = 0;
2630 if ( p == c2.paragraph() )
2631 break;
2632 p = p->next();
2559 } 2633 }
2560 start = 0;
2561 if ( p == c2.parag() )
2562 break;
2563 p = p->next();
2564 } 2634 }
2635 // ### workaround for plain text export until we get proper
2636 // mime types: turn unicode line seperators into the more
2637 // widely understood \n. Makes copy and pasting code snipplets
2638 // from within Assistent possible
2639 QChar* uc = (QChar*) s.unicode();
2640 for ( uint ii = 0; ii < s.length(); ii++ )
2641 if ( uc[(int)ii] == QChar_linesep )
2642 uc[(int)ii] = QChar('\n');
2565 return s; 2643 return s;
2566} 2644}
2567 2645
2568void QTextDocument::setFormat( int id, QTextFormat *f, int flags ) 2646void QTextDocument::setFormat( int id, QTextFormat *f, int flags )
2569{ 2647{
2570 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id ); 2648 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( id );
2571 if ( it == selections.end() ) 2649 if ( it == selections.end() )
2572 return; 2650 return;
2573 2651
2574 QTextDocumentSelection sel = *it; 2652 QTextDocumentSelection sel = *it;
2575 2653
2576 QTextCursor c1 = sel.startCursor; 2654 QTextCursor c1 = sel.startCursor;
2577 QTextCursor c2 = sel.endCursor; 2655 QTextCursor c2 = sel.endCursor;
2578 if ( sel.swapped ) { 2656 if ( sel.swapped ) {
2579 c2 = sel.startCursor; 2657 c2 = sel.startCursor;
2580 c1 = sel.endCursor; 2658 c1 = sel.endCursor;
2581 } 2659 }
2582 2660
2583 c2.restoreState(); 2661 c2.restoreState();
2584 c1.restoreState(); 2662 c1.restoreState();
2585 2663
2586 if ( c1.parag() == c2.parag() ) { 2664 if ( c1.paragraph() == c2.paragraph() ) {
2587 c1.parag()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags ); 2665 c1.paragraph()->setFormat( c1.index(), c2.index() - c1.index(), f, TRUE, flags );
2588 return; 2666 return;
2589 } 2667 }
2590 2668
2591 c1.parag()->setFormat( c1.index(), c1.parag()->length() - c1.index(), f, TRUE, flags ); 2669 c1.paragraph()->setFormat( c1.index(), c1.paragraph()->length() - c1.index(), f, TRUE, flags );
2592 QTextParag *p = c1.parag()->next(); 2670 QTextParagraph *p = c1.paragraph()->next();
2593 while ( p && p != c2.parag() ) { 2671 while ( p && p != c2.paragraph() ) {
2594 p->setFormat( 0, p->length(), f, TRUE, flags ); 2672 p->setFormat( 0, p->length(), f, TRUE, flags );
2595 p = p->next(); 2673 p = p->next();
2596 } 2674 }
2597 c2.parag()->setFormat( 0, c2.index(), f, TRUE, flags ); 2675 c2.paragraph()->setFormat( 0, c2.index(), f, TRUE, flags );
2598}
2599
2600void QTextDocument::copySelectedText( int id )
2601{
2602#ifndef QT_NO_CLIPBOARD
2603 if ( !hasSelection( id ) )
2604 return;
2605
2606 QApplication::clipboard()->setText( selectedText( id ) );
2607#endif
2608} 2676}
2609 2677
2610void QTextDocument::removeSelectedText( int id, QTextCursor *cursor ) 2678void QTextDocument::removeSelectedText( int id, QTextCursor *cursor )
2611{ 2679{
2612 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2680 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2613 if ( it == selections.end() ) 2681 if ( it == selections.end() )
2614 return; 2682 return;
2615 2683
2616 QTextDocumentSelection sel = *it; 2684 QTextDocumentSelection sel = *it;
2617 2685
2618 QTextCursor c1 = sel.startCursor; 2686 QTextCursor c1 = sel.startCursor;
2619 QTextCursor c2 = sel.endCursor; 2687 QTextCursor c2 = sel.endCursor;
2620 if ( sel.swapped ) { 2688 if ( sel.swapped ) {
2621 c2 = sel.startCursor; 2689 c2 = sel.startCursor;
2622 c1 = sel.endCursor; 2690 c1 = sel.endCursor;
2623 } 2691 }
2624 2692
2625 // ### no support for editing tables yet 2693 // ### no support for editing tables yet
2626 if ( c1.nestedDepth() || c2.nestedDepth() ) 2694 if ( c1.nestedDepth() || c2.nestedDepth() )
2627 return; 2695 return;
2628 2696
2629 c2.restoreState(); 2697 c2.restoreState();
2630 c1.restoreState(); 2698 c1.restoreState();
2631 2699
2632 *cursor = c1; 2700 *cursor = c1;
2633 removeSelection( id ); 2701 removeSelection( id );
2634 2702
2635 if ( c1.parag() == c2.parag() ) { 2703 if ( c1.paragraph() == c2.paragraph() ) {
2636 c1.parag()->remove( c1.index(), c2.index() - c1.index() ); 2704 c1.paragraph()->remove( c1.index(), c2.index() - c1.index() );
2637 return; 2705 return;
2638 } 2706 }
2639 2707
2640 if ( c1.parag() == fParag && c1.index() == 0 && 2708 if ( c1.paragraph() == fParag && c1.index() == 0 &&
2641 c2.parag() == lParag && c2.index() == lParag->length() - 1 ) 2709 c2.paragraph() == lParag && c2.index() == lParag->length() - 1 )
2642 cursor->setValid( FALSE ); 2710 cursor->setValid( FALSE );
2643 2711
2644 bool didGoLeft = FALSE; 2712 bool didGoLeft = FALSE;
2645 if ( c1.index() == 0 && c1.parag() != fParag ) { 2713 if ( c1.index() == 0 && c1.paragraph() != fParag ) {
2646 cursor->gotoPreviousLetter(); 2714 cursor->gotoPreviousLetter();
2647 if ( cursor->isValid() ) 2715 if ( cursor->isValid() )
2648 didGoLeft = TRUE; 2716 didGoLeft = TRUE;
2649 } 2717 }
2650 2718
2651 c1.parag()->remove( c1.index(), c1.parag()->length() - 1 - c1.index() ); 2719 c1.paragraph()->remove( c1.index(), c1.paragraph()->length() - 1 - c1.index() );
2652 QTextParag *p = c1.parag()->next(); 2720 QTextParagraph *p = c1.paragraph()->next();
2653 int dy = 0; 2721 int dy = 0;
2654 QTextParag *tmp; 2722 QTextParagraph *tmp;
2655 while ( p && p != c2.parag() ) { 2723 while ( p && p != c2.paragraph() ) {
2656 tmp = p->next(); 2724 tmp = p->next();
2657 dy -= p->rect().height(); 2725 dy -= p->rect().height();
2658 delete p; 2726 delete p;
2659 p = tmp; 2727 p = tmp;
2660 } 2728 }
2661 c2.parag()->remove( 0, c2.index() ); 2729 c2.paragraph()->remove( 0, c2.index() );
2662 while ( p ) { 2730 while ( p ) {
2663 p->move( dy ); 2731 p->move( dy );
2664 p->invalidate( 0 ); 2732 p->invalidate( 0 );
2665 p->setEndState( -1 ); 2733 p->setEndState( -1 );
2666 p = p->next(); 2734 p = p->next();
2667 } 2735 }
2668 2736
2669 c1.parag()->join( c2.parag() ); 2737 c1.paragraph()->join( c2.paragraph() );
2670 2738
2671 if ( didGoLeft ) 2739 if ( didGoLeft )
2672 cursor->gotoNextLetter(); 2740 cursor->gotoNextLetter();
2673} 2741}
2674 2742
2675void QTextDocument::indentSelection( int id ) 2743void QTextDocument::indentSelection( int id )
2676{ 2744{
2677 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id ); 2745 QMap<int, QTextDocumentSelection>::Iterator it = selections.find( id );
2678 if ( it == selections.end() ) 2746 if ( it == selections.end() )
2679 return; 2747 return;
2680 2748
2681 QTextDocumentSelection sel = *it; 2749 QTextDocumentSelection sel = *it;
2682 QTextParag *startParag = sel.startCursor.parag(); 2750 QTextParagraph *startParag = sel.startCursor.paragraph();
2683 QTextParag *endParag = sel.endCursor.parag(); 2751 QTextParagraph *endParag = sel.endCursor.paragraph();
2684 if ( sel.endCursor.parag()->paragId() < sel.startCursor.parag()->paragId() ) { 2752 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) {
2685 endParag = sel.startCursor.parag(); 2753 endParag = sel.startCursor.paragraph();
2686 startParag = sel.endCursor.parag(); 2754 startParag = sel.endCursor.paragraph();
2687 } 2755 }
2688 2756
2689 QTextParag *p = startParag; 2757 QTextParagraph *p = startParag;
2690 while ( p && p != endParag ) { 2758 while ( p && p != endParag ) {
2691 p->indent(); 2759 p->indent();
2692 p = p->next(); 2760 p = p->next();
2693 } 2761 }
2694} 2762}
2695 2763
2696void QTextDocument::addCommand( QTextCommand *cmd ) 2764void QTextDocument::addCommand( QTextCommand *cmd )
2697{ 2765{
2698 commandHistory->addCommand( cmd ); 2766 commandHistory->addCommand( cmd );
2699} 2767}
2700 2768
2701QTextCursor *QTextDocument::undo( QTextCursor *c ) 2769QTextCursor *QTextDocument::undo( QTextCursor *c )
2702{ 2770{
2703 return commandHistory->undo( c ); 2771 return commandHistory->undo( c );
2704} 2772}
2705 2773
2706QTextCursor *QTextDocument::redo( QTextCursor *c ) 2774QTextCursor *QTextDocument::redo( QTextCursor *c )
2707{ 2775{
2708 return commandHistory->redo( c ); 2776 return commandHistory->redo( c );
2709} 2777}
2710 2778
2711bool QTextDocument::find( const QString &expr, bool cs, bool wo, bool forward, 2779bool QTextDocument::find( QTextCursor& cursor, const QString &e, bool cs, bool wo, bool forward )
2712 int *parag, int *index, QTextCursor *cursor )
2713{ 2780{
2714 QTextParag *p = forward ? fParag : lParag; 2781 removeSelection( Standard );
2715 if ( parag ) 2782 QTextParagraph *p = 0;
2716 p = paragAt( *parag ); 2783 QString expr = e;
2717 else if ( cursor ) 2784 // if we search for 'word only' than we have to be sure that
2718 p = cursor->parag(); 2785 // the expression contains no space or punct character at the
2719 bool first = TRUE; 2786 // beginning or in the end. Otherwise we would run into a
2720 2787 // endlessloop.
2721 while ( p ) { 2788 if ( wo ) {
2722 QString s = p->string()->toString(); 2789 for ( ;; ) {
2723 s.remove( s.length() - 1, 1 ); // get rid of trailing space 2790 if ( expr[ 0 ].isSpace() || expr[ 0 ].isPunct() )
2724 int start = forward ? 0 : s.length() - 1; 2791 expr = expr.right( expr.length() - 1 );
2725 if ( first && index ) 2792 else
2726 start = *index; 2793 break;
2727 else if ( first )
2728 start = cursor->index();
2729 if ( !forward && first ) {
2730 start -= expr.length() + 1;
2731 if ( start < 0 ) {
2732 first = FALSE;
2733 p = p->prev();
2734 continue;
2735 }
2736 } 2794 }
2737 first = FALSE;
2738
2739 for ( ;; ) { 2795 for ( ;; ) {
2740 int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs ); 2796 if ( expr.at( expr.length() - 1 ).isSpace() || expr.at( expr.length() - 1 ).isPunct() )
2741 if ( res == -1 ) 2797 expr = expr.left( expr.length() - 1 );
2798 else
2742 break; 2799 break;
2743 2800 }
2744 bool ok = TRUE; 2801 }
2745 if ( wo ) { 2802 for (;;) {
2803 if ( p != cursor.paragraph() ) {
2804 p = cursor.paragraph();
2805 QString s = cursor.paragraph()->string()->toString();
2806 int start = cursor.index();
2807 for ( ;; ) {
2808 int res = forward ? s.find( expr, start, cs ) : s.findRev( expr, start, cs );
2746 int end = res + expr.length(); 2809 int end = res + expr.length();
2747 if ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) && 2810 if ( res == -1 || ( !forward && start < end ) )
2748 ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) )
2749 ok = TRUE;
2750 else
2751 ok = FALSE;
2752 }
2753 if ( ok ) {
2754 cursor->setParag( p );
2755 cursor->setIndex( res );
2756 setSelectionStart( Standard, cursor );
2757 cursor->setIndex( res + expr.length() );
2758 setSelectionEnd( Standard, cursor );
2759 if ( parag )
2760 *parag = p->paragId();
2761 if ( index )
2762 *index = res;
2763 return TRUE;
2764 }
2765 if ( forward ) {
2766 start = res + 1;
2767 } else {
2768 if ( res == 0 )
2769 break; 2811 break;
2770 start = res - 1; 2812 if ( !wo || ( ( res == 0 || s[ res - 1 ].isSpace() || s[ res - 1 ].isPunct() ) &&
2813 ( end == (int)s.length() || s[ end ].isSpace() || s[ end ].isPunct() ) ) ) {
2814 removeSelection( Standard );
2815 cursor.setIndex( forward ? end : res );
2816 setSelectionStart( Standard, cursor );
2817 cursor.setIndex( forward ? res : end );
2818 setSelectionEnd( Standard, cursor );
2819 return TRUE;
2820 }
2821 start = res + (forward ? 1 : -1);
2771 } 2822 }
2772 } 2823 }
2773 p = forward ? p->next() : p->prev(); 2824 if ( forward ) {
2825 if ( cursor.paragraph() == lastParagraph() && cursor.atParagEnd () )
2826 break;
2827 cursor.gotoNextLetter();
2828 } else {
2829 if ( cursor.paragraph() == firstParagraph() && cursor.atParagStart() )
2830 break;
2831 cursor.gotoPreviousLetter();
2832 }
2774 } 2833 }
2775
2776 return FALSE; 2834 return FALSE;
2777} 2835}
2778 2836
2779void QTextDocument::setTextFormat( Qt::TextFormat f ) 2837void QTextDocument::setTextFormat( Qt::TextFormat f )
2780{ 2838{
2781 txtFormat = f; 2839 txtFormat = f;
2782 if ( txtFormat == Qt::RichText && fParag && fParag == lParag && fParag->length() <= 1 ) { 2840 if ( fParag == lParag && fParag->length() <= 1 )
2783 QPtrVector<QStyleSheetItem> v = fParag->styleSheetItems(); 2841 fParag->rtext = ( f == Qt::RichText );
2784 v.resize( v.size() + 1 );
2785 v.insert( v.size() - 1, styleSheet()->item( "p" ) );
2786 fParag->setStyleSheetItems( v );
2787 }
2788
2789} 2842}
2790 2843
2791Qt::TextFormat QTextDocument::textFormat() const 2844Qt::TextFormat QTextDocument::textFormat() const
2792{ 2845{
2793 return txtFormat; 2846 return txtFormat;
2794} 2847}
2795 2848
2796bool QTextDocument::inSelection( int selId, const QPoint &pos ) const 2849bool QTextDocument::inSelection( int selId, const QPoint &pos ) const
2797{ 2850{
2798 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( selId ); 2851 QMap<int, QTextDocumentSelection>::ConstIterator it = selections.find( selId );
2799 if ( it == selections.end() ) 2852 if ( it == selections.end() )
2800 return FALSE; 2853 return FALSE;
2801 2854
2802 QTextDocumentSelection sel = *it; 2855 QTextDocumentSelection sel = *it;
2803 QTextParag *startParag = sel.startCursor.parag(); 2856 QTextParagraph *startParag = sel.startCursor.paragraph();
2804 QTextParag *endParag = sel.endCursor.parag(); 2857 QTextParagraph *endParag = sel.endCursor.paragraph();
2805 if ( sel.startCursor.parag() == sel.endCursor.parag() && 2858 if ( sel.startCursor.paragraph() == sel.endCursor.paragraph() &&
2806 sel.startCursor.parag()->selectionStart( selId ) == sel.endCursor.parag()->selectionEnd( selId ) ) 2859 sel.startCursor.paragraph()->selectionStart( selId ) == sel.endCursor.paragraph()->selectionEnd( selId ) )
2807 return FALSE; 2860 return FALSE;
2808 if ( sel.endCursor.parag()->paragId() < sel.startCursor.parag()->paragId() ) { 2861 if ( sel.endCursor.paragraph()->paragId() < sel.startCursor.paragraph()->paragId() ) {
2809 endParag = sel.startCursor.parag(); 2862 endParag = sel.startCursor.paragraph();
2810 startParag = sel.endCursor.parag(); 2863 startParag = sel.endCursor.paragraph();
2811 } 2864 }
2812 2865
2813 QTextParag *p = startParag; 2866 QTextParagraph *p = startParag;
2814 while ( p ) { 2867 while ( p ) {
2815 if ( p->rect().contains( pos ) ) { 2868 if ( p->rect().contains( pos ) ) {
2816 bool inSel = FALSE; 2869 bool inSel = FALSE;
2817 int selStart = p->selectionStart( selId ); 2870 int selStart = p->selectionStart( selId );
2818 int selEnd = p->selectionEnd( selId ); 2871 int selEnd = p->selectionEnd( selId );
2819 int y = 0; 2872 int y = 0;
2820 int h = 0; 2873 int h = 0;
2821 for ( int i = 0; i < p->length(); ++i ) { 2874 for ( int i = 0; i < p->length(); ++i ) {
2822 if ( i == selStart ) 2875 if ( i == selStart )
2823 inSel = TRUE; 2876 inSel = TRUE;
2824 if ( i == selEnd ) 2877 if ( i == selEnd )
2825 break; 2878 break;
2826 if ( p->at( i )->lineStart ) { 2879 if ( p->at( i )->lineStart ) {
2827 y = (*p->lineStarts.find( i ))->y; 2880 y = (*p->lineStarts.find( i ))->y;
2828 h = (*p->lineStarts.find( i ))->h; 2881 h = (*p->lineStarts.find( i ))->h;
2829 } 2882 }
2830 if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) { 2883 if ( pos.y() - p->rect().y() >= y && pos.y() - p->rect().y() <= y + h ) {
2831 if ( inSel && pos.x() >= p->at( i )->x && 2884 if ( inSel && pos.x() >= p->at( i )->x &&
2832 pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) ) 2885 pos.x() <= p->at( i )->x + p->at( i )->format()->width( p->at( i )->c ) )
2833 return TRUE; 2886 return TRUE;
2834 } 2887 }
2835 } 2888 }
2836 } 2889 }
2837 if ( pos.y() < p->rect().y() ) 2890 if ( pos.y() < p->rect().y() )
2838 break; 2891 break;
2839 if ( p == endParag ) 2892 if ( p == endParag )
2840 break; 2893 break;
2841 p = p->next(); 2894 p = p->next();
2842 } 2895 }
2843 2896
2844 return FALSE; 2897 return FALSE;
2845} 2898}
2846 2899
2847void QTextDocument::doLayout( QPainter *p, int w ) 2900void QTextDocument::doLayout( QPainter *p, int w )
2848{ 2901{
2849 minw = wused = 0; 2902 minw = wused = 0;
2850 if ( !is_printer( p ) ) 2903 if ( !is_printer( p ) )
2851 p = 0; 2904 p = 0;
2852 withoutDoubleBuffer = ( p != 0 ); 2905 withoutDoubleBuffer = ( p != 0 );
2853 QPainter * oldPainter = QTextFormat::painter(); 2906 QPainter * oldPainter = QTextFormat::painter();
2854 QTextFormat::setPainter( p ); 2907 QTextFormat::setPainter( p );
2855 flow_->setWidth( w ); 2908 flow_->setWidth( w );
2856 cw = w; 2909 cw = w;
2857 vw = w; 2910 vw = w;
2858 QTextParag *parag = fParag; 2911 QTextParagraph *parag = fParag;
2859 while ( parag ) { 2912 while ( parag ) {
2860 parag->invalidate( 0 ); 2913 parag->invalidate( 0 );
2861 if ( p ) 2914 if ( p )
2862 parag->adjustToPainter( p ); 2915 parag->adjustToPainter( p );
2863 parag->format(); 2916 parag->format();
2864 parag = parag->next(); 2917 parag = parag->next();
2865 } 2918 }
2866 QTextFormat::setPainter( oldPainter ); 2919 QTextFormat::setPainter( oldPainter );
2867} 2920}
2868 2921
2869QPixmap *QTextDocument::bufferPixmap( const QSize &s ) 2922QPixmap *QTextDocument::bufferPixmap( const QSize &s )
2870{ 2923{
2871 if ( !buf_pixmap ) { 2924 if ( !buf_pixmap )
2872 int w = QABS( s.width() ); 2925 buf_pixmap = new QPixmap( s.expandedTo( QSize(1,1) ) );
2873 int h = QABS( s.height() ); 2926 else if ( buf_pixmap->size() != s )
2874 buf_pixmap = new QPixmap( w, h ); 2927 buf_pixmap->resize( s.expandedTo( buf_pixmap->size() ) );
2875 } else {
2876 if ( buf_pixmap->width() < s.width() ||
2877 buf_pixmap->height() < s.height() ) {
2878 buf_pixmap->resize( QMAX( s.width(), buf_pixmap->width() ),
2879 QMAX( s.height(), buf_pixmap->height() ) );
2880 }
2881 }
2882
2883 return buf_pixmap; 2928 return buf_pixmap;
2884} 2929}
2885 2930
2886void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper ) 2931void QTextDocument::draw( QPainter *p, const QRect &rect, const QColorGroup &cg, const QBrush *paper )
2887{ 2932{
2888 if ( !firstParag() ) 2933 if ( !firstParagraph() )
2889 return; 2934 return;
2890 2935
2891 if ( paper ) { 2936 if ( paper ) {
2892 p->setBrushOrigin( 0, 0 ); 2937 p->setBrushOrigin( 0, 0 );
2893 2938
2894 p->fillRect( rect, *paper ); 2939 p->fillRect( rect, *paper );
2895 } 2940 }
2896 2941
2897 if ( formatCollection()->defaultFormat()->color() != cg.text() ) { 2942 if ( formatCollection()->defaultFormat()->color() != cg.text() )
2898 QDict<QTextFormat> formats = formatCollection()->dict(); 2943 setDefaultFormat( formatCollection()->defaultFormat()->font(), cg.text() );
2899 QDictIterator<QTextFormat> it( formats );
2900 while ( it.current() ) {
2901 if ( it.current() == formatCollection()->defaultFormat() ) {
2902 ++it;
2903 continue;
2904 }
2905 it.current()->setColor( cg.text() );
2906 ++it;
2907 }
2908 formatCollection()->defaultFormat()->setColor( cg.text() );
2909 }
2910 2944
2911 QTextParag *parag = firstParag(); 2945 QTextParagraph *parag = firstParagraph();
2912 while ( parag ) { 2946 while ( parag ) {
2913 if ( !parag->isValid() ) 2947 if ( !parag->isValid() )
2914 parag->format(); 2948 parag->format();
2915 int y = parag->rect().y(); 2949 int y = parag->rect().y();
2916 QRect pr( parag->rect() ); 2950 QRect pr( parag->rect() );
2917 pr.setX( 0 ); 2951 pr.setX( 0 );
2918 pr.setWidth( QWIDGETSIZE_MAX ); 2952 pr.setWidth( QWIDGETSIZE_MAX );
2919 if ( !rect.isNull() && !rect.intersects( pr ) ) { 2953 if ( !rect.isNull() && !rect.intersects( pr ) ) {
2920 parag = parag->next(); 2954 parag = parag->next();
2921 continue; 2955 continue;
2922 } 2956 }
2923 p->translate( 0, y ); 2957 p->translate( 0, y );
2924 if ( rect.isValid() ) 2958 if ( rect.isValid() )
2925 parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() ); 2959 parag->paint( *p, cg, 0, FALSE, rect.x(), rect.y(), rect.width(), rect.height() );
2926 else 2960 else
2927 parag->paint( *p, cg, 0, FALSE ); 2961 parag->paint( *p, cg, 0, FALSE );
2928 p->translate( 0, -y ); 2962 p->translate( 0, -y );
2929 parag = parag->next(); 2963 parag = parag->next();
2930 if ( !flow()->isEmpty() ) 2964 if ( !flow()->isEmpty() )
2931 flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE ); 2965 flow()->drawFloatingItems( p, rect.x(), rect.y(), rect.width(), rect.height(), cg, FALSE );
2932 } 2966 }
2933} 2967}
2934 2968
2935void QTextDocument::drawParag( QPainter *p, QTextParag *parag, int cx, int cy, int cw, int ch, 2969void QTextDocument::drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch,
2936 QPixmap *&doubleBuffer, const QColorGroup &cg, 2970 QPixmap *&doubleBuffer, const QColorGroup &cg,
2937 bool drawCursor, QTextCursor *cursor, bool resetChanged ) 2971 bool drawCursor, QTextCursor *cursor, bool resetChanged )
2938{ 2972{
2939 QPainter *painter = 0; 2973 QPainter *painter = 0;
2940 if ( resetChanged ) 2974 if ( resetChanged )
2941 parag->setChanged( FALSE ); 2975 parag->setChanged( FALSE );
2942 QRect ir( parag->rect() ); 2976 QRect ir( parag->rect() );
2943 bool useDoubleBuffer = !parag->document()->parent(); 2977 bool useDoubleBuffer = !parag->document()->parent();
2944 if ( !useDoubleBuffer && parag->document()->nextDoubleBuffered ) 2978 if ( !useDoubleBuffer && parag->document()->nextDoubleBuffered )
2945 useDoubleBuffer = TRUE; 2979 useDoubleBuffer = TRUE;
2946 if ( is_printer( p ) ) 2980 if ( is_printer( p ) )
2947 useDoubleBuffer = FALSE; 2981 useDoubleBuffer = FALSE;
2948 2982
2949 if ( useDoubleBuffer ) { 2983 if ( useDoubleBuffer ) {
2950 painter = new QPainter; 2984 painter = new QPainter;
2951 if ( cx >= 0 && cy >= 0 ) 2985 if ( cx >= 0 && cy >= 0 )
2952 ir = ir.intersect( QRect( cx, cy, cw, ch ) ); 2986 ir = ir.intersect( QRect( cx, cy, cw, ch ) );
2953 if ( !doubleBuffer || 2987 if ( !doubleBuffer ||
2954 ir.width() > doubleBuffer->width() || 2988 ir.width() > doubleBuffer->width() ||
2955 ir.height() > doubleBuffer->height() ) { 2989 ir.height() > doubleBuffer->height() ) {
2956 doubleBuffer = bufferPixmap( ir.size() ); 2990 doubleBuffer = bufferPixmap( ir.size() );
2957 painter->begin( doubleBuffer ); 2991 painter->begin( doubleBuffer );
2958 } else { 2992 } else {
2959 painter->begin( doubleBuffer ); 2993 painter->begin( doubleBuffer );
2960 } 2994 }
2961 } else { 2995 } else {
2962 painter = p; 2996 painter = p;
2963 painter->translate( ir.x(), ir.y() ); 2997 painter->translate( ir.x(), ir.y() );
2964 } 2998 }
2965 2999
2966 painter->setBrushOrigin( -ir.x(), -ir.y() ); 3000 painter->setBrushOrigin( -ir.x(), -ir.y() );
2967 3001
2968 if ( useDoubleBuffer || is_printer( painter ) ) { 3002 if ( useDoubleBuffer || is_printer( painter ) )
2969 if ( !parag->backgroundColor() ) 3003 painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), parag->backgroundBrush( cg ) );
2970 painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ), 3004 else if ( cursor && cursor->paragraph() == parag )
2971 cg.brush( QColorGroup::Base ) ); 3005 painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ),
2972 else 3006 parag->backgroundBrush( cg ) );
2973 painter->fillRect( QRect( 0, 0, ir.width(), ir.height() ),
2974 *parag->backgroundColor() );
2975 } else {
2976 if ( cursor && cursor->parag() == parag ) {
2977 if ( !parag->backgroundColor() )
2978 painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ),
2979 cg.brush( QColorGroup::Base ) );
2980 else
2981 painter->fillRect( QRect( parag->at( cursor->index() )->x, 0, 2, ir.height() ),
2982 *parag->backgroundColor() );
2983 }
2984 }
2985 3007
2986 painter->translate( -( ir.x() - parag->rect().x() ), 3008 painter->translate( -( ir.x() - parag->rect().x() ),
2987 -( ir.y() - parag->rect().y() ) ); 3009 -( ir.y() - parag->rect().y() ) );
2988 parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch ); 3010 parag->paint( *painter, cg, drawCursor ? cursor : 0, TRUE, cx, cy, cw, ch );
2989 3011
2990 if ( useDoubleBuffer ) { 3012 if ( useDoubleBuffer ) {
2991 delete painter; 3013 delete painter;
2992 painter = 0; 3014 painter = 0;
2993 p->drawPixmap( ir.topLeft(), *doubleBuffer, QRect( QPoint( 0, 0 ), ir.size() ) ); 3015 p->drawPixmap( ir.topLeft(), *doubleBuffer, QRect( QPoint( 0, 0 ), ir.size() ) );
2994 } else { 3016 } else {
2995 painter->translate( -ir.x(), -ir.y() ); 3017 painter->translate( -ir.x(), -ir.y() );
2996 } 3018 }
2997 3019
2998 if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) { 3020 if ( useDoubleBuffer ) {
2999 p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(), 3021 if ( parag->rect().x() + parag->rect().width() < parag->document()->x() + parag->document()->width() ) {
3000 ( parag->document()->x() + parag->document()->width() ) - 3022 p->fillRect( parag->rect().x() + parag->rect().width(), parag->rect().y(),
3001 ( parag->rect().x() + parag->rect().width() ), 3023 ( parag->document()->x() + parag->document()->width() ) -
3002 parag->rect().height(), cg.brush( QColorGroup::Base ) ); 3024 ( parag->rect().x() + parag->rect().width() ),
3025 parag->rect().height(), cg.brush( QColorGroup::Base ) );
3026 }
3003 } 3027 }
3004 3028
3005 parag->document()->nextDoubleBuffered = FALSE; 3029 parag->document()->nextDoubleBuffered = FALSE;
3006} 3030}
3007 3031
3008QTextParag *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, 3032QTextParagraph *QTextDocument::draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg,
3009 bool onlyChanged, bool drawCursor, QTextCursor *cursor, bool resetChanged ) 3033 bool onlyChanged, bool drawCursor, QTextCursor *cursor, bool resetChanged )
3010{ 3034{
3011 if ( withoutDoubleBuffer || par && par->withoutDoubleBuffer ) { 3035 if ( withoutDoubleBuffer || par && par->withoutDoubleBuffer ) {
3012 withoutDoubleBuffer = TRUE; 3036 withoutDoubleBuffer = TRUE;
3013 QRect r; 3037 QRect r;
3014 draw( p, r, cg ); 3038 draw( p, r, cg );
3015 return 0; 3039 return 0;
3016 } 3040 }
3017 withoutDoubleBuffer = FALSE; 3041 withoutDoubleBuffer = FALSE;
3018 3042
3019 if ( !firstParag() ) 3043 if ( !firstParagraph() )
3020 return 0; 3044 return 0;
3021 3045
3022 if ( drawCursor && cursor )
3023 tmpCursor = cursor;
3024 if ( cx < 0 && cy < 0 ) { 3046 if ( cx < 0 && cy < 0 ) {
3025 cx = 0; 3047 cx = 0;
3026 cy = 0; 3048 cy = 0;
3027 cw = width(); 3049 cw = width();
3028 ch = height(); 3050 ch = height();
3029 } 3051 }
3030 3052
3031 QTextParag *lastFormatted = 0; 3053 QTextParagraph *lastFormatted = 0;
3032 QTextParag *parag = firstParag(); 3054 QTextParagraph *parag = firstParagraph();
3033 3055
3034 QPixmap *doubleBuffer = 0; 3056 QPixmap *doubleBuffer = 0;
3035 QPainter painter; 3057 QPainter painter;
3036 3058
3059 bool fullWidthSelection = FALSE;
3037 while ( parag ) { 3060 while ( parag ) {
3038 lastFormatted = parag; 3061 lastFormatted = parag;
3039 if ( !parag->isValid() ) 3062 if ( !parag->isValid() )
3040 parag->format(); 3063 parag->format();
3041 3064
3042 if ( !parag->rect().intersects( QRect( cx, cy, cw, ch ) ) ) { 3065 QRect pr = parag->rect();
3043 QRect pr( parag->rect() ); 3066 if ( fullWidthSelection )
3044 pr.setWidth( parag->document()->width() ); 3067 pr.setWidth( parag->document()->width() );
3045 if ( pr.intersects( QRect( cx, cy, cw, ch ) ) ) 3068 if ( pr.y() > cy + ch )
3046 p->fillRect( pr.intersect( QRect( cx, cy, cw, ch ) ), cg.brush( QColorGroup::Base ) ); 3069 goto floating;
3047 if ( parag->rect().y() > cy + ch ) { 3070 if ( !pr.intersects( QRect( cx, cy, cw, ch ) ) || ( onlyChanged && !parag->hasChanged() ) ) {
3048 tmpCursor = 0;
3049 goto floating;
3050 }
3051 parag = parag->next();
3052 continue;
3053 }
3054
3055 if ( !parag->hasChanged() && onlyChanged ) {
3056 parag = parag->next(); 3071 parag = parag->next();
3057 continue; 3072 continue;
3058 } 3073 }
3059 3074
3060 drawParag( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged ); 3075 drawParagraph( p, parag, cx, cy, cw, ch, doubleBuffer, cg, drawCursor, cursor, resetChanged );
3061 parag = parag->next(); 3076 parag = parag->next();
3062 } 3077 }
3063 3078
3064 parag = lastParag(); 3079 parag = lastParagraph();
3065 3080
3066 floating: 3081 floating:
3067 if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) { 3082 if ( parag->rect().y() + parag->rect().height() < parag->document()->height() ) {
3068 if ( !parag->document()->parent() ) { // !useDoubleBuffer 3083 if ( !parag->document()->parent() ) {
3069 p->fillRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(), 3084 p->fillRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(),
3070 parag->document()->height() - ( parag->rect().y() + parag->rect().height() ), 3085 parag->document()->height() - ( parag->rect().y() + parag->rect().height() ),
3071 cg.brush( QColorGroup::Base ) ); 3086 cg.brush( QColorGroup::Base ) );
3072 } 3087 }
3073 if ( !flow()->isEmpty() ) { 3088 if ( !flow()->isEmpty() ) {
3074 QRect cr( cx, cy, cw, ch ); 3089 QRect cr( cx, cy, cw, ch );
3075 // cr = cr.intersect( QRect( 0, parag->rect().y() + parag->rect().height(), parag->document()->width(),
3076 // parag->document()->height() - ( parag->rect().y() + parag->rect().height() ) ) );
3077 flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE ); 3090 flow()->drawFloatingItems( p, cr.x(), cr.y(), cr.width(), cr.height(), cg, FALSE );
3078 } 3091 }
3079 } 3092 }
3080 3093
3081 if ( buf_pixmap && buf_pixmap->height() > 300 ) { 3094 if ( buf_pixmap && buf_pixmap->height() > 300 ) {
3082 delete buf_pixmap; 3095 delete buf_pixmap;
3083 buf_pixmap = 0; 3096 buf_pixmap = 0;
3084 } 3097 }
3085 3098
3086 tmpCursor = 0;
3087 return lastFormatted; 3099 return lastFormatted;
3088} 3100}
3089 3101
3090void QTextDocument::setDefaultFont( const QFont &f ) 3102/*
3103 #### this function only sets the default font size in the format collection
3104 */
3105void QTextDocument::setDefaultFormat( const QFont &font, const QColor &color )
3091{ 3106{
3092 int s = f.pointSize(); 3107 bool reformat = font != fCollection->defaultFormat()->font();
3093 bool usePixels = FALSE; 3108 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
3094 if ( s == -1 ) { 3109 d->setDefaultFormat( font, color );
3095 s = f.pixelSize(); 3110 fCollection->updateDefaultFormat( font, color, sheet_ );
3096 usePixels = TRUE; 3111
3112 if ( !reformat )
3113 return;
3114 tStopWidth = formatCollection()->defaultFormat()->width( 'x' ) * 8;
3115
3116 // invalidate paragraphs and custom items
3117 QTextParagraph *p = fParag;
3118 while ( p ) {
3119 p->invalidate( 0 );
3120 for ( int i = 0; i < p->length() - 1; ++i )
3121 if ( p->at( i )->isCustom() )
3122 p->at( i )->customItem()->invalidate();
3123 p = p->next();
3097 } 3124 }
3098 updateFontSizes( s, usePixels );
3099} 3125}
3100 3126
3101void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParag *p ) 3127void QTextDocument::registerCustomItem( QTextCustomItem *i, QTextParagraph *p )
3102{ 3128{
3103 if ( i && i->placement() != QTextCustomItem::PlaceInline ) { 3129 if ( i && i->placement() != QTextCustomItem::PlaceInline ) {
3104 flow_->registerFloatingItem( i ); 3130 flow_->registerFloatingItem( i );
3105 p->registerFloatingItem( i ); 3131 p->registerFloatingItem( i );
3106 i->setParagraph( p ); 3132 i->setParagraph( p );
3107 } 3133 }
3108 p->mightHaveCustomItems = mightHaveCustomItems = TRUE; 3134 p->mightHaveCustomItems = mightHaveCustomItems = TRUE;
3109} 3135}
3110 3136
3111void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParag *p ) 3137void QTextDocument::unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p )
3112{ 3138{
3113 flow_->unregisterFloatingItem( i ); 3139 flow_->unregisterFloatingItem( i );
3114 p->unregisterFloatingItem( i ); 3140 p->unregisterFloatingItem( i );
3115 i->setParagraph( 0 ); 3141 i->setParagraph( 0 );
3116} 3142}
3117 3143
3118bool QTextDocument::hasFocusParagraph() const 3144bool QTextDocument::hasFocusParagraph() const
3119{ 3145{
3120 return !!focusIndicator.parag; 3146 return !!focusIndicator.parag;
3121} 3147}
3122 3148
3123QString QTextDocument::focusHref() const 3149QString QTextDocument::focusHref() const
3124{ 3150{
3125 return focusIndicator.href; 3151 return focusIndicator.href;
3126} 3152}
3127 3153
3128bool QTextDocument::focusNextPrevChild( bool next ) 3154bool QTextDocument::focusNextPrevChild( bool next )
3129{ 3155{
3130 if ( !focusIndicator.parag ) { 3156 if ( !focusIndicator.parag ) {
3131 if ( next ) { 3157 if ( next ) {
3132 focusIndicator.parag = fParag; 3158 focusIndicator.parag = fParag;
3133 focusIndicator.start = 0; 3159 focusIndicator.start = 0;
3134 focusIndicator.len = 0; 3160 focusIndicator.len = 0;
3135 } else { 3161 } else {
3136 focusIndicator.parag = lParag; 3162 focusIndicator.parag = lParag;
3137 focusIndicator.start = lParag->length(); 3163 focusIndicator.start = lParag->length();
3138 focusIndicator.len = 0; 3164 focusIndicator.len = 0;
3139 } 3165 }
3140 } else { 3166 } else {
3141 focusIndicator.parag->setChanged( TRUE ); 3167 focusIndicator.parag->setChanged( TRUE );
3142 } 3168 }
3143 focusIndicator.href = QString::null; 3169 focusIndicator.href = QString::null;
3144 3170
3145 if ( next ) { 3171 if ( next ) {
3146 QTextParag *p = focusIndicator.parag; 3172 QTextParagraph *p = focusIndicator.parag;
3147 int index = focusIndicator.start + focusIndicator.len; 3173 int index = focusIndicator.start + focusIndicator.len;
3148 while ( p ) { 3174 while ( p ) {
3149 for ( int i = index; i < p->length(); ++i ) { 3175 for ( int i = index; i < p->length(); ++i ) {
3150 if ( p->at( i )->isAnchor() ) { 3176 if ( p->at( i )->isAnchor() ) {
3151 p->setChanged( TRUE ); 3177 p->setChanged( TRUE );
3152 focusIndicator.parag = p; 3178 focusIndicator.parag = p;
3153 focusIndicator.start = i; 3179 focusIndicator.start = i;
3154 focusIndicator.len = 0; 3180 focusIndicator.len = 0;
3155 focusIndicator.href = p->at( i )->anchorHref(); 3181 focusIndicator.href = p->at( i )->anchorHref();
3156 while ( i < p->length() ) { 3182 while ( i < p->length() ) {
3157 if ( !p->at( i )->isAnchor() ) 3183 if ( !p->at( i )->isAnchor() )
3158 return TRUE; 3184 return TRUE;
3159 focusIndicator.len++; 3185 focusIndicator.len++;
3160 i++; 3186 i++;
3161 } 3187 }
3162 } else if ( p->at( i )->isCustom() ) { 3188 } else if ( p->at( i )->isCustom() ) {
3163 if ( p->at( i )->customItem()->isNested() ) { 3189 if ( p->at( i )->customItem()->isNested() ) {
3164 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 3190 QTextTable *t = (QTextTable*)p->at( i )->customItem();
3165 QPtrList<QTextTableCell> cells = t->tableCells(); 3191 QPtrList<QTextTableCell> cells = t->tableCells();
3166 // first try to continue 3192 // first try to continue
3167 QTextTableCell *c; 3193 QTextTableCell *c;
3168 bool resetCells = TRUE; 3194 bool resetCells = TRUE;
3169 for ( c = cells.first(); c; c = cells.next() ) { 3195 for ( c = cells.first(); c; c = cells.next() ) {
3170 if ( c->richText()->hasFocusParagraph() ) { 3196 if ( c->richText()->hasFocusParagraph() ) {
3171 if ( c->richText()->focusNextPrevChild( next ) ) { 3197 if ( c->richText()->focusNextPrevChild( next ) ) {
3172 p->setChanged( TRUE ); 3198 p->setChanged( TRUE );
3173 focusIndicator.parag = p; 3199 focusIndicator.parag = p;
3174 focusIndicator.start = i; 3200 focusIndicator.start = i;
3175 focusIndicator.len = 0; 3201 focusIndicator.len = 0;
3176 focusIndicator.href = c->richText()->focusHref(); 3202 focusIndicator.href = c->richText()->focusHref();
3177 return TRUE; 3203 return TRUE;
3178 } else { 3204 } else {
3179 resetCells = FALSE; 3205 resetCells = FALSE;
3180 c = cells.next(); 3206 c = cells.next();
3181 break; 3207 break;
3182 } 3208 }
3183 } 3209 }
3184 } 3210 }
3185 // now really try 3211 // now really try
3186 if ( resetCells ) 3212 if ( resetCells )
3187 c = cells.first(); 3213 c = cells.first();
3188 for ( ; c; c = cells.next() ) { 3214 for ( ; c; c = cells.next() ) {
3189 if ( c->richText()->focusNextPrevChild( next ) ) { 3215 if ( c->richText()->focusNextPrevChild( next ) ) {
3190 p->setChanged( TRUE ); 3216 p->setChanged( TRUE );
3191 focusIndicator.parag = p; 3217 focusIndicator.parag = p;
3192 focusIndicator.start = i; 3218 focusIndicator.start = i;
3193 focusIndicator.len = 0; 3219 focusIndicator.len = 0;
3194 focusIndicator.href = c->richText()->focusHref(); 3220 focusIndicator.href = c->richText()->focusHref();
3195 return TRUE; 3221 return TRUE;
3196 } 3222 }
3197 } 3223 }
3198 } 3224 }
3199 } 3225 }
3200 } 3226 }
3201 index = 0; 3227 index = 0;
3202 p = p->next(); 3228 p = p->next();
3203 } 3229 }
3204 } else { 3230 } else {
3205 QTextParag *p = focusIndicator.parag; 3231 QTextParagraph *p = focusIndicator.parag;
3206 int index = focusIndicator.start - 1; 3232 int index = focusIndicator.start - 1;
3207 if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 ) 3233 if ( focusIndicator.len == 0 && index < focusIndicator.parag->length() - 1 )
3208 index++; 3234 index++;
3209 while ( p ) { 3235 while ( p ) {
3210 for ( int i = index; i >= 0; --i ) { 3236 for ( int i = index; i >= 0; --i ) {
3211 if ( p->at( i )->isAnchor() ) { 3237 if ( p->at( i )->isAnchor() ) {
3212 p->setChanged( TRUE ); 3238 p->setChanged( TRUE );
3213 focusIndicator.parag = p; 3239 focusIndicator.parag = p;
3214 focusIndicator.start = i; 3240 focusIndicator.start = i;
3215 focusIndicator.len = 0; 3241 focusIndicator.len = 0;
3216 focusIndicator.href = p->at( i )->anchorHref(); 3242 focusIndicator.href = p->at( i )->anchorHref();
3217 while ( i >= -1 ) { 3243 while ( i >= -1 ) {
3218 if ( i < 0 || !p->at( i )->isAnchor() ) { 3244 if ( i < 0 || !p->at( i )->isAnchor() ) {
3219 focusIndicator.start++; 3245 focusIndicator.start++;
3220 return TRUE; 3246 return TRUE;
3221 } 3247 }
3222 if ( i < 0 ) 3248 if ( i < 0 )
3223 break; 3249 break;
3224 focusIndicator.len++; 3250 focusIndicator.len++;
3225 focusIndicator.start--; 3251 focusIndicator.start--;
3226 i--; 3252 i--;
3227 } 3253 }
3228 } else if ( p->at( i )->isCustom() ) { 3254 } else if ( p->at( i )->isCustom() ) {
3229 if ( p->at( i )->customItem()->isNested() ) { 3255 if ( p->at( i )->customItem()->isNested() ) {
3230 QTextTable *t = (QTextTable*)p->at( i )->customItem(); 3256 QTextTable *t = (QTextTable*)p->at( i )->customItem();
3231 QPtrList<QTextTableCell> cells = t->tableCells(); 3257 QPtrList<QTextTableCell> cells = t->tableCells();
3232 // first try to continue 3258 // first try to continue
3233 QTextTableCell *c; 3259 QTextTableCell *c;
3234 bool resetCells = TRUE; 3260 bool resetCells = TRUE;
3235 for ( c = cells.last(); c; c = cells.prev() ) { 3261 for ( c = cells.last(); c; c = cells.prev() ) {
3236 if ( c->richText()->hasFocusParagraph() ) { 3262 if ( c->richText()->hasFocusParagraph() ) {
3237 if ( c->richText()->focusNextPrevChild( next ) ) { 3263 if ( c->richText()->focusNextPrevChild( next ) ) {
@@ -3253,65 +3279,65 @@ bool QTextDocument::focusNextPrevChild( bool next )
3253 // now really try 3279 // now really try
3254 if ( resetCells ) 3280 if ( resetCells )
3255 c = cells.last(); 3281 c = cells.last();
3256 for ( ; c; c = cells.prev() ) { 3282 for ( ; c; c = cells.prev() ) {
3257 if ( c->richText()->focusNextPrevChild( next ) ) { 3283 if ( c->richText()->focusNextPrevChild( next ) ) {
3258 p->setChanged( TRUE ); 3284 p->setChanged( TRUE );
3259 focusIndicator.parag = p; 3285 focusIndicator.parag = p;
3260 focusIndicator.start = i; 3286 focusIndicator.start = i;
3261 focusIndicator.len = 0; 3287 focusIndicator.len = 0;
3262 focusIndicator.href = c->richText()->focusHref(); 3288 focusIndicator.href = c->richText()->focusHref();
3263 return TRUE; 3289 return TRUE;
3264 } 3290 }
3265 if ( cells.at() == 0 ) 3291 if ( cells.at() == 0 )
3266 break; 3292 break;
3267 } 3293 }
3268 } 3294 }
3269 } 3295 }
3270 } 3296 }
3271 p = p->prev(); 3297 p = p->prev();
3272 if ( p ) 3298 if ( p )
3273 index = p->length() - 1; 3299 index = p->length() - 1;
3274 } 3300 }
3275 } 3301 }
3276 3302
3277 focusIndicator.parag = 0; 3303 focusIndicator.parag = 0;
3278 3304
3279 return FALSE; 3305 return FALSE;
3280} 3306}
3281 3307
3282int QTextDocument::length() const 3308int QTextDocument::length() const
3283{ 3309{
3284 int l = 0; 3310 int l = 0;
3285 QTextParag *p = fParag; 3311 QTextParagraph *p = fParag;
3286 while ( p ) { 3312 while ( p ) {
3287 l += p->length() - 1; // don't count trailing space 3313 l += p->length() - 1; // don't count trailing space
3288 p = p->next(); 3314 p = p->next();
3289 } 3315 }
3290 return l; 3316 return l;
3291} 3317}
3292 3318
3293// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3319// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3294 3320
3295int QTextFormat::width( const QChar &c ) const 3321int QTextFormat::width( const QChar &c ) const
3296{ 3322{
3297 if ( c.unicode() == 0xad ) // soft hyphen 3323 if ( c.unicode() == 0xad ) // soft hyphen
3298 return 0; 3324 return 0;
3299 if ( !pntr || !pntr->isActive() ) { 3325 if ( !pntr || !pntr->isActive() ) {
3300 if ( c == '\t' ) 3326 if ( c == '\t' )
3301 return fm.width( 'x' ) * 8; 3327 return fm.width( 'x' ) * 8;
3302 if ( ha == AlignNormal ) { 3328 if ( ha == AlignNormal ) {
3303 int w; 3329 int w;
3304 if ( c.row() ) 3330 if ( c.row() )
3305 w = fm.width( c ); 3331 w = fm.width( c );
3306 else 3332 else
3307 w = widths[ c.unicode() ]; 3333 w = widths[ c.unicode() ];
3308 if ( w == 0 && !c.row() ) { 3334 if ( w == 0 && !c.row() ) {
3309 w = fm.width( c ); 3335 w = fm.width( c );
3310 ( (QTextFormat*)this )->widths[ c.unicode() ] = w; 3336 ( (QTextFormat*)this )->widths[ c.unicode() ] = w;
3311 } 3337 }
3312 return w; 3338 return w;
3313 } else { 3339 } else {
3314 QFont f( fn ); 3340 QFont f( fn );
3315 if ( usePixelSizes ) 3341 if ( usePixelSizes )
3316 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3342 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3317 else 3343 else
@@ -3356,102 +3382,109 @@ int QTextFormat::width( const QString &str, int pos ) const
3356 if ( usePixelSizes ) 3382 if ( usePixelSizes )
3357 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 3383 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
3358 else 3384 else
3359 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 3385 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
3360 } 3386 }
3361 pntr->setFont( f ); 3387 pntr->setFont( f );
3362 w = pntr->fontMetrics().width( str[ pos ] ); 3388 w = pntr->fontMetrics().width( str[ pos ] );
3363 } 3389 }
3364 return w; 3390 return w;
3365} 3391}
3366 3392
3367// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3393// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3368 3394
3369QTextString::QTextString() 3395QTextString::QTextString()
3370{ 3396{
3371 bidiDirty = FALSE; 3397 bidiDirty = FALSE;
3372 bidi = FALSE; 3398 bidi = FALSE;
3373 rightToLeft = FALSE; 3399 rightToLeft = FALSE;
3374 dir = QChar::DirON; 3400 dir = QChar::DirON;
3375} 3401}
3376 3402
3377QTextString::QTextString( const QTextString &s ) 3403QTextString::QTextString( const QTextString &s )
3378{ 3404{
3379 bidiDirty = s.bidiDirty; 3405 bidiDirty = s.bidiDirty;
3380 bidi = s.bidi; 3406 bidi = s.bidi;
3381 rightToLeft = s.rightToLeft; 3407 rightToLeft = s.rightToLeft;
3382 dir = s.dir; 3408 dir = s.dir;
3383 data = s.subString(); 3409 data = s.subString();
3384} 3410}
3385 3411
3386void QTextString::insert( int index, const QString &s, QTextFormat *f ) 3412void QTextString::insert( int index, const QString &s, QTextFormat *f )
3387{ 3413{
3414 insert( index, s.unicode(), s.length(), f );
3415}
3416
3417void QTextString::insert( int index, const QChar *unicode, int len, QTextFormat *f )
3418{
3388 int os = data.size(); 3419 int os = data.size();
3389 data.resize( data.size() + s.length() ); 3420 data.resize( data.size() + len );
3390 if ( index < os ) { 3421 if ( index < os ) {
3391 memmove( data.data() + index + s.length(), data.data() + index, 3422 memmove( data.data() + index + len, data.data() + index,
3392 sizeof( QTextStringChar ) * ( os - index ) ); 3423 sizeof( QTextStringChar ) * ( os - index ) );
3393 } 3424 }
3394 for ( int i = 0; i < (int)s.length(); ++i ) { 3425 for ( int i = 0; i < len; ++i ) {
3395 data[ (int)index + i ].x = 0; 3426 data[ (int)index + i ].x = 0;
3396 data[ (int)index + i ].lineStart = 0; 3427 data[ (int)index + i ].lineStart = 0;
3397 data[ (int)index + i ].d.format = 0; 3428 data[ (int)index + i ].d.format = 0;
3398 data[ (int)index + i ].type = QTextStringChar::Regular; 3429 data[ (int)index + i ].type = QTextStringChar::Regular;
3399 data[ (int)index + i ].rightToLeft = 0; 3430 data[ (int)index + i ].rightToLeft = 0;
3400 data[ (int)index + i ].startOfRun = 0; 3431 data[ (int)index + i ].startOfRun = 0;
3401 data[ (int)index + i ].c = s[ i ]; 3432 data[ (int)index + i ].c = unicode[i];
3402 data[ (int)index + i ].setFormat( f ); 3433 data[ (int)index + i ].setFormat( f );
3403 } 3434 }
3404 bidiDirty = TRUE; 3435 bidiDirty = TRUE;
3405} 3436}
3406 3437
3407QTextString::~QTextString() 3438QTextString::~QTextString()
3408{ 3439{
3409 clear(); 3440 clear();
3410} 3441}
3411 3442
3412void QTextString::insert( int index, QTextStringChar *c ) 3443void QTextString::insert( int index, QTextStringChar *c, bool doAddRefFormat )
3413{ 3444{
3414 int os = data.size(); 3445 int os = data.size();
3415 data.resize( data.size() + 1 ); 3446 data.resize( data.size() + 1 );
3416 if ( index < os ) { 3447 if ( index < os ) {
3417 memmove( data.data() + index + 1, data.data() + index, 3448 memmove( data.data() + index + 1, data.data() + index,
3418 sizeof( QTextStringChar ) * ( os - index ) ); 3449 sizeof( QTextStringChar ) * ( os - index ) );
3419 } 3450 }
3420 data[ (int)index ].c = c->c; 3451 data[ (int)index ].c = c->c;
3421 data[ (int)index ].x = 0; 3452 data[ (int)index ].x = 0;
3422 data[ (int)index ].lineStart = 0; 3453 data[ (int)index ].lineStart = 0;
3423 data[ (int)index ].rightToLeft = 0; 3454 data[ (int)index ].rightToLeft = 0;
3424 data[ (int)index ].d.format = 0; 3455 data[ (int)index ].d.format = 0;
3425 data[ (int)index ].type = QTextStringChar::Regular; 3456 data[ (int)index ].type = QTextStringChar::Regular;
3457 if ( doAddRefFormat && c->format() )
3458 c->format()->addRef();
3426 data[ (int)index ].setFormat( c->format() ); 3459 data[ (int)index ].setFormat( c->format() );
3427 bidiDirty = TRUE; 3460 bidiDirty = TRUE;
3428} 3461}
3429 3462
3430void QTextString::truncate( int index ) 3463void QTextString::truncate( int index )
3431{ 3464{
3432 index = QMAX( index, 0 ); 3465 index = QMAX( index, 0 );
3433 index = QMIN( index, (int)data.size() - 1 ); 3466 index = QMIN( index, (int)data.size() - 1 );
3434 if ( index < (int)data.size() ) { 3467 if ( index < (int)data.size() ) {
3435 for ( int i = index + 1; i < (int)data.size(); ++i ) { 3468 for ( int i = index + 1; i < (int)data.size(); ++i ) {
3436 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3469 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3437 delete data[ i ].customItem(); 3470 delete data[ i ].customItem();
3438 if ( data[ i ].d.custom->format ) 3471 if ( data[ i ].d.custom->format )
3439 data[ i ].d.custom->format->removeRef(); 3472 data[ i ].d.custom->format->removeRef();
3440 delete data[ i ].d.custom; 3473 delete data[ i ].d.custom;
3441 data[ i ].d.custom = 0; 3474 data[ i ].d.custom = 0;
3442 } else if ( data[ i ].format() ) { 3475 } else if ( data[ i ].format() ) {
3443 data[ i ].format()->removeRef(); 3476 data[ i ].format()->removeRef();
3444 } 3477 }
3445 } 3478 }
3446 } 3479 }
3447 data.truncate( index ); 3480 data.truncate( index );
3448 bidiDirty = TRUE; 3481 bidiDirty = TRUE;
3449} 3482}
3450 3483
3451void QTextString::remove( int index, int len ) 3484void QTextString::remove( int index, int len )
3452{ 3485{
3453 for ( int i = index; i < (int)data.size() && i - index < len; ++i ) { 3486 for ( int i = index; i < (int)data.size() && i - index < len; ++i ) {
3454 if ( !(data[ i ].type == QTextStringChar::Regular) ) { 3487 if ( !(data[ i ].type == QTextStringChar::Regular) ) {
3455 delete data[ i ].customItem(); 3488 delete data[ i ].customItem();
3456 if ( data[ i ].d.custom->format ) 3489 if ( data[ i ].d.custom->format )
3457 data[ i ].d.custom->format->removeRef(); 3490 data[ i ].d.custom->format->removeRef();
@@ -3516,104 +3549,99 @@ void QTextString::checkBidi() const
3516 case QChar::DirLRO: 3549 case QChar::DirLRO:
3517 case QChar::DirLRE: 3550 case QChar::DirLRE:
3518 ((QTextString *)this)->rightToLeft = FALSE; 3551 ((QTextString *)this)->rightToLeft = FALSE;
3519 rtlKnown = TRUE; 3552 rtlKnown = TRUE;
3520 break; 3553 break;
3521 case QChar::DirR: 3554 case QChar::DirR:
3522 case QChar::DirAL: 3555 case QChar::DirAL:
3523 case QChar::DirRLO: 3556 case QChar::DirRLO:
3524 case QChar::DirRLE: 3557 case QChar::DirRLE:
3525 ((QTextString *)this)->rightToLeft = TRUE; 3558 ((QTextString *)this)->rightToLeft = TRUE;
3526 rtlKnown = TRUE; 3559 rtlKnown = TRUE;
3527 break; 3560 break;
3528 default: 3561 default:
3529 break; 3562 break;
3530 } 3563 }
3531 } 3564 }
3532 uchar row = c->c.row(); 3565 uchar row = c->c.row();
3533 if( (row > 0x04 && row < 0x09) || (row > 0xfa && row < 0xff) ) { 3566 if( (row > 0x04 && row < 0x09) || (row > 0xfa && row < 0xff) ) {
3534 ((QTextString *)this)->bidi = TRUE; 3567 ((QTextString *)this)->bidi = TRUE;
3535 if ( rtlKnown ) 3568 if ( rtlKnown )
3536 return; 3569 return;
3537 } 3570 }
3538 len--; 3571 len--;
3539 ++c; 3572 ++c;
3540 } 3573 }
3541} 3574}
3542 3575
3543void QTextDocument::setStyleSheet( QStyleSheet *s ) 3576void QTextDocument::setStyleSheet( QStyleSheet *s )
3544{ 3577{
3545 if ( !s ) 3578 if ( !s )
3546 return; 3579 return;
3547 sheet_ = s; 3580 sheet_ = s;
3548 fCollection->setStyleSheet( s ); 3581 list_tm = list_bm = par_tm = par_bm = 12;
3549 updateStyles(); 3582 list_lm = 40;
3550} 3583 li_tm = li_bm = 0;
3551 3584 QStyleSheetItem* item = s->item( "ol" );
3552void QTextDocument::updateStyles() 3585 if ( item ) {
3553{ 3586 list_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3554 invalidate(); 3587 list_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3555 if ( par ) 3588 list_lm = QMAX(0,item->margin( QStyleSheetItem::MarginLeft ));
3556 underlLinks = par->underlLinks; 3589 }
3557 fCollection->updateStyles(); 3590 if ( (item = s->item( "li" ) ) ) {
3558 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 3591 li_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3559 d->updateStyles(); 3592 li_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3560} 3593 }
3561 3594 if ( (item = s->item( "p" ) ) ) {
3562void QTextDocument::updateFontSizes( int base, bool usePixels ) 3595 par_tm = QMAX(0,item->margin( QStyleSheetItem::MarginTop ));
3563{ 3596 par_bm = QMAX(0,item->margin( QStyleSheetItem::MarginBottom ));
3564 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 3597 }
3565 d->updateFontSizes( base, usePixels );
3566 invalidate();
3567 fCollection->updateFontSizes( base, usePixels );
3568} 3598}
3569 3599
3570void QTextDocument::updateFontAttributes( const QFont &f, const QFont &old ) 3600void QTextDocument::setUnderlineLinks( bool b ) {
3571{ 3601 underlLinks = b;
3572 for ( QTextDocument *d = childList.first(); d; d = childList.next() ) 3602 for ( QTextDocument *d = childList.first(); d; d = childList.next() )
3573 d->updateFontAttributes( f, old ); 3603 d->setUnderlineLinks( b );
3574 invalidate();
3575 fCollection->updateFontAttributes( f, old );
3576} 3604}
3577 3605
3578void QTextStringChar::setFormat( QTextFormat *f ) 3606void QTextStringChar::setFormat( QTextFormat *f )
3579{ 3607{
3580 if ( type == Regular ) { 3608 if ( type == Regular ) {
3581 d.format = f; 3609 d.format = f;
3582 } else { 3610 } else {
3583 if ( !d.custom ) { 3611 if ( !d.custom ) {
3584 d.custom = new CustomData; 3612 d.custom = new CustomData;
3585 d.custom->custom = 0; 3613 d.custom->custom = 0;
3586 } 3614 }
3587 d.custom->format = f; 3615 d.custom->format = f;
3588 } 3616 }
3589} 3617}
3590 3618
3591void QTextStringChar::setCustomItem( QTextCustomItem *i ) 3619void QTextStringChar::setCustomItem( QTextCustomItem *i )
3592{ 3620{
3593 if ( type == Regular ) { 3621 if ( type == Regular ) {
3594 QTextFormat *f = format(); 3622 QTextFormat *f = format();
3595 d.custom = new CustomData; 3623 d.custom = new CustomData;
3596 d.custom->format = f; 3624 d.custom->format = f;
3597 } else { 3625 } else {
3598 delete d.custom->custom; 3626 delete d.custom->custom;
3599 } 3627 }
3600 d.custom->custom = i; 3628 d.custom->custom = i;
3601 type = (type == Anchor ? CustomAnchor : Custom); 3629 type = (type == Anchor ? CustomAnchor : Custom);
3602} 3630}
3603 3631
3604void QTextStringChar::loseCustomItem() 3632void QTextStringChar::loseCustomItem()
3605{ 3633{
3606 if ( type == Custom ) { 3634 if ( type == Custom ) {
3607 QTextFormat *f = d.custom->format; 3635 QTextFormat *f = d.custom->format;
3608 d.custom->custom = 0; 3636 d.custom->custom = 0;
3609 delete d.custom; 3637 delete d.custom;
3610 type = Regular; 3638 type = Regular;
3611 d.format = f; 3639 d.format = f;
3612 } else if ( type == CustomAnchor ) { 3640 } else if ( type == CustomAnchor ) {
3613 d.custom->custom = 0; 3641 d.custom->custom = 0;
3614 type = Anchor; 3642 type = Anchor;
3615 } 3643 }
3616} 3644}
3617 3645
3618QString QTextStringChar::anchorName() const 3646QString QTextStringChar::anchorName() const
3619{ 3647{
@@ -3622,2814 +3650,2468 @@ QString QTextStringChar::anchorName() const
3622 else 3650 else
3623 return d.custom->anchorName; 3651 return d.custom->anchorName;
3624} 3652}
3625 3653
3626QString QTextStringChar::anchorHref() const 3654QString QTextStringChar::anchorHref() const
3627{ 3655{
3628 if ( type == Regular ) 3656 if ( type == Regular )
3629 return QString::null; 3657 return QString::null;
3630 else 3658 else
3631 return d.custom->anchorHref; 3659 return d.custom->anchorHref;
3632} 3660}
3633 3661
3634void QTextStringChar::setAnchor( const QString& name, const QString& href ) 3662void QTextStringChar::setAnchor( const QString& name, const QString& href )
3635{ 3663{
3636 if ( type == Regular ) { 3664 if ( type == Regular ) {
3637 QTextFormat *f = format(); 3665 QTextFormat *f = format();
3638 d.custom = new CustomData; 3666 d.custom = new CustomData;
3639 d.custom->custom = 0; 3667 d.custom->custom = 0;
3640 d.custom->format = f; 3668 d.custom->format = f;
3641 type = Anchor; 3669 type = Anchor;
3642 } else if ( type == Custom ) { 3670 } else if ( type == Custom ) {
3643 type = CustomAnchor; 3671 type = CustomAnchor;
3644 } 3672 }
3645 d.custom->anchorName = name; 3673 d.custom->anchorName = name;
3646 d.custom->anchorHref = href; 3674 d.custom->anchorHref = href;
3647} 3675}
3648 3676
3649 3677
3650int QTextString::width( int idx ) const 3678int QTextString::width( int idx ) const
3651{ 3679{
3652 int w = 0; 3680 int w = 0;
3653 QTextStringChar *c = &at( idx ); 3681 QTextStringChar *c = &at( idx );
3654 if ( c->c.unicode() == 0xad ) 3682 if ( c->c.unicode() == 0xad || c->c.unicode() == 0x2028 )
3655 return 0; 3683 return 0;
3656 if( c->isCustom() ) { 3684 if( c->isCustom() ) {
3657 if( c->customItem()->placement() == QTextCustomItem::PlaceInline ) 3685 if( c->customItem()->placement() == QTextCustomItem::PlaceInline )
3658 w = c->customItem()->width; 3686 w = c->customItem()->width;
3659 } else { 3687 } else {
3660 int r = c->c.row(); 3688 int r = c->c.row();
3661 if( r < 0x06 || r > 0x1f ) 3689 if( r < 0x06 || r > 0x1f )
3662 w = c->format()->width( c->c ); 3690 w = c->format()->width( c->c );
3663 else { 3691 else {
3664 // complex text. We need some hacks to get the right metric here 3692 // complex text. We need some hacks to get the right metric here
3665 QString str; 3693 QString str;
3666 int pos = 0; 3694 int pos = 0;
3667 if( idx > 4 ) 3695 if( idx > 4 )
3668 pos = idx - 4; 3696 pos = idx - 4;
3669 int off = idx - pos; 3697 int off = idx - pos;
3670 int end = QMIN( length(), idx + 4 ); 3698 int end = QMIN( length(), idx + 4 );
3671 while ( pos < end ) { 3699 while ( pos < end ) {
3672 str += at(pos).c; 3700 str += at(pos).c;
3673 pos++; 3701 pos++;
3674 } 3702 }
3675 w = c->format()->width( str, off ); 3703 w = c->format()->width( str, off );
3676 } 3704 }
3677 } 3705 }
3678 return w; 3706 return w;
3679} 3707}
3680 3708
3681QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const 3709QMemArray<QTextStringChar> QTextString::subString( int start, int len ) const
3682{ 3710{
3683 if ( len == 0xFFFFFF ) 3711 if ( len == 0xFFFFFF )
3684 len = data.size(); 3712 len = data.size();
3685 QMemArray<QTextStringChar> a; 3713 QMemArray<QTextStringChar> a;
3686 a.resize( len ); 3714 a.resize( len );
3687 for ( int i = 0; i < len; ++i ) { 3715 for ( int i = 0; i < len; ++i ) {
3688 QTextStringChar *c = &data[ i + start ]; 3716 QTextStringChar *c = &data[ i + start ];
3689 a[ i ].c = c->c; 3717 a[ i ].c = c->c;
3690 a[ i ].x = 0; 3718 a[ i ].x = 0;
3691 a[ i ].lineStart = 0; 3719 a[ i ].lineStart = 0;
3692 a[ i ].rightToLeft = 0; 3720 a[ i ].rightToLeft = 0;
3693 a[ i ].d.format = 0; 3721 a[ i ].d.format = 0;
3694 a[ i ].type = QTextStringChar::Regular; 3722 a[ i ].type = QTextStringChar::Regular;
3695 a[ i ].setFormat( c->format() ); 3723 a[ i ].setFormat( c->format() );
3696 if ( c->format() ) 3724 if ( c->format() )
3697 c->format()->addRef(); 3725 c->format()->addRef();
3698 } 3726 }
3699 return a; 3727 return a;
3700} 3728}
3701 3729
3702QTextStringChar *QTextStringChar::clone() const
3703{
3704 QTextStringChar *chr = new QTextStringChar;
3705 chr->c = c;
3706 chr->x = 0;
3707 chr->lineStart = 0;
3708 chr->rightToLeft = 0;
3709 chr->d.format = 0;
3710 chr->type = QTextStringChar::Regular;
3711 chr->setFormat( format() );
3712 if ( chr->format() )
3713 chr->format()->addRef();
3714 return chr;
3715}
3716
3717// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3730// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3718 3731
3719QTextParag::QTextParag( QTextDocument *d, QTextParag *pr, QTextParag *nx, bool updateIds ) 3732QTextParagraph::QTextParagraph( QTextDocument *d, QTextParagraph *pr, QTextParagraph *nx, bool updateIds )
3720 : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ), align( 0 ),mSelections( 0 ), 3733 : invalid( 0 ), p( pr ), n( nx ), docOrPseudo( d ),
3721 mStyleSheetItemsVec( 0 ), mFloatingItems( 0 ), listS( QStyleSheetItem::ListDisc ), 3734 changed(FALSE), firstFormat(TRUE), firstPProcess(TRUE), needPreProcess(FALSE), fullWidth(TRUE),
3722 numSubParag( -1 ), tm( -1 ), bm( -1 ), lm( -1 ), rm( -1 ), flm( -1 ), 3735 lastInFrame(FALSE), visible(TRUE), breakable(TRUE), movedDown(FALSE),
3723 tArray(0), tabStopWidth(0), eData( 0 ) 3736 mightHaveCustomItems(FALSE), hasdoc( d != 0 ), litem(FALSE), rtext(FALSE),
3724{ 3737 align( 0 ),mSelections( 0 ),
3725 listS = QStyleSheetItem::ListDisc; 3738 mFloatingItems( 0 ), lstyle( QStyleSheetItem::ListDisc ),
3726 if ( ! (hasdoc = docOrPseudo != 0 ) ) 3739 utm( 0 ), ubm( 0 ), ulm( 0 ), urm( 0 ), uflm( 0 ), ulinespacing( 0 ),
3727 docOrPseudo = new QTextParagPseudoDocument; 3740 tArray(0), tabStopWidth(0), eData( 0 ), ldepth( 0 )
3741{
3742 lstyle = QStyleSheetItem::ListDisc;
3743 if ( !hasdoc )
3744 docOrPseudo = new QTextParagraphPseudoDocument;
3728 bgcol = 0; 3745 bgcol = 0;
3729 breakable = TRUE;
3730 isBr = FALSE;
3731 movedDown = FALSE;
3732 mightHaveCustomItems = FALSE;
3733 visible = TRUE;
3734 list_val = -1; 3746 list_val = -1;
3735 newLinesAllowed = FALSE; 3747 QTextFormat* defFormat = formatCollection()->defaultFormat();
3736 lastInFrame = FALSE;
3737 defFormat = formatCollection()->defaultFormat();
3738 if ( !hasdoc ) { 3748 if ( !hasdoc ) {
3739 tabStopWidth = defFormat->width( 'x' ) * 8; 3749 tabStopWidth = defFormat->width( 'x' ) * 8;
3740 pseudoDocument()->commandHistory = new QTextCommandHistory( 100 ); 3750 pseudoDocument()->commandHistory = new QTextCommandHistory( 100 );
3741 } 3751 }
3742#if defined(PARSER_DEBUG)
3743 qDebug( debug_indent + "new QTextParag" );
3744#endif
3745 fullWidth = TRUE;
3746 3752
3747 if ( p ) 3753 if ( p )
3748 p->n = this; 3754 p->n = this;
3749 if ( n ) 3755 if ( n )
3750 n->p = this; 3756 n->p = this;
3751 3757
3752 3758
3753 if ( !p && hasdoc ) 3759 if ( !p && hasdoc )
3754 document()->setFirstParag( this ); 3760 document()->setFirstParagraph( this );
3755 if ( !n && hasdoc ) 3761 if ( !n && hasdoc )
3756 document()->setLastParag( this ); 3762 document()->setLastParagraph( this );
3757 3763
3758 changed = FALSE;
3759 firstFormat = TRUE;
3760 state = -1; 3764 state = -1;
3761 needPreProcess = FALSE;
3762 3765
3763 if ( p ) 3766 if ( p )
3764 id = p->id + 1; 3767 id = p->id + 1;
3765 else 3768 else
3766 id = 0; 3769 id = 0;
3767 if ( n && updateIds ) { 3770 if ( n && updateIds ) {
3768 QTextParag *s = n; 3771 QTextParagraph *s = n;
3769 while ( s ) { 3772 while ( s ) {
3770 s->id = s->p->id + 1; 3773 s->id = s->p->id + 1;
3771 s->numSubParag = -1; 3774 s->invalidateStyleCache();
3772 s->lm = s->rm = s->tm = s->bm = -1, s->flm = -1;
3773 s = s->n; 3775 s = s->n;
3774 } 3776 }
3775 } 3777 }
3776 firstPProcess = TRUE;
3777 3778
3778 str = new QTextString(); 3779 str = new QTextString();
3779 str->insert( 0, " ", formatCollection()->defaultFormat() ); 3780 str->insert( 0, " ", formatCollection()->defaultFormat() );
3780} 3781}
3781 3782
3782QTextParag::~QTextParag() 3783QTextParagraph::~QTextParagraph()
3783{ 3784{
3784 delete str; 3785 delete str;
3785 if ( hasdoc ) { 3786 if ( hasdoc ) {
3786 register QTextDocument *doc = document(); 3787 register QTextDocument *doc = document();
3787 if ( this == doc->minwParag ) { 3788 if ( this == doc->minwParag ) {
3788 doc->minwParag = 0; 3789 doc->minwParag = 0;
3789 doc->minw = 0; 3790 doc->minw = 0;
3790 } 3791 }
3791 if ( this == doc->curParag ) 3792 if ( this == doc->curParag )
3792 doc->curParag = 0; 3793 doc->curParag = 0;
3793 } else { 3794 } else {
3794 delete pseudoDocument(); 3795 delete pseudoDocument();
3795 } 3796 }
3796 if ( tArray ) 3797 if ( tArray )
3797 delete [] tArray; 3798 delete [] tArray;
3798 delete eData; 3799 delete eData;
3799 QMap<int, QTextParagLineStart*>::Iterator it = lineStarts.begin(); 3800 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin();
3800 for ( ; it != lineStarts.end(); ++it ) 3801 for ( ; it != lineStarts.end(); ++it )
3801 delete *it; 3802 delete *it;
3802 if ( mSelections ) 3803 if ( mSelections )
3803 delete mSelections; 3804 delete mSelections;
3804 if ( mFloatingItems ) 3805 if ( mFloatingItems )
3805 delete mFloatingItems; 3806 delete mFloatingItems;
3806 if ( mStyleSheetItemsVec )
3807 delete mStyleSheetItemsVec;
3808 if ( p ) 3807 if ( p )
3809 p->setNext( n ); 3808 p->setNext( n );
3810 if ( n ) 3809 if ( n )
3811 n->setPrev( p ); 3810 n->setPrev( p );
3812} 3811}
3813 3812
3814void QTextParag::setNext( QTextParag *s ) 3813void QTextParagraph::setNext( QTextParagraph *s )
3815{ 3814{
3816 n = s; 3815 n = s;
3817 if ( !n && hasdoc ) 3816 if ( !n && hasdoc )
3818 document()->setLastParag( this ); 3817 document()->setLastParagraph( this );
3819} 3818}
3820 3819
3821void QTextParag::setPrev( QTextParag *s ) 3820void QTextParagraph::setPrev( QTextParagraph *s )
3822{ 3821{
3823 p = s; 3822 p = s;
3824 if ( !p && hasdoc ) 3823 if ( !p && hasdoc )
3825 document()->setFirstParag( this ); 3824 document()->setFirstParagraph( this );
3826} 3825}
3827 3826
3828void QTextParag::invalidate( int chr ) 3827void QTextParagraph::invalidate( int chr )
3829{ 3828{
3830 if ( invalid < 0 ) 3829 if ( invalid < 0 )
3831 invalid = chr; 3830 invalid = chr;
3832 else 3831 else
3833 invalid = QMIN( invalid, chr ); 3832 invalid = QMIN( invalid, chr );
3834 if ( mFloatingItems ) { 3833 if ( mFloatingItems ) {
3835 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) 3834 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() )
3836 i->ypos = -1; 3835 i->ypos = -1;
3837 } 3836 }
3838 lm = rm = bm = tm = flm = -1; 3837 invalidateStyleCache();
3839} 3838}
3840 3839
3841void QTextParag::insert( int index, const QString &s ) 3840void QTextParagraph::invalidateStyleCache()
3841{
3842 if ( list_val < 0 )
3843 list_val = -1;
3844}
3845
3846
3847void QTextParagraph::insert( int index, const QString &s )
3848{
3849 insert( index, s.unicode(), s.length() );
3850}
3851
3852void QTextParagraph::insert( int index, const QChar *unicode, int len )
3842{ 3853{
3843 if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() ) 3854 if ( hasdoc && !document()->useFormatCollection() && document()->preProcessor() )
3844 str->insert( index, s, 3855 str->insert( index, unicode, len,
3845 document()->preProcessor()->format( QTextPreProcessor::Standard ) ); 3856 document()->preProcessor()->format( QTextPreProcessor::Standard ) );
3846 else 3857 else
3847 str->insert( index, s, formatCollection()->defaultFormat() ); 3858 str->insert( index, unicode, len, formatCollection()->defaultFormat() );
3848 invalidate( index ); 3859 invalidate( index );
3849 needPreProcess = TRUE; 3860 needPreProcess = TRUE;
3850} 3861}
3851 3862
3852void QTextParag::truncate( int index ) 3863void QTextParagraph::truncate( int index )
3853{ 3864{
3854 str->truncate( index ); 3865 str->truncate( index );
3855 insert( length(), " " ); 3866 insert( length(), " " );
3856 needPreProcess = TRUE; 3867 needPreProcess = TRUE;
3857} 3868}
3858 3869
3859void QTextParag::remove( int index, int len ) 3870void QTextParagraph::remove( int index, int len )
3860{ 3871{
3861 if ( index + len - str->length() > 0 ) 3872 if ( index + len - str->length() > 0 )
3862 return; 3873 return;
3863 for ( int i = index; i < index + len; ++i ) { 3874 for ( int i = index; i < index + len; ++i ) {
3864 QTextStringChar *c = at( i ); 3875 QTextStringChar *c = at( i );
3865 if ( hasdoc && c->isCustom() ) { 3876 if ( hasdoc && c->isCustom() ) {
3866 document()->unregisterCustomItem( c->customItem(), this ); 3877 document()->unregisterCustomItem( c->customItem(), this );
3867 } 3878 }
3868 } 3879 }
3869 str->remove( index, len ); 3880 str->remove( index, len );
3870 invalidate( 0 ); 3881 invalidate( 0 );
3871 needPreProcess = TRUE; 3882 needPreProcess = TRUE;
3872} 3883}
3873 3884
3874void QTextParag::join( QTextParag *s ) 3885void QTextParagraph::join( QTextParagraph *s )
3875{ 3886{
3876 int oh = r.height() + s->r.height(); 3887 int oh = r.height() + s->r.height();
3877 n = s->n; 3888 n = s->n;
3878 if ( n ) 3889 if ( n )
3879 n->p = this; 3890 n->p = this;
3880 else if ( hasdoc ) 3891 else if ( hasdoc )
3881 document()->setLastParag( this ); 3892 document()->setLastParagraph( this );
3882 3893
3883 int start = str->length(); 3894 int start = str->length();
3884 if ( length() > 0 && at( length() - 1 )->c == ' ' ) { 3895 if ( length() > 0 && at( length() - 1 )->c == ' ' ) {
3885 remove( length() - 1, 1 ); 3896 remove( length() - 1, 1 );
3886 --start; 3897 --start;
3887 } 3898 }
3888 append( s->str->toString(), TRUE ); 3899 append( s->str->toString(), TRUE );
3889 3900
3890 for ( int i = 0; i < s->length(); ++i ) { 3901 for ( int i = 0; i < s->length(); ++i ) {
3891 if ( !hasdoc || document()->useFormatCollection() ) { 3902 if ( !hasdoc || document()->useFormatCollection() ) {
3892 s->str->at( i ).format()->addRef(); 3903 s->str->at( i ).format()->addRef();
3893 str->setFormat( i + start, s->str->at( i ).format(), TRUE ); 3904 str->setFormat( i + start, s->str->at( i ).format(), TRUE );
3894 } 3905 }
3895 if ( s->str->at( i ).isCustom() ) { 3906 if ( s->str->at( i ).isCustom() ) {
3896 QTextCustomItem * item = s->str->at( i ).customItem(); 3907 QTextCustomItem * item = s->str->at( i ).customItem();
3897 str->at( i + start ).setCustomItem( item ); 3908 str->at( i + start ).setCustomItem( item );
3898 s->str->at( i ).loseCustomItem(); 3909 s->str->at( i ).loseCustomItem();
3910 if ( hasdoc ) {
3911 document()->unregisterCustomItem( item, s );
3912 document()->registerCustomItem( item, this );
3913 }
3899 } 3914 }
3900 if ( s->str->at( i ).isAnchor() ) { 3915 if ( s->str->at( i ).isAnchor() ) {
3901 str->at( i + start ).setAnchor( s->str->at( i ).anchorName(), 3916 str->at( i + start ).setAnchor( s->str->at( i ).anchorName(),
3902 s->str->at( i ).anchorHref() ); 3917 s->str->at( i ).anchorHref() );
3903 } 3918 }
3904 } 3919 }
3905 3920
3906 if ( !extraData() && s->extraData() ) { 3921 if ( !extraData() && s->extraData() ) {
3907 setExtraData( s->extraData() ); 3922 setExtraData( s->extraData() );
3908 s->setExtraData( 0 ); 3923 s->setExtraData( 0 );
3909 } else if ( extraData() && s->extraData() ) { 3924 } else if ( extraData() && s->extraData() ) {
3910 extraData()->join( s->extraData() ); 3925 extraData()->join( s->extraData() );
3911 } 3926 }
3912 delete s; 3927 delete s;
3913 invalidate( 0 ); 3928 invalidate( 0 );
3914 r.setHeight( oh ); 3929 r.setHeight( oh );
3915 needPreProcess = TRUE; 3930 needPreProcess = TRUE;
3916 if ( n ) { 3931 if ( n ) {
3917 QTextParag *s = n; 3932 QTextParagraph *s = n;
3933 s->invalidate( 0 );
3918 while ( s ) { 3934 while ( s ) {
3919 s->id = s->p->id + 1; 3935 s->id = s->p->id + 1;
3920 s->state = -1; 3936 s->state = -1;
3921 s->needPreProcess = TRUE; 3937 s->needPreProcess = TRUE;
3922 s->changed = TRUE; 3938 s->changed = TRUE;
3939 s->invalidateStyleCache();
3923 s = s->n; 3940 s = s->n;
3924 } 3941 }
3925 } 3942 }
3926 format(); 3943 format();
3927 state = -1; 3944 state = -1;
3928} 3945}
3929 3946
3930void QTextParag::move( int &dy ) 3947void QTextParagraph::move( int &dy )
3931{ 3948{
3932 if ( dy == 0 ) 3949 if ( dy == 0 )
3933 return; 3950 return;
3934 changed = TRUE; 3951 changed = TRUE;
3935 r.moveBy( 0, dy ); 3952 r.moveBy( 0, dy );
3936 if ( mFloatingItems ) { 3953 if ( mFloatingItems ) {
3937 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) 3954 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() )
3938 i->ypos += dy; 3955 i->ypos += dy;
3939 } 3956 }
3940 if ( p ) 3957 if ( p )
3941 p->lastInFrame = TRUE; 3958 p->lastInFrame = TRUE;
3942 3959
3943 // do page breaks if required 3960 // do page breaks if required
3944 if ( hasdoc && document()->isPageBreakEnabled() ) { 3961 if ( hasdoc && document()->isPageBreakEnabled() ) {
3945 int shift; 3962 int shift;
3946 if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) { 3963 if ( ( shift = document()->formatter()->formatVertically( document(), this ) ) ) {
3947 if ( p ) 3964 if ( p )
3948 p->setChanged( TRUE ); 3965 p->setChanged( TRUE );
3949 dy += shift; 3966 dy += shift;
3950 } 3967 }
3951 } 3968 }
3952} 3969}
3953 3970
3954void QTextParag::format( int start, bool doMove ) 3971void QTextParagraph::format( int start, bool doMove )
3955{ 3972{
3956 if ( !str || str->length() == 0 || !formatter() ) 3973 if ( !str || str->length() == 0 || !formatter() )
3957 return; 3974 return;
3958 3975
3959 if ( hasdoc && 3976 if ( hasdoc &&
3960 document()->preProcessor() && 3977 document()->preProcessor() &&
3961 ( needPreProcess || state == -1 ) ) 3978 ( needPreProcess || state == -1 ) )
3962 document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid ); 3979 document()->preProcessor()->process( document(), this, invalid <= 0 ? 0 : invalid );
3963 needPreProcess = FALSE; 3980 needPreProcess = FALSE;
3964 3981
3965 if ( invalid == -1 ) 3982 if ( invalid == -1 )
3966 return; 3983 return;
3967 3984
3968 r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) ); 3985 r.moveTopLeft( QPoint( documentX(), p ? p->r.y() + p->r.height() : documentY() ) );
3969 r.setWidth( documentWidth() );
3970 if ( p ) 3986 if ( p )
3971 p->lastInFrame = FALSE; 3987 p->lastInFrame = FALSE;
3972 3988
3973 movedDown = FALSE; 3989 movedDown = FALSE;
3974 bool formattedAgain = FALSE; 3990 bool formattedAgain = FALSE;
3975 3991
3976 formatAgain: 3992 formatAgain:
3977 3993
3994 r.setWidth( documentWidth() );
3978 if ( hasdoc && mFloatingItems ) { 3995 if ( hasdoc && mFloatingItems ) {
3979 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) { 3996 for ( QTextCustomItem *i = mFloatingItems->first(); i; i = mFloatingItems->next() ) {
3980 i->ypos = r.y(); 3997 i->ypos = r.y();
3981 if ( i->placement() == QTextCustomItem::PlaceRight ) { 3998 if ( i->placement() == QTextCustomItem::PlaceRight ) {
3982 i->xpos = r.x() + r.width() - i->width; 3999 i->xpos = r.x() + r.width() - i->width;
3983 } 4000 }
3984 } 4001 }
3985 } 4002 }
3986 QMap<int, QTextParagLineStart*> oldLineStarts = lineStarts; 4003 QMap<int, QTextLineStart*> oldLineStarts = lineStarts;
3987 lineStarts.clear(); 4004 lineStarts.clear();
3988 int y = formatter()->format( document(), this, start, oldLineStarts ); 4005 int y = formatter()->format( document(), this, start, oldLineStarts );
3989 4006
3990 4007
3991 r.setWidth( QMAX( r.width(), formatter()->minimumWidth() ) ); 4008 r.setWidth( QMAX( r.width(), formatter()->minimumWidth() ) );
3992 4009
3993 4010
3994 QMap<int, QTextParagLineStart*>::Iterator it = oldLineStarts.begin(); 4011 QMap<int, QTextLineStart*>::Iterator it = oldLineStarts.begin();
3995 4012
3996 for ( ; it != oldLineStarts.end(); ++it ) 4013 for ( ; it != oldLineStarts.end(); ++it )
3997 delete *it; 4014 delete *it;
3998 4015
3999 QTextStringChar *c = 0; 4016 QTextStringChar *c = 0;
4000 // do not do this on mac, as the paragraph 4017 // do not do this on mac, as the paragraph
4001 // with has to be the full document width on mac as the selections 4018 // with has to be the full document width on mac as the selections
4002 // always extend completely to the right. This is a bit unefficient, 4019 // always extend completely to the right. This is a bit unefficient,
4003 // as this results in a bigger double buffer than needed but ok for 4020 // as this results in a bigger double buffer than needed but ok for
4004 // now. 4021 // now.
4005 if ( lineStarts.count() == 1 ) { //&& ( !doc || document()->flow()->isEmpty() ) ) { 4022 if ( lineStarts.count() == 1 ) {
4006 if ( !string()->isBidi() ) { 4023 if ( !string()->isBidi() ) {
4007 c = &str->at( str->length() - 1 ); 4024 c = &str->at( str->length() - 1 );
4008 r.setWidth( c->x + str->width( str->length() - 1 ) ); 4025 r.setWidth( c->x + str->width( str->length() - 1 ) );
4009 } else { 4026 } else {
4010 r.setWidth( lineStarts[0]->w ); 4027 r.setWidth( lineStarts[0]->w );
4011 } 4028 }
4012 } 4029 }
4013 4030
4014 if ( newLinesAllowed ) { 4031 if ( !hasdoc ) { // qt_format_text bounding rect handling
4015 it = lineStarts.begin(); 4032 it = lineStarts.begin();
4016 int usedw = 0; 4033 int usedw = 0;
4017 for ( ; it != lineStarts.end(); ++it ) 4034 for ( ; it != lineStarts.end(); ++it )
4018 usedw = QMAX( usedw, (*it)->w ); 4035 usedw = QMAX( usedw, (*it)->w );
4019 if ( r.width() <= 0 ) { 4036 if ( r.width() <= 0 ) {
4020 // if the user specifies an invalid rect, this means that the 4037 // if the user specifies an invalid rect, this means that the
4021 // bounding box should grow to the width that the text actually 4038 // bounding box should grow to the width that the text actually
4022 // needs 4039 // needs
4023 r.setWidth( usedw ); 4040 r.setWidth( usedw );
4024 } else { 4041 } else {
4025 r.setWidth( QMIN( usedw, r.width() ) ); 4042 r.setWidth( QMIN( usedw, r.width() ) );
4026 } 4043 }
4027 } 4044 }
4028 4045
4029 if ( y != r.height() ) 4046 if ( y != r.height() )
4030 r.setHeight( y ); 4047 r.setHeight( y );
4031 4048
4032 if ( !visible ) { 4049 if ( !visible ) {
4033 r.setHeight( 0 ); 4050 r.setHeight( 0 );
4034 } else { 4051 } else {
4035 int minw = formatter()->minimumWidth(); 4052 int minw = formatter()->minimumWidth();
4036 int wused = formatter()->widthUsed(); 4053 int wused = formatter()->widthUsed();
4037 wused = QMAX( minw, wused ); 4054 wused = QMAX( minw, wused );
4038 if ( hasdoc ) { 4055 if ( hasdoc ) {
4039 document()->setMinimumWidth( minw, wused, this ); 4056 document()->setMinimumWidth( minw, wused, this );
4040 } else { 4057 } else {
4041 pseudoDocument()->minw = QMAX( pseudoDocument()->minw, minw ); 4058 pseudoDocument()->minw = QMAX( pseudoDocument()->minw, minw );
4042 pseudoDocument()->wused = QMAX( pseudoDocument()->wused, wused ); 4059 pseudoDocument()->wused = QMAX( pseudoDocument()->wused, wused );
4043 } 4060 }
4044 } 4061 }
4045 4062
4046 // do page breaks if required 4063 // do page breaks if required
4047 if ( hasdoc && document()->isPageBreakEnabled() ) { 4064 if ( hasdoc && document()->isPageBreakEnabled() ) {
4048 int shift = document()->formatter()->formatVertically( document(), this ); 4065 int shift = document()->formatter()->formatVertically( document(), this );
4049 if ( shift && !formattedAgain ) { 4066 if ( shift && !formattedAgain ) {
4050 formattedAgain = TRUE; 4067 formattedAgain = TRUE;
4051 goto formatAgain; 4068 goto formatAgain;
4052 } 4069 }
4053 } 4070 }
4054 4071
4055 if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) { 4072 if ( n && doMove && n->invalid == -1 && r.y() + r.height() != n->r.y() ) {
4056 int dy = ( r.y() + r.height() ) - n->r.y(); 4073 int dy = ( r.y() + r.height() ) - n->r.y();
4057 QTextParag *s = n; 4074 QTextParagraph *s = n;
4058 bool makeInvalid = p && p->lastInFrame; 4075 bool makeInvalid = p && p->lastInFrame;
4059 while ( s && dy ) { 4076 while ( s && dy ) {
4060 if ( !s->isFullWidth() ) 4077 if ( !s->isFullWidth() )
4061 makeInvalid = TRUE; 4078 makeInvalid = TRUE;
4062 if ( makeInvalid ) 4079 if ( makeInvalid )
4063 s->invalidate( 0 ); 4080 s->invalidate( 0 );
4064 s->move( dy ); 4081 s->move( dy );
4065 if ( s->lastInFrame ) 4082 if ( s->lastInFrame )
4066 makeInvalid = TRUE; 4083 makeInvalid = TRUE;
4067 s = s->n; 4084 s = s->n;
4068 } 4085 }
4069 } 4086 }
4070 4087
4071 firstFormat = FALSE; 4088 firstFormat = FALSE;
4072 changed = TRUE; 4089 changed = TRUE;
4073 invalid = -1; 4090 invalid = -1;
4074 //##### string()->setTextChanged( FALSE ); 4091 //##### string()->setTextChanged( FALSE );
4075} 4092}
4076 4093
4077int QTextParag::lineHeightOfChar( int i, int *bl, int *y ) const 4094int QTextParagraph::lineHeightOfChar( int i, int *bl, int *y ) const
4078{ 4095{
4079 if ( !isValid() ) 4096 if ( !isValid() )
4080 ( (QTextParag*)this )->format(); 4097 ( (QTextParagraph*)this )->format();
4081 4098
4082 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.end(); 4099 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end();
4083 --it; 4100 --it;
4084 for ( ;; ) { 4101 for ( ;; ) {
4085 if ( i >= it.key() ) { 4102 if ( i >= it.key() ) {
4086 if ( bl ) 4103 if ( bl )
4087 *bl = ( *it )->baseLine; 4104 *bl = ( *it )->baseLine;
4088 if ( y ) 4105 if ( y )
4089 *y = ( *it )->y; 4106 *y = ( *it )->y;
4090 return ( *it )->h; 4107 return ( *it )->h;
4091 } 4108 }
4092 if ( it == lineStarts.begin() ) 4109 if ( it == lineStarts.begin() )
4093 break; 4110 break;
4094 --it; 4111 --it;
4095 } 4112 }
4096 4113
4097 qWarning( "QTextParag::lineHeightOfChar: couldn't find lh for %d", i ); 4114 qWarning( "QTextParagraph::lineHeightOfChar: couldn't find lh for %d", i );
4098 return 15; 4115 return 15;
4099} 4116}
4100 4117
4101QTextStringChar *QTextParag::lineStartOfChar( int i, int *index, int *line ) const 4118QTextStringChar *QTextParagraph::lineStartOfChar( int i, int *index, int *line ) const
4102{ 4119{
4103 if ( !isValid() ) 4120 if ( !isValid() )
4104 ( (QTextParag*)this )->format(); 4121 ( (QTextParagraph*)this )->format();
4105 4122
4106 int l = (int)lineStarts.count() - 1; 4123 int l = (int)lineStarts.count() - 1;
4107 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.end(); 4124 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.end();
4108 --it; 4125 --it;
4109 for ( ;; ) { 4126 for ( ;; ) {
4110 if ( i >= it.key() ) { 4127 if ( i >= it.key() ) {
4111 if ( index ) 4128 if ( index )
4112 *index = it.key(); 4129 *index = it.key();
4113 if ( line ) 4130 if ( line )
4114 *line = l; 4131 *line = l;
4115 return &str->at( it.key() ); 4132 return &str->at( it.key() );
4116 } 4133 }
4117 if ( it == lineStarts.begin() ) 4134 if ( it == lineStarts.begin() )
4118 break; 4135 break;
4119 --it; 4136 --it;
4120 --l; 4137 --l;
4121 } 4138 }
4122 4139
4123 qWarning( "QTextParag::lineStartOfChar: couldn't find %d", i ); 4140 qWarning( "QTextParagraph::lineStartOfChar: couldn't find %d", i );
4124 return 0; 4141 return 0;
4125} 4142}
4126 4143
4127int QTextParag::lines() const 4144int QTextParagraph::lines() const
4128{ 4145{
4129 if ( !isValid() ) 4146 if ( !isValid() )
4130 ( (QTextParag*)this )->format(); 4147 ( (QTextParagraph*)this )->format();
4131 4148
4132 return (int)lineStarts.count(); 4149 return (int)lineStarts.count();
4133} 4150}
4134 4151
4135QTextStringChar *QTextParag::lineStartOfLine( int line, int *index ) const 4152QTextStringChar *QTextParagraph::lineStartOfLine( int line, int *index ) const
4136{ 4153{
4137 if ( !isValid() ) 4154 if ( !isValid() )
4138 ( (QTextParag*)this )->format(); 4155 ( (QTextParagraph*)this )->format();
4139 4156
4140 if ( line >= 0 && line < (int)lineStarts.count() ) { 4157 if ( line >= 0 && line < (int)lineStarts.count() ) {
4141 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); 4158 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
4142 while ( line-- > 0 ) 4159 while ( line-- > 0 )
4143 ++it; 4160 ++it;
4144 int i = it.key(); 4161 int i = it.key();
4145 if ( index ) 4162 if ( index )
4146 *index = i; 4163 *index = i;
4147 return &str->at( i ); 4164 return &str->at( i );
4148 } 4165 }
4149 4166
4150 qWarning( "QTextParag::lineStartOfLine: couldn't find %d", line ); 4167 qWarning( "QTextParagraph::lineStartOfLine: couldn't find %d", line );
4151 return 0; 4168 return 0;
4152} 4169}
4153 4170
4154int QTextParag::leftGap() const 4171int QTextParagraph::leftGap() const
4155{ 4172{
4156 if ( !isValid() ) 4173 if ( !isValid() )
4157 ( (QTextParag*)this )->format(); 4174 ( (QTextParagraph*)this )->format();
4158 4175
4159 int line = 0; 4176 int line = 0;
4160 int x = str->at(0).x; /* set x to x of first char */ 4177 int x = str->at(0).x; /* set x to x of first char */
4161 if ( str->isBidi() ) { 4178 if ( str->isBidi() ) {
4162 for ( int i = 1; i < str->length(); ++i ) 4179 for ( int i = 1; i < str->length()-1; ++i )
4163 x = QMIN(x, str->at(i).x); 4180 x = QMIN(x, str->at(i).x);
4164 return x; 4181 return x;
4165 } 4182 }
4166 4183
4167 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); 4184 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
4168 while (line < (int)lineStarts.count()) { 4185 while (line < (int)lineStarts.count()) {
4169 int i = it.key(); /* char index */ 4186 int i = it.key(); /* char index */
4170 x = QMIN(x, str->at(i).x); 4187 x = QMIN(x, str->at(i).x);
4171 ++it; 4188 ++it;
4172 ++line; 4189 ++line;
4173 } 4190 }
4174 return x; 4191 return x;
4175} 4192}
4176 4193
4177void QTextParag::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags ) 4194void QTextParagraph::setFormat( int index, int len, QTextFormat *f, bool useCollection, int flags )
4178{ 4195{
4179 if ( !f ) 4196 if ( !f )
4180 return; 4197 return;
4181 if ( index < 0 ) 4198 if ( index < 0 )
4182 index = 0; 4199 index = 0;
4183 if ( index > str->length() - 1 ) 4200 if ( index > str->length() - 1 )
4184 index = str->length() - 1; 4201 index = str->length() - 1;
4185 if ( index + len >= str->length() ) 4202 if ( index + len >= str->length() )
4186 len = str->length() - index; 4203 len = str->length() - index;
4187 4204
4188 QTextFormatCollection *fc = 0; 4205 QTextFormatCollection *fc = 0;
4189 if ( useCollection ) 4206 if ( useCollection )
4190 fc = formatCollection(); 4207 fc = formatCollection();
4191 QTextFormat *of; 4208 QTextFormat *of;
4192 for ( int i = 0; i < len; ++i ) { 4209 for ( int i = 0; i < len; ++i ) {
4193 of = str->at( i + index ).format(); 4210 of = str->at( i + index ).format();
4194 if ( !changed && f->key() != of->key() ) 4211 if ( !changed && f->key() != of->key() )
4195 changed = TRUE; 4212 changed = TRUE;
4196 if ( invalid == -1 && 4213 if ( invalid == -1 &&
4197 ( f->font().family() != of->font().family() || 4214 ( f->font().family() != of->font().family() ||
4198 f->font().pointSize() != of->font().pointSize() || 4215 f->font().pointSize() != of->font().pointSize() ||
4199 f->font().weight() != of->font().weight() || 4216 f->font().weight() != of->font().weight() ||
4200 f->font().italic() != of->font().italic() || 4217 f->font().italic() != of->font().italic() ||
4201 f->vAlign() != of->vAlign() ) ) { 4218 f->vAlign() != of->vAlign() ) ) {
4202 invalidate( 0 ); 4219 invalidate( 0 );
4203 } 4220 }
4204 if ( flags == -1 || flags == QTextFormat::Format || !fc ) { 4221 if ( flags == -1 || flags == QTextFormat::Format || !fc ) {
4205 if ( fc ) 4222 if ( fc )
4206 f = fc->format( f ); 4223 f = fc->format( f );
4207 str->setFormat( i + index, f, useCollection ); 4224 str->setFormat( i + index, f, useCollection );
4208 } else { 4225 } else {
4209 QTextFormat *fm = fc->format( of, f, flags ); 4226 QTextFormat *fm = fc->format( of, f, flags );
4210 str->setFormat( i + index, fm, useCollection ); 4227 str->setFormat( i + index, fm, useCollection );
4211 } 4228 }
4212 } 4229 }
4213} 4230}
4214 4231
4215void QTextParag::indent( int *oldIndent, int *newIndent ) 4232void QTextParagraph::indent( int *oldIndent, int *newIndent )
4216{ 4233{
4217 if ( !hasdoc || !document()->indent() || style() && style()->displayMode() != QStyleSheetItem::DisplayBlock ) { 4234 if ( !hasdoc || !document()->indent() || isListItem() ) {
4218 if ( oldIndent ) 4235 if ( oldIndent )
4219 *oldIndent = 0; 4236 *oldIndent = 0;
4220 if ( newIndent ) 4237 if ( newIndent )
4221 *newIndent = 0; 4238 *newIndent = 0;
4222 if ( oldIndent && newIndent ) 4239 if ( oldIndent && newIndent )
4223 *newIndent = *oldIndent; 4240 *newIndent = *oldIndent;
4224 return; 4241 return;
4225 } 4242 }
4226 document()->indent()->indent( document(), this, oldIndent, newIndent ); 4243 document()->indent()->indent( document(), this, oldIndent, newIndent );
4227} 4244}
4228 4245
4229void QTextParag::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections, 4246void QTextParagraph::paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor, bool drawSelections,
4230 int clipx, int clipy, int clipw, int cliph ) 4247 int clipx, int clipy, int clipw, int cliph )
4231{ 4248{
4232 if ( !visible ) 4249 if ( !visible )
4233 return; 4250 return;
4234 QTextStringChar *chr = at( 0 ); 4251 QTextStringChar *chr = 0;
4235 int i = 0; 4252 int i, y, h, baseLine, xstart, xend;
4236 int h = 0; 4253 i = y =h = baseLine = 0;
4237 int baseLine = 0, lastBaseLine = 0; 4254 QRect cursorRect;
4238 QTextStringChar *formatChar = 0; 4255 drawSelections &= ( mSelections != 0 );
4239 int lastY = -1; 4256 // macintosh full-width selection style
4240 int startX = 0; 4257 bool fullWidthStyle = FALSE;
4241 int bw = 0; 4258 int fullSelectionWidth = 0;
4242 int cy = 0; 4259 if ( drawSelections && fullWidthStyle )
4243 int curx = -1, cury = 0, curh = 0; 4260 fullSelectionWidth = (hasdoc ? document()->width() : r.width());
4244 bool lastDirection = chr->rightToLeft; 4261
4245 const int full_sel_width = (hasdoc ? document()->width() : r.width());
4246#if 0 // seems we don't need that anymore
4247 int tw = 0;
4248#endif
4249
4250 QString qstr = str->toString(); 4262 QString qstr = str->toString();
4251 // ### workaround so that \n are not drawn, actually this should be 4263 // ### workaround so that \n are not drawn, actually this should
4252 // fixed in QFont somewhere (under Windows you get ugly boxes 4264 // be fixed in QFont somewhere (under Windows you get ugly boxes
4253 // otherwise) 4265 // otherwise)
4254 QChar* uc = (QChar*) qstr.unicode(); 4266 QChar* uc = (QChar*) qstr.unicode();
4255 for ( uint ii = 0; ii < qstr.length(); ii++ ) { 4267 for ( uint ii = 0; ii < qstr.length(); ii++ )
4256 if ( uc[(int)ii]== '\n' ) 4268 if ( uc[(int)ii]== '\n' || uc[(int)ii] == QChar_linesep || uc[(int)ii] == '\t' )
4257 uc[(int)ii] = 0x20; 4269 uc[(int)ii] = 0x20;
4258 }
4259
4260
4261 const int nSels = hasdoc ? document()->numSelections() : 1;
4262 QMemArray<int> selectionStarts( nSels );
4263 QMemArray<int> selectionEnds( nSels );
4264 if ( drawSelections ) {
4265 bool hasASelection = FALSE;
4266 for ( i = 0; i < nSels; ++i ) {
4267 if ( !hasSelection( i ) ) {
4268 selectionStarts[ i ] = -1;
4269 selectionEnds[ i ] = -1;
4270 } else {
4271 hasASelection = TRUE;
4272 selectionStarts[ i ] = selectionStart( i );
4273 int end = selectionEnd( i );
4274 if ( end == length() - 1 && n && n->hasSelection( i ) )
4275 end++;
4276 selectionEnds[ i ] = end;
4277 }
4278 }
4279 if ( !hasASelection )
4280 drawSelections = FALSE;
4281 }
4282 4270
4283 int line = -1; 4271 int line = -1;
4284 int cw;
4285 bool didListLabel = FALSE;
4286 int paintStart = 0; 4272 int paintStart = 0;
4287 int paintEnd = -1; 4273 int selection = -1;
4288 int lasth = 0;
4289 for ( i = 0; i < length(); i++ ) { 4274 for ( i = 0; i < length(); i++ ) {
4290 chr = at( i ); 4275 chr = at( i );
4291#if 0 // seems we don't need that anymore 4276
4292 if ( !str->isBidi() && is_printer( &painter ) ) { // ### fix our broken ps-printer 4277 // we flush at end of document
4293 if ( !chr->lineStart ) 4278 bool flush = i== length()-1;
4294 chr->x = QMAX( chr->x, tw ); 4279 bool selectionStateChanged = FALSE;
4295 else 4280 if ( !flush ) {
4296 tw = 0; 4281 QTextStringChar *nextchr = at( i+1 );
4282 // we flush at end of line
4283 flush |= nextchr->lineStart;
4284 // we flush on format changes
4285 flush |= ( nextchr->format() != chr->format() );
4286 // we flush on anchor changes
4287 flush |= ( nextchr->isAnchor() != chr->isAnchor() );
4288 // we flush on start of run
4289 flush |= nextchr->startOfRun;
4290 // we flush on bidi changes
4291 flush |= ( nextchr->rightToLeft != chr->rightToLeft );
4292 // we flush on tab
4293 flush |= ( chr->c == '\t' );
4294 // we flush on soft hypens
4295 flush |= ( chr->c.unicode() == 0xad );
4296 // we flush on custom items
4297 flush |= chr->isCustom();
4298 // we flush before custom items
4299 flush |= nextchr->isCustom();
4300 // when painting justified, we flush on spaces
4301 if ((alignment() & Qt3::AlignJustify) == Qt3::AlignJustify )
4302 flush |= QTextFormatter::isBreakable( str, i );
4303 // we flush when the string is getting too long
4304 flush |= ( i - paintStart >= 256 );
4305 // we flush when the selection state changes
4306 if ( drawSelections ) {
4307 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin();
4308 it != mSelections->end(); ++it )
4309 selectionStateChanged |=( (*it).start == i || (*it).start == i+1 || (*it).end == i+1 );
4310 flush |= selectionStateChanged;
4311 }
4297 } 4312 }
4298#endif
4299 cw = string()->width( i );
4300 if ( chr->c == '\t' && i < length() - 1 )
4301 cw = at( i + 1 )->x - chr->x + 1;
4302 if ( chr->c.unicode() == 0xad && i < length() - 1 )
4303 cw = 0;
4304 4313
4305 // init a new line 4314 // init a new line
4306 if ( chr->lineStart ) { 4315 if ( chr->lineStart ) {
4307#if 0 // seems we don't need that anymore 4316 if (fullWidthStyle && drawSelections && selection >= 0)
4308 tw = 0; 4317 painter.fillRect( xend, y, fullSelectionWidth - xend, h,
4309#endif 4318 (selection == QTextDocument::Standard || !hasdoc) ?
4319 cg.color( QColorGroup::Highlight ) :
4320 document()->selectionColor( selection ) );
4310 ++line; 4321 ++line;
4311 lineInfo( line, cy, h, baseLine ); 4322 paintStart = i;
4312 lasth = h; 4323 lineInfo( line, y, h, baseLine );
4313 if ( clipy != -1 && cy > clipy - r.y() + cliph ) // outside clip area, leave 4324 if ( clipy != -1 && cliph != 0 && y + r.y() - h > clipy + cliph ) { // outside clip area, leave
4314 break; 4325 break;
4315 if ( lastBaseLine == 0 ) 4326 }
4316 lastBaseLine = baseLine;
4317 }
4318 4327
4319 // draw bullet list items 4328 // if this is the first line and we are a list item, draw the the bullet label
4320 if ( !didListLabel && line == 0 && style() && style()->displayMode() == QStyleSheetItem::DisplayListItem ) { 4329 if ( line == 0 && isListItem() )
4321 didListLabel = TRUE; 4330 drawLabel( &painter, chr->x, y, 0, 0, baseLine, cg );
4322 drawLabel( &painter, chr->x, cy, 0, 0, baseLine, cg );
4323 } 4331 }
4324 4332
4325 // check for cursor mark 4333 // check for cursor mark
4326 if ( cursor && this == cursor->parag() && i == cursor->index() ) { 4334 if ( cursor && this == cursor->paragraph() && i == cursor->index() ) {
4327 curx = cursor->x(); 4335 QTextStringChar *c = i == 0 ? chr : chr - 1;
4328 QTextStringChar *c = chr; 4336 cursorRect.setRect( cursor->x() , y + baseLine - c->format()->ascent(),
4329 if ( i > 0 ) 4337 1, c->format()->height() );
4330 --c;
4331 curh = c->format()->height();
4332 cury = cy + baseLine - c->format()->ascent();
4333 }
4334
4335 // first time - start again...
4336 if ( !formatChar || lastY == -1 ) {
4337 formatChar = chr;
4338 lastY = cy;
4339 startX = chr->x;
4340 if ( !chr->isCustom() && chr->c != '\n' )
4341 paintEnd = i;
4342 bw = cw;
4343 if ( !chr->isCustom() )
4344 continue;
4345 } 4338 }
4346 4339
4347 // check if selection state changed 4340 // check if we are in a selection and store which one it is
4348 bool selectionChange = FALSE; 4341 selection = -1;
4349 if ( drawSelections ) { 4342 if ( drawSelections ) {
4350 for ( int j = 0; j < nSels; ++j ) { 4343 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->begin();
4351 selectionChange = selectionStarts[ j ] == i || selectionEnds[ j ] == i; 4344 it != mSelections->end(); ++it )
4352 if ( selectionChange ) 4345 if ( (*it).start <= i && i < (*it).end + ( (*it).end == length()-1 && n && n->hasSelection(it.key()) ) ? 1:0
4346 // exclude the standard selection from printing
4347 && (it.key() != QTextDocument::Standard || !is_printer( &painter) ) ) {
4348 selection = it.key();
4353 break; 4349 break;
4354 } 4350 }
4355 } 4351 }
4356 4352
4357 //if something (format, etc.) changed, draw what we have so far 4353 if ( flush ) { // something changed, draw what we have so far
4358 if ( ( ( ( alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify && at(paintEnd)->c.isSpace() ) || 4354 if ( chr->rightToLeft ) {
4359 lastDirection != (bool)chr->rightToLeft || 4355 xstart = chr->x;
4360 chr->startOfRun || 4356 xend = at( paintStart )->x + str->width( paintStart );
4361 lastY != cy || chr->format() != formatChar->format() || chr->isAnchor() != formatChar->isAnchor() ||
4362 ( paintEnd != -1 && at( paintEnd )->c =='\t' ) || chr->c == '\t' ||
4363 ( paintEnd != -1 && at( paintEnd )->c.unicode() == 0xad ) || chr->c.unicode() == 0xad ||
4364 selectionChange || chr->isCustom() ) ) {
4365 if ( paintStart <= paintEnd ) {
4366 // ### temporary hack until I get the new placement/shaping stuff working
4367 int x = startX;
4368 if ( ( alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify && paintEnd != -1 &&
4369 paintEnd > 1 && at( paintEnd )->c.isSpace() ) {
4370 int add = str->at(paintEnd).x - str->at(paintEnd-1).x - str->width(paintEnd-1);
4371 bw += ( lastDirection ? 0 : add );
4372 }
4373 drawParagString( painter, qstr, paintStart, paintEnd - paintStart + 1, x, lastY,
4374 lastBaseLine, bw, lasth, drawSelections,
4375 formatChar, i, selectionStarts, selectionEnds, cg, lastDirection );
4376 }
4377#if 0 // seems we don't need that anymore
4378 if ( !str->isBidi() && is_printer( &painter ) ) { // ### fix our broken ps-printer
4379 if ( !chr->lineStart ) {
4380 // ### the next line doesn't look 100% correct for arabic
4381 tw = startX + painter.fontMetrics().width( qstr.mid(paintStart, paintEnd - paintStart +1) );
4382 chr->x = QMAX( chr->x, tw );
4383 } else {
4384 tw = 0;
4385 }
4386 }
4387#endif
4388 if ( !chr->isCustom() ) {
4389 if ( chr->c != '\n' ) {
4390 paintStart = i;
4391 paintEnd = i;
4392 } else {
4393 paintStart = i+1;
4394 paintEnd = -1;
4395 }
4396 formatChar = chr;
4397 lastY = cy;
4398 startX = chr->x;
4399 bw = cw;
4400 } else { 4357 } else {
4401 if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline ) { 4358 xstart = at( paintStart )->x;
4402 chr->customItem()->draw( &painter, chr->x, cy, clipx - r.x(), clipy - r.y(), clipw, cliph, cg, 4359 if ( !selectionStateChanged && i < length() - 1 && !str->at( i + 1 ).lineStart )
4403 nSels && selectionStarts[ 0 ] <= i && selectionEnds[ 0 ] >= i ); 4360 xend = str->at( i + 1 ).x;
4404 paintStart = i+1; 4361 else
4405 paintEnd = -1; 4362 xend = chr->x + str->width( i );
4406 formatChar = chr;
4407 lastY = cy;
4408 startX = chr->x + string()->width( i );
4409 bw = 0;
4410 } else {
4411 chr->customItem()->resize( chr->customItem()->width );
4412 paintStart = i+1;
4413 paintEnd = -1;
4414 formatChar = chr;
4415 lastY = cy;
4416 startX = chr->x + string()->width( i );
4417 bw = 0;
4418 }
4419 } 4363 }
4420 } else { 4364
4421 if ( chr->c != '\n' ) { 4365 if ( (clipx == -1 || clipw == -1) || (xend >= clipx && xstart <= clipx + clipw) ) {
4422 if( chr->rightToLeft ) { 4366 if ( !chr->isCustom() )
4423 startX = chr->x; 4367 drawString( painter, qstr, paintStart, i - paintStart + 1, xstart, y,
4424 } 4368 baseLine, xend-xstart, h, selection,
4425 paintEnd = i; 4369 chr, cg, chr->rightToLeft );
4370 else if ( chr->customItem()->placement() == QTextCustomItem::PlaceInline )
4371 chr->customItem()->draw( &painter, chr->x, y,
4372 clipx == -1 ? clipx : (clipx - r.x()),
4373 clipy == -1 ? clipy : (clipy - r.y()),
4374 clipw, cliph, cg, selection >= 0 );
4426 } 4375 }
4427 bw += cw; 4376 paintStart = i+1;
4428 } 4377 }
4429 lastBaseLine = baseLine; 4378
4430 lasth = h;
4431 lastDirection = chr->rightToLeft;
4432 } 4379 }
4433 4380
4434 // if we are through the parag, but still have some stuff left to draw, draw it now 4381 if (fullWidthStyle && drawSelections && selection >= 0 && next() && next()->mSelections)
4435 if ( paintStart <= paintEnd ) { 4382 for ( QMap<int, QTextParagraphSelection>::ConstIterator it = next()->mSelections->begin();
4436 bool selectionChange = FALSE; 4383 it != next()->mSelections->end(); ++it )
4437 if ( drawSelections ) { 4384 if (((*it).start) == 0) {
4438 for ( int j = 0; j < nSels; ++j ) { 4385 painter.fillRect( xend, y, fullSelectionWidth - xend, h,
4439 selectionChange = selectionStarts[ j ] == i || selectionEnds[ j ] == i; 4386 (selection == QTextDocument::Standard || !hasdoc) ?
4440 if ( selectionChange ) 4387 cg.color( QColorGroup::Highlight ) :
4441 break; 4388 document()->selectionColor( selection ) );
4389 break;
4442 } 4390 }
4443 }
4444 int x = startX;
4445 drawParagString( painter, qstr, paintStart, paintEnd-paintStart+1, x, lastY,
4446 lastBaseLine, bw, h, drawSelections,
4447 formatChar, i, selectionStarts, selectionEnds, cg, lastDirection );
4448 }
4449 4391
4450 // if we should draw a cursor, draw it now 4392 // time to draw the cursor
4451 if ( curx != -1 && cursor ) { 4393 const int cursor_extent = 4;
4452 painter.fillRect( QRect( curx, cury, 1, curh - lineSpacing() ), cg.color( QColorGroup::Text ) ); 4394 if ( !cursorRect.isNull() && cursor &&
4395 ((clipx == -1 || clipw == -1) || (cursorRect.right()+cursor_extent >= clipx && cursorRect.left()-cursor_extent <= clipx + clipw)) ) {
4396 painter.fillRect( cursorRect, cg.color( QColorGroup::Text ) );
4453 painter.save(); 4397 painter.save();
4454 if ( string()->isBidi() ) { 4398 if ( string()->isBidi() ) {
4455 const int d = 4;
4456 if ( at( cursor->index() )->rightToLeft ) { 4399 if ( at( cursor->index() )->rightToLeft ) {
4457 painter.setPen( Qt::black ); 4400 painter.setPen( Qt::black );
4458 painter.drawLine( curx, cury, curx - d / 2, cury + d / 2 ); 4401 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4459 painter.drawLine( curx, cury + d, curx - d / 2, cury + d / 2 ); 4402 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() - cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4460 } else { 4403 } else {
4461 painter.setPen( Qt::black ); 4404 painter.setPen( Qt::black );
4462 painter.drawLine( curx, cury, curx + d / 2, cury + d / 2 ); 4405 painter.drawLine( cursorRect.x(), cursorRect.y(), cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4463 painter.drawLine( curx, cury + d, curx + d / 2, cury + d / 2 ); 4406 painter.drawLine( cursorRect.x(), cursorRect.y() + cursor_extent, cursorRect.x() + cursor_extent / 2, cursorRect.y() + cursor_extent / 2 );
4464 } 4407 }
4465 } 4408 }
4466 painter.restore(); 4409 painter.restore();
4467 } 4410 }
4468} 4411}
4469 4412
4470//#define BIDI_DEBUG 4413//#define BIDI_DEBUG
4471 4414
4472void QTextParag::drawParagString( QPainter &painter, const QString &s, int start, int len, int startX, 4415void QTextParagraph::drawString( QPainter &painter, const QString &s, int start, int len, int xstart,
4473 int lastY, int baseLine, int bw, int h, bool drawSelections, 4416 int y, int baseLine, int w, int h, int selection,
4474 QTextStringChar *formatChar, int i, const QMemArray<int> &selectionStarts, 4417 QTextStringChar *formatChar, const QColorGroup& cg,
4475 const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft ) 4418 bool rightToLeft )
4476{ 4419{
4420 int i = start + len - 1;
4477 bool plainText = hasdoc ? document()->textFormat() == Qt::PlainText : FALSE; 4421 bool plainText = hasdoc ? document()->textFormat() == Qt::PlainText : FALSE;
4478 QTextFormat* format = formatChar->format(); 4422 QTextFormat* format = formatChar->format();
4479 QString str( s ); 4423 QString str( s );
4480 if ( str[ (int)str.length() - 1 ].unicode() == 0xad ) 4424 if ( str[ (int)str.length() - 1 ].unicode() == 0xad )
4481 str.remove( str.length() - 1, 1 ); 4425 str.remove( str.length() - 1, 1 );
4482 if ( !plainText || hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() ) 4426 if ( !plainText || hasdoc && format->color() != document()->formatCollection()->defaultFormat()->color() )
4483 painter.setPen( QPen( format->color() ) ); 4427 painter.setPen( QPen( format->color() ) );
4484 else 4428 else
4485 painter.setPen( cg.text() ); 4429 painter.setPen( cg.text() );
4486 painter.setFont( format->font() ); 4430 painter.setFont( format->font() );
4487 4431
4488 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) { 4432 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() ) {
4489 if ( format->useLinkColor() ) { 4433 if ( format->useLinkColor() ) {
4490 if ( document()->linkColor.isValid() ) 4434 if ( document()->linkColor.isValid() )
4491 painter.setPen( document()->linkColor ); 4435 painter.setPen( document()->linkColor );
4492 else 4436 else
4493 painter.setPen( QPen( Qt::blue ) ); 4437 painter.setPen( QPen( Qt::blue ) );
4494 } 4438 }
4495 if ( document()->underlineLinks() ) { 4439 if ( document()->underlineLinks() ) {
4496 QFont fn = format->font(); 4440 QFont fn = format->font();
4497 fn.setUnderline( TRUE ); 4441 fn.setUnderline( TRUE );
4498 painter.setFont( fn ); 4442 painter.setFont( fn );
4499 } 4443 }
4500 } 4444 }
4501 4445
4502 if ( drawSelections ) { 4446 if ( selection >= 0 ) {
4503 const int nSels = hasdoc ? document()->numSelections() : 1; 4447 if ( !hasdoc || document()->invertSelectionText( selection ) )
4504 const int startSel = is_printer( 0 ) ? 1 : 0; 4448 painter.setPen( cg.color( QColorGroup::HighlightedText ) );
4505 for ( int j = startSel; j < nSels; ++j ) { 4449 painter.fillRect( xstart, y, w, h,
4506 if ( i > selectionStarts[ j ] && i <= selectionEnds[ j ] ) { 4450 (selection == QTextDocument::Standard || !hasdoc) ?
4507 if ( !hasdoc || document()->invertSelectionText( j ) ) 4451 cg.color( QColorGroup::Highlight ) : document()->selectionColor( selection ) );
4508 painter.setPen( QPen( cg.color( QColorGroup::HighlightedText ) ) );
4509 if ( j == QTextDocument::Standard )
4510 painter.fillRect( startX, lastY, bw, h, cg.color( QColorGroup::Highlight ) );
4511 else
4512 painter.fillRect( startX, lastY, bw, h, hasdoc ? document()->selectionColor( j ) : cg.color( QColorGroup::Highlight ) );
4513 }
4514 }
4515 } 4452 }
4516 4453
4517 if ( str[ start ] != '\t' && str[ start ].unicode() != 0xad ) { 4454 if ( str[ start ] != '\t' && str[ start ].unicode() != 0xad ) {
4518 if ( format->vAlign() == QTextFormat::AlignNormal ) { 4455 if ( format->vAlign() == QTextFormat::AlignNormal ) {
4519 painter.drawText( startX, lastY + baseLine, str.mid( start ), len ); 4456 painter.drawText( xstart, y + baseLine, str.mid( start ), len );
4520#ifdef BIDI_DEBUG 4457#ifdef BIDI_DEBUG
4521 painter.save(); 4458 painter.save();
4522 painter.setPen ( Qt::red ); 4459 painter.setPen ( Qt::red );
4523 painter.drawLine( startX, lastY, startX, lastY + baseLine ); 4460 painter.drawLine( xstart, y, xstart, y + baseLine );
4524 painter.drawLine( startX, lastY + baseLine/2, startX + 10, lastY + baseLine/2 ); 4461 painter.drawLine( xstart, y + baseLine/2, xstart + 10, y + baseLine/2 );
4525 int w = 0; 4462 int w = 0;
4526 int i = 0; 4463 int i = 0;
4527 while( i < len ) 4464 while( i < len )
4528 w += painter.fontMetrics().charWidth( str, start + i++ ); 4465 w += painter.fontMetrics().charWidth( str, start + i++ );
4529 painter.setPen ( Qt::blue ); 4466 painter.setPen ( Qt::blue );
4530 painter.drawLine( startX + w - 1, lastY, startX + w - 1, lastY + baseLine ); 4467 painter.drawLine( xstart + w - 1, y, xstart + w - 1, y + baseLine );
4531 painter.drawLine( startX + w - 1, lastY + baseLine/2, startX + w - 1 - 10, lastY + baseLine/2 ); 4468 painter.drawLine( xstart + w - 1, y + baseLine/2, xstart + w - 1 - 10, y + baseLine/2 );
4532 painter.restore(); 4469 painter.restore();
4533#endif 4470#endif
4534 } else if ( format->vAlign() == QTextFormat::AlignSuperScript ) { 4471 } else if ( format->vAlign() == QTextFormat::AlignSuperScript ) {
4535 QFont f( painter.font() ); 4472 QFont f( painter.font() );
4536 if ( format->fontSizesInPixels() ) 4473 if ( format->fontSizesInPixels() )
4537 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 4474 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
4538 else 4475 else
4539 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 4476 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
4540 painter.setFont( f ); 4477 painter.setFont( f );
4541 painter.drawText( startX, lastY + baseLine - ( painter.fontMetrics().height() / 2 ), 4478 painter.drawText( xstart, y + baseLine - ( painter.fontMetrics().height() / 2 ),
4542 str.mid( start ), len ); 4479 str.mid( start ), len );
4543 } else if ( format->vAlign() == QTextFormat::AlignSubScript ) { 4480 } else if ( format->vAlign() == QTextFormat::AlignSubScript ) {
4544 QFont f( painter.font() ); 4481 QFont f( painter.font() );
4545 if ( format->fontSizesInPixels() ) 4482 if ( format->fontSizesInPixels() )
4546 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 ); 4483 f.setPixelSize( ( f.pixelSize() * 2 ) / 3 );
4547 else 4484 else
4548 f.setPointSize( ( f.pointSize() * 2 ) / 3 ); 4485 f.setPointSize( ( f.pointSize() * 2 ) / 3 );
4549 painter.setFont( f ); 4486 painter.setFont( f );
4550 painter.drawText( startX, lastY + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len ); 4487 painter.drawText( xstart, y + baseLine + painter.fontMetrics().height() / 6, str.mid( start ), len );
4551 } 4488 }
4552 } 4489 }
4553 if ( i + 1 < length() && at( i + 1 )->lineStart && at( i )->c.unicode() == 0xad ) { 4490 if ( i + 1 < length() && at( i + 1 )->lineStart && at( i )->c.unicode() == 0xad ) {
4554 painter.drawText( startX + bw, lastY + baseLine, "\xad" ); 4491 painter.drawText( xstart + w, y + baseLine, "\xad" );
4555 } 4492 }
4556 if ( format->isMisspelled() ) { 4493 if ( format->isMisspelled() ) {
4557 painter.save(); 4494 painter.save();
4558 painter.setPen( QPen( Qt::red, 1, Qt::DotLine ) ); 4495 painter.setPen( QPen( Qt::red, 1, Qt::DotLine ) );
4559 painter.drawLine( startX, lastY + baseLine + 1, startX + bw, lastY + baseLine + 1 ); 4496 painter.drawLine( xstart, y + baseLine + 1, xstart + w, y + baseLine + 1 );
4560 painter.restore(); 4497 painter.restore();
4561 } 4498 }
4562 4499
4563 i -= len; 4500 i -= len;
4564 4501
4565 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() && 4502 if ( hasdoc && formatChar->isAnchor() && !formatChar->anchorHref().isEmpty() &&
4566 document()->focusIndicator.parag == this && 4503 document()->focusIndicator.parag == this &&
4567 ( document()->focusIndicator.start >= i && 4504 ( document()->focusIndicator.start >= i &&
4568 document()->focusIndicator.start + document()->focusIndicator.len <= i + len || 4505 document()->focusIndicator.start + document()->focusIndicator.len <= i + len ||
4569 document()->focusIndicator.start <= i && 4506 document()->focusIndicator.start <= i &&
4570 document()->focusIndicator.start + document()->focusIndicator.len >= i + len ) ) { 4507 document()->focusIndicator.start + document()->focusIndicator.len >= i + len ) ) {
4571 painter.drawWinFocusRect( QRect( startX, lastY, bw, h ) ); 4508 painter.drawWinFocusRect( QRect( xstart, y, w, h ) );
4572 } 4509 }
4573 4510
4574} 4511}
4575 4512
4576void QTextParag::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ) 4513void QTextParagraph::drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg )
4577{ 4514{
4578 if ( !style() )
4579 return;
4580 QRect r ( x, y, w, h ); 4515 QRect r ( x, y, w, h );
4581 QStyleSheetItem::ListStyle s = listStyle(); 4516 QStyleSheetItem::ListStyle s = listStyle();
4582 4517
4583 p->save(); 4518 p->save();
4584 p->setPen( defFormat->color() ); 4519 QTextFormat *format = at( 0 )->format();
4585 4520 if ( format ) {
4586 QFont font2( defFormat->font() ); 4521 p->setPen( format->color() );
4587 if ( length() > 0 ) { 4522 p->setFont( format->font() );
4588 QTextFormat *format = at( 0 )->format();
4589 if ( format ) {
4590 if ( format->fontSizesInPixels() )
4591 font2.setPixelSize( at( 0 )->format()->font().pixelSize() );
4592 else
4593 font2.setPointSize( at( 0 )->format()->font().pointSize() );
4594 }
4595 } 4523 }
4596 p->setFont( font2 );
4597 QFontMetrics fm( p->fontMetrics() ); 4524 QFontMetrics fm( p->fontMetrics() );
4598 int size = fm.lineSpacing() / 3; 4525 int size = fm.lineSpacing() / 3;
4599 4526
4600 switch ( s ) { 4527 switch ( s ) {
4601 case QStyleSheetItem::ListDecimal: 4528 case QStyleSheetItem::ListDecimal:
4602 case QStyleSheetItem::ListLowerAlpha: 4529 case QStyleSheetItem::ListLowerAlpha:
4603 case QStyleSheetItem::ListUpperAlpha: 4530 case QStyleSheetItem::ListUpperAlpha:
4604 { 4531 {
4605 int n = numberOfSubParagraph(); 4532 if ( list_val == -1 ) { // uninitialised list value, calcluate the right one
4533 int depth = listDepth();
4534 list_val--;
4535 // ### evil, square and expensive. This needs to be done when formatting, not when painting
4536 QTextParagraph* s = prev();
4537 int depth_s;
4538 while ( s && (depth_s = s->listDepth()) >= depth ) {
4539 if ( depth_s == depth && s->isListItem() )
4540 list_val--;
4541 s = s->prev();
4542 }
4543 }
4544
4545 int n = list_val;
4546 if ( n < -1 )
4547 n = -n - 1;
4606 QString l; 4548 QString l;
4607 switch ( s ) { 4549 switch ( s ) {
4608 case QStyleSheetItem::ListLowerAlpha: 4550 case QStyleSheetItem::ListLowerAlpha:
4609 if ( n < 27 ) { 4551 if ( n < 27 ) {
4610 l = QChar( ('a' + (char) (n-1))); 4552 l = QChar( ('a' + (char) (n-1)));
4611 break; 4553 break;
4612 } 4554 }
4613 case QStyleSheetItem::ListUpperAlpha: 4555 case QStyleSheetItem::ListUpperAlpha:
4614 if ( n < 27 ) { 4556 if ( n < 27 ) {
4615 l = QChar( ('A' + (char) (n-1))); 4557 l = QChar( ('A' + (char) (n-1)));
4616 break; 4558 break;
4617 } 4559 }
4618 break; 4560 break;
4619 default: //QStyleSheetItem::ListDecimal: 4561 default: //QStyleSheetItem::ListDecimal:
4620 l.setNum( n ); 4562 l.setNum( n );
4621 break; 4563 break;
4622 } 4564 }
4623 l += QString::fromLatin1(". "); 4565 l += QString::fromLatin1(". ");
4624 p->drawText( r.right() - fm.width( l ), r.top() + base, l ); 4566 p->drawText( r.right() - fm.width( l ), r.top() + base, l );
4625 } 4567 }
4626 break; 4568 break;
4627 case QStyleSheetItem::ListSquare: 4569 case QStyleSheetItem::ListSquare:
4628 { 4570 {
4629 QRect er( r.right() - size * 2, r.top() + fm.height() / 2 - size / 2, size, size ); 4571 QRect er( r.right() - size * 2, r.top() + fm.height() / 2 - size / 2, size, size );
4630 p->fillRect( er , cg.brush( QColorGroup::Foreground ) ); 4572 p->fillRect( er , cg.brush( QColorGroup::Text ) );
4631 } 4573 }
4632 break; 4574 break;
4633 case QStyleSheetItem::ListCircle: 4575 case QStyleSheetItem::ListCircle:
4634 { 4576 {
4635 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size); 4577 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size);
4636 p->drawEllipse( er ); 4578 p->drawEllipse( er );
4637 } 4579 }
4638 break; 4580 break;
4639 case QStyleSheetItem::ListDisc: 4581 case QStyleSheetItem::ListDisc:
4640 default: 4582 default:
4641 { 4583 {
4642 p->setBrush( cg.brush( QColorGroup::Foreground )); 4584 p->setBrush( cg.brush( QColorGroup::Text ));
4643 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size); 4585 QRect er( r.right()-size*2, r.top() + fm.height() / 2 - size / 2, size, size);
4644 p->drawEllipse( er ); 4586 p->drawEllipse( er );
4645 p->setBrush( Qt::NoBrush ); 4587 p->setBrush( Qt::NoBrush );
4646 } 4588 }
4647 break; 4589 break;
4648 } 4590 }
4649 4591
4650 p->restore(); 4592 p->restore();
4651} 4593}
4652 4594
4653void QTextParag::setStyleSheetItems( const QPtrVector<QStyleSheetItem> &vec ) 4595void QTextParagraph::readStyleInformation( QDataStream& stream )
4654{
4655 styleSheetItemsVec() = vec;
4656 invalidate( 0 );
4657 lm = rm = tm = bm = flm = -1;
4658 numSubParag = -1;
4659}
4660
4661void QTextParag::setList( bool b, int listStyle )
4662{ 4596{
4663 if ( !hasdoc ) 4597 int int_align, int_lstyle;
4664 return; 4598 uchar uchar_litem, uchar_rtext, uchar_dir;
4665 4599 stream >> int_align >> int_lstyle >> utm >> ubm >> ulm >> urm >> uflm
4666 if ( !style() ) { 4600 >> ulinespacing >> ldepth >> uchar_litem >> uchar_rtext >> uchar_dir;
4667 styleSheetItemsVec().resize( 2 ); 4601 align = int_align; lstyle = (QStyleSheetItem::ListStyle) int_lstyle;
4668 mStyleSheetItemsVec->insert( 0, document()->styleSheet()->item( "html" ) ); 4602 litem = uchar_litem; rtext = uchar_rtext; str->setDirection( (QChar::Direction)uchar_dir );
4669 mStyleSheetItemsVec->insert( 1, document()->styleSheet()->item( "p" ) ); 4603 QTextParagraph* s = prev() ? prev() : this;
4670 } 4604 while ( s ) {
4671 4605 s->invalidate( 0 );
4672 if ( b ) { 4606 s = s->next();
4673 if ( style()->displayMode() != QStyleSheetItem::DisplayListItem || this->listStyle() != listStyle ) {
4674 styleSheetItemsVec().remove( styleSheetItemsVec().size() - 1 );
4675 QStyleSheetItem *item = (*mStyleSheetItemsVec)[ mStyleSheetItemsVec->size() - 1 ];
4676 if ( item )
4677 mStyleSheetItemsVec->remove( mStyleSheetItemsVec->size() - 1 );
4678 mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 1,
4679 listStyle == QStyleSheetItem::ListDisc || listStyle == QStyleSheetItem::ListCircle
4680 || listStyle == QStyleSheetItem::ListSquare ?
4681 document()->styleSheet()->item( "ul" ) : document()->styleSheet()->item( "ol" ) );
4682 mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 1, document()->styleSheet()->item( "li" ) );
4683 setListStyle( (QStyleSheetItem::ListStyle)listStyle );
4684 } else {
4685 return;
4686 }
4687 } else {
4688 if ( style()->displayMode() != QStyleSheetItem::DisplayBlock ) {
4689 styleSheetItemsVec().remove( styleSheetItemsVec().size() - 1 );
4690 if ( mStyleSheetItemsVec->size() >= 2 ) {
4691 mStyleSheetItemsVec->remove( mStyleSheetItemsVec->size() - 2 );
4692 mStyleSheetItemsVec->resize( mStyleSheetItemsVec->size() - 2 );
4693 } else {
4694 mStyleSheetItemsVec->resize( mStyleSheetItemsVec->size() - 1 );
4695 }
4696 } else {
4697 return;
4698 }
4699 }
4700 invalidate( 0 );
4701 lm = rm = tm = bm = flm = -1;
4702 numSubParag = -1;
4703 if ( next() ) {
4704 QTextParag *s = next();
4705 while ( s ) {
4706 s->numSubParag = -1;
4707 s->lm = s->rm = s->tm = s->bm = flm = -1;
4708 s->numSubParag = -1;
4709 s->invalidate( 0 );
4710 s = s->next();
4711 }
4712 } 4607 }
4713} 4608}
4714 4609
4715void QTextParag::incDepth() 4610void QTextParagraph::writeStyleInformation( QDataStream& stream ) const
4716{ 4611{
4717 if ( !style() || !hasdoc ) 4612 stream << (int) align << (int) lstyle << utm << ubm << ulm << urm << uflm << ulinespacing << ldepth << (uchar)litem << (uchar)rtext << (uchar)str->direction();
4718 return;
4719 if ( style()->displayMode() != QStyleSheetItem::DisplayListItem )
4720 return;
4721 styleSheetItemsVec().resize( styleSheetItemsVec().size() + 1 );
4722 mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 1, (*mStyleSheetItemsVec)[ mStyleSheetItemsVec->size() - 2 ] );
4723 mStyleSheetItemsVec->insert( mStyleSheetItemsVec->size() - 2,
4724 listStyle() == QStyleSheetItem::ListDisc || listStyle() == QStyleSheetItem::ListCircle ||
4725 listStyle() == QStyleSheetItem::ListSquare ?
4726 document()->styleSheet()->item( "ul" ) : document()->styleSheet()->item( "ol" ) );
4727 invalidate( 0 );
4728 lm = -1;
4729 flm = -1;
4730} 4613}
4731 4614
4732void QTextParag::decDepth()
4733{
4734 if ( !style() || !hasdoc )
4735 return;
4736 if ( style()->displayMode() != QStyleSheetItem::DisplayListItem )
4737 return;
4738 int numLists = 0;
4739 QStyleSheetItem *lastList = 0;
4740 int lastIndex = 0;
4741 int i;
4742 if ( mStyleSheetItemsVec ) {
4743 for ( i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) {
4744 QStyleSheetItem *item = (*mStyleSheetItemsVec)[ i ];
4745 if ( item->name() == "ol" || item->name() == "ul" ) {
4746 lastList = item;
4747 lastIndex = i;
4748 numLists++;
4749 }
4750 }
4751 }
4752 4615
4753 if ( !lastList )
4754 return;
4755 styleSheetItemsVec().remove( lastIndex );
4756 for ( i = lastIndex; i < (int)mStyleSheetItemsVec->size() - 1; ++i )
4757 mStyleSheetItemsVec->insert( i, (*mStyleSheetItemsVec)[ i + 1 ] );
4758 mStyleSheetItemsVec->resize( mStyleSheetItemsVec->size() - 1 );
4759 if ( numLists == 1 )
4760 setList( FALSE, -1 );
4761 invalidate( 0 );
4762 lm = -1;
4763 flm = -1;
4764}
4765 4616
4766int QTextParag::listDepth() const 4617void QTextParagraph::setListDepth( int depth ) {
4767{ 4618 if ( !hasdoc || depth == ldepth )
4768 int numLists = 0; 4619 return;
4769 int i; 4620 ldepth = depth;
4770 if ( mStyleSheetItemsVec ) { 4621 QTextParagraph* s = prev() ? prev() : this;
4771 for ( i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) { 4622 while ( s ) {
4772 QStyleSheetItem *item = (*mStyleSheetItemsVec)[ i ]; 4623 s->invalidate( 0 );
4773 if ( item->name() == "ol" || item->name() == "ul" ) 4624 s = s->next();
4774 numLists++;
4775 }
4776 } 4625 }
4777 return numLists - 1;
4778} 4626}
4779 4627
4780int *QTextParag::tabArray() const 4628int *QTextParagraph::tabArray() const
4781{ 4629{
4782 int *ta = tArray; 4630 int *ta = tArray;
4783 if ( !ta && hasdoc ) 4631 if ( !ta && hasdoc )
4784 ta = document()->tabArray(); 4632 ta = document()->tabArray();
4785 return ta; 4633 return ta;
4786} 4634}
4787 4635
4788int QTextParag::nextTab( int, int x ) 4636int QTextParagraph::nextTab( int, int x )
4789{ 4637{
4790 int *ta = tArray; 4638 int *ta = tArray;
4791 if ( hasdoc ) { 4639 if ( hasdoc ) {
4792 if ( !ta ) 4640 if ( !ta )
4793 ta = document()->tabArray(); 4641 ta = document()->tabArray();
4794 tabStopWidth = document()->tabStopWidth(); 4642 tabStopWidth = document()->tabStopWidth();
4795 } 4643 }
4796 if ( ta ) { 4644 if ( ta ) {
4797 int i = 0; 4645 int i = 0;
4798 while ( ta[ i ] ) { 4646 while ( ta[ i ] ) {
4799 if ( ta[ i ] >= x ) 4647 if ( ta[ i ] >= x )
4800 return tArray[ i ]; 4648 return tArray[ i ];
4801 ++i; 4649 ++i;
4802 } 4650 }
4803 return tArray[ 0 ]; 4651 return tArray[ 0 ];
4804 } else { 4652 } else {
4805 int d; 4653 int d;
4806 if ( tabStopWidth != 0 ) 4654 if ( tabStopWidth != 0 )
4807 d = x / tabStopWidth; 4655 d = x / tabStopWidth;
4808 else 4656 else
4809 return x; 4657 return x;
4810 return tabStopWidth * ( d + 1 ); 4658 return tabStopWidth * ( d + 1 );
4811 } 4659 }
4812} 4660}
4813 4661
4814void QTextParag::adjustToPainter( QPainter *p ) 4662void QTextParagraph::adjustToPainter( QPainter *p )
4815{ 4663{
4816 for ( int i = 0; i < length(); ++i ) { 4664 for ( int i = 0; i < length(); ++i ) {
4817 if ( at( i )->isCustom() ) 4665 if ( at( i )->isCustom() )
4818 at( i )->customItem()->adjustToPainter( p ); 4666 at( i )->customItem()->adjustToPainter( p );
4819 } 4667 }
4820} 4668}
4821 4669
4822QTextFormatCollection *QTextParag::formatCollection() const 4670QTextFormatCollection *QTextParagraph::formatCollection() const
4823{ 4671{
4824 if ( hasdoc ) 4672 if ( hasdoc )
4825 return document()->formatCollection(); 4673 return document()->formatCollection();
4826 if ( !qFormatCollection ) { 4674 if ( !qFormatCollection ) {
4827 qFormatCollection = new QTextFormatCollection; 4675 qFormatCollection = new QTextFormatCollection;
4828 static QSingleCleanupHandler<QTextFormatCollection> qtfCleanup; 4676 static QSingleCleanupHandler<QTextFormatCollection> qtfCleanup;
4829 qtfCleanup.set( &qFormatCollection ); 4677 qtfCleanup.set( &qFormatCollection );
4830 } 4678 }
4831 return qFormatCollection; 4679 return qFormatCollection;
4832} 4680}
4833 4681
4834QString QTextParag::richText() const 4682QString QTextParagraph::richText() const
4835{ 4683{
4836 QString s; 4684 QString s;
4837 QTextStringChar *formatChar = 0; 4685 QTextStringChar *formatChar = 0;
4838 QString spaces; 4686 QString spaces;
4839 bool lastCharWasSpace = FALSE; 4687 bool doStart = richTextExportStart && richTextExportStart->paragraph() == this;
4840 int firstcol = 0; 4688 bool doEnd = richTextExportEnd && richTextExportEnd->paragraph() == this;
4841 for ( int i = 0; i < length()-1; ++i ) { 4689 int i;
4690 for ( i = 0; i < length()-1; ++i ) {
4691 if ( doStart && i && richTextExportStart->index() == i )
4692 s += "<selstart/>";
4693 if ( doEnd && richTextExportEnd->index() == i )
4694 s += "<selend/>";
4842 QTextStringChar *c = &str->at( i ); 4695 QTextStringChar *c = &str->at( i );
4843 if ( c->isAnchor() && !c->anchorName().isEmpty() ) { 4696 if ( c->isAnchor() && !c->anchorName().isEmpty() ) {
4844 if ( c->anchorName().contains( '#' ) ) { 4697 if ( c->anchorName().contains( '#' ) ) {
4845 QStringList l = QStringList::split( '#', c->anchorName() ); 4698 QStringList l = QStringList::split( '#', c->anchorName() );
4846 for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) 4699 for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it )
4847 s += "<a name=\"" + *it + "\"></a>"; 4700 s += "<a name=\"" + *it + "\"></a>";
4848 } else { 4701 } else {
4849 s += "<a name=\"" + c->anchorName() + "\"></a>"; 4702 s += "<a name=\"" + c->anchorName() + "\"></a>";
4850 } 4703 }
4851 } 4704 }
4852 if ( !formatChar ) { 4705 if ( !formatChar ) {
4853 s += c->format()->makeFormatChangeTags( 0, QString::null, c->anchorHref() ); 4706 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(),
4707 0, QString::null, c->anchorHref() );
4854 formatChar = c; 4708 formatChar = c;
4855 } else if ( ( formatChar->format()->key() != c->format()->key() ) || 4709 } else if ( ( formatChar->format()->key() != c->format()->key() ) ||
4856 (formatChar->isAnchor() != c->isAnchor() && 4710 (c->anchorHref() != formatChar->anchorHref() ) ) {
4857 (!c->anchorHref().isEmpty() || !formatChar->anchorHref().isEmpty() ) ) ) {// lisp was here 4711 s += c->format()->makeFormatChangeTags( formatCollection()->defaultFormat(),
4858 4712 formatChar->format() , formatChar->anchorHref(), c->anchorHref() );
4859 if ( !spaces.isEmpty() ) {
4860 if ( spaces[0] == '\t' || lastCharWasSpace )
4861 s += "<wsp>" + spaces + "</wsp>";
4862 else if ( spaces.length() > 1 )
4863 s += "<wsp>" + spaces.mid(1) + "</wsp> ";
4864 else
4865 s += spaces;
4866 lastCharWasSpace = TRUE;
4867 spaces = QString::null;
4868 }
4869 s += c->format()->makeFormatChangeTags( formatChar->format() , formatChar->anchorHref(), c->anchorHref() );
4870 formatChar = c; 4713 formatChar = c;
4871 } 4714 }
4872 4715 if ( c->c == '<' )
4873 if ( c->c == ' ' || c->c == '\t' ) {
4874 spaces += c->c;
4875 continue;
4876 } else if ( !spaces.isEmpty() ) {
4877 if ( spaces[0] == '\t' || lastCharWasSpace )
4878 s += "<wsp>" + spaces + "</wsp>";
4879 else if ( spaces.length() > 1 )
4880 s += "<wsp>" + spaces.mid(1) + "</wsp> ";
4881 else
4882 s += spaces;
4883 spaces = QString::null;
4884 if ( s.length() - firstcol > 60 ) {
4885 s += '\n';
4886 firstcol = s.length();
4887 }
4888 }
4889
4890 lastCharWasSpace = FALSE;
4891 if ( c->c == '<' ) {
4892 s += "&lt;"; 4716 s += "&lt;";
4893 } else if ( c->c == '>' ) { 4717 else if ( c->c == '>' )
4894 s += "&gt;"; 4718 s += "&gt;";
4895 } else if ( c->isCustom() ) { 4719 else if ( c->isCustom() )
4896 s += c->customItem()->richText(); 4720 s += c->customItem()->richText();
4897 } else { 4721 else if ( c->c == '\n' || c->c == QChar_linesep )
4898 s += c->c; 4722 s += "<br />"; // space on purpose for compatibility with Netscape, Lynx & Co.
4899 }
4900 }
4901 if ( !spaces.isEmpty() ) {
4902 if ( spaces.length() > 1 || spaces[0] == '\t' || lastCharWasSpace )
4903 s += "<wsp>" + spaces + "</wsp>";
4904 else 4723 else
4905 s += spaces; 4724 s += c->c;
4906 } 4725 }
4907 4726 if ( doEnd && richTextExportEnd->index() == i )
4727 s += "<selend/>";
4908 if ( formatChar ) 4728 if ( formatChar )
4909 s += formatChar->format()->makeFormatEndTags( formatChar->anchorHref() ); 4729 s += formatChar->format()->makeFormatEndTags( formatCollection()->defaultFormat(), formatChar->anchorHref() );
4910 return s; 4730 return s;
4911} 4731}
4912 4732
4913void QTextParag::addCommand( QTextCommand *cmd ) 4733void QTextParagraph::addCommand( QTextCommand *cmd )
4914{ 4734{
4915 if ( !hasdoc ) 4735 if ( !hasdoc )
4916 pseudoDocument()->commandHistory->addCommand( cmd ); 4736 pseudoDocument()->commandHistory->addCommand( cmd );
4917 else 4737 else
4918 document()->commands()->addCommand( cmd ); 4738 document()->commands()->addCommand( cmd );
4919} 4739}
4920 4740
4921QTextCursor *QTextParag::undo( QTextCursor *c ) 4741QTextCursor *QTextParagraph::undo( QTextCursor *c )
4922{ 4742{
4923 if ( !hasdoc ) 4743 if ( !hasdoc )
4924 return pseudoDocument()->commandHistory->undo( c ); 4744 return pseudoDocument()->commandHistory->undo( c );
4925 return document()->commands()->undo( c ); 4745 return document()->commands()->undo( c );
4926} 4746}
4927 4747
4928QTextCursor *QTextParag::redo( QTextCursor *c ) 4748QTextCursor *QTextParagraph::redo( QTextCursor *c )
4929{ 4749{
4930 if ( !hasdoc ) 4750 if ( !hasdoc )
4931 return pseudoDocument()->commandHistory->redo( c ); 4751 return pseudoDocument()->commandHistory->redo( c );
4932 return document()->commands()->redo( c ); 4752 return document()->commands()->redo( c );
4933} 4753}
4934 4754
4935int QTextParag::topMargin() const 4755int QTextParagraph::topMargin() const
4936{ 4756{
4937 if ( !p && ( !hasdoc || !document()->addMargins() ) )
4938 return 0;
4939 if ( tm != -1 )
4940 return tm;
4941 QStyleSheetItem *item = style();
4942 if ( !item ) {
4943 ( (QTextParag*)this )->tm = 0;
4944 return 0;
4945 }
4946
4947 int m = 0; 4757 int m = 0;
4948 if ( item->margin( QStyleSheetItem::MarginTop ) != QStyleSheetItem::Undefined ) 4758 if ( rtext ) {
4949 m = item->margin( QStyleSheetItem::MarginTop ); 4759 m = isListItem() ? (document()->li_tm/QMAX(1,listDepth())) : document()->par_tm;
4950 if ( mStyleSheetItemsVec ) { 4760 if ( listDepth() == 1 &&( !prev() || prev()->listDepth() < listDepth() ) )
4951 QStyleSheetItem *it = 0; 4761 m = QMAX( m, document()->list_tm );
4952 QStyleSheetItem *p = prev() ? prev()->style() : 0;
4953 for ( int i = (int)mStyleSheetItemsVec->size() - 2 ; i >= 0; --i ) {
4954 it = (*mStyleSheetItemsVec)[ i ];
4955 if ( it != p )
4956 break;
4957 int mar = it->margin( QStyleSheetItem::MarginTop );
4958 m += (mar != QStyleSheetItem::Undefined) ? mar : 0;
4959 if ( it->displayMode() != QStyleSheetItem::DisplayInline )
4960 break;
4961 }
4962 } 4762 }
4963 m = scale( m, QTextFormat::painter() ); 4763 m += utm;
4964 4764 return scale( m, QTextFormat::painter() );
4965 ( (QTextParag*)this )->tm = m;
4966 return tm;
4967} 4765}
4968 4766
4969int QTextParag::bottomMargin() const 4767int QTextParagraph::bottomMargin() const
4970{ 4768{
4971 if ( bm != -1 )
4972 return bm;
4973 QStyleSheetItem *item = style();
4974 if ( !item || !next() ) {
4975 ( (QTextParag*)this )->bm = 0;
4976 return 0;
4977 }
4978
4979 int m = 0; 4769 int m = 0;
4980 if ( item->margin( QStyleSheetItem::MarginBottom ) != QStyleSheetItem::Undefined ) 4770 if ( rtext ) {
4981 m = item->margin( QStyleSheetItem::MarginBottom ); 4771 m = isListItem() ? (document()->li_bm/QMAX(1,listDepth())) : document()->par_bm;
4982 if ( mStyleSheetItemsVec ) { 4772 if ( listDepth() == 1 &&( !next() || next()->listDepth() < listDepth() ) )
4983 QStyleSheetItem *it = 0; 4773 m = QMAX( m, document()->list_bm );
4984 QStyleSheetItem *n = next() ? next()->style() : 0;
4985 for ( int i =(int)mStyleSheetItemsVec->size() - 2 ; i >= 0; --i ) {
4986 it = (*mStyleSheetItemsVec)[ i ];
4987 if ( it != n )
4988 break;
4989 int mar = it->margin( QStyleSheetItem::MarginBottom );
4990 m += mar != QStyleSheetItem::Undefined ? mar : 0;
4991 if ( it->displayMode() != QStyleSheetItem::DisplayInline )
4992 break;
4993 }
4994 } 4774 }
4995 m = scale ( m, QTextFormat::painter() ); 4775 m += ubm;
4996 4776 return scale( m, QTextFormat::painter() );
4997 ( (QTextParag*)this )->bm = m;
4998 return bm;
4999} 4777}
5000 4778
5001int QTextParag::leftMargin() const 4779int QTextParagraph::leftMargin() const
5002{ 4780{
5003 if ( lm != -1 ) 4781 int m = ulm;
5004 return lm; 4782 if ( listDepth() )
5005 QStyleSheetItem *item = style(); 4783 m += listDepth() * document()->list_lm;
5006 if ( !item ) { 4784 return scale( m, QTextFormat::painter() );
5007 ( (QTextParag*)this )->lm = 0;
5008 return 0;
5009 }
5010 int m = 0;
5011 if ( mStyleSheetItemsVec ) {
5012 for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) {
5013 item = (*mStyleSheetItemsVec)[ i ];
5014 int mar = item->margin( QStyleSheetItem::MarginLeft );
5015 m += mar != QStyleSheetItem::Undefined ? mar : 0;
5016 if ( item->name() == "ol" || item->name() == "ul" ) {
5017 QPainter* oldPainter = QTextFormat::painter();
5018 QTextFormat::setPainter( 0 );
5019 m += defFormat->width( '1' ) +
5020 defFormat->width( '2' ) +
5021 defFormat->width( '3' ) +
5022 defFormat->width( '.' );
5023 QTextFormat::setPainter( oldPainter );
5024 }
5025 }
5026 }
5027
5028 m = scale ( m, QTextFormat::painter() );
5029
5030 ( (QTextParag*)this )->lm = m;
5031 return lm;
5032} 4785}
5033 4786
5034int QTextParag::firstLineMargin() const 4787int QTextParagraph::firstLineMargin() const
5035{ 4788{
5036 if ( flm != -1 ) 4789 int m = uflm;
5037 return lm; 4790 return scale( m, QTextFormat::painter() );
5038 QStyleSheetItem *item = style();
5039 if ( !item ) {
5040 ( (QTextParag*)this )->flm = 0;
5041 return 0;
5042 }
5043 int m = 0;
5044 if ( mStyleSheetItemsVec ) {
5045 for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) {
5046 item = (*mStyleSheetItemsVec)[ i ];
5047 int mar = item->margin( QStyleSheetItem::MarginFirstLine );
5048 m += mar != QStyleSheetItem::Undefined ? mar : 0;
5049 }
5050 }
5051
5052 m = scale( m, QTextFormat::painter() );
5053
5054 ( (QTextParag*)this )->flm = m;
5055 return flm;
5056} 4791}
5057 4792
5058int QTextParag::rightMargin() const 4793int QTextParagraph::rightMargin() const
5059{ 4794{
5060 if ( rm != -1 ) 4795 int m = urm;
5061 return rm; 4796 return scale( m, QTextFormat::painter() );
5062 QStyleSheetItem *item = style();
5063 if ( !item ) {
5064 ( (QTextParag*)this )->rm = 0;
5065 return 0;
5066 }
5067 int m = 0;
5068 if ( mStyleSheetItemsVec ) {
5069 for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) {
5070 item = (*mStyleSheetItemsVec)[ i ];
5071 int mar = item->margin( QStyleSheetItem::MarginRight );
5072 m += mar != QStyleSheetItem::Undefined ? mar : 0;
5073 }
5074 }
5075 m = scale( m, QTextFormat::painter() );
5076
5077 ( (QTextParag*)this )->rm = m;
5078 return rm;
5079} 4797}
5080 4798
5081int QTextParag::lineSpacing() const 4799int QTextParagraph::lineSpacing() const
5082{ 4800{
5083 QStyleSheetItem *item = style(); 4801 int l = ulinespacing;
5084 if ( !item ) 4802 l = scale( l, QTextFormat::painter() );
5085 return 0; 4803 return l;
5086
5087 int ls = item->lineSpacing();
5088 if ( ls == QStyleSheetItem::Undefined )
5089 return 0;
5090 ls = scale( ls, QTextFormat::painter() );
5091
5092 return ls;
5093} 4804}
5094 4805
5095void QTextParag::copyParagData( QTextParag *parag ) 4806void QTextParagraph::copyParagData( QTextParagraph *parag )
5096{ 4807{
5097 setStyleSheetItems( parag->styleSheetItems() ); 4808 rtext = parag->rtext;
5098 setListStyle( parag->listStyle() ); 4809 lstyle = parag->lstyle;
5099 setAlignment( parag->alignment() ); 4810 ldepth = parag->ldepth;
4811 litem = parag->litem;
4812 align = parag->align;
4813 utm = parag->utm;
4814 ubm = parag->ubm;
4815 urm = parag->urm;
4816 ulm = parag->ulm;
4817 uflm = parag->uflm;
4818 ulinespacing = parag->ulinespacing;
5100 QColor *c = parag->backgroundColor(); 4819 QColor *c = parag->backgroundColor();
5101 if ( c ) 4820 if ( c )
5102 setBackgroundColor( *c ); 4821 setBackgroundColor( *c );
4822 str->setDirection( parag->str->direction() );
5103} 4823}
5104 4824
5105void QTextParag::show() 4825void QTextParagraph::show()
5106{ 4826{
5107 if ( visible || !hasdoc ) 4827 if ( visible || !hasdoc )
5108 return; 4828 return;
5109 visible = TRUE; 4829 visible = TRUE;
5110} 4830}
5111 4831
5112void QTextParag::hide() 4832void QTextParagraph::hide()
5113{ 4833{
5114 if ( !visible || !hasdoc ) 4834 if ( !visible || !hasdoc )
5115 return; 4835 return;
5116 visible = FALSE; 4836 visible = FALSE;
5117} 4837}
5118 4838
5119void QTextParag::setDirection( QChar::Direction d ) 4839void QTextParagraph::setDirection( QChar::Direction d )
5120{ 4840{
5121 if ( str && str->direction() != d ) { 4841 if ( str && str->direction() != d ) {
5122 str->setDirection( d ); 4842 str->setDirection( d );
5123 invalidate( 0 ); 4843 invalidate( 0 );
5124 } 4844 }
5125} 4845}
5126 4846
5127QChar::Direction QTextParag::direction() const 4847QChar::Direction QTextParagraph::direction() const
5128{ 4848{
5129 return (str ? str->direction() : QChar::DirON ); 4849 return (str ? str->direction() : QChar::DirON );
5130} 4850}
5131 4851
5132void QTextParag::setChanged( bool b, bool recursive ) 4852void QTextParagraph::setChanged( bool b, bool recursive )
5133{ 4853{
5134 changed = b; 4854 changed = b;
5135 if ( recursive ) { 4855 if ( recursive ) {
5136 if ( document() && document()->parentParag() ) 4856 if ( document() && document()->parentParagraph() )
5137 document()->parentParag()->setChanged( b, recursive ); 4857 document()->parentParagraph()->setChanged( b, recursive );
5138 } 4858 }
5139} 4859}
5140 4860
5141// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4861// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5142 4862
5143 4863
5144QTextPreProcessor::QTextPreProcessor() 4864QTextPreProcessor::QTextPreProcessor()
5145{ 4865{
5146} 4866}
5147 4867
5148// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4868// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5149 4869
5150QTextFormatter::QTextFormatter() 4870QTextFormatter::QTextFormatter()
5151 : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE ) 4871 : thisminw(0), thiswused(0), wrapEnabled( TRUE ), wrapColumn( -1 ), biw( FALSE )
5152{ 4872{
5153} 4873}
5154 4874
5155/* only used for bidi or complex text reordering 4875QTextLineStart *QTextFormatter::formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line,
5156 */
5157QTextParagLineStart *QTextFormatter::formatLine( QTextParag *parag, QTextString *string, QTextParagLineStart *line,
5158 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) 4876 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space )
5159{ 4877{
5160#ifndef QT_NO_COMPLEXTEXT 4878#ifndef QT_NO_COMPLEXTEXT
5161 if( string->isBidi() ) 4879 if( string->isBidi() )
5162 return bidiReorderLine( parag, string, line, startChar, lastChar, align, space ); 4880 return bidiReorderLine( parag, string, line, startChar, lastChar, align, space );
5163#endif 4881#endif
5164 space = QMAX( space, 0 ); // #### with nested tables this gets negative because of a bug I didn't find yet, so workaround for now. This also means non-left aligned nested tables do not work at the moment
5165 int start = (startChar - &string->at(0)); 4882 int start = (startChar - &string->at(0));
5166 int last = (lastChar - &string->at(0) ); 4883 int last = (lastChar - &string->at(0) );
5167 // do alignment Auto == Left in this case 4884 // do alignment Auto == Left in this case
5168 if ( align & Qt::AlignHCenter || align & Qt::AlignRight ) { 4885 if ( align & Qt::AlignHCenter || align & Qt::AlignRight ) {
5169 if ( align & Qt::AlignHCenter ) 4886 if ( align & Qt::AlignHCenter )
5170 space /= 2; 4887 space /= 2;
5171 for ( int j = start; j <= last; ++j ) 4888 for ( int j = start; j <= last; ++j )
5172 string->at( j ).x += space; 4889 string->at( j ).x += space;
5173 } else if ( align & Qt3::AlignJustify ) { 4890 } else if ( align & Qt3::AlignJustify ) {
5174 int numSpaces = 0; 4891 int numSpaces = 0;
5175 for ( int j = start; j < last; ++j ) { 4892 // End at "last-1", the last space ends up with a width of 0
4893 for ( int j = last-1; j >= start; --j ) {
4894 // Start at last tab, if any.
4895 if ( string->at( j ).c == '\t' ) {
4896 start = j+1;
4897 break;
4898 }
5176 if( isBreakable( string, j ) ) { 4899 if( isBreakable( string, j ) ) {
5177 numSpaces++; 4900 numSpaces++;
5178 } 4901 }
5179 } 4902 }
5180 int toAdd = 0; 4903 int toAdd = 0;
5181 for ( int k = start + 1; k <= last; ++k ) { 4904 for ( int k = start + 1; k <= last; ++k ) {
5182 if( isBreakable( string, k ) && numSpaces ) { 4905 if( isBreakable( string, k ) && numSpaces ) {
5183 int s = space / numSpaces; 4906 int s = space / numSpaces;
5184 toAdd += s; 4907 toAdd += s;
5185 space -= s; 4908 space -= s;
5186 numSpaces--; 4909 numSpaces--;
5187 } 4910 }
5188 string->at( k ).x += toAdd; 4911 string->at( k ).x += toAdd;
5189 } 4912 }
5190 } 4913 }
5191 4914
5192 if ( last >= 0 && last < string->length() ) 4915 if ( last >= 0 && last < string->length() )
5193 line->w = string->at( last ).x + string->width( last ); 4916 line->w = string->at( last ).x + string->width( last );
5194 else 4917 else
5195 line->w = 0; 4918 line->w = 0;
5196 4919
5197 return new QTextParagLineStart(); 4920 return new QTextLineStart();
5198} 4921}
5199 4922
5200#ifndef QT_NO_COMPLEXTEXT 4923#ifndef QT_NO_COMPLEXTEXT
5201 4924
5202#ifdef BIDI_DEBUG 4925#ifdef BIDI_DEBUG
5203#include <iostream> 4926#include <iostream>
5204#endif 4927#endif
5205 4928
5206// collects one line of the paragraph and transforms it to visual order 4929// collects one line of the paragraph and transforms it to visual order
5207QTextParagLineStart *QTextFormatter::bidiReorderLine( QTextParag * /*parag*/, QTextString *text, QTextParagLineStart *line, 4930QTextLineStart *QTextFormatter::bidiReorderLine( QTextParagraph * /*parag*/, QTextString *text, QTextLineStart *line,
5208 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space ) 4931 QTextStringChar *startChar, QTextStringChar *lastChar, int align, int space )
5209{ 4932{
5210 int start = (startChar - &text->at(0)); 4933 int start = (startChar - &text->at(0));
5211 int last = (lastChar - &text->at(0) ); 4934 int last = (lastChar - &text->at(0) );
5212 //qDebug("doing BiDi reordering from %d to %d!", start, last);
5213 4935
5214 QBidiControl *control = new QBidiControl( line->context(), line->status ); 4936 QBidiControl *control = new QBidiControl( line->context(), line->status );
5215 QString str; 4937 QString str;
5216 str.setUnicode( 0, last - start + 1 ); 4938 str.setUnicode( 0, last - start + 1 );
5217 // fill string with logically ordered chars. 4939 // fill string with logically ordered chars.
5218 QTextStringChar *ch = startChar; 4940 QTextStringChar *ch = startChar;
5219 QChar *qch = (QChar *)str.unicode(); 4941 QChar *qch = (QChar *)str.unicode();
5220 while ( ch <= lastChar ) { 4942 while ( ch <= lastChar ) {
5221 *qch = ch->c; 4943 *qch = ch->c;
5222 qch++; 4944 qch++;
5223 ch++; 4945 ch++;
5224 } 4946 }
5225 int x = startChar->x; 4947 int x = startChar->x;
5226 4948
5227 QPtrList<QTextRun> *runs; 4949 QPtrList<QTextRun> *runs;
5228 runs = QComplexText::bidiReorderLine(control, str, 0, last - start + 1, 4950 runs = QComplexText::bidiReorderLine(control, str, 0, last - start + 1,
5229 (text->isRightToLeft() ? QChar::DirR : QChar::DirL) ); 4951 (text->isRightToLeft() ? QChar::DirR : QChar::DirL) );
5230 4952
5231 // now construct the reordered string out of the runs... 4953 // now construct the reordered string out of the runs...
5232 4954
5233 int numSpaces = 0; 4955 int numSpaces = 0;
5234 // set the correct alignment. This is a bit messy.... 4956 // set the correct alignment. This is a bit messy....
5235 if( align == Qt3::AlignAuto ) { 4957 if( align == Qt3::AlignAuto ) {
5236 // align according to directionality of the paragraph... 4958 // align according to directionality of the paragraph...
5237 if ( text->isRightToLeft() ) 4959 if ( text->isRightToLeft() )
5238 align = Qt::AlignRight; 4960 align = Qt::AlignRight;
5239 } 4961 }
5240 4962
5241 if ( align & Qt::AlignHCenter ) 4963 if ( align & Qt::AlignHCenter )
5242 x += space/2; 4964 x += space/2;
5243 else if ( align & Qt::AlignRight ) 4965 else if ( align & Qt::AlignRight )
5244 x += space; 4966 x += space;
5245 else if ( align & Qt3::AlignJustify ) { 4967 else if ( align & Qt3::AlignJustify ) {
5246 for ( int j = start; j < last; ++j ) { 4968 // End at "last-1", the last space ends up with a width of 0
4969 for ( int j = last-1; j >= start; --j ) {
4970 // Start at last tab, if any.
4971 if ( text->at( j ).c == '\t' ) {
4972 start = j+1;
4973 break;
4974 }
5247 if( isBreakable( text, j ) ) { 4975 if( isBreakable( text, j ) ) {
5248 numSpaces++; 4976 numSpaces++;
5249 } 4977 }
5250 } 4978 }
5251 } 4979 }
5252 int toAdd = 0; 4980 int toAdd = 0;
5253 bool first = TRUE; 4981 bool first = TRUE;
5254 QTextRun *r = runs->first(); 4982 QTextRun *r = runs->first();
5255 int xmax = -0xffffff; 4983 int xmax = -0xffffff;
5256 while ( r ) { 4984 while ( r ) {
5257 if(r->level %2) { 4985 if(r->level %2) {
5258 // odd level, need to reverse the string 4986 // odd level, need to reverse the string
5259 int pos = r->stop + start; 4987 int pos = r->stop + start;
5260 while(pos >= r->start + start) { 4988 while(pos >= r->start + start) {
5261 QTextStringChar *c = &text->at(pos); 4989 QTextStringChar *c = &text->at(pos);
5262 if( numSpaces && !first && isBreakable( text, pos ) ) { 4990 if( numSpaces && !first && isBreakable( text, pos ) ) {
5263 int s = space / numSpaces; 4991 int s = space / numSpaces;
5264 toAdd += s; 4992 toAdd += s;
5265 space -= s; 4993 space -= s;
5266 numSpaces--; 4994 numSpaces--;
5267 } else if ( first ) { 4995 } else if ( first ) {
5268 first = FALSE; 4996 first = FALSE;
5269 if ( c->c == ' ' ) 4997 if ( c->c == ' ' )
5270 x -= c->format()->width( ' ' ); 4998 x -= c->format()->width( ' ' );
5271 } 4999 }
5272 c->x = x + toAdd; 5000 c->x = x + toAdd;
5273 c->rightToLeft = TRUE; 5001 c->rightToLeft = TRUE;
5274 c->startOfRun = FALSE; 5002 c->startOfRun = FALSE;
5275 int ww = 0; 5003 int ww = 0;
5276 if ( c->c.unicode() >= 32 || c->c == '\t' || c->c == '\n' || c->isCustom() ) { 5004 if ( c->c.unicode() >= 32 || c->c == '\t' || c->c == '\n' || c->isCustom() ) {
5277 ww = text->width( pos ); 5005 ww = text->width( pos );
5278 } else { 5006 } else {
5279 ww = c->format()->width( ' ' ); 5007 ww = c->format()->width( ' ' );
5280 } 5008 }
5281 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww; 5009 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww;
5282 x += ww; 5010 x += ww;
5283 pos--; 5011 pos--;
5284 } 5012 }
5285 } else { 5013 } else {
5286 int pos = r->start + start; 5014 int pos = r->start + start;
5287 while(pos <= r->stop + start) { 5015 while(pos <= r->stop + start) {
5288 QTextStringChar* c = &text->at(pos); 5016 QTextStringChar* c = &text->at(pos);
5289 if( numSpaces && !first && isBreakable( text, pos ) ) { 5017 if( numSpaces && !first && isBreakable( text, pos ) ) {
5290 int s = space / numSpaces; 5018 int s = space / numSpaces;
5291 toAdd += s; 5019 toAdd += s;
5292 space -= s; 5020 space -= s;
5293 numSpaces--; 5021 numSpaces--;
5294 } else if ( first ) { 5022 } else if ( first ) {
5295 first = FALSE; 5023 first = FALSE;
5296 if ( c->c == ' ' ) 5024 if ( c->c == ' ' )
5297 x -= c->format()->width( ' ' ); 5025 x -= c->format()->width( ' ' );
5298 } 5026 }
5299 c->x = x + toAdd; 5027 c->x = x + toAdd;
5300 c->rightToLeft = FALSE; 5028 c->rightToLeft = FALSE;
5301 c->startOfRun = FALSE; 5029 c->startOfRun = FALSE;
5302 int ww = 0; 5030 int ww = 0;
5303 if ( c->c.unicode() >= 32 || c->c == '\t' || c->isCustom() ) { 5031 if ( c->c.unicode() >= 32 || c->c == '\t' || c->isCustom() ) {
5304 ww = text->width( pos ); 5032 ww = text->width( pos );
5305 } else { 5033 } else {
5306 ww = c->format()->width( ' ' ); 5034 ww = c->format()->width( ' ' );
5307 } 5035 }
5308 //qDebug("setting char %d at pos %d", pos, x);
5309 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww; 5036 if ( xmax < x + toAdd + ww ) xmax = x + toAdd + ww;
5310 x += ww; 5037 x += ww;
5311 pos++; 5038 pos++;
5312 } 5039 }
5313 } 5040 }
5314 text->at( r->start + start ).startOfRun = TRUE; 5041 text->at( r->start + start ).startOfRun = TRUE;
5315 r = runs->next(); 5042 r = runs->next();
5316 } 5043 }
5317 5044
5318 line->w = xmax + 10; 5045 line->w = xmax + 10;
5319 QTextParagLineStart *ls = new QTextParagLineStart( control->context, control->status ); 5046 QTextLineStart *ls = new QTextLineStart( control->context, control->status );
5320 delete control; 5047 delete control;
5321 delete runs; 5048 delete runs;
5322 return ls; 5049 return ls;
5323} 5050}
5324#endif 5051#endif
5325 5052
5326bool QTextFormatter::isBreakable( QTextString *string, int pos ) const 5053bool QTextFormatter::isBreakable( QTextString *string, int pos )
5327{ 5054{
5328 const QChar &c = string->at( pos ).c; 5055 const QChar &c = string->at( pos ).c;
5329 char ch = c.latin1(); 5056 char ch = c.latin1();
5057 if ( c == QChar_linesep )
5058 return TRUE;
5330 if ( c.isSpace() && ch != '\n' && c.unicode() != 0x00a0U ) 5059 if ( c.isSpace() && ch != '\n' && c.unicode() != 0x00a0U )
5331 return TRUE; 5060 return TRUE;
5332 if ( c.unicode() == 0xad ) // soft hyphen 5061 if ( c.unicode() == 0xad ) // soft hyphen
5333 return TRUE; 5062 return TRUE;
5334 if ( !ch ) { 5063 if ( !ch ) {
5335 // not latin1, need to do more sophisticated checks for other scripts 5064 // not latin1, need to do more sophisticated checks for other scripts
5336 uchar row = c.row(); 5065 uchar row = c.row();
5337 if ( row == 0x0e ) { 5066 if ( row == 0x0e ) {
5338 // 0e00 - 0e7f == Thai 5067 // 0e00 - 0e7f == Thai
5339 if ( c.cell() < 0x80 ) { 5068 if ( c.cell() < 0x80 ) {
5340#ifdef HAVE_THAI_BREAKS 5069#ifdef HAVE_THAI_BREAKS
5341 // check for thai 5070 // check for thai
5342 if( string != cachedString ) { 5071 if( string != cachedString ) {
5343 // build up string of thai chars 5072 // build up string of thai chars
5344 QTextCodec *thaiCodec = QTextCodec::codecForMib(2259); 5073 QTextCodec *thaiCodec = QTextCodec::codecForMib(2259);
5345 if ( !thaiCache ) 5074 if ( !thaiCache )
5346 thaiCache = new QCString; 5075 thaiCache = new QCString;
5347 if ( !thaiIt ) 5076 if ( !thaiIt )
5348 thaiIt = ThBreakIterator::createWordInstance(); 5077 thaiIt = ThBreakIterator::createWordInstance();
5349 *thaiCache = thaiCodec->fromUnicode( s->string() ); 5078 *thaiCache = thaiCodec->fromUnicode( s->string() );
5350 } 5079 }
5351 thaiIt->setText(thaiCache->data()); 5080 thaiIt->setText(thaiCache->data());
5352 for(int i = thaiIt->first(); i != thaiIt->DONE; i = thaiIt->next() ) { 5081 for(int i = thaiIt->first(); i != thaiIt->DONE; i = thaiIt->next() ) {
5353 if( i == pos ) 5082 if( i == pos )
5354 return TRUE; 5083 return TRUE;
5355 if( i > pos ) 5084 if( i > pos )
5356 return FALSE; 5085 return FALSE;
5357 } 5086 }
5358 return FALSE; 5087 return FALSE;
5359#else 5088#else
5360 // if we don't have a thai line breaking lib, allow 5089 // if we don't have a thai line breaking lib, allow
5361 // breaks everywhere except directly before punctuation. 5090 // breaks everywhere except directly before punctuation.
5362 return TRUE; 5091 return TRUE;
5363#endif 5092#endif
5364 } else 5093 } else
5365 return FALSE; 5094 return FALSE;
5366 } 5095 }
5367 if ( row < 0x11 ) // no asian font 5096 if ( row < 0x11 ) // no asian font
5368 return FALSE; 5097 return FALSE;
5369 if ( row > 0x2d && row < 0xfb || row == 0x11 ) 5098 if ( row > 0x2d && row < 0xfb || row == 0x11 )
5370 // asian line breaking. Everywhere allowed except directly 5099 // asian line breaking. Everywhere allowed except directly
5371 // in front of a punctuation character. 5100 // in front of a punctuation character.
5372 return TRUE; 5101 return TRUE;
5373 } 5102 }
5374 return FALSE; 5103 return FALSE;
5375} 5104}
5376 5105
5377void QTextFormatter::insertLineStart( QTextParag *parag, int index, QTextParagLineStart *ls ) 5106void QTextFormatter::insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls )
5378{ 5107{
5379 if ( index > 0 ) { // we can assume that only first line starts are insrted multiple times 5108 if ( index > 0 ) { // we can assume that only first line starts are insrted multiple times
5380 parag->lineStartList().insert( index, ls ); 5109 parag->lineStartList().insert( index, ls );
5381 return; 5110 return;
5382 } 5111 }
5383 QMap<int, QTextParagLineStart*>::Iterator it; 5112 QMap<int, QTextLineStart*>::Iterator it;
5384 if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) { 5113 if ( ( it = parag->lineStartList().find( index ) ) == parag->lineStartList().end() ) {
5385 parag->lineStartList().insert( index, ls ); 5114 parag->lineStartList().insert( index, ls );
5386 } else { 5115 } else {
5387 delete *it; 5116 delete *it;
5388 parag->lineStartList().remove( it ); 5117 parag->lineStartList().remove( it );
5389 parag->lineStartList().insert( index, ls ); 5118 parag->lineStartList().insert( index, ls );
5390 } 5119 }
5391} 5120}
5392 5121
5393 5122
5394/* Standard pagebreak algorithm using QTextFlow::adjustFlow. Returns 5123/* Standard pagebreak algorithm using QTextFlow::adjustFlow. Returns
5395 the shift of the paragraphs bottom line. 5124 the shift of the paragraphs bottom line.
5396 */ 5125 */
5397int QTextFormatter::formatVertically( QTextDocument* doc, QTextParag* parag ) 5126int QTextFormatter::formatVertically( QTextDocument* doc, QTextParagraph* parag )
5398{ 5127{
5399 int oldHeight = parag->rect().height(); 5128 int oldHeight = parag->rect().height();
5400 QMap<int, QTextParagLineStart*>& lineStarts = parag->lineStartList(); 5129 QMap<int, QTextLineStart*>& lineStarts = parag->lineStartList();
5401 QMap<int, QTextParagLineStart*>::Iterator it = lineStarts.begin(); 5130 QMap<int, QTextLineStart*>::Iterator it = lineStarts.begin();
5402 int h = doc->addMargins() ? parag->topMargin() : 0; 5131 int h = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin() ) / 2: 0;
5403 for ( ; it != lineStarts.end() ; ++it ) { 5132 for ( ; it != lineStarts.end() ; ++it ) {
5404 QTextParagLineStart * ls = it.data(); 5133 QTextLineStart * ls = it.data();
5405 ls->y = h; 5134 ls->y = h;
5406 QTextStringChar *c = &parag->string()->at(it.key()); 5135 QTextStringChar *c = &parag->string()->at(it.key());
5407 if ( c && c->customItem() && c->customItem()->ownLine() ) { 5136 if ( c && c->customItem() && c->customItem()->ownLine() ) {
5408 int h = c->customItem()->height; 5137 int h = c->customItem()->height;
5409 c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() ); 5138 c->customItem()->pageBreak( parag->rect().y() + ls->y + ls->baseLine - h, doc->flow() );
5410 int delta = c->customItem()->height - h; 5139 int delta = c->customItem()->height - h;
5411 ls->h += delta; 5140 ls->h += delta;
5412 if ( delta ) 5141 if ( delta )
5413 parag->setMovedDown( TRUE ); 5142 parag->setMovedDown( TRUE );
5414 } else { 5143 } else {
5415 int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h ); 5144 int shift = doc->flow()->adjustFlow( parag->rect().y() + ls->y, ls->w, ls->h );
5416 ls->y += shift; 5145 ls->y += shift;
5417 if ( shift ) 5146 if ( shift )
5418 parag->setMovedDown( TRUE ); 5147 parag->setMovedDown( TRUE );
5419 } 5148 }
5420 h = ls->y + ls->h; 5149 h = ls->y + ls->h;
5421 } 5150 }
5422 int m = parag->bottomMargin(); 5151 int m = parag->bottomMargin();
5423 if ( parag->next() && doc && !doc->addMargins() ) 5152 if ( !parag->next() )
5424 m = QMAX( m, parag->next()->topMargin() );
5425 if ( parag->next() && parag->next()->isLineBreak() )
5426 m = 0; 5153 m = 0;
5154 else
5155 m = QMAX(m, parag->next()->topMargin() ) / 2;
5427 h += m; 5156 h += m;
5428 parag->setHeight( h ); 5157 parag->setHeight( h );
5429 return h - oldHeight; 5158 return h - oldHeight;
5430} 5159}
5431 5160
5432// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5161// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5433 5162
5434QTextFormatterBreakInWords::QTextFormatterBreakInWords() 5163QTextFormatterBreakInWords::QTextFormatterBreakInWords()
5435{ 5164{
5436} 5165}
5437 5166
5438int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParag *parag, 5167#define SPACE(s) doc?(s>0?s:0):s
5439 int start, const QMap<int, QTextParagLineStart*> & ) 5168
5169int QTextFormatterBreakInWords::format( QTextDocument *doc,QTextParagraph *parag,
5170 int start, const QMap<int, QTextLineStart*> & )
5440{ 5171{
5441 QTextStringChar *c = 0; 5172 QTextStringChar *c = 0;
5442 QTextStringChar *firstChar = 0; 5173 QTextStringChar *firstChar = 0;
5443 int left = doc ? parag->leftMargin() + doc->leftMargin() : 4; 5174 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0;
5444 int x = left + ( doc ? parag->firstLineMargin() : 0 ); 5175 int x = left + ( doc ? parag->firstLineMargin() : 0 );
5445 int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 ); 5176 int dw = parag->documentVisibleWidth() - ( doc ? doc->rightMargin() : 0 );
5446 int y = doc && doc->addMargins() ? parag->topMargin() : 0; 5177 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0;
5447 int h = y; 5178 int h = y;
5448 int len = parag->length(); 5179 int len = parag->length();
5449 if ( doc ) 5180 if ( doc )
5450 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 ); 5181 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 4 );
5451 int rm = parag->rightMargin(); 5182 int rm = parag->rightMargin();
5452 int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5183 int w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5453 bool fullWidth = TRUE; 5184 bool fullWidth = TRUE;
5454 int minw = 0; 5185 int minw = 0;
5455 int wused = 0; 5186 int wused = 0;
5456 bool wrapEnabled = isWrapEnabled( parag ); 5187 bool wrapEnabled = isWrapEnabled( parag );
5457 5188
5458 start = 0; //######### what is the point with start?! (Matthias) 5189 start = 0; //######### what is the point with start?! (Matthias)
5459 if ( start == 0 ) 5190 if ( start == 0 )
5460 c = &parag->string()->at( 0 ); 5191 c = &parag->string()->at( 0 );
5461 5192
5462 int i = start; 5193 int i = start;
5463 QTextParagLineStart *lineStart = new QTextParagLineStart( y, y, 0 ); 5194 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
5464 insertLineStart( parag, 0, lineStart ); 5195 insertLineStart( parag, 0, lineStart );
5465 5196
5466 QPainter *painter = QTextFormat::painter(); 5197 QPainter *painter = QTextFormat::painter();
5467 5198
5468 int col = 0; 5199 int col = 0;
5469 int ww = 0; 5200 int ww = 0;
5470 QChar lastChr; 5201 QChar lastChr;
5471 for ( ; i < len; ++i, ++col ) { 5202 for ( ; i < len; ++i, ++col ) {
5472 if ( c ) 5203 if ( c )
5473 lastChr = c->c; 5204 lastChr = c->c;
5474 c = &parag->string()->at( i ); 5205 c = &parag->string()->at( i );
5475 c->rightToLeft = FALSE; 5206 c->rightToLeft = FALSE;
5476 // ### the lines below should not be needed 5207 // ### the lines below should not be needed
5477 if ( painter ) 5208 if ( painter )
5478 c->format()->setPainter( painter ); 5209 c->format()->setPainter( painter );
5479 if ( i > 0 ) { 5210 if ( i > 0 ) {
5480 c->lineStart = 0; 5211 c->lineStart = 0;
5481 } else { 5212 } else {
5482 c->lineStart = 1; 5213 c->lineStart = 1;
5483 firstChar = c; 5214 firstChar = c;
5484 } 5215 }
5485 if ( c->c.unicode() >= 32 || c->isCustom() ) { 5216 if ( c->c.unicode() >= 32 || c->isCustom() ) {
5486 ww = parag->string()->width( i ); 5217 ww = parag->string()->width( i );
5487 } else if ( c->c == '\t' ) { 5218 } else if ( c->c == '\t' ) {
5488 int nx = parag->nextTab( i, x - left ) + left; 5219 int nx = parag->nextTab( i, x - left ) + left;
5489 if ( nx < x ) 5220 if ( nx < x )
5490 ww = w - x; 5221 ww = w - x;
5491 else 5222 else
5492 ww = nx - x; 5223 ww = nx - x;
5493 } else { 5224 } else {
5494 ww = c->format()->width( ' ' ); 5225 ww = c->format()->width( ' ' );
5495 } 5226 }
5496 5227
5497 if ( c->isCustom() && c->customItem()->ownLine() ) { 5228 if ( c->isCustom() && c->customItem()->ownLine() ) {
5498 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5229 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5499 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5230 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5500 c->customItem()->resize( w - x ); 5231 c->customItem()->resize( w - x );
5501 w = dw; 5232 w = dw;
5502 y += h; 5233 y += h;
5503 h = c->height(); 5234 h = c->height();
5504 lineStart = new QTextParagLineStart( y, h, h ); 5235 lineStart = new QTextLineStart( y, h, h );
5505 insertLineStart( parag, i, lineStart ); 5236 insertLineStart( parag, i, lineStart );
5506 c->lineStart = 1; 5237 c->lineStart = 1;
5507 firstChar = c; 5238 firstChar = c;
5508 x = 0xffffff; 5239 x = 0xffffff;
5509 continue; 5240 continue;
5510 } 5241 }
5511 5242
5512 if ( wrapEnabled && 5243 if ( wrapEnabled &&
5513 ( wrapAtColumn() == -1 && x + ww > w || 5244 ( wrapAtColumn() == -1 && x + ww > w ||
5514 wrapAtColumn() != -1 && col >= wrapAtColumn() ) || 5245 wrapAtColumn() != -1 && col >= wrapAtColumn() ) ) {
5515 parag->isNewLinesAllowed() && lastChr == '\n' ) {
5516 x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5246 x = doc ? parag->document()->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5517 w = dw; 5247 w = dw;
5518 y += h; 5248 y += h;
5519 h = c->height(); 5249 h = c->height();
5520 lineStart = formatLine( parag, parag->string(), lineStart, firstChar, c-1 ); 5250 lineStart = formatLine( parag, parag->string(), lineStart, firstChar, SPACE(c-1) );
5521 lineStart->y = y; 5251 lineStart->y = y;
5522 insertLineStart( parag, i, lineStart ); 5252 insertLineStart( parag, i, lineStart );
5523 lineStart->baseLine = c->ascent(); 5253 lineStart->baseLine = c->ascent();
5524 lineStart->h = c->height(); 5254 lineStart->h = c->height();
5525 c->lineStart = 1; 5255 c->lineStart = 1;
5526 firstChar = c; 5256 firstChar = c;
5527 col = 0; 5257 col = 0;
5528 if ( wrapAtColumn() != -1 ) 5258 if ( wrapAtColumn() != -1 )
5529 minw = QMAX( minw, w ); 5259 minw = QMAX( minw, w );
5530 } else if ( lineStart ) { 5260 } else if ( lineStart ) {
5531 lineStart->baseLine = QMAX( lineStart->baseLine, c->ascent() ); 5261 lineStart->baseLine = QMAX( lineStart->baseLine, c->ascent() );
5532 h = QMAX( h, c->height() ); 5262 h = QMAX( h, c->height() );
5533 lineStart->h = h; 5263 lineStart->h = h;
5534 } 5264 }
5535 5265
5536 c->x = x; 5266 c->x = x;
5537 x += ww; 5267 x += ww;
5538 wused = QMAX( wused, x ); 5268 wused = QMAX( wused, x );
5539 } 5269 }
5540 5270
5541 int m = parag->bottomMargin(); 5271 int m = parag->bottomMargin();
5542 if ( parag->next() && doc && !doc->addMargins() ) 5272 if ( !parag->next() )
5543 m = QMAX( m, parag->next()->topMargin() );
5544 parag->setFullWidth( fullWidth );
5545 if ( parag->next() && parag->next()->isLineBreak() )
5546 m = 0; 5273 m = 0;
5274 else
5275 m = QMAX(m, parag->next()->topMargin() ) / 2;
5276 parag->setFullWidth( fullWidth );
5547 y += h + m; 5277 y += h + m;
5278 if ( doc )
5279 minw += doc->rightMargin();
5548 if ( !wrapEnabled ) 5280 if ( !wrapEnabled )
5549 minw = QMAX(minw, wused); 5281 minw = QMAX(minw, wused);
5550 5282
5551 thisminw = minw; 5283 thisminw = minw;
5552 thiswused = wused; 5284 thiswused = wused;
5553 return y; 5285 return y;
5554} 5286}
5555 5287
5556// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5288// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5557 5289
5558QTextFormatterBreakWords::QTextFormatterBreakWords() 5290QTextFormatterBreakWords::QTextFormatterBreakWords()
5559{ 5291{
5560} 5292}
5561 5293
5562#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \ 5294#define DO_FLOW( lineStart ) do{ if ( doc && doc->isPageBreakEnabled() ) { \
5563 int yflow = lineStart->y + parag->rect().y();\ 5295 int yflow = lineStart->y + parag->rect().y();\
5564 int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \ 5296 int shift = doc->flow()->adjustFlow( yflow, dw, lineStart->h ); \
5565 lineStart->y += shift;\ 5297 lineStart->y += shift;\
5566 y += shift;\ 5298 y += shift;\
5567 }}while(FALSE) 5299 }}while(FALSE)
5568 5300
5569int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParag *parag, 5301int QTextFormatterBreakWords::format( QTextDocument *doc, QTextParagraph *parag,
5570 int start, const QMap<int, QTextParagLineStart*> & ) 5302 int start, const QMap<int, QTextLineStart*> & )
5571{ 5303{
5572 QTextStringChar *c = 0; 5304 QTextStringChar *c = 0;
5573 QTextStringChar *firstChar = 0; 5305 QTextStringChar *firstChar = 0;
5574 QTextString *string = parag->string(); 5306 QTextString *string = parag->string();
5575 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0; 5307 int left = doc ? parag->leftMargin() + doc->leftMargin() : 0;
5576 int x = left + ( doc ? parag->firstLineMargin() : 0 ); 5308 int x = left + ( doc ? parag->firstLineMargin() : 0 );
5577 int y = doc && doc->addMargins() ? parag->topMargin() : 0; 5309 int y = parag->prev() ? QMAX(parag->prev()->bottomMargin(),parag->topMargin()) / 2: 0;
5578 int h = y; 5310 int h = y;
5579 int len = parag->length(); 5311 int len = parag->length();
5580 if ( doc ) 5312 if ( doc )
5581 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 ); 5313 x = doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), x, 0 );
5582 int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 ); 5314 int dw = parag->documentVisibleWidth() - ( doc ? ( left != x ? 0 : doc->rightMargin() ) : 0 );
5583 5315
5584 int curLeft = x; 5316 int curLeft = x;
5585 int rm = parag->rightMargin(); 5317 int rm = parag->rightMargin();
5586 int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0; 5318 int rdiff = doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 0 ) : 0;
5587 int w = dw - rdiff; 5319 int w = dw - rdiff;
5588 bool fullWidth = TRUE; 5320 bool fullWidth = TRUE;
5589 int marg = left + rdiff; 5321 int marg = left + rdiff;
5590 int minw = 0; 5322 int minw = 0;
5591 int wused = 0; 5323 int wused = 0;
5592 int tminw = marg; 5324 int tminw = marg;
5593 int linespace = doc ? parag->lineSpacing() : 0; 5325 int linespacing = doc ? parag->lineSpacing() : 0;
5594 bool wrapEnabled = isWrapEnabled( parag ); 5326 bool wrapEnabled = isWrapEnabled( parag );
5595 5327
5596 start = 0; 5328 start = 0;
5597 if ( start == 0 ) 5329 if ( start == 0 )
5598 c = &parag->string()->at( 0 ); 5330 c = &parag->string()->at( 0 );
5599 5331
5600 int i = start; 5332 int i = start;
5601 QTextParagLineStart *lineStart = new QTextParagLineStart( y, y, 0 ); 5333 QTextLineStart *lineStart = new QTextLineStart( y, y, 0 );
5602 insertLineStart( parag, 0, lineStart ); 5334 insertLineStart( parag, 0, lineStart );
5603 int lastBreak = -1; 5335 int lastBreak = -1;
5604 int tmpBaseLine = 0, tmph = 0; 5336 int tmpBaseLine = 0, tmph = 0;
5605 bool lastWasNonInlineCustom = FALSE; 5337 bool lastWasNonInlineCustom = FALSE;
5606 5338
5607 int align = parag->alignment(); 5339 int align = parag->alignment();
5608 if ( align == Qt3::AlignAuto && doc && doc->alignment() != Qt3::AlignAuto ) 5340 if ( align == Qt3::AlignAuto && doc && doc->alignment() != Qt3::AlignAuto )
5609 align = doc->alignment(); 5341 align = doc->alignment();
5610 5342
5611 align &= Qt3::AlignHorizontal_Mask; 5343 align &= Qt3::AlignHorizontal_Mask;
5612 5344
5613 QPainter *painter = QTextFormat::painter(); 5345 QPainter *painter = QTextFormat::painter();
5614 int col = 0; 5346 int col = 0;
5615 int ww = 0; 5347 int ww = 0;
5616 QChar lastChr; 5348 QChar lastChr;
5617 for ( ; i < len; ++i, ++col ) { 5349 for ( ; i < len; ++i, ++col ) {
5618 if ( c ) 5350 if ( c )
5619 lastChr = c->c; 5351 lastChr = c->c;
5620 // ### next line should not be needed 5352 // ### next line should not be needed
5621 if ( painter ) 5353 if ( painter )
5622 c->format()->setPainter( painter ); 5354 c->format()->setPainter( painter );
5623 c = &string->at( i ); 5355 c = &string->at( i );
5624 c->rightToLeft = FALSE; 5356 c->rightToLeft = FALSE;
5625 if ( i > 0 && (x > curLeft || ww == 0) || lastWasNonInlineCustom ) { 5357 if ( i > 0 && (x > curLeft || ww == 0) || lastWasNonInlineCustom ) {
5626 c->lineStart = 0; 5358 c->lineStart = 0;
5627 } else { 5359 } else {
5628 c->lineStart = 1; 5360 c->lineStart = 1;
5629 firstChar = c; 5361 firstChar = c;
5630 } 5362 }
5631 5363
5632 if ( c->isCustom() && c->customItem()->placement() != QTextCustomItem::PlaceInline ) 5364 if ( c->isCustom() && c->customItem()->placement() != QTextCustomItem::PlaceInline )
5633 lastWasNonInlineCustom = TRUE; 5365 lastWasNonInlineCustom = TRUE;
5634 else 5366 else
5635 lastWasNonInlineCustom = FALSE; 5367 lastWasNonInlineCustom = FALSE;
5636 5368
5637 if ( c->c.unicode() >= 32 || c->isCustom() ) { 5369 if ( c->c.unicode() >= 32 || c->isCustom() ) {
5638 ww = string->width( i ); 5370 ww = string->width( i );
5639 } else if ( c->c == '\t' ) { 5371 } else if ( c->c == '\t' ) {
5640 int nx = parag->nextTab( i, x - left ) + left; 5372 int nx = parag->nextTab( i, x - left ) + left;
5641 if ( nx < x ) 5373 if ( nx < x )
5642 ww = w - x; 5374 ww = w - x;
5643 else 5375 else
5644 ww = nx - x; 5376 ww = nx - x;
5645 } else { 5377 } else {
5646 ww = c->format()->width( ' ' ); 5378 ww = c->format()->width( ' ' );
5647 } 5379 }
5648 5380
5649 // last character ("invisible" space) has no width 5381 // last character ("invisible" space) has no width
5650 if ( i == len - 1 ) 5382 if ( i == len - 1 )
5651 ww = 0; 5383 ww = 0;
5652 5384
5653 QTextCustomItem* ci = c->customItem(); 5385 QTextCustomItem* ci = c->customItem();
5654 if ( c->isCustom() && ci->ownLine() ) { 5386 if ( c->isCustom() && ci->ownLine() ) {
5655 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5387 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5656 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5388 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5657 QTextParagLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, w - x ); 5389 QTextLineStart *lineStart2 = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) );
5658 ci->resize( w - x); 5390 ci->resize( w - x);
5659 if ( ci->width < w - x ) { 5391 if ( ci->width < w - x ) {
5660 if ( align & Qt::AlignHCenter ) 5392 if ( align & Qt::AlignHCenter )
5661 x = ( w - ci->width ) / 2; 5393 x = ( w - ci->width ) / 2;
5662 else if ( align & Qt::AlignRight ) { 5394 else if ( align & Qt::AlignRight ) {
5663 x = w - ci->width; 5395 x = w - ci->width;
5664 } 5396 }
5665 } 5397 }
5666 c->x = x; 5398 c->x = x;
5667 curLeft = x; 5399 curLeft = x;
5668 if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) { 5400 if ( i == 0 || !isBreakable( string, i - 1 ) || string->at( i - 1 ).lineStart == 0 ) {
5669 y += QMAX( h, tmph ); 5401 y += QMAX( h, QMAX( tmph, linespacing ) );
5670 tmph = c->height() + linespace; 5402 tmph = c->height();
5671 h = tmph; 5403 h = tmph;
5672 lineStart = lineStart2; 5404 lineStart = lineStart2;
5673 lineStart->y = y; 5405 lineStart->y = y;
5674 insertLineStart( parag, i, lineStart ); 5406 insertLineStart( parag, i, lineStart );
5675 c->lineStart = 1; 5407 c->lineStart = 1;
5676 firstChar = c; 5408 firstChar = c;
5677 } else { 5409 } else {
5678 tmph = c->height() + linespace; 5410 tmph = c->height();
5679 h = tmph; 5411 h = tmph;
5680 delete lineStart2; 5412 delete lineStart2;
5681 } 5413 }
5682 lineStart->h = h; 5414 lineStart->h = h;
5683 lineStart->baseLine = h; 5415 lineStart->baseLine = h;
5684 tmpBaseLine = lineStart->baseLine; 5416 tmpBaseLine = lineStart->baseLine;
5685 lastBreak = -2; 5417 lastBreak = -2;
5686 x = 0xffffff; 5418 x = 0xffffff;
5687 minw = QMAX( minw, tminw ); 5419 minw = QMAX( minw, tminw );
5688 5420
5689 int tw = ci->minimumWidth(); 5421 int tw = ci->minimumWidth() + ( doc ? doc->leftMargin() : 0 );
5690 if ( tw < QWIDGETSIZE_MAX ) 5422 if ( tw < QWIDGETSIZE_MAX )
5691 tminw = tw; 5423 tminw = tw;
5692 else 5424 else
5693 tminw = marg; 5425 tminw = marg;
5694 wused = QMAX( wused, ci->width ); 5426 wused = QMAX( wused, ci->width );
5695 continue; 5427 continue;
5696 } else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) { 5428 } else if ( c->isCustom() && ci->placement() != QTextCustomItem::PlaceInline ) {
5697 int tw = ci->minimumWidth(); 5429 int tw = ci->minimumWidth();
5698 if ( tw < QWIDGETSIZE_MAX ) 5430 if ( tw < QWIDGETSIZE_MAX )
5699 minw = QMAX( minw, tw ); 5431 minw = QMAX( minw, tw );
5700 } 5432 }
5701 5433
5702 if ( wrapEnabled && ( !c->c.isSpace() || lastBreak == -2 ) 5434 bool lastWasOwnLineCustomItem = lastBreak == -2;
5703 && ( lastBreak != -1 || allowBreakInWords() ) && 5435 bool hadBreakableChar = lastBreak != -1;
5704 ( wrapAtColumn() == -1 && x + ww > w && lastBreak != -1 || 5436 bool lastWasHardBreak = lastChr == QChar_linesep;
5705 wrapAtColumn() == -1 && x + ww > w - 4 && lastBreak == -1 && allowBreakInWords() || 5437
5706 wrapAtColumn() != -1 && col >= wrapAtColumn() ) || 5438 // we break if
5707 parag->isNewLinesAllowed() && lastChr == '\n' && firstChar < c ) { 5439 // 1. the last character was a hard break (QChar_linesep) or
5440 // 2. the last charater was a own-line custom item (eg. table or ruler) or
5441 // 3. wrapping was enabled, it was not a space and following
5442 // condition is true: We either had a breakable character
5443 // previously or we ar allowed to break in words and - either
5444 // we break at w pixels and the current char would exceed that
5445 // or - we break at a column and the current character would
5446 // exceed that.
5447 if ( lastWasHardBreak || lastWasOwnLineCustomItem ||
5448 ( wrapEnabled &&
5449 ( (!c->c.isSpace() && (hadBreakableChar || allowBreakInWords()) &&
5450 ( (wrapAtColumn() == -1 && x + ww > w) ||
5451 (wrapAtColumn() != -1 && col >= wrapAtColumn()) ) ) )
5452 )
5453 ) {
5708 if ( wrapAtColumn() != -1 ) 5454 if ( wrapAtColumn() != -1 )
5709 minw = QMAX( minw, x + ww ); 5455 minw = QMAX( minw, x + ww );
5710 if ( lastBreak < 0 ) { 5456 // if a break was forced (no breakable char, hard break or own line custom item), break immediately....
5457 if ( !hadBreakableChar || lastWasHardBreak || lastWasOwnLineCustomItem ) {
5711 if ( lineStart ) { 5458 if ( lineStart ) {
5712 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5459 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5713 h = QMAX( h, tmph ); 5460 h = QMAX( h, tmph );
5714 lineStart->h = h; 5461 lineStart->h = h;
5715 DO_FLOW( lineStart ); 5462 DO_FLOW( lineStart );
5716 } 5463 }
5717 lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, w - x ); 5464 lineStart = formatLine( parag, string, lineStart, firstChar, c-1, align, SPACE(w - x) );
5718 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5465 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5719 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5466 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5720 if ( parag->isNewLinesAllowed() && c->c == '\t' ) { 5467 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling
5721 int nx = parag->nextTab( i, x - left ) + left; 5468 int nx = parag->nextTab( i, x - left ) + left;
5722 if ( nx < x ) 5469 if ( nx < x )
5723 ww = w - x; 5470 ww = w - x;
5724 else 5471 else
5725 ww = nx - x; 5472 ww = nx - x;
5726 } 5473 }
5727 curLeft = x; 5474 curLeft = x;
5728 y += h; 5475 y += QMAX( h, linespacing );
5729 tmph = c->height() + linespace; 5476 tmph = c->height();
5730 h = 0; 5477 h = 0;
5731 lineStart->y = y; 5478 lineStart->y = y;
5732 insertLineStart( parag, i, lineStart ); 5479 insertLineStart( parag, i, lineStart );
5733 lineStart->baseLine = c->ascent(); 5480 lineStart->baseLine = c->ascent();
5734 lineStart->h = c->height(); 5481 lineStart->h = c->height();
5735 c->lineStart = 1; 5482 c->lineStart = 1;
5736 firstChar = c; 5483 firstChar = c;
5737 tmpBaseLine = lineStart->baseLine; 5484 tmpBaseLine = lineStart->baseLine;
5738 lastBreak = -1; 5485 lastBreak = -1;
5739 col = 0; 5486 col = 0;
5740 } else { 5487 } else { // ... otherwise if we had a breakable char, break there
5741 DO_FLOW( lineStart ); 5488 DO_FLOW( lineStart );
5742 i = lastBreak; 5489 i = lastBreak;
5743 lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ), align, w - string->at( i ).x ); 5490 lineStart = formatLine( parag, string, lineStart, firstChar, parag->at( lastBreak ),align, SPACE(w - string->at( i ).x) );
5744 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left; 5491 x = doc ? doc->flow()->adjustLMargin( y + parag->rect().y(), parag->rect().height(), left, 4 ) : left;
5745 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 ); 5492 w = dw - ( doc ? doc->flow()->adjustRMargin( y + parag->rect().y(), parag->rect().height(), rm, 4 ) : 0 );
5746 if ( parag->isNewLinesAllowed() && c->c == '\t' ) { 5493 if ( !doc && c->c == '\t' ) { // qt_format_text tab handling
5747 int nx = parag->nextTab( i, x - left ) + left; 5494 int nx = parag->nextTab( i, x - left ) + left;
5748 if ( nx < x ) 5495 if ( nx < x )
5749 ww = w - x; 5496 ww = w - x;
5750 else 5497 else
5751 ww = nx - x; 5498 ww = nx - x;
5752 } 5499 }
5753 curLeft = x; 5500 curLeft = x;
5754 y += h; 5501 y += QMAX( h, linespacing );
5755 tmph = c->height() + linespace; 5502 tmph = c->height();
5756 h = tmph; 5503 h = tmph;
5757 lineStart->y = y; 5504 lineStart->y = y;
5758 insertLineStart( parag, i + 1, lineStart ); 5505 insertLineStart( parag, i + 1, lineStart );
5759 lineStart->baseLine = c->ascent(); 5506 lineStart->baseLine = c->ascent();
5760 lineStart->h = c->height(); 5507 lineStart->h = c->height();
5761 c->lineStart = 1; 5508 c->lineStart = 1;
5762 firstChar = c; 5509 firstChar = c;
5763 tmpBaseLine = lineStart->baseLine; 5510 tmpBaseLine = lineStart->baseLine;
5764 lastBreak = -1; 5511 lastBreak = -1;
5765 col = 0; 5512 col = 0;
5766 tminw = marg; 5513 tminw = marg;
5767 continue; 5514 continue;
5768 } 5515 }
5769 } else if ( lineStart && ( isBreakable( string, i ) || parag->isNewLinesAllowed() && c->c == '\n' ) ) { 5516 } else if ( lineStart && isBreakable( string, i ) ) {
5770 if ( len <= 2 || i < len - 1 ) { 5517 if ( len <= 2 || i < len - 1 ) {
5771 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); 5518 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() );
5772 tmph = QMAX( tmph, c->height() + linespace ); 5519 tmph = QMAX( tmph, c->height() );
5773 } 5520 }
5774 minw = QMAX( minw, tminw ); 5521 minw = QMAX( minw, tminw );
5775 tminw = marg + ww; 5522 tminw = marg + ww;
5776 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5523 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5777 h = QMAX( h, tmph ); 5524 h = QMAX( h, tmph );
5778 lineStart->h = h; 5525 lineStart->h = h;
5779 if ( i < len - 2 || c->c != ' ' ) 5526 if ( i < len - 2 || c->c != ' ' )
5780 lastBreak = i; 5527 lastBreak = i;
5781 } else { 5528 } else {
5782 tminw += ww; 5529 tminw += ww;
5783 int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height() + linespace - c->ascent() ); 5530 int belowBaseLine = QMAX( tmph - tmpBaseLine, c->height()- c->ascent() );
5784 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() ); 5531 tmpBaseLine = QMAX( tmpBaseLine, c->ascent() );
5785 tmph = tmpBaseLine + belowBaseLine; 5532 tmph = tmpBaseLine + belowBaseLine;
5786 } 5533 }
5787 5534
5788 c->x = x; 5535 c->x = x;
5789 x += ww; 5536 x += ww;
5790 wused = QMAX( wused, x ); 5537 wused = QMAX( wused, x );
5791 } 5538 }
5792 5539
5793 // ### hack. The last char in the paragraph is always invisible, and somehow sometimes has a wrong format. It changes between 5540 // ### hack. The last char in the paragraph is always invisible,
5794 // layouting and printing. This corrects some layouting errors in BiDi mode due to this. 5541 // ### and somehow sometimes has a wrong format. It changes
5542 // ### between // layouting and printing. This corrects some
5543 // ### layouting errors in BiDi mode due to this.
5795 if ( len > 1 && !c->isAnchor() ) { 5544 if ( len > 1 && !c->isAnchor() ) {
5796 c->format()->removeRef(); 5545 c->format()->removeRef();
5797 c->setFormat( string->at( len - 2 ).format() ); 5546 c->setFormat( string->at( len - 2 ).format() );
5798 c->format()->addRef(); 5547 c->format()->addRef();
5799 } 5548 }
5800 5549
5801 if ( lineStart ) { 5550 if ( lineStart ) {
5802 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine ); 5551 lineStart->baseLine = QMAX( lineStart->baseLine, tmpBaseLine );
5803 h = QMAX( h, tmph ); 5552 h = QMAX( h, tmph );
5804 lineStart->h = h; 5553 lineStart->h = h;
5805 // last line in a paragraph is not justified 5554 // last line in a paragraph is not justified
5806 if ( align == Qt3::AlignJustify ) 5555 if ( align == Qt3::AlignJustify || lastChr == QChar_linesep )
5807 align = Qt3::AlignAuto; 5556 align = Qt3::AlignAuto;
5808 DO_FLOW( lineStart ); 5557 DO_FLOW( lineStart );
5809 lineStart = formatLine( parag, string, lineStart, firstChar, c, align, w - x ); 5558 lineStart = formatLine( parag, string, lineStart, firstChar, c, align, SPACE(w - x) );
5810 delete lineStart; 5559 delete lineStart;
5811 } 5560 }
5812 5561
5813 minw = QMAX( minw, tminw ); 5562 minw = QMAX( minw, tminw );
5563 if ( doc )
5564 minw += doc->rightMargin();
5814 5565
5815 int m = parag->bottomMargin(); 5566 int m = parag->bottomMargin();
5816 if ( parag->next() && doc && !doc->addMargins() ) 5567 if ( !parag->next() )
5817 m = QMAX( m, parag->next()->topMargin() );
5818 parag->setFullWidth( fullWidth );
5819 if ( parag->next() && parag->next()->isLineBreak() )
5820 m = 0; 5568 m = 0;
5821 y += h + m; 5569 else
5570 m = QMAX(m, parag->next()->topMargin() ) / 2;
5571 parag->setFullWidth( fullWidth );
5572 y += QMAX( h, linespacing ) + m;
5822 5573
5823 wused += rm; 5574 wused += rm;
5824 if ( !wrapEnabled || wrapAtColumn() != -1 ) 5575 if ( !wrapEnabled || wrapAtColumn() != -1 )
5825 minw = QMAX(minw, wused); 5576 minw = QMAX(minw, wused);
5577
5578 // This is the case where we are breaking wherever we darn well please
5579 // in cases like that, the minw should not be the length of the entire
5580 // word, because we necessarily want to show the word on the whole line.
5581 // example: word wrap in iconview
5582 if ( allowBreakInWords() && minw > wused )
5583 minw = wused;
5584
5826 thisminw = minw; 5585 thisminw = minw;
5827 thiswused = wused; 5586 thiswused = wused;
5828 return y; 5587 return y;
5829} 5588}
5830 5589
5831// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5590// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5832 5591
5833QTextIndent::QTextIndent() 5592QTextIndent::QTextIndent()
5834{ 5593{
5835} 5594}
5836 5595
5837// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5596// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5838 5597
5839QTextFormatCollection::QTextFormatCollection() 5598QTextFormatCollection::QTextFormatCollection()
5840 : cKey( 307 ), sheet( 0 ) 5599 : cKey( 307 )
5841{ 5600{
5842 defFormat = new QTextFormat( QApplication::font(), 5601 defFormat = new QTextFormat( QApplication::font(),
5843 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) ); 5602 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) );
5844 lastFormat = cres = 0; 5603 lastFormat = cres = 0;
5845 cflags = -1; 5604 cflags = -1;
5846 cKey.setAutoDelete( TRUE ); 5605 cKey.setAutoDelete( TRUE );
5847 cachedFormat = 0; 5606 cachedFormat = 0;
5848} 5607}
5849 5608
5850QTextFormatCollection::~QTextFormatCollection() 5609QTextFormatCollection::~QTextFormatCollection()
5851{ 5610{
5852 delete defFormat; 5611 delete defFormat;
5853} 5612}
5854 5613
5855QTextFormat *QTextFormatCollection::format( QTextFormat *f ) 5614QTextFormat *QTextFormatCollection::format( QTextFormat *f )
5856{ 5615{
5857 if ( f->parent() == this || f == defFormat ) { 5616 if ( f->parent() == this || f == defFormat ) {
5858#ifdef DEBUG_COLLECTION
5859 qDebug( "need '%s', best case!", f->key().latin1() );
5860#endif
5861 lastFormat = f; 5617 lastFormat = f;
5862 lastFormat->addRef(); 5618 lastFormat->addRef();
5863 return lastFormat; 5619 return lastFormat;
5864 } 5620 }
5865 5621
5866 if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) { 5622 if ( f == lastFormat || ( lastFormat && f->key() == lastFormat->key() ) ) {
5867#ifdef DEBUG_COLLECTION
5868 qDebug( "need '%s', good case!", f->key().latin1() );
5869#endif
5870 lastFormat->addRef(); 5623 lastFormat->addRef();
5871 return lastFormat; 5624 return lastFormat;
5872 } 5625 }
5873 5626
5874 QTextFormat *fm = cKey.find( f->key() ); 5627 QTextFormat *fm = cKey.find( f->key() );
5875 if ( fm ) { 5628 if ( fm ) {
5876#ifdef DEBUG_COLLECTION
5877 qDebug( "need '%s', normal case!", f->key().latin1() );
5878#endif
5879 lastFormat = fm; 5629 lastFormat = fm;
5880 lastFormat->addRef(); 5630 lastFormat->addRef();
5881 return lastFormat; 5631 return lastFormat;
5882 } 5632 }
5883 5633
5884 if ( f->key() == defFormat->key() ) 5634 if ( f->key() == defFormat->key() )
5885 return defFormat; 5635 return defFormat;
5886 5636
5887#ifdef DEBUG_COLLECTION
5888 qDebug( "need '%s', worst case!", f->key().latin1() );
5889#endif
5890 lastFormat = createFormat( *f ); 5637 lastFormat = createFormat( *f );
5891 lastFormat->collection = this; 5638 lastFormat->collection = this;
5892 cKey.insert( lastFormat->key(), lastFormat ); 5639 cKey.insert( lastFormat->key(), lastFormat );
5893 return lastFormat; 5640 return lastFormat;
5894} 5641}
5895 5642
5896QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, int flags ) 5643QTextFormat *QTextFormatCollection::format( QTextFormat *of, QTextFormat *nf, int flags )
5897{ 5644{
5898 if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) { 5645 if ( cres && kof == of->key() && knf == nf->key() && cflags == flags ) {
5899#ifdef DEBUG_COLLECTION
5900 qDebug( "mix of '%s' and '%s, best case!", of->key().latin1(), nf->key().latin1() );
5901#endif
5902 cres->addRef(); 5646 cres->addRef();
5903 return cres; 5647 return cres;
5904 } 5648 }
5905 5649
5906 cres = createFormat( *of ); 5650 cres = createFormat( *of );
5907 kof = of->key(); 5651 kof = of->key();
5908 knf = nf->key(); 5652 knf = nf->key();
5909 cflags = flags; 5653 cflags = flags;
5910 if ( flags & QTextFormat::Bold ) 5654 if ( flags & QTextFormat::Bold )
5911 cres->fn.setBold( nf->fn.bold() ); 5655 cres->fn.setBold( nf->fn.bold() );
5912 if ( flags & QTextFormat::Italic ) 5656 if ( flags & QTextFormat::Italic )
5913 cres->fn.setItalic( nf->fn.italic() ); 5657 cres->fn.setItalic( nf->fn.italic() );
5914 if ( flags & QTextFormat::Underline ) 5658 if ( flags & QTextFormat::Underline )
5915 cres->fn.setUnderline( nf->fn.underline() ); 5659 cres->fn.setUnderline( nf->fn.underline() );
5660 if ( flags & QTextFormat::StrikeOut )
5661 cres->fn.setStrikeOut( nf->fn.strikeOut() );
5916 if ( flags & QTextFormat::Family ) 5662 if ( flags & QTextFormat::Family )
5917 cres->fn.setFamily( nf->fn.family() ); 5663 cres->fn.setFamily( nf->fn.family() );
5918 if ( flags & QTextFormat::Size ) { 5664 if ( flags & QTextFormat::Size ) {
5919 if ( of->usePixelSizes ) 5665 if ( of->usePixelSizes )
5920 cres->fn.setPixelSize( nf->fn.pixelSize() ); 5666 cres->fn.setPixelSize( nf->fn.pixelSize() );
5921 else 5667 else
5922 cres->fn.setPointSize( nf->fn.pointSize() ); 5668 cres->fn.setPointSize( nf->fn.pointSize() );
5923 } 5669 }
5924 if ( flags & QTextFormat::Color ) 5670 if ( flags & QTextFormat::Color )
5925 cres->col = nf->col; 5671 cres->col = nf->col;
5926 if ( flags & QTextFormat::Misspelled ) 5672 if ( flags & QTextFormat::Misspelled )
5927 cres->missp = nf->missp; 5673 cres->missp = nf->missp;
5928 if ( flags & QTextFormat::VAlign ) 5674 if ( flags & QTextFormat::VAlign )
5929 cres->ha = nf->ha; 5675 cres->ha = nf->ha;
5930 cres->update(); 5676 cres->update();
5931 5677
5932 QTextFormat *fm = cKey.find( cres->key() ); 5678 QTextFormat *fm = cKey.find( cres->key() );
5933 if ( !fm ) { 5679 if ( !fm ) {
5934#ifdef DEBUG_COLLECTION
5935 qDebug( "mix of '%s' and '%s, worst case!", of->key().latin1(), nf->key().latin1() );
5936#endif
5937 cres->collection = this; 5680 cres->collection = this;
5938 cKey.insert( cres->key(), cres ); 5681 cKey.insert( cres->key(), cres );
5939 } else { 5682 } else {
5940#ifdef DEBUG_COLLECTION
5941 qDebug( "mix of '%s' and '%s, good case!", of->key().latin1(), nf->key().latin1() );
5942#endif
5943 delete cres; 5683 delete cres;
5944 cres = fm; 5684 cres = fm;
5945 cres->addRef(); 5685 cres->addRef();
5946 } 5686 }
5947 5687
5948 return cres; 5688 return cres;
5949} 5689}
5950 5690
5951QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c ) 5691QTextFormat *QTextFormatCollection::format( const QFont &f, const QColor &c )
5952{ 5692{
5953 if ( cachedFormat && cfont == f && ccol == c ) { 5693 if ( cachedFormat && cfont == f && ccol == c ) {
5954#ifdef DEBUG_COLLECTION
5955 qDebug( "format of font and col '%s' - best case", cachedFormat->key().latin1() );
5956#endif
5957 cachedFormat->addRef(); 5694 cachedFormat->addRef();
5958 return cachedFormat; 5695 return cachedFormat;
5959 } 5696 }
5960 5697
5961 QString key = QTextFormat::getKey( f, c, FALSE, QTextFormat::AlignNormal ); 5698 QString key = QTextFormat::getKey( f, c, FALSE, QTextFormat::AlignNormal );
5962 cachedFormat = cKey.find( key ); 5699 cachedFormat = cKey.find( key );
5963 cfont = f; 5700 cfont = f;
5964 ccol = c; 5701 ccol = c;
5965 5702
5966 if ( cachedFormat ) { 5703 if ( cachedFormat ) {
5967#ifdef DEBUG_COLLECTION
5968 qDebug( "format of font and col '%s' - good case", cachedFormat->key().latin1() );
5969#endif
5970 cachedFormat->addRef(); 5704 cachedFormat->addRef();
5971 return cachedFormat; 5705 return cachedFormat;
5972 } 5706 }
5973 5707
5974 if ( key == defFormat->key() ) 5708 if ( key == defFormat->key() )
5975 return defFormat; 5709 return defFormat;
5976 5710
5977 cachedFormat = createFormat( f, c ); 5711 cachedFormat = createFormat( f, c );
5978 cachedFormat->collection = this; 5712 cachedFormat->collection = this;
5979 cKey.insert( cachedFormat->key(), cachedFormat ); 5713 cKey.insert( cachedFormat->key(), cachedFormat );
5980 if ( cachedFormat->key() != key ) 5714 if ( cachedFormat->key() != key )
5981 qWarning("ASSERT: keys for format not identical: '%s '%s'", cachedFormat->key().latin1(), key.latin1() ); 5715 qWarning("ASSERT: keys for format not identical: '%s '%s'", cachedFormat->key().latin1(), key.latin1() );
5982#ifdef DEBUG_COLLECTION
5983 qDebug( "format of font and col '%s' - worst case", cachedFormat->key().latin1() );
5984#endif
5985 return cachedFormat; 5716 return cachedFormat;
5986} 5717}
5987 5718
5988void QTextFormatCollection::remove( QTextFormat *f ) 5719void QTextFormatCollection::remove( QTextFormat *f )
5989{ 5720{
5990 if ( lastFormat == f ) 5721 if ( lastFormat == f )
5991 lastFormat = 0; 5722 lastFormat = 0;
5992 if ( cres == f ) 5723 if ( cres == f )
5993 cres = 0; 5724 cres = 0;
5994 if ( cachedFormat == f ) 5725 if ( cachedFormat == f )
5995 cachedFormat = 0; 5726 cachedFormat = 0;
5996 cKey.remove( f->key() ); 5727 cKey.remove( f->key() );
5997} 5728}
5998 5729
5999void QTextFormatCollection::debug() 5730#define UPDATE( up, lo, rest ) \
6000{ 5731 if ( font.lo##rest() != defFormat->fn.lo##rest() && fm->fn.lo##rest() == defFormat->fn.lo##rest() ) \
6001#ifdef DEBUG_COLLECTION 5732 fm->fn.set##up##rest( font.lo##rest() )
6002 qDebug( "------------ QTextFormatCollection: debug --------------- BEGIN" );
6003 QDictIterator<QTextFormat> it( cKey );
6004 for ( ; it.current(); ++it ) {
6005 qDebug( "format '%s' (%p): refcount: %d", it.current()->key().latin1(),
6006 it.current(), it.current()->ref );
6007 }
6008 qDebug( "------------ QTextFormatCollection: debug --------------- END" );
6009#endif
6010}
6011
6012void QTextFormatCollection::updateStyles()
6013{
6014 QDictIterator<QTextFormat> it( cKey );
6015 QTextFormat *f;
6016 while ( ( f = it.current() ) ) {
6017 ++it;
6018 f->updateStyle();
6019 }
6020 updateKeys();
6021}
6022
6023void QTextFormatCollection::updateFontSizes( int base, bool usePixels )
6024{
6025 QDictIterator<QTextFormat> it( cKey );
6026 QTextFormat *f;
6027 while ( ( f = it.current() ) ) {
6028 ++it;
6029 f->stdSize = base;
6030 f->usePixelSizes = usePixels;
6031 if ( usePixels )
6032 f->fn.setPixelSize( f->stdSize );
6033 else
6034 f->fn.setPointSize( f->stdSize );
6035 styleSheet()->scaleFont( f->fn, f->logicalFontSize );
6036 f->update();
6037 }
6038 f = defFormat;
6039 f->stdSize = base;
6040 f->usePixelSizes = usePixels;
6041 if ( usePixels )
6042 f->fn.setPixelSize( f->stdSize );
6043 else
6044 f->fn.setPointSize( f->stdSize );
6045 styleSheet()->scaleFont( f->fn, f->logicalFontSize );
6046 f->update();
6047 updateKeys();
6048}
6049 5733
6050void QTextFormatCollection::updateFontAttributes( const QFont &f, const QFont &old ) 5734void QTextFormatCollection::updateDefaultFormat( const QFont &font, const QColor &color, QStyleSheet *sheet )
6051{ 5735{
6052 QDictIterator<QTextFormat> it( cKey ); 5736 QDictIterator<QTextFormat> it( cKey );
6053 QTextFormat *fm; 5737 QTextFormat *fm;
5738 bool usePixels = font.pointSize() == -1;
5739 bool changeSize = usePixels ? font.pixelSize() != defFormat->fn.pixelSize() :
5740 font.pointSize() != defFormat->fn.pointSize();
5741 int base = usePixels ? font.pixelSize() : font.pointSize();
6054 while ( ( fm = it.current() ) ) { 5742 while ( ( fm = it.current() ) ) {
6055 ++it; 5743 ++it;
6056 if ( fm->fn.family() == old.family() && 5744 UPDATE( F, f, amily );
6057 fm->fn.weight() == old.weight() && 5745 UPDATE( W, w, eight );
6058 fm->fn.italic() == old.italic() && 5746 UPDATE( B, b, old );
6059 fm->fn.underline() == old.underline() ) { 5747 UPDATE( I, i, talic );
6060 fm->fn.setFamily( f.family() ); 5748 UPDATE( U, u, nderline );
6061 fm->fn.setWeight( f.weight() ); 5749 if ( changeSize ) {
6062 fm->fn.setItalic( f.italic() ); 5750 fm->stdSize = base;
6063 fm->fn.setUnderline( f.underline() ); 5751 fm->usePixelSizes = usePixels;
6064 fm->update(); 5752 if ( usePixels )
6065 } 5753 fm->fn.setPixelSize( fm->stdSize );
6066 } 5754 else
6067 fm = defFormat; 5755 fm->fn.setPointSize( fm->stdSize );
6068 if ( fm->fn.family() == old.family() && 5756 sheet->scaleFont( fm->fn, fm->logicalFontSize );
6069 fm->fn.weight() == old.weight() && 5757 }
6070 fm->fn.italic() == old.italic() && 5758 if ( color.isValid() && color != defFormat->col && fm->col == defFormat->col )
6071 fm->fn.underline() == old.underline() ) { 5759 fm->col = color;
6072 fm->fn.setFamily( f.family() );
6073 fm->fn.setWeight( f.weight() );
6074 fm->fn.setItalic( f.italic() );
6075 fm->fn.setUnderline( f.underline() );
6076 fm->update(); 5760 fm->update();
6077 } 5761 }
5762
5763 defFormat->fn = font;
5764 defFormat->col = color;
5765 defFormat->update();
5766 defFormat->stdSize = base;
5767 defFormat->usePixelSizes = usePixels;
5768
6078 updateKeys(); 5769 updateKeys();
6079} 5770}
6080 5771
6081
6082// the keys in cKey have changed, rebuild the hashtable 5772// the keys in cKey have changed, rebuild the hashtable
6083void QTextFormatCollection::updateKeys() 5773void QTextFormatCollection::updateKeys()
6084{ 5774{
6085 if ( cKey.isEmpty() ) 5775 if ( cKey.isEmpty() )
6086 return; 5776 return;
6087 cKey.setAutoDelete( FALSE ); 5777 cKey.setAutoDelete( FALSE );
6088 QTextFormat** formats = new QTextFormat*[ cKey.count() + 1]; 5778 QTextFormat** formats = new QTextFormat*[ cKey.count() + 1 ];
6089 QTextFormat **f = formats; 5779 QTextFormat **f = formats;
6090 QDictIterator<QTextFormat> it( cKey ); 5780 QDictIterator<QTextFormat> it( cKey );
6091 while ( ( *f = it.current() ) ) { 5781 while ( ( *f = it.current() ) ) {
6092 ++it; 5782 ++it;
6093 ++f; 5783 ++f;
6094 } 5784 }
6095 cKey.clear(); 5785 cKey.clear();
6096 for ( f = formats; *f; f++ ) 5786 for ( f = formats; *f; f++ )
6097 cKey.insert( (*f)->key(), *f ); 5787 cKey.insert( (*f)->key(), *f );
6098 cKey.setAutoDelete( TRUE ); 5788 cKey.setAutoDelete( TRUE );
5789 delete [] formats;
6099} 5790}
6100 5791
6101 5792
6102 5793
6103// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5794// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6104 5795
6105void QTextFormat::setBold( bool b ) 5796void QTextFormat::setBold( bool b )
6106{ 5797{
6107 if ( b == fn.bold() ) 5798 if ( b == fn.bold() )
6108 return; 5799 return;
6109 fn.setBold( b ); 5800 fn.setBold( b );
6110 update(); 5801 update();
6111} 5802}
6112 5803
6113void QTextFormat::setMisspelled( bool b ) 5804void QTextFormat::setMisspelled( bool b )
6114{ 5805{
6115 if ( b == (bool)missp ) 5806 if ( b == (bool)missp )
6116 return; 5807 return;
6117 missp = b; 5808 missp = b;
6118 update(); 5809 update();
6119} 5810}
6120 5811
6121void QTextFormat::setVAlign( VerticalAlignment a ) 5812void QTextFormat::setVAlign( VerticalAlignment a )
6122{ 5813{
6123 if ( a == ha ) 5814 if ( a == ha )
6124 return; 5815 return;
6125 ha = a; 5816 ha = a;
6126 update(); 5817 update();
6127} 5818}
6128 5819
6129void QTextFormat::setItalic( bool b ) 5820void QTextFormat::setItalic( bool b )
6130{ 5821{
6131 if ( b == fn.italic() ) 5822 if ( b == fn.italic() )
6132 return; 5823 return;
6133 fn.setItalic( b ); 5824 fn.setItalic( b );
6134 update(); 5825 update();
6135} 5826}
6136 5827
6137void QTextFormat::setUnderline( bool b ) 5828void QTextFormat::setUnderline( bool b )
6138{ 5829{
6139 if ( b == fn.underline() ) 5830 if ( b == fn.underline() )
6140 return; 5831 return;
6141 fn.setUnderline( b ); 5832 fn.setUnderline( b );
6142 update(); 5833 update();
6143} 5834}
6144 5835
5836void QTextFormat::setStrikeOut( bool b )
5837{
5838 if ( b == fn.strikeOut() )
5839 return;
5840 fn.setStrikeOut( b );
5841 update();
5842}
5843
6145void QTextFormat::setFamily( const QString &f ) 5844void QTextFormat::setFamily( const QString &f )
6146{ 5845{
6147 if ( f == fn.family() ) 5846 if ( f == fn.family() )
6148 return; 5847 return;
6149 fn.setFamily( f ); 5848 fn.setFamily( f );
6150 update(); 5849 update();
6151} 5850}
6152 5851
6153void QTextFormat::setPointSize( int s ) 5852void QTextFormat::setPointSize( int s )
6154{ 5853{
6155 if ( s == fn.pointSize() ) 5854 if ( s == fn.pointSize() )
6156 return; 5855 return;
6157 fn.setPointSize( s ); 5856 fn.setPointSize( s );
6158 usePixelSizes = FALSE; 5857 usePixelSizes = FALSE;
6159 update(); 5858 update();
6160} 5859}
6161 5860
6162void QTextFormat::setFont( const QFont &f ) 5861void QTextFormat::setFont( const QFont &f )
6163{ 5862{
6164 if ( f == fn && !k.isEmpty() ) 5863 if ( f == fn && !k.isEmpty() )
6165 return; 5864 return;
6166 fn = f; 5865 fn = f;
6167 update(); 5866 update();
6168} 5867}
6169 5868
6170void QTextFormat::setColor( const QColor &c ) 5869void QTextFormat::setColor( const QColor &c )
6171{ 5870{
6172 if ( c == col ) 5871 if ( c == col )
6173 return; 5872 return;
6174 col = c; 5873 col = c;
6175 update(); 5874 update();
6176} 5875}
6177 5876
6178static int makeLogicFontSize( int s ) 5877QString QTextFormat::makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f,
6179{ 5878 const QString& oldAnchorHref, const QString& anchorHref ) const
6180 int defSize = QApplication::font().pointSize();
6181 if ( s < defSize - 4 )
6182 return 1;
6183 if ( s < defSize )
6184 return 2;
6185 if ( s < defSize + 4 )
6186 return 3;
6187 if ( s < defSize + 8 )
6188 return 4;
6189 if ( s < defSize + 12 )
6190 return 5;
6191 if (s < defSize + 16 )
6192 return 6;
6193 return 7;
6194}
6195
6196static QTextFormat *defaultFormat = 0;
6197
6198QString QTextFormat::makeFormatChangeTags( QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const
6199{ 5879{
6200 if ( !defaultFormat ) // #### wrong, use the document's default format instead
6201 defaultFormat = new QTextFormat( QApplication::font(),
6202 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) );
6203
6204 QString tag; 5880 QString tag;
6205 if ( f ) { 5881 if ( f )
6206 if ( f->font() != defaultFormat->font() ) { 5882 tag += f->makeFormatEndTags( defaultFormat, oldAnchorHref );
6207 if ( f->font().family() != defaultFormat->font().family()
6208 || f->font().pointSize() != defaultFormat->font().pointSize()
6209 || f->color().rgb() != defaultFormat->color().rgb() )
6210 tag += "</font>";
6211 if ( f->font().underline() && f->font().underline() != defaultFormat->font().underline() )
6212 tag += "</u>";
6213 if ( f->font().italic() && f->font().italic() != defaultFormat->font().italic() )
6214 tag += "</i>";
6215 if ( f->font().bold() && f->font().bold() != defaultFormat->font().bold() )
6216 tag += "</b>";
6217 }
6218 if ( !oldAnchorHref.isEmpty() )
6219 tag += "</a>";
6220 }
6221 5883
6222 if ( !anchorHref.isEmpty() ) 5884 if ( !anchorHref.isEmpty() )
6223 tag += "<a href=\"" + anchorHref + "\">"; 5885 tag += "<a href=\"" + anchorHref + "\">";
6224 5886
6225 if ( font() != defaultFormat->font() ) {
6226 if ( font().bold() && font().bold() != defaultFormat->font().bold() )
6227 tag += "<b>";
6228 if ( font().italic() && font().italic() != defaultFormat->font().italic() )
6229 tag += "<i>";
6230 if ( font().underline() && font().underline() != defaultFormat->font().underline() )
6231 tag += "<u>";
6232 }
6233 if ( font() != defaultFormat->font() 5887 if ( font() != defaultFormat->font()
5888 || vAlign() != defaultFormat->vAlign()
6234 || color().rgb() != defaultFormat->color().rgb() ) { 5889 || color().rgb() != defaultFormat->color().rgb() ) {
6235 QString f; 5890 QString s;
6236 if ( font().family() != defaultFormat->font().family() ) 5891 if ( font().family() != defaultFormat->font().family() )
6237 f +=" face=\"" + fn.family() + "\""; 5892 s += QString(!!s?";":"") + "font-family:" + fn.family();
6238 if ( font().pointSize() != defaultFormat->font().pointSize() ) { 5893 if ( font().italic() && font().italic() != defaultFormat->font().italic() )
6239 f +=" size=\"" + QString::number( makeLogicFontSize( fn.pointSize() ) ) + "\""; 5894 s += QString(!!s?";":"") + "font-style:" + (font().italic() ? "italic" : "normal");
6240 f +=" style=\"font-size:" + QString::number( fn.pointSize() ) + "pt\""; 5895 if ( font().pointSize() != defaultFormat->font().pointSize() )
5896 s += QString(!!s?";":"") + "font-size:" + QString::number( fn.pointSize() ) + "pt";
5897 if ( font().weight() != defaultFormat->font().weight() )
5898 s += QString(!!s?";":"") + "font-weight:" + QString::number( fn.weight() * 8 );
5899 if ( font().underline() != defaultFormat->font().underline() )
5900 s += QString(!!s?";":"") + "text-decoration:" + ( font().underline() ? "underline" : "none");
5901 if ( vAlign() != defaultFormat->vAlign() ) {
5902 s += QString(!!s?";":"") + "vertical-align:";
5903 if ( vAlign() == QTextFormat::AlignSuperScript )
5904 s += "super";
5905 else if ( vAlign() == QTextFormat::AlignSubScript )
5906 s += "sub";
5907 else
5908 s += "normal";
6241 } 5909 }
6242 if ( color().rgb() != defaultFormat->color().rgb() ) 5910 if ( color().rgb() != defaultFormat->color().rgb() )
6243 f +=" color=\"" + col.name() + "\""; 5911 s += QString(!!s?";":"") + "color:" + col.name();
6244 if ( !f.isEmpty() ) 5912 if ( !s.isEmpty() )
6245 tag += "<font" + f + ">"; 5913 tag += "<span style=\"" + s + "\">";
6246 } 5914 }
6247 5915
6248 return tag; 5916 return tag;
6249} 5917}
6250 5918
6251QString QTextFormat::makeFormatEndTags( const QString& anchorHref ) const 5919QString QTextFormat::makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const
6252{ 5920{
6253 if ( !defaultFormat )
6254 defaultFormat = new QTextFormat( QApplication::font(),
6255 QApplication::palette().color( QPalette::Active, QColorGroup::Text ) );
6256
6257 QString tag; 5921 QString tag;
6258 if ( font() != defaultFormat->font() ) { 5922 if ( font().family() != defaultFormat->font().family()
6259 if ( font().family() != defaultFormat->font().family() 5923 || font().pointSize() != defaultFormat->font().pointSize()
6260 || font().pointSize() != defaultFormat->font().pointSize() 5924 || font().weight() != defaultFormat->font().weight()
6261 || color().rgb() != defaultFormat->color().rgb() ) 5925 || font().italic() != defaultFormat->font().italic()
6262 tag += "</font>"; 5926 || font().underline() != defaultFormat->font().underline()
6263 if ( font().underline() && font().underline() != defaultFormat->font().underline() ) 5927 || font().strikeOut() != defaultFormat->font().strikeOut()
6264 tag += "</u>"; 5928 || vAlign() != defaultFormat->vAlign()
6265 if ( font().italic() && font().italic() != defaultFormat->font().italic() ) 5929 || color().rgb() != defaultFormat->color().rgb() )
6266 tag += "</i>"; 5930 tag += "</span>";
6267 if ( font().bold() && font().bold() != defaultFormat->font().bold() )
6268 tag += "</b>";
6269 }
6270 if ( !anchorHref.isEmpty() ) 5931 if ( !anchorHref.isEmpty() )
6271 tag += "</a>"; 5932 tag += "</a>";
6272 return tag; 5933 return tag;
6273} 5934}
6274 5935
6275QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr ) const 5936QTextFormat QTextFormat::makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const
6276{ 5937{
6277 QTextFormat format(*this); 5938 QTextFormat format(*this);
6278 if ( style ) { 5939 if (!style )
6279 format.style = style->name(); 5940 return format;
6280 if ( style->name() == "font") { 5941
6281 if ( attr.contains("color") ) { 5942 if ( !style->isAnchor() && style->color().isValid() ) {
6282 QString s = attr["color"]; 5943 // the style is not an anchor and defines a color.
6283 if ( !s.isEmpty() ) { 5944 // It might be used inside an anchor and it should
6284 format.col.setNamedColor( s ); 5945 // override the link color.
6285 format.linkColor = FALSE; 5946 format.linkColor = FALSE;
6286 } 5947 }
6287 } 5948 switch ( style->verticalAlignment() ) {
6288 if ( attr.contains("size") ) { 5949 case QStyleSheetItem::VAlignBaseline:
6289 QString a = attr["size"]; 5950 format.setVAlign( QTextFormat::AlignNormal );
6290 int n = a.toInt(); 5951 break;
6291 if ( a[0] == '+' || a[0] == '-' ) 5952 case QStyleSheetItem::VAlignSuper:
6292 n += format.logicalFontSize; 5953 format.setVAlign( QTextFormat::AlignSuperScript );
6293 format.logicalFontSize = n; 5954 break;
6294 if ( format.usePixelSizes ) 5955 case QStyleSheetItem::VAlignSub:
6295 format.fn.setPixelSize( format.stdSize ); 5956 format.setVAlign( QTextFormat::AlignSubScript );
6296 else 5957 break;
6297 format.fn.setPointSize( format.stdSize ); 5958 }
6298 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 5959
6299 } 5960 if ( style->fontWeight() != QStyleSheetItem::Undefined )
6300 if ( attr.contains("style" ) ) { 5961 format.fn.setWeight( style->fontWeight() );
6301 QString a = attr["style"]; 5962 if ( style->fontSize() != QStyleSheetItem::Undefined ) {
6302 if ( a.startsWith( "font-size:" ) ) { 5963 format.fn.setPointSize( style->fontSize() );
6303 QString s = a.mid( a.find( ':' ) + 1 ); 5964 } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) {
6304 int n = s.left( s.length() - 2 ).toInt(); 5965 format.logicalFontSize = style->logicalFontSize();
6305 format.logicalFontSize = 0; 5966 if ( format.usePixelSizes )
6306 if ( format.usePixelSizes ) 5967 format.fn.setPixelSize( format.stdSize );
6307 format.fn.setPixelSize( n ); 5968 else
6308 else 5969 format.fn.setPointSize( format.stdSize );
6309 format.fn.setPointSize( n ); 5970 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
6310 } 5971 } else if ( style->logicalFontSizeStep() ) {
6311 } 5972 format.logicalFontSize += style->logicalFontSizeStep();
6312 if ( attr.contains("face") ) { 5973 if ( format.usePixelSizes )
6313 QString a = attr["face"]; 5974 format.fn.setPixelSize( format.stdSize );
6314 if ( a.contains(',') ) 5975 else
6315 a = a.left( a.find(',') ); 5976 format.fn.setPointSize( format.stdSize );
6316 format.fn.setFamily( a ); 5977 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
6317 } 5978 }
6318 } else { 5979 if ( !style->fontFamily().isEmpty() )
6319 if ( !style->isAnchor() && style->color().isValid() ) { 5980 format.fn.setFamily( style->fontFamily() );
6320 // the style is not an anchor and defines a color. 5981 if ( style->color().isValid() )
6321 // It might be used inside an anchor and it should 5982 format.col = style->color();
6322 // override the link color. 5983 if ( style->definesFontItalic() )
5984 format.fn.setItalic( style->fontItalic() );
5985 if ( style->definesFontUnderline() )
5986 format.fn.setUnderline( style->fontUnderline() );
5987 if ( style->definesFontStrikeOut() )
5988 format.fn.setStrikeOut( style->fontStrikeOut() );
5989
5990
5991 if ( style->name() == "font") {
5992 if ( attr.contains("color") ) {
5993 QString s = attr["color"];
5994 if ( !s.isEmpty() ) {
5995 format.col.setNamedColor( s );
6323 format.linkColor = FALSE; 5996 format.linkColor = FALSE;
6324 } 5997 }
6325 switch ( style->verticalAlignment() ) { 5998 }
6326 case QStyleSheetItem::VAlignBaseline: 5999 if ( attr.contains("face") ) {
6327 format.setVAlign( QTextFormat::AlignNormal ); 6000 QString a = attr["face"];
6328 break; 6001 QString family = QTextDocument::section( a, ",", 0, 0 );
6329 case QStyleSheetItem::VAlignSuper: 6002 if ( !!family )
6330 format.setVAlign( QTextFormat::AlignSuperScript ); 6003 format.fn.setFamily( family );
6331 break; 6004 }
6332 case QStyleSheetItem::VAlignSub: 6005 if ( attr.contains("size") ) {
6333 format.setVAlign( QTextFormat::AlignSubScript ); 6006 QString a = attr["size"];
6334 break; 6007 int n = a.toInt();
6335 } 6008 if ( a[0] == '+' || a[0] == '-' )
6336 6009 n += format.logicalFontSize;
6337 if ( style->fontWeight() != QStyleSheetItem::Undefined ) 6010 format.logicalFontSize = n;
6338 format.fn.setWeight( style->fontWeight() ); 6011 if ( format.usePixelSizes )
6339 if ( style->fontSize() != QStyleSheetItem::Undefined ) { 6012 format.fn.setPixelSize( format.stdSize );
6340 format.fn.setPointSize( style->fontSize() ); 6013 else
6341 } else if ( style->logicalFontSize() != QStyleSheetItem::Undefined ) { 6014 format.fn.setPointSize( format.stdSize );
6342 format.logicalFontSize = style->logicalFontSize(); 6015 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize );
6343 if ( format.usePixelSizes ) 6016 }
6344 format.fn.setPixelSize( format.stdSize ); 6017 }
6345 else 6018 if ( attr.contains("style" ) ) {
6346 format.fn.setPointSize( format.stdSize ); 6019 QString a = attr["style"];
6347 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 6020 for ( int s = 0; s < a.contains(';')+1; s++ ) {
6348 } else if ( style->logicalFontSizeStep() ) { 6021 QString style = QTextDocument::section( a, ";", s, s );
6349 format.logicalFontSize += style->logicalFontSizeStep(); 6022 if ( style.startsWith("font-size:" ) && QTextDocument::endsWith(style, "pt") ) {
6350 if ( format.usePixelSizes ) 6023 format.logicalFontSize = 0;
6351 format.fn.setPixelSize( format.stdSize ); 6024 format.setPointSize( int( scaleFontsFactor * style.mid( 10, style.length() - 12 ).toInt() ) );
6025 } if ( style.startsWith("font-style:" ) ) {
6026 QString s = style.mid( 11 ).stripWhiteSpace();
6027 if ( s == "normal" )
6028 format.fn.setItalic( FALSE );
6029 else if ( s == "italic" || s == "oblique" )
6030 format.fn.setItalic( TRUE );
6031 } else if ( style.startsWith("font-weight:" ) ) {
6032 QString s = style.mid( 12 );
6033 bool ok = TRUE;
6034 int n = s.toInt( &ok );
6035 if ( ok )
6036 format.fn.setWeight( n/8 );
6037 } else if ( style.startsWith("font-family:" ) ) {
6038 format.fn.setFamily( QTextDocument::section(style.mid(12),",",0,0).stripWhiteSpace() );
6039 } else if ( style.startsWith("text-decoration:" ) ) {
6040 QString s = style.mid( 16 ).stripWhiteSpace();
6041 format.fn.setUnderline( s == "underline" );
6042 } else if ( style.startsWith("vertical-align:" ) ) {
6043 QString s = style.mid( 15 ).stripWhiteSpace();
6044 if ( s == "sub" )
6045 format.setVAlign( QTextFormat::AlignSubScript );
6046 else if ( s == "super" )
6047 format.setVAlign( QTextFormat::AlignSuperScript );
6352 else 6048 else
6353 format.fn.setPointSize( format.stdSize ); 6049 format.setVAlign( QTextFormat::AlignNormal );
6354 style->styleSheet()->scaleFont( format.fn, format.logicalFontSize ); 6050 } else if ( style.startsWith("color:" ) ) {
6051 format.col.setNamedColor( style.mid(6) );
6052 format.linkColor = FALSE;
6355 } 6053 }
6356 if ( !style->fontFamily().isEmpty() )
6357 format.fn.setFamily( style->fontFamily() );
6358 if ( style->color().isValid() )
6359 format.col = style->color();
6360 if ( style->definesFontItalic() )
6361 format.fn.setItalic( style->fontItalic() );
6362 if ( style->definesFontUnderline() )
6363 format.fn.setUnderline( style->fontUnderline() );
6364 } 6054 }
6365 } 6055 }
6366 6056
6367 format.update(); 6057 format.update();
6368 return format; 6058 return format;
6369} 6059}
6370 6060
6371struct QPixmapInt 6061struct QPixmapInt
6372{ 6062{
6373 QPixmapInt() : ref( 0 ) {} 6063 QPixmapInt() : ref( 0 ) {}
6374 QPixmap pm; 6064 QPixmap pm;
6375 int ref; 6065 int ref;
6376}; 6066};
6377 6067
6378static QMap<QString, QPixmapInt> *pixmap_map = 0; 6068static QMap<QString, QPixmapInt> *pixmap_map = 0;
6379 6069
6380QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, 6070QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context,
6381 QMimeSourceFactory &factory ) 6071 QMimeSourceFactory &factory )
6382 : QTextCustomItem( p ) 6072 : QTextCustomItem( p )
6383{ 6073{
6384#if defined(PARSER_DEBUG)
6385 qDebug( debug_indent + "new QTextImage (pappi: %p)", p );
6386#endif
6387
6388 width = height = 0; 6074 width = height = 0;
6389 if ( attr.contains("width") ) 6075 if ( attr.contains("width") )
6390 width = attr["width"].toInt(); 6076 width = attr["width"].toInt();
6391 if ( attr.contains("height") ) 6077 if ( attr.contains("height") )
6392 height = attr["height"].toInt(); 6078 height = attr["height"].toInt();
6393 6079
6394 reg = 0; 6080 reg = 0;
6395 QString imageName = attr["src"]; 6081 QString imageName = attr["src"];
6396 6082
6397 if (!imageName) 6083 if (!imageName)
6398 imageName = attr["source"]; 6084 imageName = attr["source"];
6399 6085
6400#if defined(PARSER_DEBUG)
6401 qDebug( debug_indent + " .." + imageName );
6402#endif
6403
6404 if ( !imageName.isEmpty() ) { 6086 if ( !imageName.isEmpty() ) {
6405 imgId = QString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory ); 6087 imgId = QString( "%1,%2,%3,%4" ).arg( imageName ).arg( width ).arg( height ).arg( (ulong)&factory );
6406 if ( !pixmap_map ) 6088 if ( !pixmap_map )
6407 pixmap_map = new QMap<QString, QPixmapInt>; 6089 pixmap_map = new QMap<QString, QPixmapInt>;
6408 if ( pixmap_map->contains( imgId ) ) { 6090 if ( pixmap_map->contains( imgId ) ) {
6409 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6091 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6410 pm = pmi.pm; 6092 pm = pmi.pm;
6411 pmi.ref++; 6093 pmi.ref++;
6412 width = pm.width(); 6094 width = pm.width();
6413 height = pm.height(); 6095 height = pm.height();
6414 } else { 6096 } else {
6415 QImage img; 6097 QImage img;
6416 const QMimeSource* m = 6098 const QMimeSource* m =
6417 factory.data( imageName, context ); 6099 factory.data( imageName, context );
6418 if ( !m ) { 6100 if ( !m ) {
6419 qWarning("QTextImage: no mimesource for %s", imageName.latin1() ); 6101 qWarning("QTextImage: no mimesource for %s", imageName.latin1() );
6420 } 6102 }
6421 else { 6103 else {
6422 if ( !QImageDrag::decode( m, img ) ) { 6104 if ( !QImageDrag::decode( m, img ) ) {
6423 qWarning("QTextImage: cannot decode %s", imageName.latin1() ); 6105 qWarning("QTextImage: cannot decode %s", imageName.latin1() );
6424 } 6106 }
6425 } 6107 }
6426 6108
6427 if ( !img.isNull() ) { 6109 if ( !img.isNull() ) {
6428 if ( width == 0 ) { 6110 if ( width == 0 ) {
6429 width = img.width(); 6111 width = img.width();
6430 if ( height != 0 ) { 6112 if ( height != 0 ) {
6431 width = img.width() * height / img.height(); 6113 width = img.width() * height / img.height();
6432 } 6114 }
6433 } 6115 }
6434 if ( height == 0 ) { 6116 if ( height == 0 ) {
6435 height = img.height(); 6117 height = img.height();
@@ -6458,64 +6140,65 @@ QTextImage::QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, co
6458 reg = new QRegion( all.subtract( mask ) ); 6140 reg = new QRegion( all.subtract( mask ) );
6459 } 6141 }
6460 } 6142 }
6461 6143
6462 if ( pm.isNull() && (width*height)==0 ) 6144 if ( pm.isNull() && (width*height)==0 )
6463 width = height = 50; 6145 width = height = 50;
6464 6146
6465 place = PlaceInline; 6147 place = PlaceInline;
6466 if ( attr["align"] == "left" ) 6148 if ( attr["align"] == "left" )
6467 place = PlaceLeft; 6149 place = PlaceLeft;
6468 else if ( attr["align"] == "right" ) 6150 else if ( attr["align"] == "right" )
6469 place = PlaceRight; 6151 place = PlaceRight;
6470 6152
6471 tmpwidth = width; 6153 tmpwidth = width;
6472 tmpheight = height; 6154 tmpheight = height;
6473 6155
6474 attributes = attr; 6156 attributes = attr;
6475} 6157}
6476 6158
6477QTextImage::~QTextImage() 6159QTextImage::~QTextImage()
6478{ 6160{
6479 if ( pixmap_map && pixmap_map->contains( imgId ) ) { 6161 if ( pixmap_map && pixmap_map->contains( imgId ) ) {
6480 QPixmapInt& pmi = pixmap_map->operator[](imgId); 6162 QPixmapInt& pmi = pixmap_map->operator[](imgId);
6481 pmi.ref--; 6163 pmi.ref--;
6482 if ( !pmi.ref ) { 6164 if ( !pmi.ref ) {
6483 pixmap_map->remove( imgId ); 6165 pixmap_map->remove( imgId );
6484 if ( pixmap_map->isEmpty() ) { 6166 if ( pixmap_map->isEmpty() ) {
6485 delete pixmap_map; 6167 delete pixmap_map;
6486 pixmap_map = 0; 6168 pixmap_map = 0;
6487 } 6169 }
6488 } 6170 }
6489 } 6171 }
6172 delete reg;
6490} 6173}
6491 6174
6492QString QTextImage::richText() const 6175QString QTextImage::richText() const
6493{ 6176{
6494 QString s; 6177 QString s;
6495 s += "<img "; 6178 s += "<img ";
6496 QMap<QString, QString>::ConstIterator it = attributes.begin(); 6179 QMap<QString, QString>::ConstIterator it = attributes.begin();
6497 for ( ; it != attributes.end(); ++it ) 6180 for ( ; it != attributes.end(); ++it )
6498 s += it.key() + "=" + *it + " "; 6181 s += it.key() + "=" + *it + " ";
6499 s += ">"; 6182 s += ">";
6500 return s; 6183 return s;
6501} 6184}
6502 6185
6503void QTextImage::adjustToPainter( QPainter* p ) 6186void QTextImage::adjustToPainter( QPainter* p )
6504{ 6187{
6505 width = scale( tmpwidth, p ); 6188 width = scale( tmpwidth, p );
6506 height = scale( tmpheight, p ); 6189 height = scale( tmpheight, p );
6507} 6190}
6508 6191
6509#if !defined(Q_WS_X11) 6192#if !defined(Q_WS_X11)
6510#include <qbitmap.h> 6193#include <qbitmap.h>
6511#include "qcleanuphandler.h" 6194#include "qcleanuphandler.h"
6512static QPixmap *qrt_selection = 0; 6195static QPixmap *qrt_selection = 0;
6513static QSingleCleanupHandler<QPixmap> qrt_cleanup_pixmap; 6196static QSingleCleanupHandler<QPixmap> qrt_cleanup_pixmap;
6514static void qrt_createSelectionPixmap( const QColorGroup &cg ) 6197static void qrt_createSelectionPixmap( const QColorGroup &cg )
6515{ 6198{
6516 qrt_selection = new QPixmap( 2, 2 ); 6199 qrt_selection = new QPixmap( 2, 2 );
6517 qrt_cleanup_pixmap.set( &qrt_selection ); 6200 qrt_cleanup_pixmap.set( &qrt_selection );
6518 qrt_selection->fill( Qt::color0 ); 6201 qrt_selection->fill( Qt::color0 );
6519 QBitmap m( 2, 2 ); 6202 QBitmap m( 2, 2 );
6520 m.fill( Qt::color1 ); 6203 m.fill( Qt::color1 );
6521 QPainter p( &m ); 6204 QPainter p( &m );
@@ -6616,162 +6299,156 @@ void QTextHorizontalLine::draw( QPainter* p, int x, int y, int , int , int , int
6616// Small set of utility functions to make the parser a bit simpler 6299// Small set of utility functions to make the parser a bit simpler
6617// 6300//
6618 6301
6619bool QTextDocument::hasPrefix(const QChar* doc, int length, int pos, QChar c) 6302bool QTextDocument::hasPrefix(const QChar* doc, int length, int pos, QChar c)
6620{ 6303{
6621 if ( pos >= length ) 6304 if ( pos >= length )
6622 return FALSE; 6305 return FALSE;
6623 return doc[ pos ].lower() == c.lower(); 6306 return doc[ pos ].lower() == c.lower();
6624} 6307}
6625 6308
6626bool QTextDocument::hasPrefix( const QChar* doc, int length, int pos, const QString& s ) 6309bool QTextDocument::hasPrefix( const QChar* doc, int length, int pos, const QString& s )
6627{ 6310{
6628 if ( pos + (int) s.length() >= length ) 6311 if ( pos + (int) s.length() >= length )
6629 return FALSE; 6312 return FALSE;
6630 for ( int i = 0; i < (int)s.length(); i++ ) { 6313 for ( int i = 0; i < (int)s.length(); i++ ) {
6631 if ( doc[ pos + i ].lower() != s[ i ].lower() ) 6314 if ( doc[ pos + i ].lower() != s[ i ].lower() )
6632 return FALSE; 6315 return FALSE;
6633 } 6316 }
6634 return TRUE; 6317 return TRUE;
6635} 6318}
6636 6319
6637static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col ) 6320static bool qt_is_cell_in_use( QPtrList<QTextTableCell>& cells, int row, int col )
6638{ 6321{
6639 for ( QTextTableCell* c = cells.first(); c; c = cells.next() ) { 6322 for ( QTextTableCell* c = cells.first(); c; c = cells.next() ) {
6640 if ( row >= c->row() && row < c->row() + c->rowspan() 6323 if ( row >= c->row() && row < c->row() + c->rowspan()
6641 && col >= c->column() && col < c->column() + c->colspan() ) 6324 && col >= c->column() && col < c->column() + c->colspan() )
6642 return TRUE; 6325 return TRUE;
6643 } 6326 }
6644 return FALSE; 6327 return FALSE;
6645} 6328}
6646 6329
6647QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, 6330QTextCustomItem* QTextDocument::parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt,
6648 const QChar* doc, int length, int& pos, QTextParag *curpar ) 6331 const QChar* doc, int length, int& pos, QTextParagraph *curpar )
6649{ 6332{
6650 6333
6651 QTextTable* table = new QTextTable( this, attr ); 6334 QTextTable* table = new QTextTable( this, attr );
6652 int row = -1; 6335 int row = -1;
6653 int col = -1; 6336 int col = -1;
6654 6337
6655 QString rowbgcolor; 6338 QString rowbgcolor;
6656 QString rowalign; 6339 QString rowalign;
6657 QString tablebgcolor = attr["bgcolor"]; 6340 QString tablebgcolor = attr["bgcolor"];
6658 6341
6659 QPtrList<QTextTableCell> multicells; 6342 QPtrList<QTextTableCell> multicells;
6660 6343
6661 QString tagname; 6344 QString tagname;
6662 (void) eatSpace(doc, length, pos); 6345 (void) eatSpace(doc, length, pos);
6663 while ( pos < length) { 6346 while ( pos < length) {
6664 if (hasPrefix(doc, length, pos, QChar('<')) ){ 6347 if (hasPrefix(doc, length, pos, QChar('<')) ){
6665 if (hasPrefix(doc, length, pos+1, QChar('/'))) { 6348 if (hasPrefix(doc, length, pos+1, QChar('/'))) {
6666 tagname = parseCloseTag( doc, length, pos ); 6349 tagname = parseCloseTag( doc, length, pos );
6667 if ( tagname == "table" ) { 6350 if ( tagname == "table" ) {
6668#if defined(PARSER_DEBUG)
6669 debug_indent.remove( debug_indent.length() - 3, 2 );
6670#endif
6671 return table; 6351 return table;
6672 } 6352 }
6673 } else { 6353 } else {
6674 QMap<QString, QString> attr2; 6354 QMap<QString, QString> attr2;
6675 bool emptyTag = FALSE; 6355 bool emptyTag = FALSE;
6676 tagname = parseOpenTag( doc, length, pos, attr2, emptyTag ); 6356 tagname = parseOpenTag( doc, length, pos, attr2, emptyTag );
6677 if ( tagname == "tr" ) { 6357 if ( tagname == "tr" ) {
6678 rowbgcolor = attr2["bgcolor"]; 6358 rowbgcolor = attr2["bgcolor"];
6679 rowalign = attr2["align"]; 6359 rowalign = attr2["align"];
6680 row++; 6360 row++;
6681 col = -1; 6361 col = -1;
6682 } 6362 }
6683 else if ( tagname == "td" || tagname == "th" ) { 6363 else if ( tagname == "td" || tagname == "th" ) {
6684 col++; 6364 col++;
6685 while ( qt_is_cell_in_use( multicells, row, col ) ) { 6365 while ( qt_is_cell_in_use( multicells, row, col ) ) {
6686 col++; 6366 col++;
6687 } 6367 }
6688 6368
6689 if ( row >= 0 && col >= 0 ) { 6369 if ( row >= 0 && col >= 0 ) {
6690 const QStyleSheetItem* s = sheet_->item(tagname); 6370 const QStyleSheetItem* s = sheet_->item(tagname);
6691 if ( !attr2.contains("bgcolor") ) { 6371 if ( !attr2.contains("bgcolor") ) {
6692 if (!rowbgcolor.isEmpty() ) 6372 if (!rowbgcolor.isEmpty() )
6693 attr2["bgcolor"] = rowbgcolor; 6373 attr2["bgcolor"] = rowbgcolor;
6694 else if (!tablebgcolor.isEmpty() ) 6374 else if (!tablebgcolor.isEmpty() )
6695 attr2["bgcolor"] = tablebgcolor; 6375 attr2["bgcolor"] = tablebgcolor;
6696 } 6376 }
6697 if ( !attr2.contains("align") ) { 6377 if ( !attr2.contains("align") ) {
6698 if (!rowalign.isEmpty() ) 6378 if (!rowalign.isEmpty() )
6699 attr2["align"] = rowalign; 6379 attr2["align"] = rowalign;
6700 } 6380 }
6701 6381
6702 // extract the cell contents 6382 // extract the cell contents
6703 int end = pos; 6383 int end = pos;
6704 while ( end < length 6384 while ( end < length
6705 && !hasPrefix( doc, length, end, "</td") 6385 && !hasPrefix( doc, length, end, "</td")
6706 && !hasPrefix( doc, length, end, "<td") 6386 && !hasPrefix( doc, length, end, "<td")
6707 && !hasPrefix( doc, length, end, "</th") 6387 && !hasPrefix( doc, length, end, "</th")
6708 && !hasPrefix( doc, length, end, "<th") 6388 && !hasPrefix( doc, length, end, "<th")
6709 && !hasPrefix( doc, length, end, "<td") 6389 && !hasPrefix( doc, length, end, "<td")
6710 && !hasPrefix( doc, length, end, "</tr") 6390 && !hasPrefix( doc, length, end, "</tr")
6711 && !hasPrefix( doc, length, end, "<tr") 6391 && !hasPrefix( doc, length, end, "<tr")
6712 && !hasPrefix( doc, length, end, "</table") ) { 6392 && !hasPrefix( doc, length, end, "</table") ) {
6713 if ( hasPrefix( doc, length, end, "<table" ) ) { // nested table 6393 if ( hasPrefix( doc, length, end, "<table" ) ) { // nested table
6714 int nested = 1; 6394 int nested = 1;
6715 ++end; 6395 ++end;
6716 while ( end < length && nested != 0 ) { 6396 while ( end < length && nested != 0 ) {
6717 if ( hasPrefix( doc, length, end, "</table" ) ) 6397 if ( hasPrefix( doc, length, end, "</table" ) )
6718 nested--; 6398 nested--;
6719 if ( hasPrefix( doc, length, end, "<table" ) ) 6399 if ( hasPrefix( doc, length, end, "<table" ) )
6720 nested++; 6400 nested++;
6721 end++; 6401 end++;
6722 } 6402 }
6723 } 6403 }
6724 end++; 6404 end++;
6725 } 6405 }
6726 QTextTableCell* cell = new QTextTableCell( table, row, col, 6406 QTextTableCell* cell = new QTextTableCell( table, row, col,
6727 attr2, s, fmt.makeTextFormat( s, attr2 ), 6407 attr2, s, fmt.makeTextFormat( s, attr2, scaleFontsFactor ),
6728 contxt, *factory_, sheet_, 6408 contxt, *factory_, sheet_,
6729 QString( doc, length).mid( pos, end - pos ) ); 6409 QString( doc, length).mid( pos, end - pos ) );
6730 cell->richText()->parParag = curpar; 6410 cell->richText()->parentPar = curpar;
6731 if ( cell->colspan() > 1 || cell->rowspan() > 1 ) 6411 if ( cell->colspan() > 1 || cell->rowspan() > 1 )
6732 multicells.append( cell ); 6412 multicells.append( cell );
6733 col += cell->colspan()-1; 6413 col += cell->colspan()-1;
6734 pos = end; 6414 pos = end;
6735 } 6415 }
6736 } 6416 }
6737 } 6417 }
6738 6418
6739 } else { 6419 } else {
6740 ++pos; 6420 ++pos;
6741 } 6421 }
6742 } 6422 }
6743#if defined(PARSER_DEBUG)
6744 debug_indent.remove( debug_indent.length() - 3, 2 );
6745#endif
6746 return table; 6423 return table;
6747} 6424}
6748 6425
6749bool QTextDocument::eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp ) 6426bool QTextDocument::eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp )
6750{ 6427{
6751 int old_pos = pos; 6428 int old_pos = pos;
6752 while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != QChar::nbsp ) ) ) 6429 while (pos < length && doc[pos].isSpace() && ( includeNbsp || (doc[pos] != QChar::nbsp ) ) )
6753 pos++; 6430 pos++;
6754 return old_pos < pos; 6431 return old_pos < pos;
6755} 6432}
6756 6433
6757bool QTextDocument::eat(const QChar* doc, int length, int& pos, QChar c) 6434bool QTextDocument::eat(const QChar* doc, int length, int& pos, QChar c)
6758{ 6435{
6759 bool ok = pos < length && doc[pos] == c; 6436 bool ok = pos < length && doc[pos] == c;
6760 if ( ok ) 6437 if ( ok )
6761 pos++; 6438 pos++;
6762 return ok; 6439 return ok;
6763} 6440}
6764/*****************************************************************/ 6441/*****************************************************************/
6765 6442
6766struct Entity { 6443struct Entity {
6767 const char * name; 6444 const char * name;
6768 Q_UINT16 code; 6445 Q_UINT16 code;
6769}; 6446};
6770 6447
6771static const Entity entitylist [] = { 6448static const Entity entitylist [] = {
6772 { "AElig", 0x00c6 }, 6449 { "AElig", 0x00c6 },
6773 { "Aacute", 0x00c1 }, 6450 { "Aacute", 0x00c1 },
6774 { "Acirc", 0x00c2 }, 6451 { "Acirc", 0x00c2 },
6775 { "Agrave", 0x00c0 }, 6452 { "Agrave", 0x00c0 },
6776 { "Alpha", 0x0391 }, 6453 { "Alpha", 0x0391 },
6777 { "AMP", 38 }, 6454 { "AMP", 38 },
@@ -7102,77 +6779,68 @@ QString QTextDocument::parseWord(const QChar* doc, int length, int& pos, bool lo
7102 static QString term = QString::fromLatin1("/>"); 6779 static QString term = QString::fromLatin1("/>");
7103 while( pos < length && 6780 while( pos < length &&
7104 (doc[pos] != '>' && !hasPrefix( doc, length, pos, term)) 6781 (doc[pos] != '>' && !hasPrefix( doc, length, pos, term))
7105 && doc[pos] != '<' 6782 && doc[pos] != '<'
7106 && doc[pos] != '=' 6783 && doc[pos] != '='
7107 && !doc[pos].isSpace()) 6784 && !doc[pos].isSpace())
7108 { 6785 {
7109 if ( doc[pos] == '&') 6786 if ( doc[pos] == '&')
7110 s += parseHTMLSpecialChar( doc, length, pos ); 6787 s += parseHTMLSpecialChar( doc, length, pos );
7111 else { 6788 else {
7112 s += doc[pos]; 6789 s += doc[pos];
7113 pos++; 6790 pos++;
7114 } 6791 }
7115 } 6792 }
7116 if (lower) 6793 if (lower)
7117 s = s.lower(); 6794 s = s.lower();
7118 } 6795 }
7119 return s; 6796 return s;
7120} 6797}
7121 6798
7122QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm ) 6799QChar QTextDocument::parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm )
7123{ 6800{
7124 if ( pos >= length ) 6801 if ( pos >= length )
7125 return QChar::null; 6802 return QChar::null;
7126 6803
7127 QChar c = doc[pos++]; 6804 QChar c = doc[pos++];
7128 6805
7129 if (c == '<' ) 6806 if (c == '<' )
7130 return QChar::null; 6807 return QChar::null;
7131 6808
7132 if ( c.isSpace() && c != QChar::nbsp ) { 6809 if ( c.isSpace() && c != QChar::nbsp ) {
7133 if ( wsm == QStyleSheetItem::WhiteSpacePre ) { 6810 if ( wsm == QStyleSheetItem::WhiteSpacePre ) {
7134 if ( c == ' ' )
7135 return QChar::nbsp;
7136 else
7137 return c;
7138 } else if ( wsm == QStyleSheetItem_WhiteSpaceNoCompression ) {
7139 return c;
7140 } else if ( wsm == QStyleSheetItem_WhiteSpaceNormalWithNewlines ) {
7141 if ( c == '\n' ) 6811 if ( c == '\n' )
6812 return QChar_linesep;
6813 else
7142 return c; 6814 return c;
7143 while ( pos< length &&
7144 doc[pos].isSpace() && doc[pos] != QChar::nbsp && doc[pos] != '\n' )
7145 pos++;
7146 return ' ';
7147 } else { // non-pre mode: collapse whitespace except nbsp 6815 } else { // non-pre mode: collapse whitespace except nbsp
7148 while ( pos< length && 6816 while ( pos< length &&
7149 doc[pos].isSpace() && doc[pos] != QChar::nbsp ) 6817 doc[pos].isSpace() && doc[pos] != QChar::nbsp )
7150 pos++; 6818 pos++;
7151 if ( wsm == QStyleSheetItem::WhiteSpaceNoWrap ) 6819 if ( wsm == QStyleSheetItem::WhiteSpaceNoWrap )
7152 return QChar::nbsp; 6820 return QChar::nbsp;
7153 else 6821 else
7154 return ' '; 6822 return ' ';
7155 } 6823 }
7156 } 6824 }
7157 else if ( c == '&' ) 6825 else if ( c == '&' )
7158 return parseHTMLSpecialChar( doc, length, --pos ); 6826 return parseHTMLSpecialChar( doc, length, --pos );
7159 else 6827 else
7160 return c; 6828 return c;
7161} 6829}
7162 6830
7163QString QTextDocument::parseOpenTag(const QChar* doc, int length, int& pos, 6831QString QTextDocument::parseOpenTag(const QChar* doc, int length, int& pos,
7164 QMap<QString, QString> &attr, bool& emptyTag) 6832 QMap<QString, QString> &attr, bool& emptyTag)
7165{ 6833{
7166 emptyTag = FALSE; 6834 emptyTag = FALSE;
7167 pos++; 6835 pos++;
7168 if ( hasPrefix(doc, length, pos, '!') ) { 6836 if ( hasPrefix(doc, length, pos, '!') ) {
7169 if ( hasPrefix( doc, length, pos+1, "--")) { 6837 if ( hasPrefix( doc, length, pos+1, "--")) {
7170 pos += 3; 6838 pos += 3;
7171 // eat comments 6839 // eat comments
7172 QString pref = QString::fromLatin1("-->"); 6840 QString pref = QString::fromLatin1("-->");
7173 while ( !hasPrefix(doc, length, pos, pref ) && pos < length ) 6841 while ( !hasPrefix(doc, length, pos, pref ) && pos < length )
7174 pos++; 6842 pos++;
7175 if ( hasPrefix(doc, length, pos, pref ) ) { 6843 if ( hasPrefix(doc, length, pos, pref ) ) {
7176 pos += 3; 6844 pos += 3;
7177 eatSpace(doc, length, pos, TRUE); 6845 eatSpace(doc, length, pos, TRUE);
7178 } 6846 }
@@ -7326,69 +6994,64 @@ QRect QTextFlow::boundingRect() const
7326 ++r; 6994 ++r;
7327 } 6995 }
7328 return br; 6996 return br;
7329} 6997}
7330 6998
7331 6999
7332void QTextFlow::drawFloatingItems( QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) 7000void QTextFlow::drawFloatingItems( QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected )
7333{ 7001{
7334 QTextCustomItem *item; 7002 QTextCustomItem *item;
7335 for ( item = leftItems.first(); item; item = leftItems.next() ) { 7003 for ( item = leftItems.first(); item; item = leftItems.next() ) {
7336 if ( item->xpos == -1 || item->ypos == -1 ) 7004 if ( item->xpos == -1 || item->ypos == -1 )
7337 continue; 7005 continue;
7338 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); 7006 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected );
7339 } 7007 }
7340 7008
7341 for ( item = rightItems.first(); item; item = rightItems.next() ) { 7009 for ( item = rightItems.first(); item; item = rightItems.next() ) {
7342 if ( item->xpos == -1 || item->ypos == -1 ) 7010 if ( item->xpos == -1 || item->ypos == -1 )
7343 continue; 7011 continue;
7344 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected ); 7012 item->draw( p, item->xpos, item->ypos, cx, cy, cw, ch, cg, selected );
7345 } 7013 }
7346} 7014}
7347 7015
7348// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 7016// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7349 7017
7350void QTextCustomItem::pageBreak( int /*y*/ , QTextFlow* /*flow*/ ) 7018void QTextCustomItem::pageBreak( int /*y*/ , QTextFlow* /*flow*/ )
7351{ 7019{
7352} 7020}
7353 7021
7354QTextTable::QTextTable( QTextDocument *p, const QMap<QString, QString> & attr ) 7022QTextTable::QTextTable( QTextDocument *p, const QMap<QString, QString> & attr )
7355 : QTextCustomItem( p ) 7023 : QTextCustomItem( p )
7356{ 7024{
7357 cells.setAutoDelete( FALSE ); 7025 cells.setAutoDelete( FALSE );
7358#if defined(PARSER_DEBUG)
7359 debug_indent += "\t";
7360 qDebug( debug_indent + "new QTextTable (%p)", this );
7361 debug_indent += "\t";
7362#endif
7363 cellspacing = 2; 7026 cellspacing = 2;
7364 if ( attr.contains("cellspacing") ) 7027 if ( attr.contains("cellspacing") )
7365 cellspacing = attr["cellspacing"].toInt(); 7028 cellspacing = attr["cellspacing"].toInt();
7366 cellpadding = 1; 7029 cellpadding = 1;
7367 if ( attr.contains("cellpadding") ) 7030 if ( attr.contains("cellpadding") )
7368 cellpadding = attr["cellpadding"].toInt(); 7031 cellpadding = attr["cellpadding"].toInt();
7369 border = innerborder = 0; 7032 border = innerborder = 0;
7370 if ( attr.contains("border" ) ) { 7033 if ( attr.contains("border" ) ) {
7371 QString s( attr["border"] ); 7034 QString s( attr["border"] );
7372 if ( s == "TRUE" ) 7035 if ( s == "TRUE" )
7373 border = 1; 7036 border = 1;
7374 else 7037 else
7375 border = attr["border"].toInt(); 7038 border = attr["border"].toInt();
7376 } 7039 }
7377 us_b = border; 7040 us_b = border;
7378 7041
7379 innerborder = us_ib = border ? 1 : 0; 7042 innerborder = us_ib = border ? 1 : 0;
7380 7043
7381 if ( border ) 7044 if ( border )
7382 cellspacing += 2; 7045 cellspacing += 2;
7383 7046
7384 us_ib = innerborder; 7047 us_ib = innerborder;
7385 us_cs = cellspacing; 7048 us_cs = cellspacing;
7386 us_cp = cellpadding; 7049 us_cp = cellpadding;
7387 outerborder = cellspacing + border; 7050 outerborder = cellspacing + border;
7388 us_ob = outerborder; 7051 us_ob = outerborder;
7389 layout = new QGridLayout( 1, 1, cellspacing ); 7052 layout = new QGridLayout( 1, 1, cellspacing );
7390 7053
7391 fixwidth = 0; 7054 fixwidth = 0;
7392 stretch = 0; 7055 stretch = 0;
7393 if ( attr.contains("width") ) { 7056 if ( attr.contains("width") ) {
7394 bool b; 7057 bool b;
@@ -7411,68 +7074,68 @@ QTextTable::QTextTable( QTextDocument *p, const QMap<QString, QString> & attr )
7411 cachewidth = 0; 7074 cachewidth = 0;
7412 attributes = attr; 7075 attributes = attr;
7413 pageBreakFor = -1; 7076 pageBreakFor = -1;
7414} 7077}
7415 7078
7416QTextTable::~QTextTable() 7079QTextTable::~QTextTable()
7417{ 7080{
7418 delete layout; 7081 delete layout;
7419} 7082}
7420 7083
7421QString QTextTable::richText() const 7084QString QTextTable::richText() const
7422{ 7085{
7423 QString s; 7086 QString s;
7424 s = "<table "; 7087 s = "<table ";
7425 QMap<QString, QString>::ConstIterator it = attributes.begin(); 7088 QMap<QString, QString>::ConstIterator it = attributes.begin();
7426 for ( ; it != attributes.end(); ++it ) 7089 for ( ; it != attributes.end(); ++it )
7427 s += it.key() + "=" + *it + " "; 7090 s += it.key() + "=" + *it + " ";
7428 s += ">\n"; 7091 s += ">\n";
7429 7092
7430 int lastRow = -1; 7093 int lastRow = -1;
7431 bool needEnd = FALSE; 7094 bool needEnd = FALSE;
7432 QPtrListIterator<QTextTableCell> it2( cells ); 7095 QPtrListIterator<QTextTableCell> it2( cells );
7433 while ( it2.current() ) { 7096 while ( it2.current() ) {
7434 QTextTableCell *cell = it2.current(); 7097 QTextTableCell *cell = it2.current();
7435 ++it2; 7098 ++it2;
7436 if ( lastRow != cell->row() ) { 7099 if ( lastRow != cell->row() ) {
7437 if ( lastRow != -1 ) 7100 if ( lastRow != -1 )
7438 s += "</tr>\n"; 7101 s += "</tr>\n";
7439 s += "<tr>"; 7102 s += "<tr>";
7440 lastRow = cell->row(); 7103 lastRow = cell->row();
7441 needEnd = TRUE; 7104 needEnd = TRUE;
7442 } 7105 }
7443 s += "<td "; 7106 s += "<td";
7444 it = cell->attributes.begin(); 7107 it = cell->attributes.begin();
7445 for ( ; it != cell->attributes.end(); ++it ) 7108 for ( ; it != cell->attributes.end(); ++it )
7446 s += it.key() + "=" + *it + " "; 7109 s += " " + it.key() + "=" + *it;
7447 s += ">"; 7110 s += ">";
7448 s += cell->richText()->richText(); 7111 s += cell->richText()->richText();
7449 s += "</td>"; 7112 s += "</td>";
7450 } 7113 }
7451 if ( needEnd ) 7114 if ( needEnd )
7452 s += "</tr>\n"; 7115 s += "</tr>\n";
7453 s += "</table>\n"; 7116 s += "</table>\n";
7454 return s; 7117 return s;
7455} 7118}
7456 7119
7457void QTextTable::adjustToPainter( QPainter* p ) 7120void QTextTable::adjustToPainter( QPainter* p )
7458{ 7121{
7459 cellspacing = scale( us_cs, p ); 7122 cellspacing = scale( us_cs, p );
7460 cellpadding = scale( us_cp, p ); 7123 cellpadding = scale( us_cp, p );
7461 border = scale( us_b , p ); 7124 border = scale( us_b , p );
7462 innerborder = scale( us_ib, p ); 7125 innerborder = scale( us_ib, p );
7463 outerborder = scale( us_ob ,p ); 7126 outerborder = scale( us_ob ,p );
7464 width = 0; 7127 width = 0;
7465 cachewidth = 0; 7128 cachewidth = 0;
7466 for ( QTextTableCell* cell = cells.first(); cell; cell = cells.next() ) 7129 for ( QTextTableCell* cell = cells.first(); cell; cell = cells.next() )
7467 cell->adjustToPainter( p ); 7130 cell->adjustToPainter( p );
7468} 7131}
7469 7132
7470void QTextTable::adjustCells( int y , int shift ) 7133void QTextTable::adjustCells( int y , int shift )
7471{ 7134{
7472 QPtrListIterator<QTextTableCell> it( cells ); 7135 QPtrListIterator<QTextTableCell> it( cells );
7473 QTextTableCell* cell; 7136 QTextTableCell* cell;
7474 bool enlarge = FALSE; 7137 bool enlarge = FALSE;
7475 while ( ( cell = it.current() ) ) { 7138 while ( ( cell = it.current() ) ) {
7476 ++it; 7139 ++it;
7477 QRect r = cell->geometry(); 7140 QRect r = cell->geometry();
7478 if ( y <= r.top() ) { 7141 if ( y <= r.top() ) {
@@ -7547,440 +7210,403 @@ void QTextTable::draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch,
7547 p->fillRect( r.left()-s, r.top()-s, r.width()+2*s, s, cg.button() ); 7210 p->fillRect( r.left()-s, r.top()-s, r.width()+2*s, s, cg.button() );
7548 p->fillRect( r.left()-s, r.bottom(), r.width()+2*s, s, cg.button() ); 7211 p->fillRect( r.left()-s, r.bottom(), r.width()+2*s, s, cg.button() );
7549 } 7212 }
7550 qDrawShadePanel( p, r, cg, TRUE, innerborder ); 7213 qDrawShadePanel( p, r, cg, TRUE, innerborder );
7551 } 7214 }
7552 } 7215 }
7553 } 7216 }
7554 } 7217 }
7555 if ( border ) { 7218 if ( border ) {
7556 QRect r ( x, y, width, height ); 7219 QRect r ( x, y, width, height );
7557 if ( is_printer( p ) ) { 7220 if ( is_printer( p ) ) {
7558 QRect r2 = r; 7221 QRect r2 = r;
7559 r2.setLeft( r2.left() + border/2 ); 7222 r2.setLeft( r2.left() + border/2 );
7560 r2.setTop( r2.top() + border/2 ); 7223 r2.setTop( r2.top() + border/2 );
7561 r2.setRight( r2.right() - border/2 ); 7224 r2.setRight( r2.right() - border/2 );
7562 r2.setBottom( r2.bottom() - border/2 ); 7225 r2.setBottom( r2.bottom() - border/2 );
7563 QPen oldPen = p->pen(); 7226 QPen oldPen = p->pen();
7564 p->setPen( QPen( cg.text(), border ) ); 7227 p->setPen( QPen( cg.text(), border ) );
7565 p->drawRect( r2 ); 7228 p->drawRect( r2 );
7566 p->setPen( oldPen ); 7229 p->setPen( oldPen );
7567 } else { 7230 } else {
7568 int s = border+QMAX( cellspacing-2*innerborder, 0); 7231 int s = border+QMAX( cellspacing-2*innerborder, 0);
7569 if ( s ) { 7232 if ( s ) {
7570 p->fillRect( r.left(), r.top(), s, r.height(), cg.button() ); 7233 p->fillRect( r.left(), r.top(), s, r.height(), cg.button() );
7571 p->fillRect( r.right()-s, r.top(), s, r.height(), cg.button() ); 7234 p->fillRect( r.right()-s, r.top(), s, r.height(), cg.button() );
7572 p->fillRect( r.left(), r.top(), r.width(), s, cg.button() ); 7235 p->fillRect( r.left(), r.top(), r.width(), s, cg.button() );
7573 p->fillRect( r.left(), r.bottom()-s, r.width(), s, cg.button() ); 7236 p->fillRect( r.left(), r.bottom()-s, r.width(), s, cg.button() );
7574 } 7237 }
7575 qDrawShadePanel( p, r, cg, FALSE, border ); 7238 qDrawShadePanel( p, r, cg, FALSE, border );
7576 } 7239 }
7577 } 7240 }
7578 7241
7579#if defined(DEBUG_TABLE_RENDERING)
7580 p->save();
7581 p->setPen( Qt::red );
7582 p->drawRect( x, y, width, height );
7583 p->restore();
7584#endif
7585} 7242}
7586 7243
7587int QTextTable::minimumWidth() const 7244int QTextTable::minimumWidth() const
7588{ 7245{
7589 return (layout ? layout->minimumSize().width() : 0) + 2 * outerborder; 7246 return (layout ? layout->minimumSize().width() : 0) + 2 * outerborder;
7590} 7247}
7591 7248
7592void QTextTable::resize( int nwidth ) 7249void QTextTable::resize( int nwidth )
7593{ 7250{
7594 if ( fixwidth && cachewidth != 0 ) 7251 if ( fixwidth && cachewidth != 0 )
7595 return; 7252 return;
7596 if ( nwidth == cachewidth ) 7253 if ( nwidth == cachewidth )
7597 return; 7254 return;
7598 7255
7599 7256
7600 cachewidth = nwidth; 7257 cachewidth = nwidth;
7601 int w = nwidth; 7258 int w = nwidth;
7602 7259
7603 format( w ); 7260 format( w );
7604 7261
7605 if ( stretch ) 7262 if ( stretch )
7606 nwidth = nwidth * stretch / 100; 7263 nwidth = nwidth * stretch / 100;
7607 7264
7608 width = nwidth; 7265 width = nwidth;
7609 layout->invalidate(); 7266 layout->invalidate();
7610 int shw = layout->sizeHint().width() + 2*outerborder; 7267 int shw = layout->sizeHint().width() + 2*outerborder;
7611 int mw = layout->minimumSize().width() + 2*outerborder; 7268 int mw = layout->minimumSize().width() + 2*outerborder;
7612 if ( stretch ) 7269 if ( stretch )
7613 width = QMAX( mw, nwidth ); 7270 width = QMAX( mw, nwidth );
7614 else 7271 else
7615 width = QMAX( mw, QMIN( nwidth, shw ) ); 7272 width = QMAX( mw, QMIN( nwidth, shw ) );
7616 7273
7617 if ( fixwidth ) 7274 if ( fixwidth )
7618 width = fixwidth; 7275 width = fixwidth;
7619 7276
7620 layout->invalidate(); 7277 layout->invalidate();
7621 mw = layout->minimumSize().width() + 2*outerborder; 7278 mw = layout->minimumSize().width() + 2*outerborder;
7622 width = QMAX( width, mw ); 7279 width = QMAX( width, mw );
7623 7280
7624 int h = layout->heightForWidth( width-2*outerborder ); 7281 int h = layout->heightForWidth( width-2*outerborder );
7625 layout->setGeometry( QRect(0, 0, width-2*outerborder, h) ); 7282 layout->setGeometry( QRect(0, 0, width-2*outerborder, h) );
7626 height = layout->geometry().height()+2*outerborder; 7283 height = layout->geometry().height()+2*outerborder;
7627} 7284}
7628 7285
7629void QTextTable::format( int w ) 7286void QTextTable::format( int w )
7630{ 7287{
7631 for ( int i = 0; i < (int)cells.count(); ++i ) { 7288 for ( int i = 0; i < (int)cells.count(); ++i ) {
7632 QTextTableCell *cell = cells.at( i ); 7289 QTextTableCell *cell = cells.at( i );
7633 QRect r = cell->geometry(); 7290 QRect r = cell->geometry();
7634 r.setWidth( w - 2*outerborder ); 7291 r.setWidth( w - 2*outerborder );
7635 cell->setGeometry( r ); 7292 cell->setGeometry( r );
7636 } 7293 }
7637} 7294}
7638 7295
7639void QTextTable::addCell( QTextTableCell* cell ) 7296void QTextTable::addCell( QTextTableCell* cell )
7640{ 7297{
7641 cells.append( cell ); 7298 cells.append( cell );
7642 layout->addMultiCell( cell, cell->row(), cell->row() + cell->rowspan()-1, 7299 layout->addMultiCell( cell, cell->row(), cell->row() + cell->rowspan()-1,
7643 cell->column(), cell->column() + cell->colspan()-1 ); 7300 cell->column(), cell->column() + cell->colspan()-1 );
7644} 7301}
7645 7302
7646bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, bool atEnd ) 7303bool QTextTable::enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, bool atEnd )
7647{ 7304{
7648 currCell.remove( c ); 7305 currCell.remove( c );
7649 if ( !atEnd ) 7306 if ( !atEnd )
7650 return next( c, doc, parag, idx, ox, oy ); 7307 return next( c, doc, parag, idx, ox, oy );
7651 currCell.insert( c, cells.count() ); 7308 currCell.insert( c, cells.count() );
7652 return prev( c, doc, parag, idx, ox, oy ); 7309 return prev( c, doc, parag, idx, ox, oy );
7653} 7310}
7654 7311
7655bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, const QPoint &pos ) 7312bool QTextTable::enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, const QPoint &pos )
7656{ 7313{
7657 currCell.remove( c ); 7314 currCell.remove( c );
7658 int lastCell = -1; 7315 int lastCell = -1;
7659 int lastY = -1; 7316 int lastY = -1;
7660 int i; 7317 int i;
7661 for ( i = 0; i < (int)cells.count(); ++i ) { 7318 for ( i = 0; i < (int)cells.count(); ++i ) {
7662 QTextTableCell *cell = cells.at( i ); 7319 QTextTableCell *cell = cells.at( i );
7663 if ( !cell ) 7320 if ( !cell )
7664 continue; 7321 continue;
7665 QRect r( cell->geometry().x(), 7322 QRect r( cell->geometry().x(),
7666 cell->geometry().y(), 7323 cell->geometry().y(),
7667 cell->geometry().width() + 2 * innerborder + 2 * outerborder, 7324 cell->geometry().width() + 2 * innerborder + 2 * outerborder,
7668 cell->geometry().height() + 2 * innerborder + 2 * outerborder ); 7325 cell->geometry().height() + 2 * innerborder + 2 * outerborder );
7669 7326
7670 if ( r.left() <= pos.x() && r.right() >= pos.x() ) { 7327 if ( r.left() <= pos.x() && r.right() >= pos.x() ) {
7671 if ( cell->geometry().y() > lastY ) { 7328 if ( cell->geometry().y() > lastY ) {
7672 lastCell = i; 7329 lastCell = i;
7673 lastY = cell->geometry().y(); 7330 lastY = cell->geometry().y();
7674 } 7331 }
7675 if ( r.top() <= pos.y() && r.bottom() >= pos.y() ) { 7332 if ( r.top() <= pos.y() && r.bottom() >= pos.y() ) {
7676 currCell.insert( c, i ); 7333 currCell.insert( c, i );
7677 break; 7334 break;
7678 } 7335 }
7679 } 7336 }
7680 } 7337 }
7681 if ( i == (int) cells.count() ) 7338 if ( i == (int) cells.count() )
7682 return FALSE; // no cell found 7339 return FALSE; // no cell found
7683 7340
7684 if ( currCell.find( c ) == currCell.end() ) { 7341 if ( currCell.find( c ) == currCell.end() ) {
7685 if ( lastY != -1 ) 7342 if ( lastY != -1 )
7686 currCell.insert( c, lastCell ); 7343 currCell.insert( c, lastCell );
7687 else 7344 else
7688 return FALSE; 7345 return FALSE;
7689 } 7346 }
7690 7347
7691 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7348 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7692 if ( !cell ) 7349 if ( !cell )
7693 return FALSE; 7350 return FALSE;
7694 doc = cell->richText(); 7351 doc = cell->richText();
7695 parag = doc->firstParag(); 7352 parag = doc->firstParagraph();
7696 idx = 0; 7353 idx = 0;
7697 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7354 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7698 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7355 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7699 return TRUE; 7356 return TRUE;
7700} 7357}
7701 7358
7702bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 7359bool QTextTable::next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7703{ 7360{
7704 int cc = -1; 7361 int cc = -1;
7705 if ( currCell.find( c ) != currCell.end() ) 7362 if ( currCell.find( c ) != currCell.end() )
7706 cc = *currCell.find( c ); 7363 cc = *currCell.find( c );
7707 if ( cc > (int)cells.count() - 1 || cc < 0 ) 7364 if ( cc > (int)cells.count() - 1 || cc < 0 )
7708 cc = -1; 7365 cc = -1;
7709 currCell.remove( c ); 7366 currCell.remove( c );
7710 currCell.insert( c, ++cc ); 7367 currCell.insert( c, ++cc );
7711 if ( cc >= (int)cells.count() ) { 7368 if ( cc >= (int)cells.count() ) {
7712 currCell.insert( c, 0 ); 7369 currCell.insert( c, 0 );
7713 QTextCustomItem::next( c, doc, parag, idx, ox, oy ); 7370 QTextCustomItem::next( c, doc, parag, idx, ox, oy );
7714 QTextTableCell *cell = cells.first(); 7371 QTextTableCell *cell = cells.first();
7715 if ( !cell ) 7372 if ( !cell )
7716 return FALSE; 7373 return FALSE;
7717 doc = cell->richText(); 7374 doc = cell->richText();
7718 idx = -1; 7375 idx = -1;
7719 return TRUE; 7376 return TRUE;
7720 } 7377 }
7721 7378
7722 if ( currCell.find( c ) == currCell.end() ) 7379 if ( currCell.find( c ) == currCell.end() )
7723 return FALSE; 7380 return FALSE;
7724 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7381 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7725 if ( !cell ) 7382 if ( !cell )
7726 return FALSE; 7383 return FALSE;
7727 doc = cell->richText(); 7384 doc = cell->richText();
7728 parag = doc->firstParag(); 7385 parag = doc->firstParagraph();
7729 idx = 0; 7386 idx = 0;
7730 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7387 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7731 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7388 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7732 return TRUE; 7389 return TRUE;
7733} 7390}
7734 7391
7735bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 7392bool QTextTable::prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7736{ 7393{
7737 int cc = -1; 7394 int cc = -1;
7738 if ( currCell.find( c ) != currCell.end() ) 7395 if ( currCell.find( c ) != currCell.end() )
7739 cc = *currCell.find( c ); 7396 cc = *currCell.find( c );
7740 if ( cc > (int)cells.count() - 1 || cc < 0 ) 7397 if ( cc > (int)cells.count() - 1 || cc < 0 )
7741 cc = cells.count(); 7398 cc = cells.count();
7742 currCell.remove( c ); 7399 currCell.remove( c );
7743 currCell.insert( c, --cc ); 7400 currCell.insert( c, --cc );
7744 if ( cc < 0 ) { 7401 if ( cc < 0 ) {
7745 currCell.insert( c, 0 ); 7402 currCell.insert( c, 0 );
7746 QTextCustomItem::prev( c, doc, parag, idx, ox, oy ); 7403 QTextCustomItem::prev( c, doc, parag, idx, ox, oy );
7747 QTextTableCell *cell = cells.first(); 7404 QTextTableCell *cell = cells.first();
7748 if ( !cell ) 7405 if ( !cell )
7749 return FALSE; 7406 return FALSE;
7750 doc = cell->richText(); 7407 doc = cell->richText();
7751 idx = -1; 7408 idx = -1;
7752 return TRUE; 7409 return TRUE;
7753 } 7410 }
7754 7411
7755 if ( currCell.find( c ) == currCell.end() ) 7412 if ( currCell.find( c ) == currCell.end() )
7756 return FALSE; 7413 return FALSE;
7757 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7414 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7758 if ( !cell ) 7415 if ( !cell )
7759 return FALSE; 7416 return FALSE;
7760 doc = cell->richText(); 7417 doc = cell->richText();
7761 parag = doc->firstParag(); 7418 parag = doc->lastParagraph();
7762 idx = parag->length() - 1; 7419 idx = parag->length() - 1;
7763 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7420 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7764 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7421 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7765 return TRUE; 7422 return TRUE;
7766} 7423}
7767 7424
7768bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 7425bool QTextTable::down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7769{ 7426{
7770 if ( currCell.find( c ) == currCell.end() ) 7427 if ( currCell.find( c ) == currCell.end() )
7771 return FALSE; 7428 return FALSE;
7772 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7429 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7773 if ( cell->row_ == layout->numRows() - 1 ) { 7430 if ( cell->row_ == layout->numRows() - 1 ) {
7774 currCell.insert( c, 0 ); 7431 currCell.insert( c, 0 );
7775 QTextCustomItem::down( c, doc, parag, idx, ox, oy ); 7432 QTextCustomItem::down( c, doc, parag, idx, ox, oy );
7776 QTextTableCell *cell = cells.first(); 7433 QTextTableCell *cell = cells.first();
7777 if ( !cell ) 7434 if ( !cell )
7778 return FALSE; 7435 return FALSE;
7779 doc = cell->richText(); 7436 doc = cell->richText();
7780 idx = -1; 7437 idx = -1;
7781 return TRUE; 7438 return TRUE;
7782 } 7439 }
7783 7440
7784 int oldRow = cell->row_; 7441 int oldRow = cell->row_;
7785 int oldCol = cell->col_; 7442 int oldCol = cell->col_;
7786 if ( currCell.find( c ) == currCell.end() ) 7443 if ( currCell.find( c ) == currCell.end() )
7787 return FALSE; 7444 return FALSE;
7788 int cc = *currCell.find( c ); 7445 int cc = *currCell.find( c );
7789 for ( int i = cc; i < (int)cells.count(); ++i ) { 7446 for ( int i = cc; i < (int)cells.count(); ++i ) {
7790 cell = cells.at( i ); 7447 cell = cells.at( i );
7791 if ( cell->row_ > oldRow && cell->col_ == oldCol ) { 7448 if ( cell->row_ > oldRow && cell->col_ == oldCol ) {
7792 currCell.insert( c, i ); 7449 currCell.insert( c, i );
7793 break; 7450 break;
7794 } 7451 }
7795 } 7452 }
7796 doc = cell->richText(); 7453 doc = cell->richText();
7797 if ( !cell ) 7454 if ( !cell )
7798 return FALSE; 7455 return FALSE;
7799 parag = doc->firstParag(); 7456 parag = doc->firstParagraph();
7800 idx = 0; 7457 idx = 0;
7801 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7458 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7802 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7459 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7803 return TRUE; 7460 return TRUE;
7804} 7461}
7805 7462
7806bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 7463bool QTextTable::up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy )
7807{ 7464{
7808 if ( currCell.find( c ) == currCell.end() ) 7465 if ( currCell.find( c ) == currCell.end() )
7809 return FALSE; 7466 return FALSE;
7810 QTextTableCell *cell = cells.at( *currCell.find( c ) ); 7467 QTextTableCell *cell = cells.at( *currCell.find( c ) );
7811 if ( cell->row_ == 0 ) { 7468 if ( cell->row_ == 0 ) {
7812 currCell.insert( c, 0 ); 7469 currCell.insert( c, 0 );
7813 QTextCustomItem::up( c, doc, parag, idx, ox, oy ); 7470 QTextCustomItem::up( c, doc, parag, idx, ox, oy );
7814 QTextTableCell *cell = cells.first(); 7471 QTextTableCell *cell = cells.first();
7815 if ( !cell ) 7472 if ( !cell )
7816 return FALSE; 7473 return FALSE;
7817 doc = cell->richText(); 7474 doc = cell->richText();
7818 idx = -1; 7475 idx = -1;
7819 return TRUE; 7476 return TRUE;
7820 } 7477 }
7821 7478
7822 int oldRow = cell->row_; 7479 int oldRow = cell->row_;
7823 int oldCol = cell->col_; 7480 int oldCol = cell->col_;
7824 if ( currCell.find( c ) == currCell.end() ) 7481 if ( currCell.find( c ) == currCell.end() )
7825 return FALSE; 7482 return FALSE;
7826 int cc = *currCell.find( c ); 7483 int cc = *currCell.find( c );
7827 for ( int i = cc; i >= 0; --i ) { 7484 for ( int i = cc; i >= 0; --i ) {
7828 cell = cells.at( i ); 7485 cell = cells.at( i );
7829 if ( cell->row_ < oldRow && cell->col_ == oldCol ) { 7486 if ( cell->row_ < oldRow && cell->col_ == oldCol ) {
7830 currCell.insert( c, i ); 7487 currCell.insert( c, i );
7831 break; 7488 break;
7832 } 7489 }
7833 } 7490 }
7834 doc = cell->richText(); 7491 doc = cell->richText();
7835 if ( !cell ) 7492 if ( !cell )
7836 return FALSE; 7493 return FALSE;
7837 parag = doc->lastParag(); 7494 parag = doc->lastParagraph();
7838 idx = parag->length() - 1; 7495 idx = parag->length() - 1;
7839 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x(); 7496 ox += cell->geometry().x() + cell->horizontalAlignmentOffset() + outerborder + parent->x();
7840 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder; 7497 oy += cell->geometry().y() + cell->verticalAlignmentOffset() + outerborder;
7841 return TRUE; 7498 return TRUE;
7842} 7499}
7843 7500
7844QTextTableCell::QTextTableCell( QTextTable* table, 7501QTextTableCell::QTextTableCell( QTextTable* table,
7845 int row, int column, 7502 int row, int column,
7846 const QMap<QString, QString> &attr, 7503 const QMap<QString, QString> &attr,
7847 const QStyleSheetItem* /*style*/, // ### use them 7504 const QStyleSheetItem* /*style*/, // ### use them
7848 const QTextFormat& /*fmt*/, const QString& context, 7505 const QTextFormat& /*fmt*/, const QString& context,
7849 QMimeSourceFactory &factory, QStyleSheet *sheet, 7506 QMimeSourceFactory &factory, QStyleSheet *sheet,
7850 const QString& doc) 7507 const QString& doc)
7851{ 7508{
7852#if defined(PARSER_DEBUG)
7853 qDebug( debug_indent + "new QTextTableCell1 (pappi: %p)", table );
7854 qDebug( debug_indent + doc );
7855#endif
7856 cached_width = -1; 7509 cached_width = -1;
7857 cached_sizehint = -1; 7510 cached_sizehint = -1;
7858 7511
7859 maxw = QWIDGETSIZE_MAX; 7512 maxw = QWIDGETSIZE_MAX;
7860 minw = 0; 7513 minw = 0;
7861 7514
7862 parent = table; 7515 parent = table;
7863 row_ = row; 7516 row_ = row;
7864 col_ = column; 7517 col_ = column;
7865 stretch_ = 0; 7518 stretch_ = 0;
7866 richtext = new QTextDocument( table->parent ); 7519 richtext = new QTextDocument( table->parent );
7867 richtext->setTableCell( this ); 7520 richtext->setTableCell( this );
7868 QString a = *attr.find( "align" ); 7521 QString a = *attr.find( "align" );
7869 if ( !a.isEmpty() ) { 7522 if ( !a.isEmpty() ) {
7870 a = a.lower(); 7523 a = a.lower();
7871 if ( a == "left" ) 7524 if ( a == "left" )
7872 richtext->setAlignment( Qt::AlignLeft ); 7525 richtext->setAlignment( Qt::AlignLeft );
7873 else if ( a == "center" ) 7526 else if ( a == "center" )
7874 richtext->setAlignment( Qt::AlignHCenter ); 7527 richtext->setAlignment( Qt::AlignHCenter );
7875 else if ( a == "right" ) 7528 else if ( a == "right" )
7876 richtext->setAlignment( Qt::AlignRight ); 7529 richtext->setAlignment( Qt::AlignRight );
7877 } 7530 }
7878 align = 0; 7531 align = 0;
7879 QString va = *attr.find( "valign" ); 7532 QString va = *attr.find( "valign" );
7880 if ( !va.isEmpty() ) { 7533 if ( !va.isEmpty() ) {
7881 va = va.lower(); 7534 va = va.lower();
7882 if ( va == "center" ) 7535 if ( va == "center" )
7883 align |= Qt::AlignVCenter; 7536 align |= Qt::AlignVCenter;
7884 else if ( va == "bottom" ) 7537 else if ( va == "bottom" )
7885 align |= Qt::AlignBottom; 7538 align |= Qt::AlignBottom;
7886 } 7539 }
7887 richtext->setFormatter( table->parent->formatter() ); 7540 richtext->setFormatter( table->parent->formatter() );
7888 richtext->setUseFormatCollection( table->parent->useFormatCollection() ); 7541 richtext->setUseFormatCollection( table->parent->useFormatCollection() );
7889 richtext->setMimeSourceFactory( &factory ); 7542 richtext->setMimeSourceFactory( &factory );
7890 richtext->setStyleSheet( sheet ); 7543 richtext->setStyleSheet( sheet );
7891 richtext->setDefaultFont( table->parent->formatCollection()->defaultFormat()->font() ); 7544 richtext->setDefaultFormat( table->parent->formatCollection()->defaultFormat()->font(),
7545 table->parent->formatCollection()->defaultFormat()->color() );
7892 richtext->setRichText( doc, context ); 7546 richtext->setRichText( doc, context );
7893 rowspan_ = 1; 7547 rowspan_ = 1;
7894 colspan_ = 1; 7548 colspan_ = 1;
7895 if ( attr.contains("colspan") ) 7549 if ( attr.contains("colspan") )
7896 colspan_ = attr["colspan"].toInt(); 7550 colspan_ = attr["colspan"].toInt();
7897 if ( attr.contains("rowspan") ) 7551 if ( attr.contains("rowspan") )
7898 rowspan_ = attr["rowspan"].toInt(); 7552 rowspan_ = attr["rowspan"].toInt();
7899 7553
7900 background = 0; 7554 background = 0;
7901 if ( attr.contains("bgcolor") ) { 7555 if ( attr.contains("bgcolor") ) {
7902 background = new QBrush(QColor( attr["bgcolor"] )); 7556 background = new QBrush(QColor( attr["bgcolor"] ));
7903 } 7557 }
7904 7558
7905 7559
7906 hasFixedWidth = FALSE; 7560 hasFixedWidth = FALSE;
7907 if ( attr.contains("width") ) { 7561 if ( attr.contains("width") ) {
7908 bool b; 7562 bool b;
7909 QString s( attr["width"] ); 7563 QString s( attr["width"] );
7910 int w = s.toInt( &b ); 7564 int w = s.toInt( &b );
7911 if ( b ) { 7565 if ( b ) {
7912 maxw = w; 7566 maxw = w;
7913 minw = maxw; 7567 minw = maxw;
7914 hasFixedWidth = TRUE; 7568 hasFixedWidth = TRUE;
7915 } else { 7569 } else {
7916 s = s.stripWhiteSpace(); 7570 s = s.stripWhiteSpace();
7917 if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' ) 7571 if ( s.length() > 1 && s[ (int)s.length()-1 ] == '%' )
7918 stretch_ = s.left( s.length()-1).toInt(); 7572 stretch_ = s.left( s.length()-1).toInt();
7919 } 7573 }
7920 } 7574 }
7921 7575
7922 attributes = attr; 7576 attributes = attr;
7923 7577
7924 parent->addCell( this ); 7578 parent->addCell( this );
7925} 7579}
7926 7580
7927QTextTableCell::QTextTableCell( QTextTable* table, int row, int column )
7928{
7929#if defined(PARSER_DEBUG)
7930 qDebug( debug_indent + "new QTextTableCell2( pappi: %p", table );
7931#endif
7932 maxw = QWIDGETSIZE_MAX;
7933 minw = 0;
7934 cached_width = -1;
7935 cached_sizehint = -1;
7936
7937 parent = table;
7938 row_ = row;
7939 col_ = column;
7940 stretch_ = 0;
7941 richtext = new QTextDocument( table->parent );
7942 richtext->setTableCell( this );
7943 richtext->setFormatter( table->parent->formatter() );
7944 richtext->setUseFormatCollection( table->parent->useFormatCollection() );
7945 richtext->setDefaultFont( table->parent->formatCollection()->defaultFormat()->font() );
7946 richtext->setRichText( "<html></html>", QString::null );
7947 rowspan_ = 1;
7948 colspan_ = 1;
7949 background = 0;
7950 hasFixedWidth = FALSE;
7951 parent->addCell( this );
7952}
7953
7954
7955QTextTableCell::~QTextTableCell() 7581QTextTableCell::~QTextTableCell()
7956{ 7582{
7957 delete background; 7583 delete background;
7958 background = 0; 7584 background = 0;
7959 delete richtext; 7585 delete richtext;
7960 richtext = 0; 7586 richtext = 0;
7961} 7587}
7962 7588
7963QSize QTextTableCell::sizeHint() const 7589QSize QTextTableCell::sizeHint() const
7964{ 7590{
7965 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); 7591 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance);
7966 int used = richtext->widthUsed() + extra; 7592 int used = richtext->widthUsed() + extra;
7967 7593
7968 if (stretch_ ) { 7594 if (stretch_ ) {
7969 int w = parent->width * stretch_ / 100 - 2*parent->cellspacing - 2*parent->cellpadding; 7595 int w = parent->width * stretch_ / 100 - 2*parent->cellspacing - 2*parent->cellpadding;
7970 return QSize( QMIN( w, maxw ), 0 ).expandedTo( minimumSize() ); 7596 return QSize( QMIN( w, maxw ), 0 ).expandedTo( minimumSize() );
7971 } 7597 }
7972 7598
7973 return QSize( used, 0 ).expandedTo( minimumSize() ); 7599 return QSize( used, 0 ).expandedTo( minimumSize() );
7974} 7600}
7975 7601
7976QSize QTextTableCell::minimumSize() const 7602QSize QTextTableCell::minimumSize() const
7977{ 7603{
7978 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance); 7604 int extra = 2 * ( parent->innerborder + parent->cellpadding + border_tolerance);
7979 return QSize( QMAX( richtext->minimumWidth() + extra, minw), 0 ); 7605 return QSize( QMAX( richtext->minimumWidth() + extra, minw), 0 );
7980} 7606}
7981 7607
7982QSize QTextTableCell::maximumSize() const 7608QSize QTextTableCell::maximumSize() const
7983{ 7609{
7984 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); 7610 return QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
7985} 7611}
7986 7612
@@ -7998,88 +7624,221 @@ void QTextTableCell::setGeometry( const QRect& r )
7998 int extra = 2 * ( parent->innerborder + parent->cellpadding ); 7624 int extra = 2 * ( parent->innerborder + parent->cellpadding );
7999 if ( r.width() != cached_width ) 7625 if ( r.width() != cached_width )
8000 richtext->doLayout( QTextFormat::painter(), r.width() - extra ); 7626 richtext->doLayout( QTextFormat::painter(), r.width() - extra );
8001 cached_width = r.width(); 7627 cached_width = r.width();
8002 geom = r; 7628 geom = r;
8003} 7629}
8004 7630
8005QRect QTextTableCell::geometry() const 7631QRect QTextTableCell::geometry() const
8006{ 7632{
8007 return geom; 7633 return geom;
8008} 7634}
8009 7635
8010bool QTextTableCell::hasHeightForWidth() const 7636bool QTextTableCell::hasHeightForWidth() const
8011{ 7637{
8012 return TRUE; 7638 return TRUE;
8013} 7639}
8014 7640
8015int QTextTableCell::heightForWidth( int w ) const 7641int QTextTableCell::heightForWidth( int w ) const
8016{ 7642{
8017 int extra = 2 * ( parent->innerborder + parent->cellpadding ); 7643 int extra = 2 * ( parent->innerborder + parent->cellpadding );
8018 w = QMAX( minw, w ); 7644 w = QMAX( minw, w );
8019 7645
8020 if ( cached_width != w ) { 7646 if ( cached_width != w ) {
8021 QTextTableCell* that = (QTextTableCell*) this; 7647 QTextTableCell* that = (QTextTableCell*) this;
8022 that->richtext->doLayout( QTextFormat::painter(), w - extra ); 7648 that->richtext->doLayout( QTextFormat::painter(), w - extra );
8023 that->cached_width = w; 7649 that->cached_width = w;
8024 } 7650 }
8025 return richtext->height() + extra; 7651 return richtext->height() + extra;
8026} 7652}
8027 7653
8028void QTextTableCell::adjustToPainter( QPainter* p ) 7654void QTextTableCell::adjustToPainter( QPainter* p )
8029{ 7655{
8030 QTextParag *parag = richtext->firstParag(); 7656 QTextParagraph *parag = richtext->firstParagraph();
8031 while ( parag ) { 7657 while ( parag ) {
8032 parag->adjustToPainter( p ); 7658 parag->adjustToPainter( p );
8033 parag = parag->next(); 7659 parag = parag->next();
8034 } 7660 }
8035} 7661}
8036 7662
8037int QTextTableCell::horizontalAlignmentOffset() const 7663int QTextTableCell::horizontalAlignmentOffset() const
8038{ 7664{
8039 return parent->cellpadding; 7665 return parent->cellpadding;
8040} 7666}
8041 7667
8042int QTextTableCell::verticalAlignmentOffset() const 7668int QTextTableCell::verticalAlignmentOffset() const
8043{ 7669{
8044 if ( (align & Qt::AlignVCenter ) == Qt::AlignVCenter ) 7670 if ( (align & Qt::AlignVCenter ) == Qt::AlignVCenter )
8045 return ( geom.height() - richtext->height() ) / 2; 7671 return ( geom.height() - richtext->height() ) / 2;
8046 else if ( ( align & Qt::AlignBottom ) == Qt::AlignBottom ) 7672 else if ( ( align & Qt::AlignBottom ) == Qt::AlignBottom )
8047 return geom.height() - parent->cellpadding - richtext->height() ; 7673 return geom.height() - parent->cellpadding - richtext->height() ;
8048 return parent->cellpadding; 7674 return parent->cellpadding;
8049} 7675}
8050 7676
8051void QTextTableCell::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool ) 7677void QTextTableCell::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool )
8052{ 7678{
8053 if ( cached_width != geom.width() ) { 7679 if ( cached_width != geom.width() ) {
8054 int extra = 2 * ( parent->innerborder + parent->cellpadding ); 7680 int extra = 2 * ( parent->innerborder + parent->cellpadding );
8055 richtext->doLayout( p, geom.width() - extra ); 7681 richtext->doLayout( p, geom.width() - extra );
8056 cached_width = geom.width(); 7682 cached_width = geom.width();
8057 } 7683 }
8058 QColorGroup g( cg ); 7684 QColorGroup g( cg );
8059 if ( background ) 7685 if ( background )
8060 g.setBrush( QColorGroup::Base, *background ); 7686 g.setBrush( QColorGroup::Base, *background );
8061 else if ( richtext->paper() ) 7687 else if ( richtext->paper() )
8062 g.setBrush( QColorGroup::Base, *richtext->paper() ); 7688 g.setBrush( QColorGroup::Base, *richtext->paper() );
8063 7689
8064 p->save(); 7690 p->save();
8065 p->translate( x + geom.x(), y + geom.y() ); 7691 p->translate( x + geom.x(), y + geom.y() );
8066 if ( background ) 7692 if ( background )
8067 p->fillRect( 0, 0, geom.width(), geom.height(), *background ); 7693 p->fillRect( 0, 0, geom.width(), geom.height(), *background );
8068 else if ( richtext->paper() ) 7694 else if ( richtext->paper() )
8069 p->fillRect( 0, 0, geom.width(), geom.height(), *richtext->paper() ); 7695 p->fillRect( 0, 0, geom.width(), geom.height(), *richtext->paper() );
8070 7696
8071 p->translate( horizontalAlignmentOffset(), verticalAlignmentOffset() ); 7697 p->translate( horizontalAlignmentOffset(), verticalAlignmentOffset() );
8072 7698
8073 QRegion r; 7699 QRegion r;
8074 QTextCursor *c = 0;
8075 if ( richtext->parent()->tmpCursor )
8076 c = richtext->parent()->tmpCursor;
8077 if ( cx >= 0 && cy >= 0 ) 7700 if ( cx >= 0 && cy >= 0 )
8078 richtext->draw( p, cx - ( x + horizontalAlignmentOffset() + geom.x() ), 7701 richtext->draw( p, cx - ( x + horizontalAlignmentOffset() + geom.x() ),
8079 cy - ( y + geom.y() + verticalAlignmentOffset() ), 7702 cy - ( y + geom.y() + verticalAlignmentOffset() ),
8080 cw, ch, g, FALSE, (c != 0), c ); 7703 cw, ch, g, FALSE, FALSE, 0 );
8081 else 7704 else
8082 richtext->draw( p, -1, -1, -1, -1, g, FALSE, (c != 0), c ); 7705 richtext->draw( p, -1, -1, -1, -1, g, FALSE, FALSE, 0 );
8083 7706
8084 p->restore(); 7707 p->restore();
8085} 7708}
7709
7710QString QTextDocument::section( QString str, const QString &sep, int start, int end )
7711{
7712 const QChar *uc = str.unicode();
7713 if ( !uc )
7714 return QString();
7715 QString _sep = sep;
7716 const QChar *uc_sep = _sep.unicode();
7717 if(!uc_sep)
7718 return QString();
7719 bool match = FALSE, last_match = TRUE;
7720
7721 //find start
7722 int n = str.length(), sep_len = _sep.length();
7723 const QChar *begin = start < 0 ? uc + n : uc;
7724 while(start) {
7725 match = FALSE;
7726 int c = 0;
7727 for(const QChar *tmp = start < 0 ? begin - sep_len : begin;
7728 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) {
7729 if( *tmp != *(uc_sep + c) )
7730 break;
7731 if(c == sep_len - 1) {
7732 match = TRUE;
7733 break;
7734 }
7735 }
7736 last_match = match;
7737
7738 if(start < 0) {
7739 if(match) {
7740 begin -= sep_len;
7741 if(!++start)
7742 break;
7743 } else {
7744 if(start == -1 && begin == uc)
7745 break;
7746 begin--;
7747 }
7748 } else {
7749 if(match) {
7750 if(!--start)
7751 break;
7752 begin += sep_len;
7753 } else {
7754 if(start == 1 && begin == uc + n)
7755 break;
7756 begin++;
7757 }
7758 }
7759 if(begin > uc + n || begin < uc)
7760 return QString();
7761 }
7762 if(match)
7763 begin+=sep_len;
7764 if(begin > uc + n || begin < uc)
7765 return QString();
7766
7767 //now find last
7768 match = FALSE;
7769 const QChar *last = end < 0 ? uc + n : uc;
7770 if(end == -1) {
7771 int c = 0;
7772 for(const QChar *tmp = end < 0 ? last - sep_len : last;
7773 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) {
7774 if( *tmp != *(uc_sep + c) )
7775 break;
7776 if(c == sep_len - 1) {
7777 match = TRUE;
7778 break;
7779 }
7780 }
7781 } else {
7782 end++;
7783 last_match = TRUE;
7784 while(end) {
7785 match = FALSE;
7786 int c = 0;
7787 for(const QChar *tmp = end < 0 ? last - sep_len : last;
7788 c < sep_len && tmp < uc + n && tmp >= uc; tmp++, c++) {
7789 if( *tmp != *(uc_sep + c) )
7790 break;
7791 if(c == sep_len - 1) {
7792 match = TRUE;
7793 break;
7794 }
7795 }
7796 last_match = match;
7797
7798 if(end < 0) {
7799 if(match) {
7800 if(!++end)
7801 break;
7802 last -= sep_len;
7803 } else {
7804 last--;
7805 }
7806 } else {
7807 if(match) {
7808 last += sep_len;
7809 if(!--end)
7810 break;
7811 } else {
7812 last++;
7813 }
7814 }
7815 if(last >= uc + n) {
7816 last = uc + n;
7817 break;
7818 } else if(last < uc) {
7819 return QString();
7820 }
7821 }
7822 }
7823 if(match)
7824 last -= sep_len;
7825 if(last < uc || last > uc + n || begin >= last)
7826 return QString();
7827
7828 //done
7829 return QString(begin, last - begin);
7830}
7831
7832bool QTextDocument::endsWith( QString str, const QString &s)
7833{
7834 if ( str.isNull() )
7835 return s.isNull();
7836 int pos = str.length() - s.length();
7837 if ( pos < 0 )
7838 return FALSE;
7839 for ( uint i = 0; i < s.length(); i++ ) {
7840 if ( str.unicode()[pos+i] != s[(int)i] )
7841 return FALSE;
7842 }
7843 return TRUE;
7844}
diff --git a/noncore/apps/opie-write/qrichtext_p.cpp b/noncore/apps/opie-write/qrichtext_p.cpp
index fb20730..6783e0b 100644
--- a/noncore/apps/opie-write/qrichtext_p.cpp
+++ b/noncore/apps/opie-write/qrichtext_p.cpp
@@ -27,299 +27,317 @@
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
40using namespace Qt3; 40using namespace Qt3;
41 41
42QTextCommand::~QTextCommand() {} 42QTextCommand::~QTextCommand() {}
43QTextCommand::Commands QTextCommand::type() const { return Invalid; } 43QTextCommand::Commands QTextCommand::type() const { return Invalid; }
44 44
45 45
46QTextCustomItem::~QTextCustomItem() {} 46QTextCustomItem::~QTextCustomItem() {}
47void QTextCustomItem::adjustToPainter( QPainter* p){ if ( p ) width = 0; } 47void QTextCustomItem::adjustToPainter( QPainter* p){ if ( p ) width = 0; }
48QTextCustomItem::Placement QTextCustomItem::placement() const { return PlaceInline; } 48QTextCustomItem::Placement QTextCustomItem::placement() const { return PlaceInline; }
49 49
50bool QTextCustomItem::ownLine() const { return FALSE; } 50bool QTextCustomItem::ownLine() const { return FALSE; }
51void QTextCustomItem::resize( int nwidth ){ width = nwidth; } 51void QTextCustomItem::resize( int nwidth ){ width = nwidth; }
52void QTextCustomItem::invalidate() {} 52void QTextCustomItem::invalidate() {}
53 53
54bool QTextCustomItem::isNested() const { return FALSE; } 54bool QTextCustomItem::isNested() const { return FALSE; }
55int QTextCustomItem::minimumWidth() const { return 0; } 55int QTextCustomItem::minimumWidth() const { return 0; }
56 56
57QString QTextCustomItem::richText() const { return QString::null; } 57QString QTextCustomItem::richText() const { return QString::null; }
58 58
59bool QTextCustomItem::enter( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, bool atEnd ) 59bool QTextCustomItem::enter( QTextCursor *, QTextDocument*&, QTextParagraph *&, int &, int &, int &, bool )
60{ 60{
61 doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; Q_UNUSED( atEnd ) return TRUE; 61 return TRUE;
62
63} 62}
64bool QTextCustomItem::enterAt( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, const QPoint & ) 63bool QTextCustomItem::enterAt( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int &, const QPoint & )
65{ 64{
66 doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; 65 return TRUE;
67} 66}
68bool QTextCustomItem::next( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 67bool QTextCustomItem::next( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
69{ 68{
70 doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; 69 return TRUE;
71} 70}
72bool QTextCustomItem::prev( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 71bool QTextCustomItem::prev( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
73{ 72{
74 doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; 73 return TRUE;
75} 74}
76bool QTextCustomItem::down( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 75bool QTextCustomItem::down( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
77{ 76{
78 doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; 77 return TRUE;
79} 78}
80bool QTextCustomItem::up( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ) 79bool QTextCustomItem::up( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
81{ 80{
82 doc = doc; parag = parag; idx = idx; ox = ox; oy = oy; return TRUE; 81 return TRUE;
83} 82}
84 83
85void QTextFlow::setPageSize( int ps ) { pagesize = ps; } 84void QTextFlow::setPageSize( int ps ) { pagesize = ps; }
86bool QTextFlow::isEmpty() { return leftItems.isEmpty() && rightItems.isEmpty(); } 85bool QTextFlow::isEmpty() { return leftItems.isEmpty() && rightItems.isEmpty(); }
87 86
88void QTextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; } 87void QTextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; }
89 88
90void QTextTable::invalidate() { cachewidth = -1; } 89void QTextTable::invalidate() { cachewidth = -1; }
91 90
92QTextParagData::~QTextParagData() {} 91QTextParagraphData::~QTextParagraphData() {}
93void QTextParagData::join( QTextParagData * ) {} 92void QTextParagraphData::join( QTextParagraphData * ) {}
94 93
95QTextFormatter::~QTextFormatter() {} 94QTextFormatter::~QTextFormatter() {}
96void QTextFormatter::setWrapEnabled( bool b ) { wrapEnabled = b; } 95void QTextFormatter::setWrapEnabled( bool b ) { wrapEnabled = b; }
97void QTextFormatter::setWrapAtColumn( int c ) { wrapColumn = c; } 96void QTextFormatter::setWrapAtColumn( int c ) { wrapColumn = c; }
98 97
99 98
100 99
101int QTextCursor::x() const 100int QTextCursor::x() const
102{ 101{
103 QTextStringChar *c = string->at( idx ); 102 QTextStringChar *c = para->at( idx );
104 int curx = c->x; 103 int curx = c->x;
105 if ( !c->rightToLeft && 104 if ( !c->rightToLeft &&
106 c->c.isSpace() && 105 c->c.isSpace() &&
107 idx > 0 && 106 idx > 0 &&
108 ( string->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) 107 !c->lineStart &&
109 curx = string->at( idx - 1 )->x + string->string()->width( idx - 1 ); 108 ( para->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify )
109 curx = para->at( idx - 1 )->x + para->string()->width( idx - 1 );
110 if ( c->rightToLeft ) 110 if ( c->rightToLeft )
111 curx += string->string()->width( idx ); 111 curx += para->string()->width( idx );
112 return curx; 112 return curx;
113} 113}
114 114
115int QTextCursor::y() const 115int QTextCursor::y() const
116{ 116{
117 int dummy, line; 117 int dummy, line;
118 string->lineStartOfChar( idx, &dummy, &line ); 118 para->lineStartOfChar( idx, &dummy, &line );
119 return string->lineY( line ); 119 return para->lineY( line );
120}
121
122int QTextCursor::globalX() const { return totalOffsetX() + para->rect().x() + x(); }
123int QTextCursor::globalY() const { return totalOffsetY() + para->rect().y() + y(); }
124
125QTextDocument *QTextCursor::document() const
126{
127 return para ? para->document() : 0;
128}
129
130void QTextCursor::gotoPosition( QTextParagraph* p, int index )
131{
132 if ( para && p != para ) {
133 while ( para->document() != p->document() && !indices.isEmpty() )
134 pop();
135 Q_ASSERT( indices.isEmpty() || para->document() == p->document() );
136 }
137 para = p;
138 if ( index < 0 || index >= para->length() ) {
139#if defined(QT_CHECK_RANGE)
140 qWarning( "QTextCursor::gotoParagraph Index: %d out of range", index );
141#endif
142 index = index < 0 ? 0 : para->length() - 1;
143 }
144
145 tmpIndex = -1;
146 idx = index;
120} 147}
121 148
122bool QTextDocument::hasSelection( int id, bool visible ) const 149bool QTextDocument::hasSelection( int id, bool visible ) const
123{ 150{
124 return ( selections.find( id ) != selections.end() && 151 return ( selections.find( id ) != selections.end() &&
125 ( !visible || 152 ( !visible ||
126 ( (QTextDocument*)this )->selectionStartCursor( id ) != 153 ( (QTextDocument*)this )->selectionStartCursor( id ) !=
127 ( (QTextDocument*)this )->selectionEndCursor( id ) ) ); 154 ( (QTextDocument*)this )->selectionEndCursor( id ) ) );
128} 155}
129 156
130void QTextDocument::setSelectionStart( int id, QTextCursor *cursor ) 157void QTextDocument::setSelectionStart( int id, const QTextCursor &cursor )
131{ 158{
132 QTextDocumentSelection sel; 159 QTextDocumentSelection sel;
133 sel.startCursor = *cursor; 160 sel.startCursor = cursor;
134 sel.endCursor = *cursor; 161 sel.endCursor = cursor;
135 sel.swapped = FALSE; 162 sel.swapped = FALSE;
136 selections[ id ] = sel; 163 selections[ id ] = sel;
137} 164}
138 165
139QTextParag *QTextDocument::paragAt( int i ) const 166QTextParagraph *QTextDocument::paragAt( int i ) const
140{ 167{
141 QTextParag* p = curParag; 168 QTextParagraph* p = curParag;
142 if ( !p || p->paragId() > i ) 169 if ( !p || p->paragId() > i )
143 p = fParag; 170 p = fParag;
144 while ( p && p->paragId() != i ) 171 while ( p && p->paragId() != i )
145 p = p->next(); 172 p = p->next();
146 ((QTextDocument*)this)->curParag = p; 173 ((QTextDocument*)this)->curParag = p;
147 return p; 174 return p;
148} 175}
149 176
150 177
151QTextFormat::~QTextFormat() 178QTextFormat::~QTextFormat()
152{ 179{
153} 180}
154 181
155QTextFormat::QTextFormat() 182QTextFormat::QTextFormat()
156 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() ), 183 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() )
157 different( NoFlags )
158{ 184{
159 ref = 0; 185 ref = 0;
160 186
161 usePixelSizes = FALSE; 187 usePixelSizes = FALSE;
162 if ( stdSize == -1 ) { 188 if ( stdSize == -1 ) {
163 stdSize = qApp->font().pixelSize(); 189 stdSize = qApp->font().pixelSize();
164 usePixelSizes = TRUE; 190 usePixelSizes = TRUE;
165 } 191 }
166 192
167 missp = FALSE; 193 missp = FALSE;
168 ha = AlignNormal; 194 ha = AlignNormal;
169 collection = 0; 195 collection = 0;
170} 196}
171 197
172QTextFormat::QTextFormat( const QStyleSheetItem *style ) 198QTextFormat::QTextFormat( const QStyleSheetItem *style )
173 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() ), 199 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() )
174 different( NoFlags )
175{ 200{
176 ref = 0; 201 ref = 0;
177 202
178 usePixelSizes = FALSE; 203 usePixelSizes = FALSE;
179 if ( stdSize == -1 ) { 204 if ( stdSize == -1 ) {
180 stdSize = qApp->font().pixelSize(); 205 stdSize = qApp->font().pixelSize();
181 usePixelSizes = TRUE; 206 usePixelSizes = TRUE;
182 } 207 }
183 208
184 this->style = style->name();
185 missp = FALSE; 209 missp = FALSE;
186 ha = AlignNormal; 210 ha = AlignNormal;
187 collection = 0; 211 collection = 0;
188 fn = QFont( style->fontFamily(), 212 fn = QFont( style->fontFamily(),
189 style->fontSize(), 213 style->fontSize(),
190 style->fontWeight(), 214 style->fontWeight(),
191 style->fontItalic() ); 215 style->fontItalic() );
192 fn.setUnderline( style->fontUnderline() ); 216 fn.setUnderline( style->fontUnderline() );
217 fn.setStrikeOut( style->fontStrikeOut() );
193 col = style->color(); 218 col = style->color();
194 fm = QFontMetrics( fn ); 219 fm = QFontMetrics( fn );
195 leftBearing = fm.minLeftBearing(); 220 leftBearing = fm.minLeftBearing();
196 rightBearing = fm.minRightBearing(); 221 rightBearing = fm.minRightBearing();
197 hei = fm.lineSpacing(); 222 hei = fm.lineSpacing();
198 asc = fm.ascent() + (fm.leading()+1)/2; 223 asc = fm.ascent() + (fm.leading()+1)/2;
199 dsc = fm.descent(); 224 dsc = fm.descent();
200 missp = FALSE; 225 missp = FALSE;
201 ha = AlignNormal; 226 ha = AlignNormal;
202 memset( widths, 0, 256 ); 227 memset( widths, 0, 256 );
203 generateKey(); 228 generateKey();
204 addRef(); 229 addRef();
205 updateStyleFlags();
206} 230}
207 231
208QTextFormat::QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent ) 232QTextFormat::QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent )
209 : fn( f ), col( c ), fm( QFontMetrics( f ) ), linkColor( TRUE ), 233 : fn( f ), col( c ), fm( QFontMetrics( f ) ), linkColor( TRUE ),
210 logicalFontSize( 3 ), stdSize( f.pointSize() ), different( NoFlags ) 234 logicalFontSize( 3 ), stdSize( f.pointSize() )
211{ 235{
212 ref = 0; 236 ref = 0;
213 usePixelSizes = FALSE; 237 usePixelSizes = FALSE;
214 if ( stdSize == -1 ) { 238 if ( stdSize == -1 ) {
215 stdSize = f.pixelSize(); 239 stdSize = f.pixelSize();
216 usePixelSizes = TRUE; 240 usePixelSizes = TRUE;
217 } 241 }
218 collection = parent; 242 collection = parent;
219 leftBearing = fm.minLeftBearing(); 243 leftBearing = fm.minLeftBearing();
220 rightBearing = fm.minRightBearing(); 244 rightBearing = fm.minRightBearing();
221 hei = fm.lineSpacing(); 245 hei = fm.lineSpacing();
222 asc = fm.ascent() + (fm.leading()+1)/2; 246 asc = fm.ascent() + (fm.leading()+1)/2;
223 dsc = fm.descent(); 247 dsc = fm.descent();
224 missp = FALSE; 248 missp = FALSE;
225 ha = AlignNormal; 249 ha = AlignNormal;
226 memset( widths, 0, 256 ); 250 memset( widths, 0, 256 );
227 generateKey(); 251 generateKey();
228 addRef(); 252 addRef();
229 updateStyleFlags();
230} 253}
231 254
232QTextFormat::QTextFormat( const QTextFormat &f ) 255QTextFormat::QTextFormat( const QTextFormat &f )
233 : fm( f.fm ) 256 : fm( f.fm )
234{ 257{
235 ref = 0; 258 ref = 0;
236 collection = 0; 259 collection = 0;
237 fn = f.fn; 260 fn = f.fn;
238 col = f.col; 261 col = f.col;
239 leftBearing = f.leftBearing; 262 leftBearing = f.leftBearing;
240 rightBearing = f.rightBearing; 263 rightBearing = f.rightBearing;
241 memset( widths, 0, 256 ); 264 memset( widths, 0, 256 );
242 hei = f.hei; 265 hei = f.hei;
243 asc = f.asc; 266 asc = f.asc;
244 dsc = f.dsc; 267 dsc = f.dsc;
245 stdSize = f.stdSize; 268 stdSize = f.stdSize;
246 usePixelSizes = f.usePixelSizes; 269 usePixelSizes = f.usePixelSizes;
247 logicalFontSize = f.logicalFontSize; 270 logicalFontSize = f.logicalFontSize;
248 missp = f.missp; 271 missp = f.missp;
249 ha = f.ha; 272 ha = f.ha;
250 k = f.k; 273 k = f.k;
251 linkColor = f.linkColor; 274 linkColor = f.linkColor;
252 style = f.style;
253 different = f.different;
254 addRef(); 275 addRef();
255} 276}
256 277
257QTextFormat& QTextFormat::operator=( const QTextFormat &f ) 278QTextFormat& QTextFormat::operator=( const QTextFormat &f )
258{ 279{
259 ref = 0; 280 ref = 0;
260 collection = f.collection; 281 collection = f.collection;
261 fn = f.fn; 282 fn = f.fn;
262 col = f.col; 283 col = f.col;
263 fm = f.fm; 284 fm = f.fm;
264 leftBearing = f.leftBearing; 285 leftBearing = f.leftBearing;
265 rightBearing = f.rightBearing; 286 rightBearing = f.rightBearing;
266 memset( widths, 0, 256 ); 287 memset( widths, 0, 256 );
267 hei = f.hei; 288 hei = f.hei;
268 asc = f.asc; 289 asc = f.asc;
269 dsc = f.dsc; 290 dsc = f.dsc;
270 stdSize = f.stdSize; 291 stdSize = f.stdSize;
271 usePixelSizes = f.usePixelSizes; 292 usePixelSizes = f.usePixelSizes;
272 logicalFontSize = f.logicalFontSize; 293 logicalFontSize = f.logicalFontSize;
273 missp = f.missp; 294 missp = f.missp;
274 ha = f.ha; 295 ha = f.ha;
275 k = f.k; 296 k = f.k;
276 linkColor = f.linkColor; 297 linkColor = f.linkColor;
277 style = f.style;
278 different = f.different;
279 addRef(); 298 addRef();
280 return *this; 299 return *this;
281} 300}
282 301
283void QTextFormat::update() 302void QTextFormat::update()
284{ 303{
285 fm = QFontMetrics( fn ); 304 fm = QFontMetrics( fn );
286 leftBearing = fm.minLeftBearing(); 305 leftBearing = fm.minLeftBearing();
287 rightBearing = fm.minRightBearing(); 306 rightBearing = fm.minRightBearing();
288 hei = fm.lineSpacing(); 307 hei = fm.lineSpacing();
289 asc = fm.ascent() + (fm.leading()+1)/2; 308 asc = fm.ascent() + (fm.leading()+1)/2;
290 dsc = fm.descent(); 309 dsc = fm.descent();
291 memset( widths, 0, 256 ); 310 memset( widths, 0, 256 );
292 generateKey(); 311 generateKey();
293 updateStyleFlags();
294} 312}
295 313
296 314
297QPainter* QTextFormat::pntr = 0; 315QPainter* QTextFormat::pntr = 0;
298 316
299void QTextFormat::setPainter( QPainter *p ) 317void QTextFormat::setPainter( QPainter *p )
300{ 318{
301 pntr = p; 319 pntr = p;
302} 320}
303 321
304QPainter* QTextFormat::painter() 322QPainter* QTextFormat::painter()
305{ 323{
306 return pntr; 324 return pntr;
307} 325}
308 326
309 327
310int QTextFormat::minLeftBearing() const 328int QTextFormat::minLeftBearing() const
311{ 329{
312 if ( !pntr || !pntr->isActive() ) 330 if ( !pntr || !pntr->isActive() )
313 return leftBearing; 331 return leftBearing;
314 pntr->setFont( fn ); 332 pntr->setFont( fn );
315 return pntr->fontMetrics().minLeftBearing(); 333 return pntr->fontMetrics().minLeftBearing();
316} 334}
317 335
318int QTextFormat::minRightBearing() const 336int QTextFormat::minRightBearing() const
319{ 337{
320 if ( !pntr || !pntr->isActive() ) 338 if ( !pntr || !pntr->isActive() )
321 return rightBearing; 339 return rightBearing;
322 pntr->setFont( fn ); 340 pntr->setFont( fn );
323 return pntr->fontMetrics().minRightBearing(); 341 return pntr->fontMetrics().minRightBearing();
324} 342}
325 343
@@ -343,364 +361,243 @@ int QTextFormat::descent() const
343{ 361{
344 if ( !pntr || !pntr->isActive() ) 362 if ( !pntr || !pntr->isActive() )
345 return dsc; 363 return dsc;
346 pntr->setFont( fn ); 364 pntr->setFont( fn );
347 return pntr->fontMetrics().descent(); 365 return pntr->fontMetrics().descent();
348} 366}
349 367
350int QTextFormat::leading() const 368int QTextFormat::leading() const
351{ 369{
352 if ( !pntr || !pntr->isActive() ) 370 if ( !pntr || !pntr->isActive() )
353 return fm.leading(); 371 return fm.leading();
354 pntr->setFont( fn ); 372 pntr->setFont( fn );
355 return pntr->fontMetrics().leading(); 373 return pntr->fontMetrics().leading();
356} 374}
357 375
358void QTextFormat::generateKey() 376void QTextFormat::generateKey()
359{ 377{
360 k = getKey( fn, col, isMisspelled(), vAlign() ); 378 k = getKey( fn, col, isMisspelled(), vAlign() );
361} 379}
362 380
363QString QTextFormat::getKey( const QFont &fn, const QColor &col, bool misspelled, VerticalAlignment a ) 381QString QTextFormat::getKey( const QFont &fn, const QColor &col, bool misspelled, VerticalAlignment a )
364{ 382{
365 QString k = fn.key(); 383 QString k = fn.key();
366 k += '/'; 384 k += '/';
367 k += QString::number( (uint)col.rgb() ); 385 k += QString::number( (uint)col.rgb() );
368 k += '/'; 386 k += '/';
369 k += QString::number( (int)misspelled ); 387 k += QString::number( (int)misspelled );
370 k += '/'; 388 k += '/';
371 k += QString::number( (int)a ); 389 k += QString::number( (int)a );
372 return k; 390 return k;
373} 391}
374 392
375void QTextFormat::updateStyle()
376{
377 if ( !collection || !collection->styleSheet() )
378 return;
379 QStyleSheetItem *item = collection->styleSheet()->item( style );
380 if ( !item )
381 return;
382 if ( !( different & Color ) && item->color().isValid() )
383 col = item->color();
384 if ( !( different & Size ) && item->fontSize() != -1 )
385 fn.setPointSize( item->fontSize() );
386 if ( !( different & Family ) && !item->fontFamily().isEmpty() )
387 fn.setFamily( item->fontFamily() );
388 if ( !( different & Bold ) && item->fontWeight() != -1 )
389 fn.setWeight( item->fontWeight() );
390 if ( !( different & Italic ) && item->definesFontItalic() )
391 fn.setItalic( item->fontItalic() );
392 if ( !( different & Underline ) && item->definesFontUnderline() )
393 fn.setUnderline( item->fontUnderline() );
394 generateKey();
395 update();
396
397}
398
399void QTextFormat::updateStyleFlags()
400{
401 different = NoFlags;
402 if ( !collection || !collection->styleSheet() )
403 return;
404 QStyleSheetItem *item = collection->styleSheet()->item( style );
405 if ( !item )
406 return;
407 if ( item->color() != col )
408 different |= Color;
409 if ( item->fontSize() != fn.pointSize() )
410 different |= Size;
411 if ( item->fontFamily() != fn.family() )
412 different |= Family;
413 if ( item->fontItalic() != fn.italic() )
414 different |= Italic;
415 if ( item->fontUnderline() != fn.underline() )
416 different |= Underline;
417 if ( item->fontWeight() != fn.weight() )
418 different |= Bold;
419}
420
421QString QTextString::toString( const QMemArray<QTextStringChar> &data ) 393QString QTextString::toString( const QMemArray<QTextStringChar> &data )
422{ 394{
423 QString s; 395 QString s;
424 int l = data.size(); 396 int l = data.size();
425 s.setUnicode( 0, l ); 397 s.setUnicode( 0, l );
426 QTextStringChar *c = data.data(); 398 QTextStringChar *c = data.data();
427 QChar *uc = (QChar *)s.unicode(); 399 QChar *uc = (QChar *)s.unicode();
428 while ( l-- ) { 400 while ( l-- ) {
429 *uc = c->c; 401 *uc = c->c;
430 // ### workaround so that non-breaking whitespaces are drawn 402 // ### workaround so that non-breaking whitespaces are drawn
431 // properly, actually this should be fixed in QFont somewhere 403 // properly, actually this should be fixed in QFont somewhere
432 if ( *uc == (char)0xa0 ) 404 if ( *uc == (char)0xa0 )
433 *uc = 0x20; 405 *uc = 0x20;
434 uc++; 406 uc++;
435 c++; 407 c++;
436 } 408 }
437 409
438 return s; 410 return s;
439} 411}
440 412
441QString QTextString::toString() const 413QString QTextString::toString() const
442{ 414{
443 return toString( data ); 415 return toString( data );
444} 416}
445 417
446void QTextParag::setSelection( int id, int start, int end ) 418void QTextParagraph::setSelection( int id, int start, int end )
447{ 419{
448 QMap<int, QTextParagSelection>::ConstIterator it = selections().find( id ); 420 QMap<int, QTextParagraphSelection>::ConstIterator it = selections().find( id );
449 if ( it != mSelections->end() ) { 421 if ( it != mSelections->end() ) {
450 if ( start == ( *it ).start && end == ( *it ).end ) 422 if ( start == ( *it ).start && end == ( *it ).end )
451 return; 423 return;
452 } 424 }
453 425
454 QTextParagSelection sel; 426 QTextParagraphSelection sel;
455 sel.start = start; 427 sel.start = start;
456 sel.end = end; 428 sel.end = end;
457 (*mSelections)[ id ] = sel; 429 (*mSelections)[ id ] = sel;
458 setChanged( TRUE, TRUE ); 430 setChanged( TRUE, TRUE );
459} 431}
460 432
461void QTextParag::removeSelection( int id ) 433void QTextParagraph::removeSelection( int id )
462{ 434{
463 if ( !hasSelection( id ) ) 435 if ( !hasSelection( id ) )
464 return; 436 return;
465 if ( mSelections ) 437 if ( mSelections )
466 mSelections->remove( id ); 438 mSelections->remove( id );
467 setChanged( TRUE, TRUE ); 439 setChanged( TRUE, TRUE );
468} 440}
469 441
470int QTextParag::selectionStart( int id ) const 442int QTextParagraph::selectionStart( int id ) const
471{ 443{
472 if ( !mSelections ) 444 if ( !mSelections )
473 return -1; 445 return -1;
474 QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id ); 446 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
475 if ( it == mSelections->end() ) 447 if ( it == mSelections->end() )
476 return -1; 448 return -1;
477 return ( *it ).start; 449 return ( *it ).start;
478} 450}
479 451
480int QTextParag::selectionEnd( int id ) const 452int QTextParagraph::selectionEnd( int id ) const
481{ 453{
482 if ( !mSelections ) 454 if ( !mSelections )
483 return -1; 455 return -1;
484 QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id ); 456 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
485 if ( it == mSelections->end() ) 457 if ( it == mSelections->end() )
486 return -1; 458 return -1;
487 return ( *it ).end; 459 return ( *it ).end;
488} 460}
489 461
490bool QTextParag::hasSelection( int id ) const 462bool QTextParagraph::hasSelection( int id ) const
491{ 463{
492 if ( !mSelections ) 464 return mSelections ? mSelections->contains( id ) : FALSE;
493 return FALSE;
494 QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id );
495 if ( it == mSelections->end() )
496 return FALSE;
497 return ( *it ).start != ( *it ).end || length() == 1;
498} 465}
499 466
500bool QTextParag::fullSelected( int id ) const 467bool QTextParagraph::fullSelected( int id ) const
501{ 468{
502 if ( !mSelections ) 469 if ( !mSelections )
503 return FALSE; 470 return FALSE;
504 QMap<int, QTextParagSelection>::ConstIterator it = mSelections->find( id ); 471 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
505 if ( it == mSelections->end() ) 472 if ( it == mSelections->end() )
506 return FALSE; 473 return FALSE;
507 return ( *it ).start == 0 && ( *it ).end == str->length() - 1; 474 return ( *it ).start == 0 && ( *it ).end == str->length() - 1;
508} 475}
509 476
510int QTextParag::lineY( int l ) const 477int QTextParagraph::lineY( int l ) const
511{ 478{
512 if ( l > (int)lineStarts.count() - 1 ) { 479 if ( l > (int)lineStarts.count() - 1 ) {
513 qWarning( "QTextParag::lineY: line %d out of range!", l ); 480 qWarning( "QTextParagraph::lineY: line %d out of range!", l );
514 return 0; 481 return 0;
515 } 482 }
516 483
517 if ( !isValid() ) 484 if ( !isValid() )
518 ( (QTextParag*)this )->format(); 485 ( (QTextParagraph*)this )->format();
519 486
520 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); 487 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
521 while ( l-- > 0 ) 488 while ( l-- > 0 )
522 ++it; 489 ++it;
523 return ( *it )->y; 490 return ( *it )->y;
524} 491}
525 492
526int QTextParag::lineBaseLine( int l ) const 493int QTextParagraph::lineBaseLine( int l ) const
527{ 494{
528 if ( l > (int)lineStarts.count() - 1 ) { 495 if ( l > (int)lineStarts.count() - 1 ) {
529 qWarning( "QTextParag::lineBaseLine: line %d out of range!", l ); 496 qWarning( "QTextParagraph::lineBaseLine: line %d out of range!", l );
530 return 10; 497 return 10;
531 } 498 }
532 499
533 if ( !isValid() ) 500 if ( !isValid() )
534 ( (QTextParag*)this )->format(); 501 ( (QTextParagraph*)this )->format();
535 502
536 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); 503 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
537 while ( l-- > 0 ) 504 while ( l-- > 0 )
538 ++it; 505 ++it;
539 return ( *it )->baseLine; 506 return ( *it )->baseLine;
540} 507}
541 508
542int QTextParag::lineHeight( int l ) const 509int QTextParagraph::lineHeight( int l ) const
543{ 510{
544 if ( l > (int)lineStarts.count() - 1 ) { 511 if ( l > (int)lineStarts.count() - 1 ) {
545 qWarning( "QTextParag::lineHeight: line %d out of range!", l ); 512 qWarning( "QTextParagraph::lineHeight: line %d out of range!", l );
546 return 15; 513 return 15;
547 } 514 }
548 515
549 if ( !isValid() ) 516 if ( !isValid() )
550 ( (QTextParag*)this )->format(); 517 ( (QTextParagraph*)this )->format();
551 518
552 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); 519 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
553 while ( l-- > 0 ) 520 while ( l-- > 0 )
554 ++it; 521 ++it;
555 return ( *it )->h; 522 return ( *it )->h;
556} 523}
557 524
558void QTextParag::lineInfo( int l, int &y, int &h, int &bl ) const 525void QTextParagraph::lineInfo( int l, int &y, int &h, int &bl ) const
559{ 526{
560 if ( l > (int)lineStarts.count() - 1 ) { 527 if ( l > (int)lineStarts.count() - 1 ) {
561 qWarning( "QTextParag::lineInfo: line %d out of range!", l ); 528 qWarning( "QTextParagraph::lineInfo: line %d out of range!", l );
562 qDebug( "%d %d", (int)lineStarts.count() - 1, l ); 529 qDebug( "%d %d", (int)lineStarts.count() - 1, l );
563 y = 0; 530 y = 0;
564 h = 15; 531 h = 15;
565 bl = 10; 532 bl = 10;
566 return; 533 return;
567 } 534 }
568 535
569 if ( !isValid() ) 536 if ( !isValid() )
570 ( (QTextParag*)this )->format(); 537 ( (QTextParagraph*)this )->format();
571 538
572 QMap<int, QTextParagLineStart*>::ConstIterator it = lineStarts.begin(); 539 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
573 while ( l-- > 0 ) 540 while ( l-- > 0 )
574 ++it; 541 ++it;
575 y = ( *it )->y; 542 y = ( *it )->y;
576 h = ( *it )->h; 543 h = ( *it )->h;
577 bl = ( *it )->baseLine; 544 bl = ( *it )->baseLine;
578} 545}
579 546
580int QTextParag::alignment() const
581{
582 if ( align != -1 )
583 return align;
584 QStyleSheetItem *item = style();
585 if ( !item )
586 return Qt3::AlignAuto;
587 if ( mStyleSheetItemsVec ) {
588 for ( int i = 0; i < (int)mStyleSheetItemsVec->size(); ++i ) {
589 item = (*mStyleSheetItemsVec)[ i ];
590 if ( item->alignment() != QStyleSheetItem::Undefined )
591 return item->alignment();
592 }
593 }
594 return Qt3::AlignAuto;
595}
596 547
597QPtrVector<QStyleSheetItem> QTextParag::styleSheetItems() const 548void QTextParagraph::setAlignment( int a )
598{ 549{
599 QPtrVector<QStyleSheetItem> vec; 550 if ( a == (int)align )
600 if ( mStyleSheetItemsVec ) {
601 vec.resize( mStyleSheetItemsVec->size() );
602 for ( int i = 0; i < (int)vec.size(); ++i )
603 vec.insert( i, (*mStyleSheetItemsVec)[ i ] );
604 }
605 return vec;
606}
607
608QStyleSheetItem *QTextParag::style() const
609{
610 if ( !mStyleSheetItemsVec || mStyleSheetItemsVec->size() == 0 )
611 return 0;
612 return (*mStyleSheetItemsVec)[ mStyleSheetItemsVec->size() - 1 ];
613}
614
615int QTextParag::numberOfSubParagraph() const
616{
617 if ( list_val != -1 )
618 return list_val;
619 if ( numSubParag != -1 )
620 return numSubParag;
621 int n = 0;
622 QTextParag *p = (QTextParag*)this;
623 while ( p && ( styleSheetItemsVec().size() >= p->styleSheetItemsVec().size() &&
624 styleSheetItemsVec()[ (int)p->styleSheetItemsVec().size() - 1 ] == p->style() ||
625 p->styleSheetItemsVec().size() >= styleSheetItemsVec().size() &&
626 p->styleSheetItemsVec()[ (int)styleSheetItemsVec().size() - 1 ] == style() ) ) {
627 if ( p->style() == style() && listStyle() != p->listStyle()
628 && p->styleSheetItemsVec().size() == styleSheetItemsVec().size() )
629 break;
630 if ( p->style()->displayMode() == QStyleSheetItem::DisplayListItem
631 && p->style() != style() || styleSheetItemsVec().size() == p->styleSheetItemsVec().size() )
632 ++n;
633 p = p->prev();
634 }
635 ( (QTextParag*)this )->numSubParag = n;
636 return n;
637}
638
639void QTextParag::setFormat( QTextFormat *fm )
640{
641 bool doUpdate = FALSE;
642 if (defFormat && (defFormat != formatCollection()->defaultFormat()))
643 doUpdate = TRUE;
644 defFormat = formatCollection()->format( fm );
645 if ( !doUpdate )
646 return; 551 return;
647 for ( int i = 0; i < length(); ++i ) { 552 align = a;
648 if ( at( i )->format()->styleName() == defFormat->styleName() ) 553 invalidate( 0 );
649 at( i )->format()->updateStyle();
650 }
651} 554}
652 555
653QTextFormatter *QTextParag::formatter() const 556QTextFormatter *QTextParagraph::formatter() const
654{ 557{
655 if ( hasdoc ) 558 if ( hasdoc )
656 return document()->formatter(); 559 return document()->formatter();
657 if ( pseudoDocument()->pFormatter ) 560 if ( pseudoDocument()->pFormatter )
658 return pseudoDocument()->pFormatter; 561 return pseudoDocument()->pFormatter;
659 return ( ( (QTextParag*)this )->pseudoDocument()->pFormatter = new QTextFormatterBreakWords ); 562 return ( ( (QTextParagraph*)this )->pseudoDocument()->pFormatter = new QTextFormatterBreakWords );
660} 563}
661 564
662void QTextParag::setTabArray( int *a ) 565void QTextParagraph::setTabArray( int *a )
663{ 566{
664 delete [] tArray; 567 delete [] tArray;
665 tArray = a; 568 tArray = a;
666} 569}
667 570
668void QTextParag::setTabStops( int tw ) 571void QTextParagraph::setTabStops( int tw )
669{ 572{
670 if ( hasdoc ) 573 if ( hasdoc )
671 document()->setTabStops( tw ); 574 document()->setTabStops( tw );
672 else 575 else
673 tabStopWidth = tw; 576 tabStopWidth = tw;
674} 577}
675 578
676QMap<int, QTextParagSelection> &QTextParag::selections() const 579QMap<int, QTextParagraphSelection> &QTextParagraph::selections() const
677{ 580{
678 if ( !mSelections ) 581 if ( !mSelections )
679 ((QTextParag *)this)->mSelections = new QMap<int, QTextParagSelection>; 582 ((QTextParagraph *)this)->mSelections = new QMap<int, QTextParagraphSelection>;
680 return *mSelections; 583 return *mSelections;
681} 584}
682 585
683QPtrVector<QStyleSheetItem> &QTextParag::styleSheetItemsVec() const
684{
685 if ( !mStyleSheetItemsVec )
686 ((QTextParag *)this)->mStyleSheetItemsVec = new QPtrVector<QStyleSheetItem>;
687 return *mStyleSheetItemsVec;
688}
689 586
690QPtrList<QTextCustomItem> &QTextParag::floatingItems() const 587QPtrList<QTextCustomItem> &QTextParagraph::floatingItems() const
691{ 588{
692 if ( !mFloatingItems ) 589 if ( !mFloatingItems )
693 ((QTextParag *)this)->mFloatingItems = new QPtrList<QTextCustomItem>; 590 ((QTextParagraph *)this)->mFloatingItems = new QPtrList<QTextCustomItem>;
694 return *mFloatingItems; 591 return *mFloatingItems;
695} 592}
696 593
697QTextStringChar::~QTextStringChar() 594QTextStringChar::~QTextStringChar()
698{ 595{
699 if ( format() ) 596 if ( format() )
700 format()->removeRef(); 597 format()->removeRef();
701 if ( type ) // not Regular 598 if ( type ) // not Regular
702 delete d.custom; 599 delete d.custom;
703} 600}
704 601
705QTextParagPseudoDocument::QTextParagPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0){} 602QTextParagraphPseudoDocument::QTextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0){}
706QTextParagPseudoDocument::~QTextParagPseudoDocument(){ delete pFormatter; delete commandHistory; } 603QTextParagraphPseudoDocument::~QTextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; }
diff --git a/noncore/apps/opie-write/qrichtext_p.h b/noncore/apps/opie-write/qrichtext_p.h
index 94ce913..e368edb 100644
--- a/noncore/apps/opie-write/qrichtext_p.h
+++ b/noncore/apps/opie-write/qrichtext_p.h
@@ -22,365 +22,356 @@
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#ifndef QRICHTEXT_P_H 38#ifndef QRICHTEXT_P_H
39#define QRICHTEXT_P_H 39#define QRICHTEXT_P_H
40 40
41// 41//
42// W A R N I N G 42// W A R N I N G
43// ------------- 43// -------------
44// 44//
45// This file is not part of the Qt API. It exists for the convenience 45// This file is not part of the Qt API. It exists for the convenience
46// of a number of Qt sources files. This header file may change from 46// of a number of Qt sources files. This header file may change from
47// version to version without notice, or even be removed. 47// version to version without notice, or even be removed.
48// 48//
49// We mean it. 49// We mean it.
50// 50//
51// 51//
52 52
53#ifndef QT_H 53#ifndef QT_H
54#include "qt3namespace.h"
55#include "qstring.h" 54#include "qstring.h"
56#include "qlist.h" 55#include "qlist.h"
57#include "qrect.h" 56#include "qrect.h"
58#include "qfontmetrics.h" 57#include "qfontmetrics.h"
59#include "qintdict.h" 58#include "qintdict.h"
60#include "qmap.h" 59#include "qmap.h"
61#include "qstringlist.h" 60#include "qstringlist.h"
62#include "qfont.h" 61#include "qfont.h"
63#include "qcolor.h" 62#include "qcolor.h"
64#include "qsize.h" 63#include "qsize.h"
65#include "qvaluelist.h" 64#include "qvaluelist.h"
66#include "qvaluestack.h" 65#include "qvaluestack.h"
67#include "qobject.h" 66#include "qobject.h"
68#include "qdict.h" 67#include "qdict.h"
69#include "qtextstream.h" 68#include "qtextstream.h"
70#include "qpixmap.h" 69#include "qpixmap.h"
71#include "qstylesheet.h" 70#include "qstylesheet.h"
72#include "qvector.h" 71#include "qvector.h"
73#include "qpainter.h" 72#include "qpainter.h"
74#include "qlayout.h" 73#include "qlayout.h"
75#include "qobject.h" 74#include "qobject.h"
76#include "qcomplextext_p.h" 75#include "qcomplextext_p.h"
77#include "qapplication.h" 76#include "qapplication.h"
78#include <limits.h> 77#include <limits.h>
79#endif // QT_H 78#endif // QT_H
80 79
81//#define DEBUG_COLLECTION
82
83namespace Qt3 { 80namespace Qt3 {
84 81
85class QTextDocument; 82class QTextDocument;
86class QTextString; 83class QTextString;
87class QTextPreProcessor; 84class QTextPreProcessor;
88class QTextFormat; 85class QTextFormat;
89class QTextCursor; 86class QTextCursor;
90class QTextParag; 87class QTextParagraph;
91class QTextFormatter; 88class QTextFormatter;
92class QTextIndent; 89class QTextIndent;
93class QTextFormatCollection; 90class QTextFormatCollection;
94class QStyleSheetItem; 91class QStyleSheetItem;
95class QTextCustomItem; 92class QTextCustomItem;
96class QTextFlow; 93class QTextFlow;
97struct QBidiContext; 94struct QBidiContext;
98 95
99// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 96// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
100 97
101class Q_EXPORT QTextStringChar 98class Q_EXPORT QTextStringChar
102{ 99{
103 friend class QTextString; 100 friend class QTextString;
104 101
105public: 102public:
106 // this is never called, initialize variables in QTextString::insert()!!! 103 // this is never called, initialize variables in QTextString::insert()!!!
107 QTextStringChar() : lineStart( 0 ), type( Regular ), startOfRun( 0 ) {d.format=0;} 104 QTextStringChar() : lineStart( 0 ), type( Regular ), startOfRun( 0 ) {d.format=0;}
108 ~QTextStringChar(); 105 ~QTextStringChar();
109 106
110 QChar c; 107 QChar c;
111 enum Type { Regular=0, Custom=1, Anchor=2, CustomAnchor=3 }; 108 enum Type { Regular=0, Custom=1, Anchor=2, CustomAnchor=3 };
112 uint lineStart : 1; 109 uint lineStart : 1;
113 uint rightToLeft : 1; 110 uint rightToLeft : 1;
114 uint hasCursor : 1; 111 uint hasCursor : 1;
115 uint canBreak : 1; 112 uint canBreak : 1;
116 Type type : 2; 113 Type type : 2;
117 uint startOfRun : 1; 114 uint startOfRun : 1;
118 115
119 int x; 116 int x;
120 int height() const; 117 int height() const;
121 int ascent() const; 118 int ascent() const;
122 int descent() const; 119 int descent() const;
123 bool isCustom() const { return (type & Custom) != 0; } 120 bool isCustom() const { return (type & Custom) != 0; }
124 QTextFormat *format() const; 121 QTextFormat *format() const;
125 QTextCustomItem *customItem() const; 122 QTextCustomItem *customItem() const;
126 void setFormat( QTextFormat *f ); 123 void setFormat( QTextFormat *f );
127 void setCustomItem( QTextCustomItem *i ); 124 void setCustomItem( QTextCustomItem *i );
128 QTextStringChar *clone() const;
129 struct CustomData 125 struct CustomData
130 { 126 {
131 QTextFormat *format; 127 QTextFormat *format;
132 QTextCustomItem *custom; 128 QTextCustomItem *custom;
133 QString anchorName; 129 QString anchorName;
134 QString anchorHref; 130 QString anchorHref;
135 }; 131 };
136 132
137 void loseCustomItem(); 133 void loseCustomItem();
138 134
139 union { 135 union {
140 QTextFormat* format; 136 QTextFormat* format;
141 CustomData* custom; 137 CustomData* custom;
142 } d; 138 } d;
143 139
144 bool isAnchor() const { return ( type & Anchor) != 0; } 140 bool isAnchor() const { return ( type & Anchor) != 0; }
145 QString anchorName() const; 141 QString anchorName() const;
146 QString anchorHref() const; 142 QString anchorHref() const;
147 void setAnchor( const QString& name, const QString& href ); 143 void setAnchor( const QString& name, const QString& href );
148 144
149private: 145private:
150 QTextStringChar &operator=( const QTextStringChar & ) { 146 QTextStringChar &operator=( const QTextStringChar & ) {
151 //abort(); 147 //abort();
152 return *this; 148 return *this;
153 } 149 }
154 friend class QComplexText; 150 friend class QComplexText;
155 friend class QTextParag; 151 friend class QTextParagraph;
156}; 152};
157 153
158#if defined(Q_TEMPLATEDLL) 154#if defined(Q_TEMPLATEDLL)
159// MOC_SKIP_BEGIN 155// MOC_SKIP_BEGIN
160template class Q_EXPORT QMemArray<QTextStringChar>; 156Q_TEMPLATE_EXTERN template class Q_EXPORT QMemArray<QTextStringChar>;
161// MOC_SKIP_END 157// MOC_SKIP_END
162#endif 158#endif
163 159
164class Q_EXPORT QTextString 160class Q_EXPORT QTextString
165{ 161{
166public: 162public:
167 163
168 QTextString(); 164 QTextString();
169 QTextString( const QTextString &s ); 165 QTextString( const QTextString &s );
170 virtual ~QTextString(); 166 virtual ~QTextString();
171 167
172 static QString toString( const QMemArray<QTextStringChar> &data ); 168 static QString toString( const QMemArray<QTextStringChar> &data );
173 QString toString() const; 169 QString toString() const;
174 170
175 QTextStringChar &at( int i ) const; 171 QTextStringChar &at( int i ) const;
176 int length() const; 172 int length() const;
177 173
178 int width( int idx ) const; 174 int width( int idx ) const;
179 175
180 void insert( int index, const QString &s, QTextFormat *f ); 176 void insert( int index, const QString &s, QTextFormat *f );
181 void insert( int index, QTextStringChar *c ); 177 void insert( int index, const QChar *unicode, int len, QTextFormat *f );
178 void insert( int index, QTextStringChar *c, bool doAddRefFormat = FALSE );
182 void truncate( int index ); 179 void truncate( int index );
183 void remove( int index, int len ); 180 void remove( int index, int len );
184 void clear(); 181 void clear();
185 182
186 void setFormat( int index, QTextFormat *f, bool useCollection ); 183 void setFormat( int index, QTextFormat *f, bool useCollection );
187 184
188 void setBidi( bool b ) { bidi = b; } 185 void setBidi( bool b ) { bidi = b; }
189 bool isBidi() const; 186 bool isBidi() const;
190 bool isRightToLeft() const; 187 bool isRightToLeft() const;
191 QChar::Direction direction() const; 188 QChar::Direction direction() const;
192 void setDirection( QChar::Direction d ) { dir = d; bidiDirty = TRUE; } 189 void setDirection( QChar::Direction d ) { dir = d; bidiDirty = TRUE; }
193 190
194 QMemArray<QTextStringChar> subString( int start = 0, int len = 0xFFFFFF ) const; 191 QMemArray<QTextStringChar> subString( int start = 0, int len = 0xFFFFFF ) const;
195 QMemArray<QTextStringChar> rawData() const { return data; } 192 QMemArray<QTextStringChar> rawData() const { return data; }
196 193
197 void operator=( const QString &s ) { clear(); insert( 0, s, 0 ); } 194 void operator=( const QString &s ) { clear(); insert( 0, s, 0 ); }
198 void operator+=( const QString &s ); 195 void operator+=( const QString &s ) {insert( length(), s, 0 ); }
199 void prepend( const QString &s ) { insert( 0, s, 0 ); } 196 void prepend( const QString &s ) { insert( 0, s, 0 ); }
200 197
201private: 198private:
202 void checkBidi() const; 199 void checkBidi() const;
203 200
204 QMemArray<QTextStringChar> data; 201 QMemArray<QTextStringChar> data;
205 uint bidiDirty : 1; 202 uint bidiDirty : 1;
206 uint bidi : 1; // true when the paragraph has right to left characters 203 uint bidi : 1; // true when the paragraph has right to left characters
207 uint rightToLeft : 1; 204 uint rightToLeft : 1;
208 uint dir : 5; 205 uint dir : 5;
209}; 206};
210 207
211inline bool QTextString::isBidi() const 208inline bool QTextString::isBidi() const
212{ 209{
213 if ( bidiDirty ) 210 if ( bidiDirty )
214 checkBidi(); 211 checkBidi();
215 return bidi; 212 return bidi;
216} 213}
217 214
218inline bool QTextString::isRightToLeft() const 215inline bool QTextString::isRightToLeft() const
219{ 216{
220 if ( bidiDirty ) 217 if ( bidiDirty )
221 checkBidi(); 218 checkBidi();
222 return rightToLeft; 219 return rightToLeft;
223} 220}
224 221
225inline QChar::Direction QTextString::direction() const 222inline QChar::Direction QTextString::direction() const
226{ 223{
227 return (QChar::Direction) dir; 224 return (QChar::Direction) dir;
228} 225}
229 226
230// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 227// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
231 228
232#if defined(Q_TEMPLATEDLL) 229#if defined(Q_TEMPLATEDLL)
233// MOC_SKIP_BEGIN 230// MOC_SKIP_BEGIN
234template class Q_EXPORT QValueStack<int>; 231Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<int>;
235template class Q_EXPORT QValueStack<QTextParag*>; 232Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<QTextParagraph*>;
236template class Q_EXPORT QValueStack<bool>; 233Q_TEMPLATE_EXTERN template class Q_EXPORT QValueStack<bool>;
237// MOC_SKIP_END 234// MOC_SKIP_END
238#endif 235#endif
239 236
240class Q_EXPORT QTextCursor 237class Q_EXPORT QTextCursor
241{ 238{
242public: 239public:
243 QTextCursor( QTextDocument *d ); 240 QTextCursor( QTextDocument *d = 0 );
244 QTextCursor();
245 QTextCursor( const QTextCursor &c ); 241 QTextCursor( const QTextCursor &c );
246 QTextCursor &operator=( const QTextCursor &c ); 242 QTextCursor &operator=( const QTextCursor &c );
247 virtual ~QTextCursor() {} 243 virtual ~QTextCursor() {}
248 244
249 bool operator==( const QTextCursor &c ) const; 245 bool operator==( const QTextCursor &c ) const;
250 bool operator!=( const QTextCursor &c ) const { return !(*this == c); } 246 bool operator!=( const QTextCursor &c ) const { return !(*this == c); }
251 247
252 QTextDocument *document() const { return doc; } 248 QTextParagraph *paragraph() const;
253 void setDocument( QTextDocument *d ); 249 void setParagraph( QTextParagraph*p ) { gotoPosition(p, 0 ); }
254 250 QTextDocument *document() const;
255 QTextParag *parag() const;
256 int index() const; 251 int index() const;
257 void setParag( QTextParag *s, bool restore = TRUE ); 252 void setIndex( int index ) { gotoPosition(paragraph(), index ); }
258 253
254 void gotoPosition( QTextParagraph* p, int index = 0);
259 void gotoLeft(); 255 void gotoLeft();
260 void gotoRight(); 256 void gotoRight();
261 void gotoNextLetter(); 257 void gotoNextLetter();
262 void gotoPreviousLetter(); 258 void gotoPreviousLetter();
263 void gotoUp(); 259 void gotoUp();
264 void gotoDown(); 260 void gotoDown();
265 void gotoLineEnd(); 261 void gotoLineEnd();
266 void gotoLineStart(); 262 void gotoLineStart();
267 void gotoHome(); 263 void gotoHome();
268 void gotoEnd(); 264 void gotoEnd();
269 void gotoPageUp( int visibleHeight ); 265 void gotoPageUp( int visibleHeight );
270 void gotoPageDown( int visibleHeight ); 266 void gotoPageDown( int visibleHeight );
271 void gotoNextWord(); 267 void gotoNextWord();
272 void gotoPreviousWord(); 268 void gotoPreviousWord();
273 void gotoWordLeft(); 269 void gotoWordLeft();
274 void gotoWordRight(); 270 void gotoWordRight();
275 271
276 void insert( const QString &s, bool checkNewLine, QMemArray<QTextStringChar> *formatting = 0 ); 272 void insert( const QString &s, bool checkNewLine, QMemArray<QTextStringChar> *formatting = 0 );
277 void splitAndInsertEmptyParag( bool ind = TRUE, bool updateIds = TRUE ); 273 void splitAndInsertEmptyParagraph( bool ind = TRUE, bool updateIds = TRUE );
278 bool remove(); 274 bool remove();
279 void killLine();
280 void indent(); 275 void indent();
281 276
282 bool atParagStart(); 277 bool atParagStart();
283 bool atParagEnd(); 278 bool atParagEnd();
284 279
285 void setIndex( int i, bool restore = TRUE ); 280 int x() const; // x in current paragraph
286 281 int y() const; // y in current paragraph
287 void checkIndex();
288 282
289 int offsetX() const { return ox; } 283 int globalX() const;
290 int offsetY() const { return oy; } 284 int globalY() const;
291 285
292 QTextParag *topParag() const { return parags.isEmpty() ? string : parags.first(); } 286 QTextParagraph *topParagraph() const { return paras.isEmpty() ? para : paras.first(); }
293 int totalOffsetX() const; 287 int offsetX() const { return ox; } // inner document offset
294 int totalOffsetY() const; 288 int offsetY() const { return oy; } // inner document offset
289 int totalOffsetX() const; // total document offset
290 int totalOffsetY() const; // total document offset
295 291
296 bool place( const QPoint &pos, QTextParag *s ) { return place( pos, s, FALSE ); } 292 bool place( const QPoint &pos, QTextParagraph *s ) { return place( pos, s, FALSE ); }
297 bool place( const QPoint &pos, QTextParag *s, bool link ); 293 bool place( const QPoint &pos, QTextParagraph *s, bool link );
298 void restoreState(); 294 void restoreState();
299 295
300 int x() const;
301 int y() const;
302 296
303 int nestedDepth() const { return (int)indices.count(); } //### size_t/int cast 297 int nestedDepth() const { return (int)indices.count(); } //### size_t/int cast
304 void oneUp() { if ( !indices.isEmpty() ) pop(); } 298 void oneUp() { if ( !indices.isEmpty() ) pop(); }
305 void setValid( bool b ) { valid = b; } 299 void setValid( bool b ) { valid = b; }
306 bool isValid() const { return valid; } 300 bool isValid() const { return valid; }
307 301
308private: 302private:
309 enum Operation { EnterBegin, EnterEnd, Next, Prev, Up, Down }; 303 enum Operation { EnterBegin, EnterEnd, Next, Prev, Up, Down };
310 304
311 void push(); 305 void push();
312 void pop(); 306 void pop();
313 void processNesting( Operation op ); 307 void processNesting( Operation op );
314 void invalidateNested(); 308 void invalidateNested();
315 void gotoIntoNested( const QPoint &globalPos ); 309 void gotoIntoNested( const QPoint &globalPos );
316 310
317 QTextParag *string; 311 QTextParagraph *para;
318 QTextDocument *doc;
319 int idx, tmpIndex; 312 int idx, tmpIndex;
320 int ox, oy; 313 int ox, oy;
321 QValueStack<int> indices; 314 QValueStack<int> indices;
322 QValueStack<QTextParag*> parags; 315 QValueStack<QTextParagraph*> paras;
323 QValueStack<int> xOffsets; 316 QValueStack<int> xOffsets;
324 QValueStack<int> yOffsets; 317 QValueStack<int> yOffsets;
325 QValueStack<bool> nestedStack;
326 uint nested : 1;
327 uint valid : 1; 318 uint valid : 1;
328 319
329}; 320};
330 321
331// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 322// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
332 323
333class Q_EXPORT QTextCommand 324class Q_EXPORT QTextCommand
334{ 325{
335public: 326public:
336 enum Commands { Invalid, Insert, Delete, Format, Alignment, ParagType }; 327 enum Commands { Invalid, Insert, Delete, Format, Style };
337 328
338 QTextCommand( QTextDocument *d ) : doc( d ), cursor( d ) {} 329 QTextCommand( QTextDocument *d ) : doc( d ), cursor( d ) {}
339 virtual ~QTextCommand(); 330 virtual ~QTextCommand();
340 331
341 virtual Commands type() const; 332 virtual Commands type() const;
342 333
343 virtual QTextCursor *execute( QTextCursor *c ) = 0; 334 virtual QTextCursor *execute( QTextCursor *c ) = 0;
344 virtual QTextCursor *unexecute( QTextCursor *c ) = 0; 335 virtual QTextCursor *unexecute( QTextCursor *c ) = 0;
345 336
346protected: 337protected:
347 QTextDocument *doc; 338 QTextDocument *doc;
348 QTextCursor cursor; 339 QTextCursor cursor;
349 340
350}; 341};
351 342
352#if defined(Q_TEMPLATEDLL) 343#if defined(Q_TEMPLATEDLL)
353// MOC_SKIP_BEGIN 344// MOC_SKIP_BEGIN
354template class Q_EXPORT QPtrList<QTextCommand>; 345Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCommand>;
355// MOC_SKIP_END 346// MOC_SKIP_END
356#endif 347#endif
357 348
358class Q_EXPORT QTextCommandHistory 349class Q_EXPORT QTextCommandHistory
359{ 350{
360public: 351public:
361 QTextCommandHistory( int s ) : current( -1 ), steps( s ) { history.setAutoDelete( TRUE ); } 352 QTextCommandHistory( int s ) : current( -1 ), steps( s ) { history.setAutoDelete( TRUE ); }
362 virtual ~QTextCommandHistory(); 353 virtual ~QTextCommandHistory();
363 354
364 void clear() { history.clear(); current = -1; } 355 void clear() { history.clear(); current = -1; }
365 356
366 void addCommand( QTextCommand *cmd ); 357 void addCommand( QTextCommand *cmd );
367 QTextCursor *undo( QTextCursor *c ); 358 QTextCursor *undo( QTextCursor *c );
368 QTextCursor *redo( QTextCursor *c ); 359 QTextCursor *redo( QTextCursor *c );
369 360
370 bool isUndoAvailable(); 361 bool isUndoAvailable();
371 bool isRedoAvailable(); 362 bool isRedoAvailable();
372 363
373 void setUndoDepth( int d ) { steps = d; } 364 void setUndoDepth( int d ) { steps = d; }
374 int undoDepth() const { return steps; } 365 int undoDepth() const { return steps; }
375 366
376 int historySize() const { return history.count(); } 367 int historySize() const { return history.count(); }
377 int currentPosition() const { return current; } 368 int currentPosition() const { return current; }
378 369
379private: 370private:
380 QPtrList<QTextCommand> history; 371 QPtrList<QTextCommand> history;
381 int current, steps; 372 int current, steps;
382 373
383}; 374};
384 375
385inline QTextCommandHistory::~QTextCommandHistory() 376inline QTextCommandHistory::~QTextCommandHistory()
386{ 377{
@@ -392,1332 +383,1251 @@ inline QTextCommandHistory::~QTextCommandHistory()
392class Q_EXPORT QTextCustomItem 383class Q_EXPORT QTextCustomItem
393{ 384{
394public: 385public:
395 QTextCustomItem( QTextDocument *p ) 386 QTextCustomItem( QTextDocument *p )
396 : xpos(0), ypos(-1), width(-1), height(0), parent( p ) 387 : xpos(0), ypos(-1), width(-1), height(0), parent( p )
397 {} 388 {}
398 virtual ~QTextCustomItem(); 389 virtual ~QTextCustomItem();
399 virtual void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) = 0; 390 virtual void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ) = 0;
400 391
401 virtual void adjustToPainter( QPainter* ); 392 virtual void adjustToPainter( QPainter* );
402 393
403 enum Placement { PlaceInline = 0, PlaceLeft, PlaceRight }; 394 enum Placement { PlaceInline = 0, PlaceLeft, PlaceRight };
404 virtual Placement placement() const; 395 virtual Placement placement() const;
405 bool placeInline() { return placement() == PlaceInline; } 396 bool placeInline() { return placement() == PlaceInline; }
406 397
407 virtual bool ownLine() const; 398 virtual bool ownLine() const;
408 virtual void resize( int nwidth ); 399 virtual void resize( int nwidth );
409 virtual void invalidate(); 400 virtual void invalidate();
410 virtual int ascent() const { return height; } 401 virtual int ascent() const { return height; }
411 402
412 virtual bool isNested() const; 403 virtual bool isNested() const;
413 virtual int minimumWidth() const; 404 virtual int minimumWidth() const;
414 405
415 virtual QString richText() const; 406 virtual QString richText() const;
416 407
417 int xpos; // used for floating items 408 int xpos; // used for floating items
418 int ypos; // used for floating items 409 int ypos; // used for floating items
419 int width; 410 int width;
420 int height; 411 int height;
421 412
422 QRect geometry() const { return QRect( xpos, ypos, width, height ); } 413 QRect geometry() const { return QRect( xpos, ypos, width, height ); }
423 414
424 virtual bool enter( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, bool atEnd = FALSE ); 415 virtual bool enter( QTextCursor *, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, bool atEnd = FALSE );
425 virtual bool enterAt( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, const QPoint & ); 416 virtual bool enterAt( QTextCursor *, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, const QPoint & );
426 virtual bool next( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 417 virtual bool next( QTextCursor *, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
427 virtual bool prev( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 418 virtual bool prev( QTextCursor *, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
428 virtual bool down( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 419 virtual bool down( QTextCursor *, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
429 virtual bool up( QTextCursor *, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 420 virtual bool up( QTextCursor *, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
430 421
431 void setParagraph( QTextParag *p ) { parag = p; } 422 void setParagraph( QTextParagraph *p ) { parag = p; }
432 QTextParag *paragrapth() const { return parag; } 423 QTextParagraph *paragraph() const { return parag; }
433 424
434 QTextDocument *parent; 425 QTextDocument *parent;
435 QTextParag *parag; 426 QTextParagraph *parag;
436 427
437 virtual void pageBreak( int y, QTextFlow* flow ); 428 virtual void pageBreak( int y, QTextFlow* flow );
438}; 429};
439 430
440#if defined(Q_TEMPLATEDLL) 431#if defined(Q_TEMPLATEDLL)
441// MOC_SKIP_BEGIN 432// MOC_SKIP_BEGIN
442template class Q_EXPORT QMap<QString, QString>; 433Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QString, QString>;
443// MOC_SKIP_END 434// MOC_SKIP_END
444#endif 435#endif
445 436
446class Q_EXPORT QTextImage : public QTextCustomItem 437class Q_EXPORT QTextImage : public QTextCustomItem
447{ 438{
448public: 439public:
449 QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, 440 QTextImage( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context,
450 QMimeSourceFactory &factory ); 441 QMimeSourceFactory &factory );
451 virtual ~QTextImage(); 442 virtual ~QTextImage();
452 443
453 Placement placement() const { return place; } 444 Placement placement() const { return place; }
454 void adjustToPainter( QPainter* ); 445 void adjustToPainter( QPainter* );
455 int minimumWidth() const { return width; } 446 int minimumWidth() const { return width; }
456 447
457 QString richText() const; 448 QString richText() const;
458 449
459 void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); 450 void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected );
460 451
461private: 452private:
462 QRegion* reg; 453 QRegion* reg;
463 QPixmap pm; 454 QPixmap pm;
464 Placement place; 455 Placement place;
465 int tmpwidth, tmpheight; 456 int tmpwidth, tmpheight;
466 QMap<QString, QString> attributes; 457 QMap<QString, QString> attributes;
467 QString imgId; 458 QString imgId;
468 459
469}; 460};
470 461
471class Q_EXPORT QTextHorizontalLine : public QTextCustomItem 462class Q_EXPORT QTextHorizontalLine : public QTextCustomItem
472{ 463{
473public: 464public:
474 QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context, 465 QTextHorizontalLine( QTextDocument *p, const QMap<QString, QString> &attr, const QString& context,
475 QMimeSourceFactory &factory ); 466 QMimeSourceFactory &factory );
476 virtual ~QTextHorizontalLine(); 467 virtual ~QTextHorizontalLine();
477 468
478 void adjustToPainter( QPainter* ); 469 void adjustToPainter( QPainter* );
479 void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); 470 void draw(QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected );
480 QString richText() const; 471 QString richText() const;
481 472
482 bool ownLine() const { return TRUE; } 473 bool ownLine() const { return TRUE; }
483 474
484private: 475private:
485 int tmpheight; 476 int tmpheight;
486 QColor color; 477 QColor color;
487 478
488}; 479};
489 480
490#if defined(Q_TEMPLATEDLL) 481#if defined(Q_TEMPLATEDLL)
491// MOC_SKIP_BEGIN 482// MOC_SKIP_BEGIN
492template class Q_EXPORT QPtrList<QTextCustomItem>; 483Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextCustomItem>;
493// MOC_SKIP_END 484// MOC_SKIP_END
494#endif 485#endif
495 486
496class Q_EXPORT QTextFlow 487class Q_EXPORT QTextFlow
497{ 488{
498 friend class QTextDocument; 489 friend class QTextDocument;
499 friend class QTextTableCell; 490 friend class QTextTableCell;
500 491
501public: 492public:
502 QTextFlow(); 493 QTextFlow();
503 virtual ~QTextFlow(); 494 virtual ~QTextFlow();
504 495
505 virtual void setWidth( int width ); 496 virtual void setWidth( int width );
506 int width() const; 497 int width() const;
507 498
508 virtual void setPageSize( int ps ); 499 virtual void setPageSize( int ps );
509 int pageSize() const { return pagesize; } 500 int pageSize() const { return pagesize; }
510 501
511 virtual int adjustLMargin( int yp, int h, int margin, int space ); 502 virtual int adjustLMargin( int yp, int h, int margin, int space );
512 virtual int adjustRMargin( int yp, int h, int margin, int space ); 503 virtual int adjustRMargin( int yp, int h, int margin, int space );
513 504
514 virtual void registerFloatingItem( QTextCustomItem* item ); 505 virtual void registerFloatingItem( QTextCustomItem* item );
515 virtual void unregisterFloatingItem( QTextCustomItem* item ); 506 virtual void unregisterFloatingItem( QTextCustomItem* item );
516 virtual QRect boundingRect() const; 507 virtual QRect boundingRect() const;
517 virtual void drawFloatingItems(QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); 508 virtual void drawFloatingItems(QPainter* p, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected );
518 509
519 virtual int adjustFlow( int y, int w, int h ); // adjusts y according to the defined pagesize. Returns the shift. 510 virtual int adjustFlow( int y, int w, int h ); // adjusts y according to the defined pagesize. Returns the shift.
520 511
521 virtual bool isEmpty(); 512 virtual bool isEmpty();
522 513
523 void clear(); 514 void clear();
524 515
525private: 516private:
526 int w; 517 int w;
527 int pagesize; 518 int pagesize;
528 519
529 QPtrList<QTextCustomItem> leftItems; 520 QPtrList<QTextCustomItem> leftItems;
530 QPtrList<QTextCustomItem> rightItems; 521 QPtrList<QTextCustomItem> rightItems;
531 522
532}; 523};
533 524
534inline int QTextFlow::width() const { return w; } 525inline int QTextFlow::width() const { return w; }
535 526
536class QTextTable; 527class QTextTable;
537 528
538class Q_EXPORT QTextTableCell : public QLayoutItem 529class Q_EXPORT QTextTableCell : public QLayoutItem
539{ 530{
540 friend class QTextTable; 531 friend class QTextTable;
541 532
542public: 533public:
543 QTextTableCell( QTextTable* table, 534 QTextTableCell( QTextTable* table,
544 int row, int column, 535 int row, int column,
545 const QMap<QString, QString> &attr, 536 const QMap<QString, QString> &attr,
546 const QStyleSheetItem* style, 537 const QStyleSheetItem* style,
547 const QTextFormat& fmt, const QString& context, 538 const QTextFormat& fmt, const QString& context,
548 QMimeSourceFactory &factory, QStyleSheet *sheet, const QString& doc ); 539 QMimeSourceFactory &factory, QStyleSheet *sheet, const QString& doc );
549 QTextTableCell( QTextTable* table, int row, int column );
550 virtual ~QTextTableCell(); 540 virtual ~QTextTableCell();
551 541
552 QSize sizeHint() const ; 542 QSize sizeHint() const ;
553 QSize minimumSize() const ; 543 QSize minimumSize() const ;
554 QSize maximumSize() const ; 544 QSize maximumSize() const ;
555 QSizePolicy::ExpandData expanding() const; 545 QSizePolicy::ExpandData expanding() const;
556 bool isEmpty() const; 546 bool isEmpty() const;
557 void setGeometry( const QRect& ) ; 547 void setGeometry( const QRect& ) ;
558 QRect geometry() const; 548 QRect geometry() const;
559 549
560 bool hasHeightForWidth() const; 550 bool hasHeightForWidth() const;
561 int heightForWidth( int ) const; 551 int heightForWidth( int ) const;
562 552
563 void adjustToPainter( QPainter* ); 553 void adjustToPainter( QPainter* );
564 554
565 int row() const { return row_; } 555 int row() const { return row_; }
566 int column() const { return col_; } 556 int column() const { return col_; }
567 int rowspan() const { return rowspan_; } 557 int rowspan() const { return rowspan_; }
568 int colspan() const { return colspan_; } 558 int colspan() const { return colspan_; }
569 int stretch() const { return stretch_; } 559 int stretch() const { return stretch_; }
570 560
571 QTextDocument* richText() const { return richtext; } 561 QTextDocument* richText() const { return richtext; }
572 QTextTable* table() const { return parent; } 562 QTextTable* table() const { return parent; }
573 563
574 void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected ); 564 void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected );
575 565
576 QBrush *backGround() const { return background; } 566 QBrush *backGround() const { return background; }
577 virtual void invalidate(); 567 virtual void invalidate();
578 568
579 int verticalAlignmentOffset() const; 569 int verticalAlignmentOffset() const;
580 int horizontalAlignmentOffset() const; 570 int horizontalAlignmentOffset() const;
581 571
582private: 572private:
583 QRect geom; 573 QRect geom;
584 QTextTable* parent; 574 QTextTable* parent;
585 QTextDocument* richtext; 575 QTextDocument* richtext;
586 int row_; 576 int row_;
587 int col_; 577 int col_;
588 int rowspan_; 578 int rowspan_;
589 int colspan_; 579 int colspan_;
590 int stretch_; 580 int stretch_;
591 int maxw; 581 int maxw;
592 int minw; 582 int minw;
593 bool hasFixedWidth; 583 bool hasFixedWidth;
594 QBrush *background; 584 QBrush *background;
595 int cached_width; 585 int cached_width;
596 int cached_sizehint; 586 int cached_sizehint;
597 QMap<QString, QString> attributes; 587 QMap<QString, QString> attributes;
598 int align; 588 int align;
599}; 589};
600 590
601#if defined(Q_TEMPLATEDLL) 591#if defined(Q_TEMPLATEDLL)
602// MOC_SKIP_BEGIN 592// MOC_SKIP_BEGIN
603template class Q_EXPORT QPtrList<QTextTableCell>; 593Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextTableCell>;
604template class Q_EXPORT QMap<QTextCursor*, int>; 594Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<QTextCursor*, int>;
605// MOC_SKIP_END 595// MOC_SKIP_END
606#endif 596#endif
607 597
608class Q_EXPORT QTextTable: public QTextCustomItem 598class Q_EXPORT QTextTable: public QTextCustomItem
609{ 599{
610 friend class QTextTableCell; 600 friend class QTextTableCell;
611 601
612public: 602public:
613 QTextTable( QTextDocument *p, const QMap<QString, QString> &attr ); 603 QTextTable( QTextDocument *p, const QMap<QString, QString> &attr );
614 virtual ~QTextTable(); 604 virtual ~QTextTable();
615 605
616 void adjustToPainter( QPainter *p ); 606 void adjustToPainter( QPainter *p );
617 void pageBreak( int y, QTextFlow* flow ); 607 void pageBreak( int y, QTextFlow* flow );
618 void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, 608 void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch,
619 const QColorGroup& cg, bool selected ); 609 const QColorGroup& cg, bool selected );
620 610
621 bool noErase() const { return TRUE; } 611 bool noErase() const { return TRUE; }
622 bool ownLine() const { return TRUE; } 612 bool ownLine() const { return TRUE; }
623 Placement placement() const { return place; } 613 Placement placement() const { return place; }
624 bool isNested() const { return TRUE; } 614 bool isNested() const { return TRUE; }
625 void resize( int nwidth ); 615 void resize( int nwidth );
626 virtual void invalidate(); 616 virtual void invalidate();
627 617
628 virtual bool enter( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, bool atEnd = FALSE ); 618 virtual bool enter( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, bool atEnd = FALSE );
629 virtual bool enterAt( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy, const QPoint &pos ); 619 virtual bool enterAt( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy, const QPoint &pos );
630 virtual bool next( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 620 virtual bool next( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
631 virtual bool prev( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 621 virtual bool prev( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
632 virtual bool down( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 622 virtual bool down( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
633 virtual bool up( QTextCursor *c, QTextDocument *&doc, QTextParag *&parag, int &idx, int &ox, int &oy ); 623 virtual bool up( QTextCursor *c, QTextDocument *&doc, QTextParagraph *&parag, int &idx, int &ox, int &oy );
634 624
635 QString richText() const; 625 QString richText() const;
636 626
637 int minimumWidth() const; 627 int minimumWidth() const;
638 628
639 QPtrList<QTextTableCell> tableCells() const { return cells; } 629 QPtrList<QTextTableCell> tableCells() const { return cells; }
640 630
641 bool isStretching() const { return stretch; } 631 bool isStretching() const { return stretch; }
642 632
643private: 633private:
644 void format( int w ); 634 void format( int w );
645 void addCell( QTextTableCell* cell ); 635 void addCell( QTextTableCell* cell );
646 636
647private: 637private:
648 QGridLayout* layout; 638 QGridLayout* layout;
649 QPtrList<QTextTableCell> cells; 639 QPtrList<QTextTableCell> cells;
650 int cachewidth; 640 int cachewidth;
651 int fixwidth; 641 int fixwidth;
652 int cellpadding; 642 int cellpadding;
653 int cellspacing; 643 int cellspacing;
654 int border; 644 int border;
655 int outerborder; 645 int outerborder;
656 int stretch; 646 int stretch;
657 int innerborder; 647 int innerborder;
658 int us_cp, us_ib, us_b, us_ob, us_cs; 648 int us_cp, us_ib, us_b, us_ob, us_cs;
659 QMap<QString, QString> attributes; 649 QMap<QString, QString> attributes;
660 QMap<QTextCursor*, int> currCell; 650 QMap<QTextCursor*, int> currCell;
661 Placement place; 651 Placement place;
662 void adjustCells( int y , int shift ); 652 void adjustCells( int y , int shift );
663 int pageBreakFor; 653 int pageBreakFor;
664}; 654};
665 655
666// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 656// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
667 657
668class QTextTableCell; 658class QTextTableCell;
669class QTextParag; 659class QTextParagraph;
670 660
671struct Q_EXPORT QTextDocumentSelection 661struct Q_EXPORT QTextDocumentSelection
672{ 662{
673 QTextCursor startCursor, endCursor; 663 QTextCursor startCursor, endCursor;
674 bool swapped; 664 bool swapped;
675}; 665};
676 666
677#if defined(Q_TEMPLATEDLL) 667#if defined(Q_TEMPLATEDLL)
678// MOC_SKIP_BEGIN 668// MOC_SKIP_BEGIN
679template class Q_EXPORT QMap<int, QColor>; 669Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QColor>;
680template class Q_EXPORT QMap<int, bool>; 670Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, bool>;
681template class Q_EXPORT QMap<int, QTextDocumentSelection>; 671Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextDocumentSelection>;
682template class Q_EXPORT QPtrList<QTextDocument>; 672Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrList<QTextDocument>;
683// MOC_SKIP_END 673// MOC_SKIP_END
684#endif 674#endif
685 675
686class Q_EXPORT QTextDocument : public QObject 676class Q_EXPORT QTextDocument : public QObject
687{ 677{
688 Q_OBJECT 678 Q_OBJECT
689 679
690 friend class QTextTableCell; 680 friend class QTextTableCell;
691 friend class QTextCursor; 681 friend class QTextCursor;
692 friend class QTextEdit; 682 friend class QTextEdit;
693 friend class QTextParag; 683 friend class QTextParagraph;
694 684
695public: 685public:
696 enum SelectionIds { 686 enum SelectionIds {
697 Standard = 0, 687 Standard = 0,
698 Temp = 32000 // This selection must not be drawn, it's used e.g. by undo/redo to 688 Temp = 32000 // This selection must not be drawn, it's used e.g. by undo/redo to
699 // remove multiple lines with removeSelectedText() 689 // remove multiple lines with removeSelectedText()
700 }; 690 };
701 691
702 QTextDocument( QTextDocument *p ); 692 QTextDocument( QTextDocument *p );
703 QTextDocument( QTextDocument *d, QTextFormatCollection *f ); 693 QTextDocument( QTextDocument *d, QTextFormatCollection *f );
704 virtual ~QTextDocument(); 694 virtual ~QTextDocument();
705 695
706 QTextDocument *parent() const { return par; } 696 QTextDocument *parent() const { return par; }
707 QTextParag *parentParag() const { return parParag; } 697 QTextParagraph *parentParagraph() const { return parentPar; }
708 698
709 void setText( const QString &text, const QString &context ); 699 void setText( const QString &text, const QString &context );
710 QMap<QString, QString> attributes() const { return attribs; } 700 QMap<QString, QString> attributes() const { return attribs; }
711 void setAttributes( const QMap<QString, QString> &attr ) { attribs = attr; } 701 void setAttributes( const QMap<QString, QString> &attr ) { attribs = attr; }
712 702
713 QString text() const; 703 QString text() const;
714 QString text( int parag ) const; 704 QString text( int parag ) const;
715 QString originalText() const; 705 QString originalText() const;
716 706
717 int x() const; 707 int x() const;
718 int y() const; 708 int y() const;
719 int width() const; 709 int width() const;
720 int widthUsed() const; 710 int widthUsed() const;
721 int visibleWidth() const; 711 int visibleWidth() const;
722 int height() const; 712 int height() const;
723 void setWidth( int w ); 713 void setWidth( int w );
724 int minimumWidth() const; 714 int minimumWidth() const;
725 bool setMinimumWidth( int needed, int used = -1, QTextParag *parag = 0 ); 715 bool setMinimumWidth( int needed, int used = -1, QTextParagraph *parag = 0 );
726 716
727 void setY( int y ); 717 void setY( int y );
728 int leftMargin() const; 718 int leftMargin() const;
729 void setLeftMargin( int lm ); 719 void setLeftMargin( int lm );
730 int rightMargin() const; 720 int rightMargin() const;
731 void setRightMargin( int rm ); 721 void setRightMargin( int rm );
732 722
733 QTextParag *firstParag() const; 723 QTextParagraph *firstParagraph() const;
734 QTextParag *lastParag() const; 724 QTextParagraph *lastParagraph() const;
735 void setFirstParag( QTextParag *p ); 725 void setFirstParagraph( QTextParagraph *p );
736 void setLastParag( QTextParag *p ); 726 void setLastParagraph( QTextParagraph *p );
737 727
738 void invalidate(); 728 void invalidate();
739 729
740 void setPreProcessor( QTextPreProcessor *sh ); 730 void setPreProcessor( QTextPreProcessor *sh );
741 QTextPreProcessor *preProcessor() const; 731 QTextPreProcessor *preProcessor() const;
742 732
743 void setFormatter( QTextFormatter *f ); 733 void setFormatter( QTextFormatter *f );
744 QTextFormatter *formatter() const; 734 QTextFormatter *formatter() const;
745 735
746 void setIndent( QTextIndent *i ); 736 void setIndent( QTextIndent *i );
747 QTextIndent *indent() const; 737 QTextIndent *indent() const;
748 738
749 QColor selectionColor( int id ) const; 739 QColor selectionColor( int id ) const;
750 bool invertSelectionText( int id ) const; 740 bool invertSelectionText( int id ) const;
751 void setSelectionColor( int id, const QColor &c ); 741 void setSelectionColor( int id, const QColor &c );
752 void setInvertSelectionText( int id, bool b ); 742 void setInvertSelectionText( int id, bool b );
753 bool hasSelection( int id, bool visible = FALSE ) const; 743 bool hasSelection( int id, bool visible = FALSE ) const;
754 void setSelectionStart( int id, QTextCursor *cursor ); 744 void setSelectionStart( int id, const QTextCursor &cursor );
755 bool setSelectionEnd( int id, QTextCursor *cursor ); 745 bool setSelectionEnd( int id, const QTextCursor &cursor );
756 void selectAll( int id ); 746 void selectAll( int id );
757 bool removeSelection( int id ); 747 bool removeSelection( int id );
758 void selectionStart( int id, int &paragId, int &index ); 748 void selectionStart( int id, int &paragId, int &index );
759 QTextCursor selectionStartCursor( int id ); 749 QTextCursor selectionStartCursor( int id );
760 QTextCursor selectionEndCursor( int id ); 750 QTextCursor selectionEndCursor( int id );
761 void selectionEnd( int id, int &paragId, int &index ); 751 void selectionEnd( int id, int &paragId, int &index );
762 void setFormat( int id, QTextFormat *f, int flags ); 752 void setFormat( int id, QTextFormat *f, int flags );
763 QTextParag *selectionStart( int id );
764 QTextParag *selectionEnd( int id );
765 int numSelections() const { return nSelections; } 753 int numSelections() const { return nSelections; }
766 void addSelection( int id ); 754 void addSelection( int id );
767 755
768 QString selectedText( int id, bool withCustom = TRUE ) const; 756 QString selectedText( int id, bool asRichText = FALSE ) const;
769 void copySelectedText( int id );
770 void removeSelectedText( int id, QTextCursor *cursor ); 757 void removeSelectedText( int id, QTextCursor *cursor );
771 void indentSelection( int id ); 758 void indentSelection( int id );
772 759
773 QTextParag *paragAt( int i ) const; 760 QTextParagraph *paragAt( int i ) const;
774 761
775 void addCommand( QTextCommand *cmd ); 762 void addCommand( QTextCommand *cmd );
776 QTextCursor *undo( QTextCursor *c = 0 ); 763 QTextCursor *undo( QTextCursor *c = 0 );
777 QTextCursor *redo( QTextCursor *c = 0 ); 764 QTextCursor *redo( QTextCursor *c = 0 );
778 QTextCommandHistory *commands() const { return commandHistory; } 765 QTextCommandHistory *commands() const { return commandHistory; }
779 766
780 QTextFormatCollection *formatCollection() const; 767 QTextFormatCollection *formatCollection() const;
781 768
782 bool find( const QString &expr, bool cs, bool wo, bool forward, int *parag, int *index, QTextCursor *cursor ); 769 bool find( QTextCursor &cursor, const QString &expr, bool cs, bool wo, bool forward);
783 770
784 void setTextFormat( Qt::TextFormat f ); 771 void setTextFormat( Qt::TextFormat f );
785 Qt::TextFormat textFormat() const; 772 Qt::TextFormat textFormat() const;
786 773
787 bool inSelection( int selId, const QPoint &pos ) const; 774 bool inSelection( int selId, const QPoint &pos ) const;
788 775
789 QStyleSheet *styleSheet() const { return sheet_; } 776 QStyleSheet *styleSheet() const { return sheet_; }
790 QMimeSourceFactory *mimeSourceFactory() const { return factory_; } 777 QMimeSourceFactory *mimeSourceFactory() const { return factory_; }
791 QString context() const { return contxt; } 778 QString context() const { return contxt; }
792 779
793 void setStyleSheet( QStyleSheet *s ); 780 void setStyleSheet( QStyleSheet *s );
794 void updateStyles(); 781 void setDefaultFormat( const QFont &font, const QColor &color );
795 void updateFontSizes( int base, bool usePixels );
796 void updateFontAttributes( const QFont &f, const QFont &old );
797 void setMimeSourceFactory( QMimeSourceFactory *f ) { if ( f ) factory_ = f; } 782 void setMimeSourceFactory( QMimeSourceFactory *f ) { if ( f ) factory_ = f; }
798 void setContext( const QString &c ) { if ( !c.isEmpty() ) contxt = c; } 783 void setContext( const QString &c ) { if ( !c.isEmpty() ) contxt = c; }
799 784
800 void setUnderlineLinks( bool b ) { underlLinks = b; } 785 void setUnderlineLinks( bool b );
801 bool underlineLinks() const { return underlLinks; } 786 bool underlineLinks() const { return underlLinks; }
802 787
803 void setPaper( QBrush *brush ) { if ( backBrush ) delete backBrush; backBrush = brush; } 788 void setPaper( QBrush *brush ) { if ( backBrush ) delete backBrush; backBrush = brush; }
804 QBrush *paper() const { return backBrush; } 789 QBrush *paper() const { return backBrush; }
805 790
806 void doLayout( QPainter *p, int w ); 791 void doLayout( QPainter *p, int w );
807 void draw( QPainter *p, const QRect& rect, const QColorGroup &cg, const QBrush *paper = 0 ); 792 void draw( QPainter *p, const QRect& rect, const QColorGroup &cg, const QBrush *paper = 0 );
808 void drawParag( QPainter *p, QTextParag *parag, int cx, int cy, int cw, int ch, 793 void drawParagraph( QPainter *p, QTextParagraph *parag, int cx, int cy, int cw, int ch,
809 QPixmap *&doubleBuffer, const QColorGroup &cg, 794 QPixmap *&doubleBuffer, const QColorGroup &cg,
810 bool drawCursor, QTextCursor *cursor, bool resetChanged = TRUE ); 795 bool drawCursor, QTextCursor *cursor, bool resetChanged = TRUE );
811 QTextParag *draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg, 796 QTextParagraph *draw( QPainter *p, int cx, int cy, int cw, int ch, const QColorGroup &cg,
812 bool onlyChanged = FALSE, bool drawCursor = FALSE, QTextCursor *cursor = 0, 797 bool onlyChanged = FALSE, bool drawCursor = FALSE, QTextCursor *cursor = 0,
813 bool resetChanged = TRUE ); 798 bool resetChanged = TRUE );
814 799
815 void setDefaultFont( const QFont &f ); 800 void registerCustomItem( QTextCustomItem *i, QTextParagraph *p );
816 801 void unregisterCustomItem( QTextCustomItem *i, QTextParagraph *p );
817 void registerCustomItem( QTextCustomItem *i, QTextParag *p );
818 void unregisterCustomItem( QTextCustomItem *i, QTextParag *p );
819 802
820 void setFlow( QTextFlow *f ); 803 void setFlow( QTextFlow *f );
821 void takeFlow(); 804 void takeFlow();
822 QTextFlow *flow() const { return flow_; } 805 QTextFlow *flow() const { return flow_; }
823 bool isPageBreakEnabled() const { return pages; } 806 bool isPageBreakEnabled() const { return pages; }
824 void setPageBreakEnabled( bool b ) { pages = b; } 807 void setPageBreakEnabled( bool b ) { pages = b; }
825 808
826 void setUseFormatCollection( bool b ) { useFC = b; } 809 void setUseFormatCollection( bool b ) { useFC = b; }
827 bool useFormatCollection() const { return useFC; } 810 bool useFormatCollection() const { return useFC; }
828 811
829 QTextTableCell *tableCell() const { return tc; } 812 QTextTableCell *tableCell() const { return tc; }
830 void setTableCell( QTextTableCell *c ) { tc = c; } 813 void setTableCell( QTextTableCell *c ) { tc = c; }
831 814
832 void setPlainText( const QString &text ); 815 void setPlainText( const QString &text );
833 void setRichText( const QString &text, const QString &context ); 816 void setRichText( const QString &text, const QString &context );
834 QString richText( QTextParag *p = 0 ) const; 817 QString richText() const;
835 QString plainText( QTextParag *p = 0 ) const; 818 QString plainText() const;
836 819
837 bool focusNextPrevChild( bool next ); 820 bool focusNextPrevChild( bool next );
838 821
839 int alignment() const; 822 int alignment() const;
840 void setAlignment( int a ); 823 void setAlignment( int a );
841 824
842 int *tabArray() const; 825 int *tabArray() const;
843 int tabStopWidth() const; 826 int tabStopWidth() const;
844 void setTabArray( int *a ); 827 void setTabArray( int *a );
845 void setTabStops( int tw ); 828 void setTabStops( int tw );
846 829
847 void setUndoDepth( int d ) { commandHistory->setUndoDepth( d ); } 830 void setUndoDepth( int d ) { commandHistory->setUndoDepth( d ); }
848 int undoDepth() const { return commandHistory->undoDepth(); } 831 int undoDepth() const { return commandHistory->undoDepth(); }
849 832
850 int length() const; 833 int length() const;
851 void clear( bool createEmptyParag = FALSE ); 834 void clear( bool createEmptyParag = FALSE );
852 835
853 virtual QTextParag *createParag( QTextDocument *d, QTextParag *pr = 0, QTextParag *nx = 0, bool updateIds = TRUE ); 836 virtual QTextParagraph *createParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE );
854 void insertChild( QObject *o ) { QObject::insertChild( o ); } 837 void insertChild( QObject *o ) { QObject::insertChild( o ); }
855 void removeChild( QObject *o ) { QObject::removeChild( o ); } 838 void removeChild( QObject *o ) { QObject::removeChild( o ); }
856 void insertChild( QTextDocument *d ) { childList.append( d ); } 839 void insertChild( QTextDocument *d ) { childList.append( d ); }
857 void removeChild( QTextDocument *d ) { childList.removeRef( d ); } 840 void removeChild( QTextDocument *d ) { childList.removeRef( d ); }
858 QPtrList<QTextDocument> children() const { return childList; } 841 QPtrList<QTextDocument> children() const { return childList; }
859 842
860 void setAddMargins( bool b ) { addMargs = b; }
861 int addMargins() const { return addMargs; }
862
863 bool hasFocusParagraph() const; 843 bool hasFocusParagraph() const;
864 QString focusHref() const; 844 QString focusHref() const;
865 845
866 void invalidateOriginalText() { oTextValid = FALSE; oText = ""; } 846 void invalidateOriginalText() { oTextValid = FALSE; oText = ""; }
867 847
848 static QString section( QString str, const QString &sep, int start, int end = 0xffffffff );
849 static bool endsWith( QString str, const QString &s);
850
868signals: 851signals:
869 void minimumWidthChanged( int ); 852 void minimumWidthChanged( int );
870 853
871private: 854private:
872 void init(); 855 void init();
873 QPixmap *bufferPixmap( const QSize &s ); 856 QPixmap *bufferPixmap( const QSize &s );
874 // HTML parser 857 // HTML parser
875 bool hasPrefix(const QChar* doc, int length, int pos, QChar c); 858 bool hasPrefix(const QChar* doc, int length, int pos, QChar c);
876 bool hasPrefix(const QChar* doc, int length, int pos, const QString& s); 859 bool hasPrefix(const QChar* doc, int length, int pos, const QString& s);
877 QTextCustomItem* parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt, 860 QTextCustomItem* parseTable( const QMap<QString, QString> &attr, const QTextFormat &fmt,
878 const QChar* doc, int length, int& pos, QTextParag *curpar ); 861 const QChar* doc, int length, int& pos, QTextParagraph *curpar );
879 bool eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp = FALSE ); 862 bool eatSpace(const QChar* doc, int length, int& pos, bool includeNbsp = FALSE );
880 bool eat(const QChar* doc, int length, int& pos, QChar c); 863 bool eat(const QChar* doc, int length, int& pos, QChar c);
881 QString parseOpenTag(const QChar* doc, int length, int& pos, QMap<QString, QString> &attr, bool& emptyTag); 864 QString parseOpenTag(const QChar* doc, int length, int& pos, QMap<QString, QString> &attr, bool& emptyTag);
882 QString parseCloseTag( const QChar* doc, int length, int& pos ); 865 QString parseCloseTag( const QChar* doc, int length, int& pos );
883 QChar parseHTMLSpecialChar(const QChar* doc, int length, int& pos); 866 QChar parseHTMLSpecialChar(const QChar* doc, int length, int& pos);
884 QString parseWord(const QChar* doc, int length, int& pos, bool lower = TRUE); 867 QString parseWord(const QChar* doc, int length, int& pos, bool lower = TRUE);
885 QChar parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm ); 868 QChar parseChar(const QChar* doc, int length, int& pos, QStyleSheetItem::WhiteSpaceMode wsm );
886 void setRichTextInternal( const QString &text ); 869 void setRichTextInternal( const QString &text, QTextCursor* cursor = 0 );
870 void setRichTextMarginsInternal( QPtrList< QPtrVector<QStyleSheetItem> >& styles, QTextParagraph* stylesPar );
887 871
888private: 872private:
889 struct Q_EXPORT Focus { 873 struct Q_EXPORT Focus {
890 QTextParag *parag; 874 QTextParagraph *parag;
891 int start, len; 875 int start, len;
892 QString href; 876 QString href;
893 }; 877 };
894 878
895 int cx, cy, cw, vw; 879 int cx, cy, cw, vw;
896 QTextParag *fParag, *lParag; 880 QTextParagraph *fParag, *lParag;
897 QTextPreProcessor *pProcessor; 881 QTextPreProcessor *pProcessor;
898 QMap<int, QColor> selectionColors; 882 QMap<int, QColor> selectionColors;
899 QMap<int, QTextDocumentSelection> selections; 883 QMap<int, QTextDocumentSelection> selections;
900 QMap<int, bool> selectionText; 884 QMap<int, bool> selectionText;
901 QTextCommandHistory *commandHistory; 885 QTextCommandHistory *commandHistory;
902 QTextFormatter *pFormatter; 886 QTextFormatter *pFormatter;
903 QTextIndent *indenter; 887 QTextIndent *indenter;
904 QTextFormatCollection *fCollection; 888 QTextFormatCollection *fCollection;
905 Qt::TextFormat txtFormat; 889 Qt::TextFormat txtFormat;
906 uint preferRichText : 1; 890 uint preferRichText : 1;
907 uint pages : 1; 891 uint pages : 1;
908 uint useFC : 1; 892 uint useFC : 1;
909 uint withoutDoubleBuffer : 1; 893 uint withoutDoubleBuffer : 1;
910 uint underlLinks : 1; 894 uint underlLinks : 1;
911 uint nextDoubleBuffered : 1; 895 uint nextDoubleBuffered : 1;
912 uint addMargs : 1;
913 uint oTextValid : 1; 896 uint oTextValid : 1;
914 uint mightHaveCustomItems : 1; 897 uint mightHaveCustomItems : 1;
915 int align; 898 int align;
916 int nSelections; 899 int nSelections;
917 QTextFlow *flow_; 900 QTextFlow *flow_;
918 QTextDocument *par; 901 QTextDocument *par;
919 QTextParag *parParag; 902 QTextParagraph *parentPar;
920 QTextTableCell *tc; 903 QTextTableCell *tc;
921 QTextCursor *tmpCursor;
922 QBrush *backBrush; 904 QBrush *backBrush;
923 QPixmap *buf_pixmap; 905 QPixmap *buf_pixmap;
924 Focus focusIndicator; 906 Focus focusIndicator;
925 int minw; 907 int minw;
926 int wused; 908 int wused;
927 int leftmargin; 909 int leftmargin;
928 int rightmargin; 910 int rightmargin;
929 QTextParag *minwParag, *curParag; 911 QTextParagraph *minwParag, *curParag;
930 QStyleSheet* sheet_; 912 QStyleSheet* sheet_;
931 QMimeSourceFactory* factory_; 913 QMimeSourceFactory* factory_;
932 QString contxt; 914 QString contxt;
933 QMap<QString, QString> attribs; 915 QMap<QString, QString> attribs;
934 int *tArray; 916 int *tArray;
935 int tStopWidth; 917 int tStopWidth;
936 int uDepth; 918 int uDepth;
937 QString oText; 919 QString oText;
938 QPtrList<QTextDocument> childList; 920 QPtrList<QTextDocument> childList;
939 QColor linkColor; 921 QColor linkColor;
922 double scaleFontsFactor;
940 923
924 short list_tm,list_bm, list_lm, li_tm, li_bm, par_tm, par_bm;
941}; 925};
942 926
943// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 927// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
944 928
945 929
946class Q_EXPORT QTextDeleteCommand : public QTextCommand 930class Q_EXPORT QTextDeleteCommand : public QTextCommand
947{ 931{
948public: 932public:
949 QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, 933 QTextDeleteCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str,
950 const QValueList< QPtrVector<QStyleSheetItem> > &os, 934 const QByteArray& oldStyle );
951 const QValueList<QStyleSheetItem::ListStyle> &ols, 935 QTextDeleteCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str );
952 const QMemArray<int> &oas );
953 QTextDeleteCommand( QTextParag *p, int idx, const QMemArray<QTextStringChar> &str );
954 virtual ~QTextDeleteCommand(); 936 virtual ~QTextDeleteCommand();
955 937
956 Commands type() const { return Delete; } 938 Commands type() const { return Delete; }
957 QTextCursor *execute( QTextCursor *c ); 939 QTextCursor *execute( QTextCursor *c );
958 QTextCursor *unexecute( QTextCursor *c ); 940 QTextCursor *unexecute( QTextCursor *c );
959 941
960protected: 942protected:
961 int id, index; 943 int id, index;
962 QTextParag *parag; 944 QTextParagraph *parag;
963 QMemArray<QTextStringChar> text; 945 QMemArray<QTextStringChar> text;
964 QValueList< QPtrVector<QStyleSheetItem> > oldStyles; 946 QByteArray styleInformation;
965 QValueList<QStyleSheetItem::ListStyle> oldListStyles;
966 QMemArray<int> oldAligns;
967 947
968}; 948};
969 949
970class Q_EXPORT QTextInsertCommand : public QTextDeleteCommand 950class Q_EXPORT QTextInsertCommand : public QTextDeleteCommand
971{ 951{
972public: 952public:
973 QTextInsertCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str, 953 QTextInsertCommand( QTextDocument *d, int i, int idx, const QMemArray<QTextStringChar> &str,
974 const QValueList< QPtrVector<QStyleSheetItem> > &os, 954 const QByteArray& oldStyleInfo )
975 const QValueList<QStyleSheetItem::ListStyle> &ols, 955 : QTextDeleteCommand( d, i, idx, str, oldStyleInfo ) {}
976 const QMemArray<int> &oas ) 956 QTextInsertCommand( QTextParagraph *p, int idx, const QMemArray<QTextStringChar> &str )
977 : QTextDeleteCommand( d, i, idx, str, os, ols, oas ) {}
978 QTextInsertCommand( QTextParag *p, int idx, const QMemArray<QTextStringChar> &str )
979 : QTextDeleteCommand( p, idx, str ) {} 957 : QTextDeleteCommand( p, idx, str ) {}
980 virtual ~QTextInsertCommand() {} 958 virtual ~QTextInsertCommand() {}
981 959
982 Commands type() const { return Insert; } 960 Commands type() const { return Insert; }
983 QTextCursor *execute( QTextCursor *c ) { return QTextDeleteCommand::unexecute( c ); } 961 QTextCursor *execute( QTextCursor *c ) { return QTextDeleteCommand::unexecute( c ); }
984 QTextCursor *unexecute( QTextCursor *c ) { return QTextDeleteCommand::execute( c ); } 962 QTextCursor *unexecute( QTextCursor *c ) { return QTextDeleteCommand::execute( c ); }
985 963
986}; 964};
987 965
988class Q_EXPORT QTextFormatCommand : public QTextCommand 966class Q_EXPORT QTextFormatCommand : public QTextCommand
989{ 967{
990public: 968public:
991 QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl ); 969 QTextFormatCommand( QTextDocument *d, int sid, int sidx, int eid, int eidx, const QMemArray<QTextStringChar> &old, QTextFormat *f, int fl );
992 virtual ~QTextFormatCommand(); 970 virtual ~QTextFormatCommand();
993 971
994 Commands type() const { return Format; } 972 Commands type() const { return Format; }
995 QTextCursor *execute( QTextCursor *c ); 973 QTextCursor *execute( QTextCursor *c );
996 QTextCursor *unexecute( QTextCursor *c ); 974 QTextCursor *unexecute( QTextCursor *c );
997 975
998protected: 976protected:
999 int startId, startIndex, endId, endIndex; 977 int startId, startIndex, endId, endIndex;
1000 QTextFormat *format; 978 QTextFormat *format;
1001 QMemArray<QTextStringChar> oldFormats; 979 QMemArray<QTextStringChar> oldFormats;
1002 int flags; 980 int flags;
1003 981
1004}; 982};
1005 983
1006class Q_EXPORT QTextAlignmentCommand : public QTextCommand 984class Q_EXPORT QTextStyleCommand : public QTextCommand
1007{ 985{
1008public: 986public:
1009 QTextAlignmentCommand( QTextDocument *d, int fParag, int lParag, int na, const QMemArray<int> &oa ); 987 QTextStyleCommand( QTextDocument *d, int fParag, int lParag, const QByteArray& beforeChange );
1010 virtual ~QTextAlignmentCommand() {} 988 virtual ~QTextStyleCommand() {}
1011 989
1012 Commands type() const { return Alignment; } 990 Commands type() const { return Style; }
1013 QTextCursor *execute( QTextCursor *c ); 991 QTextCursor *execute( QTextCursor *c );
1014 QTextCursor *unexecute( QTextCursor *c ); 992 QTextCursor *unexecute( QTextCursor *c );
1015 993
1016private: 994 static QByteArray readStyleInformation( QTextDocument* d, int fParag, int lParag );
1017 int firstParag, lastParag; 995 static void writeStyleInformation( QTextDocument* d, int fParag, const QByteArray& style );
1018 int newAlign;
1019 QMemArray<int> oldAligns;
1020
1021};
1022
1023class Q_EXPORT QTextParagTypeCommand : public QTextCommand
1024{
1025public:
1026 QTextParagTypeCommand( QTextDocument *d, int fParag, int lParag, bool l,
1027 QStyleSheetItem::ListStyle s, const QValueList< QPtrVector<QStyleSheetItem> > &os,
1028 const QValueList<QStyleSheetItem::ListStyle> &ols );
1029 virtual ~QTextParagTypeCommand() {}
1030
1031 Commands type() const { return ParagType; }
1032 QTextCursor *execute( QTextCursor *c );
1033 QTextCursor *unexecute( QTextCursor *c );
1034 996
1035private: 997private:
1036 int firstParag, lastParag; 998 int firstParag, lastParag;
1037 bool list; 999 QByteArray before;
1038 QStyleSheetItem::ListStyle listStyle; 1000 QByteArray after;
1039 QValueList< QPtrVector<QStyleSheetItem> > oldStyles;
1040 QValueList<QStyleSheetItem::ListStyle> oldListStyles;
1041
1042}; 1001};
1043 1002
1044// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1003// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1045 1004
1046struct Q_EXPORT QTextParagSelection 1005struct Q_EXPORT QTextParagraphSelection
1047{ 1006{
1048 int start, end; 1007 int start, end;
1049}; 1008};
1050 1009
1051struct Q_EXPORT QTextParagLineStart 1010struct Q_EXPORT QTextLineStart
1052{ 1011{
1053 QTextParagLineStart() : y( 0 ), baseLine( 0 ), h( 0 ) 1012 QTextLineStart() : y( 0 ), baseLine( 0 ), h( 0 )
1054#ifndef QT_NO_COMPLEXTEXT 1013#ifndef QT_NO_COMPLEXTEXT
1055 , bidicontext( 0 ) 1014 , bidicontext( 0 )
1056#endif 1015#endif
1057 { } 1016 { }
1058 QTextParagLineStart( ushort y_, ushort bl, ushort h_ ) : y( y_ ), baseLine( bl ), h( h_ ), 1017 QTextLineStart( ushort y_, ushort bl, ushort h_ ) : y( y_ ), baseLine( bl ), h( h_ ),
1059 w( 0 ) 1018 w( 0 )
1060#ifndef QT_NO_COMPLEXTEXT 1019#ifndef QT_NO_COMPLEXTEXT
1061 , bidicontext( 0 ) 1020 , bidicontext( 0 )
1062#endif 1021#endif
1063 { } 1022 { }
1064#ifndef QT_NO_COMPLEXTEXT 1023#ifndef QT_NO_COMPLEXTEXT
1065 QTextParagLineStart( QBidiContext *c, QBidiStatus s ) : y(0), baseLine(0), h(0), 1024 QTextLineStart( QBidiContext *c, QBidiStatus s ) : y(0), baseLine(0), h(0),
1066 status( s ), bidicontext( c ) { if ( bidicontext ) bidicontext->ref(); } 1025 status( s ), bidicontext( c ) { if ( bidicontext ) bidicontext->ref(); }
1067#endif 1026#endif
1068 1027
1069 virtual ~QTextParagLineStart() 1028 virtual ~QTextLineStart()
1070 { 1029 {
1071#ifndef QT_NO_COMPLEXTEXT 1030#ifndef QT_NO_COMPLEXTEXT
1072 if ( bidicontext && bidicontext->deref() ) 1031 if ( bidicontext && bidicontext->deref() )
1073 delete bidicontext; 1032 delete bidicontext;
1074#endif 1033#endif
1075 } 1034 }
1076 1035
1077#ifndef QT_NO_COMPLEXTEXT 1036#ifndef QT_NO_COMPLEXTEXT
1078 void setContext( QBidiContext *c ) { 1037 void setContext( QBidiContext *c ) {
1079 if ( c == bidicontext ) 1038 if ( c == bidicontext )
1080 return; 1039 return;
1081 if ( bidicontext && bidicontext->deref() ) 1040 if ( bidicontext && bidicontext->deref() )
1082 delete bidicontext; 1041 delete bidicontext;
1083 bidicontext = c; 1042 bidicontext = c;
1084 if ( bidicontext ) 1043 if ( bidicontext )
1085 bidicontext->ref(); 1044 bidicontext->ref();
1086 } 1045 }
1087 QBidiContext *context() const { return bidicontext; } 1046 QBidiContext *context() const { return bidicontext; }
1088#endif 1047#endif
1089 1048
1090public: 1049public:
1091 ushort y, baseLine, h; 1050 ushort y, baseLine, h;
1092#ifndef QT_NO_COMPLEXTEXT 1051#ifndef QT_NO_COMPLEXTEXT
1093 QBidiStatus status; 1052 QBidiStatus status;
1094#endif 1053#endif
1095 int w; 1054 int w;
1096 1055
1097private: 1056private:
1098#ifndef QT_NO_COMPLEXTEXT 1057#ifndef QT_NO_COMPLEXTEXT
1099 QBidiContext *bidicontext; 1058 QBidiContext *bidicontext;
1100#endif 1059#endif
1101}; 1060};
1102 1061
1103#if defined(Q_TEMPLATEDLL) 1062#if defined(Q_TEMPLATEDLL)
1104// MOC_SKIP_BEGIN 1063// MOC_SKIP_BEGIN
1105template class Q_EXPORT QMap<int, QTextParagSelection>; 1064Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextParagraphSelection>;
1106template class Q_EXPORT QMap<int, QTextParagLineStart*>; 1065Q_TEMPLATE_EXTERN template class Q_EXPORT QMap<int, QTextLineStart*>;
1107// MOC_SKIP_END 1066// MOC_SKIP_END
1108#endif 1067#endif
1109 1068
1110class Q_EXPORT QTextParagData 1069class Q_EXPORT QTextParagraphData
1111{ 1070{
1112public: 1071public:
1113 QTextParagData() {} 1072 QTextParagraphData() {}
1114 virtual ~QTextParagData(); 1073 virtual ~QTextParagraphData();
1115 virtual void join( QTextParagData * ); 1074 virtual void join( QTextParagraphData * );
1116}; 1075};
1117 1076
1118class Q_EXPORT QTextParagPseudoDocument 1077class Q_EXPORT QTextParagraphPseudoDocument
1119{ 1078{
1120public: 1079public:
1121 QTextParagPseudoDocument(); 1080 QTextParagraphPseudoDocument();
1122 ~QTextParagPseudoDocument(); 1081 ~QTextParagraphPseudoDocument();
1123 QRect docRect; 1082 QRect docRect;
1124 QTextFormatter *pFormatter; 1083 QTextFormatter *pFormatter;
1125 QTextCommandHistory *commandHistory; 1084 QTextCommandHistory *commandHistory;
1126 int minw; 1085 int minw;
1127 int wused; 1086 int wused;
1128}; 1087};
1129 1088
1130//nase 1089//nase
1131class Q_EXPORT QTextParag 1090class Q_EXPORT QTextParagraph
1132{ 1091{
1133 friend class QTextDocument; 1092 friend class QTextDocument;
1134 friend class QTextCursor; 1093 friend class QTextCursor;
1135 1094
1136public: 1095public:
1137 QTextParag( QTextDocument *d, QTextParag *pr = 0, QTextParag *nx = 0, bool updateIds = TRUE ); 1096 QTextParagraph( QTextDocument *d, QTextParagraph *pr = 0, QTextParagraph *nx = 0, bool updateIds = TRUE );
1138 virtual ~QTextParag(); 1097 virtual ~QTextParagraph();
1139 1098
1140 QTextString *string() const; 1099 QTextString *string() const;
1141 QTextStringChar *at( int i ) const; // maybe remove later 1100 QTextStringChar *at( int i ) const; // maybe remove later
1142 int leftGap() const; 1101 int leftGap() const;
1143 int length() const; // maybe remove later 1102 int length() const; // maybe remove later
1144 1103
1145 void setListStyle( QStyleSheetItem::ListStyle ls ); 1104 void setListStyle( QStyleSheetItem::ListStyle ls ) { lstyle = ls; changed = TRUE; }
1146 QStyleSheetItem::ListStyle listStyle() const; 1105 QStyleSheetItem::ListStyle listStyle() const { return lstyle; }
1106 void setListItem( bool li ) { litem = li; changed = TRUE; }
1107 bool isListItem() const { return litem; }
1147 void setListValue( int v ) { list_val = v; } 1108 void setListValue( int v ) { list_val = v; }
1148 int listValue() const { return list_val; } 1109 int listValue() const { return list_val > 0 ? list_val : -1; }
1149 1110
1150 void setList( bool b, int listStyle ); 1111 void setListDepth( int depth );
1151 void incDepth(); 1112 int listDepth() const { return ldepth; }
1152 void decDepth();
1153 int listDepth() const;
1154 1113
1155 void setFormat( QTextFormat *fm ); 1114// void setFormat( QTextFormat *fm );
1156 QTextFormat *paragFormat() const; 1115// QTextFormat *paragFormat() const;
1157 1116
1158 QTextDocument *document() const; 1117 QTextDocument *document() const;
1159 QTextParagPseudoDocument *pseudoDocument() const; 1118 QTextParagraphPseudoDocument *pseudoDocument() const;
1160 1119
1161 QRect rect() const; 1120 QRect rect() const;
1162 void setHeight( int h ) { r.setHeight( h ); } 1121 void setHeight( int h ) { r.setHeight( h ); }
1163 void show(); 1122 void show();
1164 void hide(); 1123 void hide();
1165 bool isVisible() const { return visible; } 1124 bool isVisible() const { return visible; }
1166 1125
1167 QTextParag *prev() const; 1126 QTextParagraph *prev() const;
1168 QTextParag *next() const; 1127 QTextParagraph *next() const;
1169 void setPrev( QTextParag *s ); 1128 void setPrev( QTextParagraph *s );
1170 void setNext( QTextParag *s ); 1129 void setNext( QTextParagraph *s );
1171 1130
1172 void insert( int index, const QString &s ); 1131 void insert( int index, const QString &s );
1132 void insert( int index, const QChar *unicode, int len );
1173 void append( const QString &s, bool reallyAtEnd = FALSE ); 1133 void append( const QString &s, bool reallyAtEnd = FALSE );
1174 void truncate( int index ); 1134 void truncate( int index );
1175 void remove( int index, int len ); 1135 void remove( int index, int len );
1176 void join( QTextParag *s ); 1136 void join( QTextParagraph *s );
1177 1137
1178 void invalidate( int chr ); 1138 void invalidate( int chr );
1179 1139
1180 void move( int &dy ); 1140 void move( int &dy );
1181 void format( int start = -1, bool doMove = TRUE ); 1141 void format( int start = -1, bool doMove = TRUE );
1182 1142
1183 bool isValid() const; 1143 bool isValid() const;
1184 bool hasChanged() const; 1144 bool hasChanged() const;
1185 void setChanged( bool b, bool recursive = FALSE ); 1145 void setChanged( bool b, bool recursive = FALSE );
1186 1146
1187 int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const; 1147 int lineHeightOfChar( int i, int *bl = 0, int *y = 0 ) const;
1188 QTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const; 1148 QTextStringChar *lineStartOfChar( int i, int *index = 0, int *line = 0 ) const;
1189 int lines() const; 1149 int lines() const;
1190 QTextStringChar *lineStartOfLine( int line, int *index = 0 ) const; 1150 QTextStringChar *lineStartOfLine( int line, int *index = 0 ) const;
1191 int lineY( int l ) const; 1151 int lineY( int l ) const;
1192 int lineBaseLine( int l ) const; 1152 int lineBaseLine( int l ) const;
1193 int lineHeight( int l ) const; 1153 int lineHeight( int l ) const;
1194 void lineInfo( int l, int &y, int &h, int &bl ) const; 1154 void lineInfo( int l, int &y, int &h, int &bl ) const;
1195 1155
1196 void setSelection( int id, int start, int end ); 1156 void setSelection( int id, int start, int end );
1197 void removeSelection( int id ); 1157 void removeSelection( int id );
1198 int selectionStart( int id ) const; 1158 int selectionStart( int id ) const;
1199 int selectionEnd( int id ) const; 1159 int selectionEnd( int id ) const;
1200 bool hasSelection( int id ) const; 1160 bool hasSelection( int id ) const;
1201 bool hasAnySelection() const; 1161 bool hasAnySelection() const;
1202 bool fullSelected( int id ) const; 1162 bool fullSelected( int id ) const;
1203 1163
1204 void setEndState( int s ); 1164 void setEndState( int s );
1205 int endState() const; 1165 int endState() const;
1206 1166
1207 void setParagId( int i ); 1167 void setParagId( int i );
1208 int paragId() const; 1168 int paragId() const;
1209 1169
1210 bool firstPreProcess() const; 1170 bool firstPreProcess() const;
1211 void setFirstPreProcess( bool b ); 1171 void setFirstPreProcess( bool b );
1212 1172
1213 void indent( int *oldIndent = 0, int *newIndent = 0 ); 1173 void indent( int *oldIndent = 0, int *newIndent = 0 );
1214 1174
1215 void setExtraData( QTextParagData *data ); 1175 void setExtraData( QTextParagraphData *data );
1216 QTextParagData *extraData() const; 1176 QTextParagraphData *extraData() const;
1217 1177
1218 QMap<int, QTextParagLineStart*> &lineStartList(); 1178 QMap<int, QTextLineStart*> &lineStartList();
1219 1179
1220 void setFormat( int index, int len, QTextFormat *f, bool useCollection = TRUE, int flags = -1 ); 1180 void setFormat( int index, int len, QTextFormat *f, bool useCollection = TRUE, int flags = -1 );
1221 1181
1222 void setAlignment( int a ); 1182 void setAlignment( int a );
1223 int alignment() const; 1183 int alignment() const;
1224 1184
1225 virtual void paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor = 0, bool drawSelections = FALSE, 1185 virtual void paint( QPainter &painter, const QColorGroup &cg, QTextCursor *cursor = 0, bool drawSelections = FALSE,
1226 int clipx = -1, int clipy = -1, int clipw = -1, int cliph = -1 ); 1186 int clipx = -1, int clipy = -1, int clipw = -1, int cliph = -1 );
1227 1187
1228 void setStyleSheetItems( const QPtrVector<QStyleSheetItem> &vec );
1229 QPtrVector<QStyleSheetItem> styleSheetItems() const;
1230 QStyleSheetItem *style() const;
1231
1232 virtual int topMargin() const; 1188 virtual int topMargin() const;
1233 virtual int bottomMargin() const; 1189 virtual int bottomMargin() const;
1234 virtual int leftMargin() const; 1190 virtual int leftMargin() const;
1235 virtual int firstLineMargin() const; 1191 virtual int firstLineMargin() const;
1236 virtual int rightMargin() const; 1192 virtual int rightMargin() const;
1237 virtual int lineSpacing() const; 1193 virtual int lineSpacing() const;
1238 1194
1239 int numberOfSubParagraph() const;
1240 void registerFloatingItem( QTextCustomItem *i ); 1195 void registerFloatingItem( QTextCustomItem *i );
1241 void unregisterFloatingItem( QTextCustomItem *i ); 1196 void unregisterFloatingItem( QTextCustomItem *i );
1242 1197
1243 void setFullWidth( bool b ) { fullWidth = b; } 1198 void setFullWidth( bool b ) { fullWidth = b; }
1244 bool isFullWidth() const { return fullWidth; } 1199 bool isFullWidth() const { return fullWidth; }
1245 1200
1246 QTextTableCell *tableCell() const; 1201 QTextTableCell *tableCell() const;
1247 1202
1248 QBrush *background() const; 1203 QBrush *background() const;
1249 1204
1250 int documentWidth() const; 1205 int documentWidth() const;
1251 int documentVisibleWidth() const; 1206 int documentVisibleWidth() const;
1252 int documentX() const; 1207 int documentX() const;
1253 int documentY() const; 1208 int documentY() const;
1254 QTextFormatCollection *formatCollection() const; 1209 QTextFormatCollection *formatCollection() const;
1255 QTextFormatter *formatter() const; 1210 QTextFormatter *formatter() const;
1256 1211
1257 virtual int nextTab( int i, int x ); 1212 virtual int nextTab( int i, int x );
1258 int *tabArray() const; 1213 int *tabArray() const;
1259 void setTabArray( int *a ); 1214 void setTabArray( int *a );
1260 void setTabStops( int tw ); 1215 void setTabStops( int tw );
1261 1216
1262 void adjustToPainter( QPainter *p ); 1217 void adjustToPainter( QPainter *p );
1263 1218
1264 void setNewLinesAllowed( bool b ); 1219 void setNewLinesAllowed( bool b );
1265 bool isNewLinesAllowed() const; 1220 bool isNewLinesAllowed() const;
1266 1221
1267 QString richText() const; 1222 QString richText() const;
1268 1223
1269 void addCommand( QTextCommand *cmd ); 1224 void addCommand( QTextCommand *cmd );
1270 QTextCursor *undo( QTextCursor *c = 0 ); 1225 QTextCursor *undo( QTextCursor *c = 0 );
1271 QTextCursor *redo( QTextCursor *c = 0 ); 1226 QTextCursor *redo( QTextCursor *c = 0 );
1272 QTextCommandHistory *commands() const; 1227 QTextCommandHistory *commands() const;
1273 virtual void copyParagData( QTextParag *parag ); 1228 virtual void copyParagData( QTextParagraph *parag );
1274 1229
1275 void setBreakable( bool b ) { breakable = b; } 1230 void setBreakable( bool b ) { breakable = b; }
1276 bool isBreakable() const { return breakable; } 1231 bool isBreakable() const { return breakable; }
1277 1232
1278 void setBackgroundColor( const QColor &c ); 1233 void setBackgroundColor( const QColor &c );
1279 QColor *backgroundColor() const { return bgcol; } 1234 QColor *backgroundColor() const { return bgcol; }
1280 void clearBackgroundColor(); 1235 void clearBackgroundColor();
1281 1236
1282 bool isLineBreak() const { return isBr; }
1283
1284 void setMovedDown( bool b ) { movedDown = b; } 1237 void setMovedDown( bool b ) { movedDown = b; }
1285 bool wasMovedDown() const { return movedDown; } 1238 bool wasMovedDown() const { return movedDown; }
1286 1239
1287 void setDirection( QChar::Direction d ); 1240 void setDirection( QChar::Direction d );
1288 QChar::Direction direction() const; 1241 QChar::Direction direction() const;
1289 1242
1243 void readStyleInformation( QDataStream& stream );
1244 void writeStyleInformation( QDataStream& stream ) const;
1245
1290protected: 1246protected:
1291 virtual void drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg ); 1247 virtual void drawLabel( QPainter* p, int x, int y, int w, int h, int base, const QColorGroup& cg );
1292 virtual void drawParagString( QPainter &painter, const QString &str, int start, int len, int startX, 1248 virtual void drawString( QPainter &painter, const QString &str, int start, int len, int xstart,
1293 int lastY, int baseLine, int bw, int h, bool drawSelections, 1249 int y, int baseLine, int w, int h, int selection,
1294 QTextStringChar *formatChar, int i, const QMemArray<int> &selectionStarts, 1250 QTextStringChar *formatChar, const QColorGroup& cg,
1295 const QMemArray<int> &selectionEnds, const QColorGroup &cg, bool rightToLeft ); 1251 bool rightToLeft );
1296 1252
1297private: 1253private:
1298 QMap<int, QTextParagSelection> &selections() const; 1254 QMap<int, QTextParagraphSelection> &selections() const;
1299 QPtrVector<QStyleSheetItem> &styleSheetItemsVec() const;
1300 QPtrList<QTextCustomItem> &floatingItems() const; 1255 QPtrList<QTextCustomItem> &floatingItems() const;
1256 QBrush backgroundBrush( const QColorGroup&cg ) { if ( bgcol ) return *bgcol; return cg.brush( QColorGroup::Base ); }
1257 void invalidateStyleCache();
1301 1258
1302 QMap<int, QTextParagLineStart*> lineStarts; 1259 QMap<int, QTextLineStart*> lineStarts;
1303 int invalid; 1260 int invalid;
1304 QRect r; 1261 QRect r;
1305 QTextParag *p, *n; 1262 QTextParagraph *p, *n;
1306 void *docOrPseudo; 1263 void *docOrPseudo;
1307 uint changed : 1; 1264 uint changed : 1;
1308 uint firstFormat : 1; 1265 uint firstFormat : 1;
1309 uint firstPProcess : 1; 1266 uint firstPProcess : 1;
1310 uint needPreProcess : 1; 1267 uint needPreProcess : 1;
1311 uint fullWidth : 1; 1268 uint fullWidth : 1;
1312 uint newLinesAllowed : 1;
1313 uint lastInFrame : 1; 1269 uint lastInFrame : 1;
1314 uint visible : 1; 1270 uint visible : 1;
1315 uint breakable : 1; 1271 uint breakable : 1;
1316 uint isBr : 1;
1317 uint movedDown : 1; 1272 uint movedDown : 1;
1318 uint mightHaveCustomItems : 1; 1273 uint mightHaveCustomItems : 1;
1319 uint hasdoc : 1; 1274 uint hasdoc : 1;
1275 uint litem : 1; // whether the paragraph is a list item
1276 uint rtext : 1; // whether the paragraph needs rich text margin
1320 int align : 4; 1277 int align : 4;
1321 int state, id; 1278 int state, id;
1322 QTextString *str; 1279 QTextString *str;
1323 QMap<int, QTextParagSelection> *mSelections; 1280 QMap<int, QTextParagraphSelection> *mSelections;
1324 QPtrVector<QStyleSheetItem> *mStyleSheetItemsVec;
1325 QPtrList<QTextCustomItem> *mFloatingItems; 1281 QPtrList<QTextCustomItem> *mFloatingItems;
1326 QStyleSheetItem::ListStyle listS; 1282 QStyleSheetItem::ListStyle lstyle;
1327 int numSubParag; 1283 short utm, ubm, ulm, urm, uflm, ulinespacing;
1328 int tm, bm, lm, rm, flm;
1329 QTextFormat *defFormat;
1330 int *tArray; 1284 int *tArray;
1331 int tabStopWidth; 1285 short tabStopWidth;
1332 QTextParagData *eData; 1286 QTextParagraphData *eData;
1333 int list_val; 1287 short list_val;
1334 QColor *bgcol; 1288 QColor *bgcol;
1289 ushort ldepth;
1335 1290
1336}; 1291};
1337 1292
1338// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1293// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1339 1294
1340class Q_EXPORT QTextFormatter 1295class Q_EXPORT QTextFormatter
1341{ 1296{
1342public: 1297public:
1343 QTextFormatter(); 1298 QTextFormatter();
1344 virtual ~QTextFormatter(); 1299 virtual ~QTextFormatter();
1345 1300
1346 virtual int format( QTextDocument *doc, QTextParag *parag, int start, const QMap<int, QTextParagLineStart*> &oldLineStarts ) = 0; 1301 virtual int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts ) = 0;
1347 virtual int formatVertically( QTextDocument* doc, QTextParag* parag ); 1302 virtual int formatVertically( QTextDocument* doc, QTextParagraph* parag );
1348 1303
1349 bool isWrapEnabled( QTextParag *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;} 1304 bool isWrapEnabled( QTextParagraph *p ) const { if ( !wrapEnabled ) return FALSE; if ( p && !p->isBreakable() ) return FALSE; return TRUE;}
1350 int wrapAtColumn() const { return wrapColumn;} 1305 int wrapAtColumn() const { return wrapColumn;}
1351 virtual void setWrapEnabled( bool b ); 1306 virtual void setWrapEnabled( bool b );
1352 virtual void setWrapAtColumn( int c ); 1307 virtual void setWrapAtColumn( int c );
1353 virtual void setAllowBreakInWords( bool b ) { biw = b; } 1308 virtual void setAllowBreakInWords( bool b ) { biw = b; }
1354 bool allowBreakInWords() const { return biw; } 1309 bool allowBreakInWords() const { return biw; }
1355 1310
1356 int minimumWidth() const { return thisminw; } 1311 int minimumWidth() const { return thisminw; }
1357 int widthUsed() const { return thiswused; } 1312 int widthUsed() const { return thiswused; }
1358 1313
1314 static bool isBreakable( QTextString *string, int pos );
1315
1359protected: 1316protected:
1360 virtual QTextParagLineStart *formatLine( QTextParag *parag, QTextString *string, QTextParagLineStart *line, QTextStringChar *start, 1317 virtual QTextLineStart *formatLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start,
1361 QTextStringChar *last, int align = Qt3::AlignAuto, int space = 0 ); 1318 QTextStringChar *last, int align = Qt3::AlignAuto, int space = 0 );
1362#ifndef QT_NO_COMPLEXTEXT 1319#ifndef QT_NO_COMPLEXTEXT
1363 virtual QTextParagLineStart *bidiReorderLine( QTextParag *parag, QTextString *string, QTextParagLineStart *line, QTextStringChar *start, 1320 virtual QTextLineStart *bidiReorderLine( QTextParagraph *parag, QTextString *string, QTextLineStart *line, QTextStringChar *start,
1364 QTextStringChar *last, int align, int space ); 1321 QTextStringChar *last, int align, int space );
1365#endif 1322#endif
1366 virtual bool isBreakable( QTextString *string, int pos ) const; 1323 void insertLineStart( QTextParagraph *parag, int index, QTextLineStart *ls );
1367 void insertLineStart( QTextParag *parag, int index, QTextParagLineStart *ls );
1368 1324
1369 int thisminw; 1325 int thisminw;
1370 int thiswused; 1326 int thiswused;
1371 1327
1372private: 1328private:
1373 bool wrapEnabled; 1329 bool wrapEnabled;
1374 int wrapColumn; 1330 int wrapColumn;
1375 bool biw; 1331 bool biw;
1376 1332
1377#ifdef HAVE_THAI_BREAKS 1333#ifdef HAVE_THAI_BREAKS
1378 static QCString *thaiCache; 1334 static QCString *thaiCache;
1379 static QTextString *cachedString; 1335 static QTextString *cachedString;
1380 static ThBreakIterator *thaiIt; 1336 static ThBreakIterator *thaiIt;
1381#endif 1337#endif
1382}; 1338};
1383 1339
1384// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1340// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1385 1341
1386class Q_EXPORT QTextFormatterBreakInWords : public QTextFormatter 1342class Q_EXPORT QTextFormatterBreakInWords : public QTextFormatter
1387{ 1343{
1388public: 1344public:
1389 QTextFormatterBreakInWords(); 1345 QTextFormatterBreakInWords();
1390 virtual ~QTextFormatterBreakInWords() {} 1346 virtual ~QTextFormatterBreakInWords() {}
1391 1347
1392 int format( QTextDocument *doc, QTextParag *parag, int start, const QMap<int, QTextParagLineStart*> &oldLineStarts ); 1348 int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts );
1393 1349
1394}; 1350};
1395 1351
1396// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1352// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1397 1353
1398class Q_EXPORT QTextFormatterBreakWords : public QTextFormatter 1354class Q_EXPORT QTextFormatterBreakWords : public QTextFormatter
1399{ 1355{
1400public: 1356public:
1401 QTextFormatterBreakWords(); 1357 QTextFormatterBreakWords();
1402 virtual ~QTextFormatterBreakWords() {} 1358 virtual ~QTextFormatterBreakWords() {}
1403 1359
1404 int format( QTextDocument *doc, QTextParag *parag, int start, const QMap<int, QTextParagLineStart*> &oldLineStarts ); 1360 int format( QTextDocument *doc, QTextParagraph *parag, int start, const QMap<int, QTextLineStart*> &oldLineStarts );
1405 1361
1406}; 1362};
1407 1363
1408// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1364// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1409 1365
1410class Q_EXPORT QTextIndent 1366class Q_EXPORT QTextIndent
1411{ 1367{
1412public: 1368public:
1413 QTextIndent(); 1369 QTextIndent();
1414 virtual ~QTextIndent() {} 1370 virtual ~QTextIndent() {}
1415 1371
1416 virtual void indent( QTextDocument *doc, QTextParag *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0; 1372 virtual void indent( QTextDocument *doc, QTextParagraph *parag, int *oldIndent = 0, int *newIndent = 0 ) = 0;
1417 1373
1418}; 1374};
1419 1375
1420// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1376// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1421 1377
1422class Q_EXPORT QTextPreProcessor 1378class Q_EXPORT QTextPreProcessor
1423{ 1379{
1424public: 1380public:
1425 enum Ids { 1381 enum Ids {
1426 Standard = 0 1382 Standard = 0
1427 }; 1383 };
1428 1384
1429 QTextPreProcessor(); 1385 QTextPreProcessor();
1430 virtual ~QTextPreProcessor() {} 1386 virtual ~QTextPreProcessor() {}
1431 1387
1432 virtual void process( QTextDocument *doc, QTextParag *, int, bool = TRUE ) = 0; 1388 virtual void process( QTextDocument *doc, QTextParagraph *, int, bool = TRUE ) = 0;
1433 virtual QTextFormat *format( int id ) = 0; 1389 virtual QTextFormat *format( int id ) = 0;
1434 1390
1435}; 1391};
1436 1392
1437// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1393// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1438 1394
1439class Q_EXPORT QTextFormat 1395class Q_EXPORT QTextFormat
1440{ 1396{
1441 friend class QTextFormatCollection; 1397 friend class QTextFormatCollection;
1442 friend class QTextDocument; 1398 friend class QTextDocument;
1443 1399
1444public: 1400public:
1445 enum Flags { 1401 enum Flags {
1446 NoFlags, 1402 NoFlags,
1447 Bold = 1, 1403 Bold = 1,
1448 Italic = 2, 1404 Italic = 2,
1449 Underline = 4, 1405 Underline = 4,
1450 Family = 8, 1406 Family = 8,
1451 Size = 16, 1407 Size = 16,
1452 Color = 32, 1408 Color = 32,
1453 Misspelled = 64, 1409 Misspelled = 64,
1454 VAlign = 128, 1410 VAlign = 128,
1455 Font = Bold | Italic | Underline | Family | Size, 1411 StrikeOut= 256,
1412 Font = Bold | Italic | Underline | Family | Size | StrikeOut,
1456 Format = Font | Color | Misspelled | VAlign 1413 Format = Font | Color | Misspelled | VAlign
1457 }; 1414 };
1458 1415
1459 enum VerticalAlignment { AlignNormal, AlignSuperScript, AlignSubScript }; 1416 enum VerticalAlignment { AlignNormal, AlignSuperScript, AlignSubScript };
1460 1417
1461 QTextFormat(); 1418 QTextFormat();
1462 virtual ~QTextFormat(); 1419 virtual ~QTextFormat();
1463 1420
1464 QTextFormat( const QStyleSheetItem *s ); 1421 QTextFormat( const QStyleSheetItem *s );
1465 QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent = 0 ); 1422 QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent = 0 );
1466 QTextFormat( const QTextFormat &fm ); 1423 QTextFormat( const QTextFormat &fm );
1467 QTextFormat makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr ) const; 1424 QTextFormat makeTextFormat( const QStyleSheetItem *style, const QMap<QString,QString>& attr, double scaleFontsFactor ) const;
1468 QTextFormat& operator=( const QTextFormat &fm ); 1425 QTextFormat& operator=( const QTextFormat &fm );
1469 QColor color() const; 1426 QColor color() const;
1470 QFont font() const; 1427 QFont font() const;
1471 bool isMisspelled() const; 1428 bool isMisspelled() const;
1472 VerticalAlignment vAlign() const; 1429 VerticalAlignment vAlign() const;
1473 int minLeftBearing() const; 1430 int minLeftBearing() const;
1474 int minRightBearing() const; 1431 int minRightBearing() const;
1475 int width( const QChar &c ) const; 1432 int width( const QChar &c ) const;
1476 int width( const QString &str, int pos ) const; 1433 int width( const QString &str, int pos ) const;
1477 int height() const; 1434 int height() const;
1478 int ascent() const; 1435 int ascent() const;
1479 int descent() const; 1436 int descent() const;
1480 int leading() const; 1437 int leading() const;
1481 bool useLinkColor() const; 1438 bool useLinkColor() const;
1482 1439
1483 void setBold( bool b ); 1440 void setBold( bool b );
1484 void setItalic( bool b ); 1441 void setItalic( bool b );
1485 void setUnderline( bool b ); 1442 void setUnderline( bool b );
1443 void setStrikeOut( bool b );
1486 void setFamily( const QString &f ); 1444 void setFamily( const QString &f );
1487 void setPointSize( int s ); 1445 void setPointSize( int s );
1488 void setFont( const QFont &f ); 1446 void setFont( const QFont &f );
1489 void setColor( const QColor &c ); 1447 void setColor( const QColor &c );
1490 void setMisspelled( bool b ); 1448 void setMisspelled( bool b );
1491 void setVAlign( VerticalAlignment a ); 1449 void setVAlign( VerticalAlignment a );
1492 1450
1493 bool operator==( const QTextFormat &f ) const; 1451 bool operator==( const QTextFormat &f ) const;
1494 QTextFormatCollection *parent() const; 1452 QTextFormatCollection *parent() const;
1495 QString key() const; 1453 QString key() const;
1496 1454
1497 static QString getKey( const QFont &f, const QColor &c, bool misspelled, VerticalAlignment vAlign ); 1455 static QString getKey( const QFont &f, const QColor &c, bool misspelled, VerticalAlignment vAlign );
1498 1456
1499 void addRef(); 1457 void addRef();
1500 void removeRef(); 1458 void removeRef();
1501 1459
1502 QString makeFormatChangeTags( QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const; 1460 QString makeFormatChangeTags( QTextFormat* defaultFormat, QTextFormat *f, const QString& oldAnchorHref, const QString& anchorHref ) const;
1503 QString makeFormatEndTags( const QString& anchorHref ) const; 1461 QString makeFormatEndTags( QTextFormat* defaultFormat, const QString& anchorHref ) const;
1504 1462
1505 static void setPainter( QPainter *p ); 1463 static void setPainter( QPainter *p );
1506 static QPainter* painter(); 1464 static QPainter* painter();
1507 void updateStyle();
1508 void updateStyleFlags();
1509 void setStyle( const QString &s );
1510 QString styleName() const { return style; }
1511 1465
1512 int changed() const { return different; }
1513 bool fontSizesInPixels() { return usePixelSizes; } 1466 bool fontSizesInPixels() { return usePixelSizes; }
1514 1467
1515protected: 1468protected:
1516 virtual void generateKey(); 1469 virtual void generateKey();
1517 1470
1518private: 1471private:
1519 void update(); 1472 void update();
1520 1473
1521private: 1474private:
1522 QFont fn; 1475 QFont fn;
1523 QColor col; 1476 QColor col;
1524 QFontMetrics fm; 1477 QFontMetrics fm;
1525 uint missp : 1; 1478 uint missp : 1;
1526 uint linkColor : 1; 1479 uint linkColor : 1;
1527 uint usePixelSizes : 1; 1480 uint usePixelSizes : 1;
1528 int leftBearing, rightBearing; 1481 int leftBearing, rightBearing;
1529 VerticalAlignment ha; 1482 VerticalAlignment ha;
1530 uchar widths[ 256 ]; 1483 uchar widths[ 256 ];
1531 int hei, asc, dsc; 1484 int hei, asc, dsc;
1532 QTextFormatCollection *collection; 1485 QTextFormatCollection *collection;
1533 int ref; 1486 int ref;
1534 QString k; 1487 QString k;
1535 int logicalFontSize; 1488 int logicalFontSize;
1536 int stdSize; 1489 int stdSize;
1537 static QPainter *pntr; 1490 static QPainter *pntr;
1538 QString style;
1539 int different;
1540 1491
1541}; 1492};
1542 1493
1543// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1494// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1544 1495
1545#if defined(Q_TEMPLATEDLL) 1496#if defined(Q_TEMPLATEDLL)
1546// MOC_SKIP_BEGIN 1497// MOC_SKIP_BEGIN
1547template class Q_EXPORT QDict<QTextFormat>; 1498Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QTextFormat>;
1548// MOC_SKIP_END 1499// MOC_SKIP_END
1549#endif 1500#endif
1550 1501
1551class Q_EXPORT QTextFormatCollection 1502class Q_EXPORT QTextFormatCollection
1552{ 1503{
1553 friend class QTextDocument; 1504 friend class QTextDocument;
1554 friend class QTextFormat; 1505 friend class QTextFormat;
1555 1506
1556public: 1507public:
1557 QTextFormatCollection(); 1508 QTextFormatCollection();
1558 virtual ~QTextFormatCollection(); 1509 virtual ~QTextFormatCollection();
1559 1510
1560 void setDefaultFormat( QTextFormat *f ); 1511 void setDefaultFormat( QTextFormat *f );
1561 QTextFormat *defaultFormat() const; 1512 QTextFormat *defaultFormat() const;
1562 virtual QTextFormat *format( QTextFormat *f ); 1513 virtual QTextFormat *format( QTextFormat *f );
1563 virtual QTextFormat *format( QTextFormat *of, QTextFormat *nf, int flags ); 1514 virtual QTextFormat *format( QTextFormat *of, QTextFormat *nf, int flags );
1564 virtual QTextFormat *format( const QFont &f, const QColor &c ); 1515 virtual QTextFormat *format( const QFont &f, const QColor &c );
1565 virtual void remove( QTextFormat *f ); 1516 virtual void remove( QTextFormat *f );
1566 virtual QTextFormat *createFormat( const QTextFormat &f ) { return new QTextFormat( f ); } 1517 virtual QTextFormat *createFormat( const QTextFormat &f ) { return new QTextFormat( f ); }
1567 virtual QTextFormat *createFormat( const QFont &f, const QColor &c ) { return new QTextFormat( f, c, this ); } 1518 virtual QTextFormat *createFormat( const QFont &f, const QColor &c ) { return new QTextFormat( f, c, this ); }
1568 void debug();
1569 1519
1570 QStyleSheet *styleSheet() const { return sheet; } 1520 void updateDefaultFormat( const QFont &font, const QColor &c, QStyleSheet *sheet );
1571 void setStyleSheet( QStyleSheet *s ) { sheet = s; }
1572 void updateStyles();
1573 void updateFontSizes( int base, bool usePixels );
1574 void updateFontAttributes( const QFont &f, const QFont &old );
1575 QDict<QTextFormat> dict() const { return cKey; } 1521 QDict<QTextFormat> dict() const { return cKey; }
1576 1522
1577private: 1523private:
1578 void updateKeys(); 1524 void updateKeys();
1579 1525
1580private: 1526private:
1581 QTextFormat *defFormat, *lastFormat, *cachedFormat; 1527 QTextFormat *defFormat, *lastFormat, *cachedFormat;
1582 QDict<QTextFormat> cKey; 1528 QDict<QTextFormat> cKey;
1583 QTextFormat *cres; 1529 QTextFormat *cres;
1584 QFont cfont; 1530 QFont cfont;
1585 QColor ccol; 1531 QColor ccol;
1586 QString kof, knf; 1532 QString kof, knf;
1587 int cflags; 1533 int cflags;
1588 QStyleSheet *sheet;
1589
1590}; 1534};
1591 1535
1592// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1536// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1593 1537
1594inline int QTextString::length() const 1538inline int QTextString::length() const
1595{ 1539{
1596 return data.size(); 1540 return data.size();
1597} 1541}
1598 1542
1599inline void QTextString::operator+=( const QString &s ) 1543inline int QTextParagraph::length() const
1600{
1601 insert( length(), s, 0 );
1602}
1603
1604inline int QTextParag::length() const
1605{ 1544{
1606 return str->length(); 1545 return str->length();
1607} 1546}
1608 1547
1609inline QRect QTextParag::rect() const 1548inline QRect QTextParagraph::rect() const
1610{ 1549{
1611 return r; 1550 return r;
1612} 1551}
1613 1552
1614inline QTextParag *QTextCursor::parag() const 1553inline QTextParagraph *QTextCursor::paragraph() const
1615{ 1554{
1616 return string; 1555 return para;
1617} 1556}
1618 1557
1619inline int QTextCursor::index() const 1558inline int QTextCursor::index() const
1620{ 1559{
1621 return idx; 1560 return idx;
1622} 1561}
1623 1562
1624inline void QTextCursor::setIndex( int i, bool restore )
1625{
1626 if ( restore )
1627 restoreState();
1628 if ( i < 0 || i >= string->length() ) {
1629#if defined(QT_CHECK_RANGE)
1630 qWarning( "QTextCursor::setIndex: %d out of range", i );
1631#endif
1632 i = i < 0 ? 0 : string->length() - 1;
1633 }
1634
1635 tmpIndex = -1;
1636 idx = i;
1637}
1638
1639inline void QTextCursor::setParag( QTextParag *s, bool restore )
1640{
1641 if ( restore )
1642 restoreState();
1643 idx = 0;
1644 string = s;
1645 tmpIndex = -1;
1646}
1647
1648inline void QTextCursor::checkIndex()
1649{
1650 if ( idx >= string->length() )
1651 idx = string->length() - 1;
1652}
1653 1563
1654// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1564// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1655 1565
1656inline int QTextDocument::x() const 1566inline int QTextDocument::x() const
1657{ 1567{
1658 return cx; 1568 return cx;
1659} 1569}
1660 1570
1661inline int QTextDocument::y() const 1571inline int QTextDocument::y() const
1662{ 1572{
1663 return cy; 1573 return cy;
1664} 1574}
1665 1575
1666inline int QTextDocument::width() const 1576inline int QTextDocument::width() const
1667{ 1577{
1668 return QMAX( cw, flow_->width() ); 1578 return QMAX( cw, flow_->width() );
1669} 1579}
1670 1580
1671inline int QTextDocument::visibleWidth() const 1581inline int QTextDocument::visibleWidth() const
1672{ 1582{
1673 return vw; 1583 return vw;
1674} 1584}
1675 1585
1676inline QTextParag *QTextDocument::firstParag() const 1586inline QTextParagraph *QTextDocument::firstParagraph() const
1677{ 1587{
1678 return fParag; 1588 return fParag;
1679} 1589}
1680 1590
1681inline QTextParag *QTextDocument::lastParag() const 1591inline QTextParagraph *QTextDocument::lastParagraph() const
1682{ 1592{
1683 return lParag; 1593 return lParag;
1684} 1594}
1685 1595
1686inline void QTextDocument::setFirstParag( QTextParag *p ) 1596inline void QTextDocument::setFirstParagraph( QTextParagraph *p )
1687{ 1597{
1688 fParag = p; 1598 fParag = p;
1689} 1599}
1690 1600
1691inline void QTextDocument::setLastParag( QTextParag *p ) 1601inline void QTextDocument::setLastParagraph( QTextParagraph *p )
1692{ 1602{
1693 lParag = p; 1603 lParag = p;
1694} 1604}
1695 1605
1696inline void QTextDocument::setWidth( int w ) 1606inline void QTextDocument::setWidth( int w )
1697{ 1607{
1698 cw = QMAX( w, minw ); 1608 cw = QMAX( w, minw );
1699 flow_->setWidth( cw ); 1609 flow_->setWidth( cw );
1700 vw = w; 1610 vw = w;
1701} 1611}
1702 1612
1703inline int QTextDocument::minimumWidth() const 1613inline int QTextDocument::minimumWidth() const
1704{ 1614{
1705 return minw; 1615 return minw;
1706} 1616}
1707 1617
1708inline void QTextDocument::setY( int y ) 1618inline void QTextDocument::setY( int y )
1709{ 1619{
1710 cy = y; 1620 cy = y;
1711} 1621}
1712 1622
1713inline int QTextDocument::leftMargin() const 1623inline int QTextDocument::leftMargin() const
1714{ 1624{
1715 return leftmargin; 1625 return leftmargin;
1716} 1626}
1717 1627
1718inline void QTextDocument::setLeftMargin( int lm ) 1628inline void QTextDocument::setLeftMargin( int lm )
1719{ 1629{
1720 leftmargin = lm; 1630 leftmargin = lm;
1721} 1631}
1722 1632
1723inline int QTextDocument::rightMargin() const 1633inline int QTextDocument::rightMargin() const
@@ -1841,307 +1751,267 @@ inline QColor QTextFormat::color() const
1841{ 1751{
1842 return col; 1752 return col;
1843} 1753}
1844 1754
1845inline QFont QTextFormat::font() const 1755inline QFont QTextFormat::font() const
1846{ 1756{
1847 return fn; 1757 return fn;
1848} 1758}
1849 1759
1850inline bool QTextFormat::isMisspelled() const 1760inline bool QTextFormat::isMisspelled() const
1851{ 1761{
1852 return missp; 1762 return missp;
1853} 1763}
1854 1764
1855inline QTextFormat::VerticalAlignment QTextFormat::vAlign() const 1765inline QTextFormat::VerticalAlignment QTextFormat::vAlign() const
1856{ 1766{
1857 return ha; 1767 return ha;
1858} 1768}
1859 1769
1860inline bool QTextFormat::operator==( const QTextFormat &f ) const 1770inline bool QTextFormat::operator==( const QTextFormat &f ) const
1861{ 1771{
1862 return k == f.k; 1772 return k == f.k;
1863} 1773}
1864 1774
1865inline QTextFormatCollection *QTextFormat::parent() const 1775inline QTextFormatCollection *QTextFormat::parent() const
1866{ 1776{
1867 return collection; 1777 return collection;
1868} 1778}
1869 1779
1870inline void QTextFormat::addRef() 1780inline void QTextFormat::addRef()
1871{ 1781{
1872 ref++; 1782 ref++;
1873#ifdef DEBUG_COLLECTION
1874 qDebug( "add ref of '%s' to %d (%p)", k.latin1(), ref, this );
1875#endif
1876} 1783}
1877 1784
1878inline void QTextFormat::removeRef() 1785inline void QTextFormat::removeRef()
1879{ 1786{
1880 ref--; 1787 ref--;
1881 if ( !collection ) 1788 if ( !collection )
1882 return; 1789 return;
1883 if ( this == collection->defFormat ) 1790 if ( this == collection->defFormat )
1884 return; 1791 return;
1885#ifdef DEBUG_COLLECTION
1886 qDebug( "remove ref of '%s' to %d (%p)", k.latin1(), ref, this );
1887#endif
1888 if ( ref == 0 ) 1792 if ( ref == 0 )
1889 collection->remove( this ); 1793 collection->remove( this );
1890} 1794}
1891 1795
1892inline QString QTextFormat::key() const 1796inline QString QTextFormat::key() const
1893{ 1797{
1894 return k; 1798 return k;
1895} 1799}
1896 1800
1897inline bool QTextFormat::useLinkColor() const 1801inline bool QTextFormat::useLinkColor() const
1898{ 1802{
1899 return linkColor; 1803 return linkColor;
1900} 1804}
1901 1805
1902inline void QTextFormat::setStyle( const QString &s )
1903{
1904 style = s;
1905 updateStyleFlags();
1906}
1907 1806
1908// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1807// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1909 1808
1910inline QTextStringChar &QTextString::at( int i ) const 1809inline QTextStringChar &QTextString::at( int i ) const
1911{ 1810{
1912 return data[ i ]; 1811 return data[ i ];
1913} 1812}
1914 1813
1915// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1814// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1916 1815
1917inline QTextStringChar *QTextParag::at( int i ) const 1816inline QTextStringChar *QTextParagraph::at( int i ) const
1918{ 1817{
1919 return &str->at( i ); 1818 return &str->at( i );
1920} 1819}
1921 1820
1922inline bool QTextParag::isValid() const 1821inline bool QTextParagraph::isValid() const
1923{ 1822{
1924 return invalid == -1; 1823 return invalid == -1;
1925} 1824}
1926 1825
1927inline bool QTextParag::hasChanged() const 1826inline bool QTextParagraph::hasChanged() const
1928{ 1827{
1929 return changed; 1828 return changed;
1930} 1829}
1931 1830
1932inline void QTextParag::setBackgroundColor( const QColor & c ) 1831inline void QTextParagraph::setBackgroundColor( const QColor & c )
1933{ 1832{
1934 delete bgcol; 1833 delete bgcol;
1935 bgcol = new QColor( c ); 1834 bgcol = new QColor( c );
1936 setChanged( TRUE ); 1835 setChanged( TRUE );
1937} 1836}
1938 1837
1939inline void QTextParag::clearBackgroundColor() 1838inline void QTextParagraph::clearBackgroundColor()
1940{ 1839{
1941 delete bgcol; bgcol = 0; setChanged( TRUE ); 1840 delete bgcol; bgcol = 0; setChanged( TRUE );
1942} 1841}
1943 1842
1944inline void QTextParag::append( const QString &s, bool reallyAtEnd ) 1843inline void QTextParagraph::append( const QString &s, bool reallyAtEnd )
1945{ 1844{
1946 if ( reallyAtEnd ) 1845 if ( reallyAtEnd )
1947 insert( str->length(), s ); 1846 insert( str->length(), s );
1948 else 1847 else
1949 insert( QMAX( str->length() - 1, 0 ), s ); 1848 insert( QMAX( str->length() - 1, 0 ), s );
1950} 1849}
1951 1850
1952inline QTextParag *QTextParag::prev() const 1851inline QTextParagraph *QTextParagraph::prev() const
1953{ 1852{
1954 return p; 1853 return p;
1955} 1854}
1956 1855
1957inline QTextParag *QTextParag::next() const 1856inline QTextParagraph *QTextParagraph::next() const
1958{ 1857{
1959 return n; 1858 return n;
1960} 1859}
1961 1860
1962inline bool QTextParag::hasAnySelection() const 1861inline bool QTextParagraph::hasAnySelection() const
1963{ 1862{
1964 return mSelections ? !selections().isEmpty() : FALSE; 1863 return mSelections ? !selections().isEmpty() : FALSE;
1965} 1864}
1966 1865
1967inline void QTextParag::setEndState( int s ) 1866inline void QTextParagraph::setEndState( int s )
1968{ 1867{
1969 if ( s == state ) 1868 if ( s == state )
1970 return; 1869 return;
1971 state = s; 1870 state = s;
1972} 1871}
1973 1872
1974inline int QTextParag::endState() const 1873inline int QTextParagraph::endState() const
1975{ 1874{
1976 return state; 1875 return state;
1977} 1876}
1978 1877
1979inline void QTextParag::setParagId( int i ) 1878inline void QTextParagraph::setParagId( int i )
1980{ 1879{
1981 id = i; 1880 id = i;
1982} 1881}
1983 1882
1984inline int QTextParag::paragId() const 1883inline int QTextParagraph::paragId() const
1985{ 1884{
1986 if ( id == -1 ) 1885 if ( id == -1 )
1987 qWarning( "invalid parag id!!!!!!!! (%p)", (void*)this ); 1886 qWarning( "invalid parag id!!!!!!!! (%p)", (void*)this );
1988 return id; 1887 return id;
1989} 1888}
1990 1889
1991inline bool QTextParag::firstPreProcess() const 1890inline bool QTextParagraph::firstPreProcess() const
1992{ 1891{
1993 return firstPProcess; 1892 return firstPProcess;
1994} 1893}
1995 1894
1996inline void QTextParag::setFirstPreProcess( bool b ) 1895inline void QTextParagraph::setFirstPreProcess( bool b )
1997{ 1896{
1998 firstPProcess = b; 1897 firstPProcess = b;
1999} 1898}
2000 1899
2001inline QMap<int, QTextParagLineStart*> &QTextParag::lineStartList() 1900inline QMap<int, QTextLineStart*> &QTextParagraph::lineStartList()
2002{ 1901{
2003 return lineStarts; 1902 return lineStarts;
2004} 1903}
2005 1904
2006inline QTextString *QTextParag::string() const 1905inline QTextString *QTextParagraph::string() const
2007{ 1906{
2008 return str; 1907 return str;
2009} 1908}
2010 1909
2011inline QTextDocument *QTextParag::document() const 1910inline QTextDocument *QTextParagraph::document() const
2012{ 1911{
2013 if ( hasdoc ) 1912 if ( hasdoc )
2014 return (QTextDocument*) docOrPseudo; 1913 return (QTextDocument*) docOrPseudo;
2015 return 0; 1914 return 0;
2016} 1915}
2017 1916
2018inline QTextParagPseudoDocument *QTextParag::pseudoDocument() const 1917inline QTextParagraphPseudoDocument *QTextParagraph::pseudoDocument() const
2019{ 1918{
2020 if ( hasdoc ) 1919 if ( hasdoc )
2021 return 0; 1920 return 0;
2022 return (QTextParagPseudoDocument*) docOrPseudo; 1921 return (QTextParagraphPseudoDocument*) docOrPseudo;
2023} 1922}
2024 1923
2025 1924
2026inline QTextTableCell *QTextParag::tableCell() const 1925inline QTextTableCell *QTextParagraph::tableCell() const
2027{ 1926{
2028 return hasdoc ? document()->tableCell () : 0; 1927 return hasdoc ? document()->tableCell () : 0;
2029} 1928}
2030 1929
2031inline QTextCommandHistory *QTextParag::commands() const 1930inline QTextCommandHistory *QTextParagraph::commands() const
2032{ 1931{
2033 return hasdoc ? document()->commands() : pseudoDocument()->commandHistory; 1932 return hasdoc ? document()->commands() : pseudoDocument()->commandHistory;
2034} 1933}
2035 1934
2036 1935
2037inline void QTextParag::setAlignment( int a ) 1936inline int QTextParagraph::alignment() const
2038{
2039 if ( a == (int)align )
2040 return;
2041 align = a;
2042 invalidate( 0 );
2043}
2044
2045inline void QTextParag::setListStyle( QStyleSheetItem::ListStyle ls )
2046{
2047 listS = ls;
2048 invalidate( 0 );
2049}
2050
2051inline QStyleSheetItem::ListStyle QTextParag::listStyle() const
2052{
2053 return listS;
2054}
2055
2056inline QTextFormat *QTextParag::paragFormat() const
2057{ 1937{
2058 return defFormat; 1938 return align;
2059} 1939}
2060 1940
2061inline void QTextParag::registerFloatingItem( QTextCustomItem *i ) 1941inline void QTextParagraph::registerFloatingItem( QTextCustomItem *i )
2062{ 1942{
2063 floatingItems().append( i ); 1943 floatingItems().append( i );
2064} 1944}
2065 1945
2066inline void QTextParag::unregisterFloatingItem( QTextCustomItem *i ) 1946inline void QTextParagraph::unregisterFloatingItem( QTextCustomItem *i )
2067{ 1947{
2068 floatingItems().removeRef( i ); 1948 floatingItems().removeRef( i );
2069} 1949}
2070 1950
2071inline QBrush *QTextParag::background() const 1951inline QBrush *QTextParagraph::background() const
2072{ 1952{
2073 return tableCell() ? tableCell()->backGround() : 0; 1953 return tableCell() ? tableCell()->backGround() : 0;
2074} 1954}
2075 1955
2076inline int QTextParag::documentWidth() const 1956inline int QTextParagraph::documentWidth() const
2077{ 1957{
2078 return hasdoc ? document()->width() : pseudoDocument()->docRect.width(); 1958 return hasdoc ? document()->width() : pseudoDocument()->docRect.width();
2079} 1959}
2080 1960
2081inline int QTextParag::documentVisibleWidth() const 1961inline int QTextParagraph::documentVisibleWidth() const
2082{ 1962{
2083 return hasdoc ? document()->visibleWidth() : pseudoDocument()->docRect.width(); 1963 return hasdoc ? document()->visibleWidth() : pseudoDocument()->docRect.width();
2084} 1964}
2085 1965
2086inline int QTextParag::documentX() const 1966inline int QTextParagraph::documentX() const
2087{ 1967{
2088 return hasdoc ? document()->x() : pseudoDocument()->docRect.x(); 1968 return hasdoc ? document()->x() : pseudoDocument()->docRect.x();
2089} 1969}
2090 1970
2091inline int QTextParag::documentY() const 1971inline int QTextParagraph::documentY() const
2092{ 1972{
2093 return hasdoc ? document()->y() : pseudoDocument()->docRect.y(); 1973 return hasdoc ? document()->y() : pseudoDocument()->docRect.y();
2094} 1974}
2095 1975
2096inline void QTextParag::setExtraData( QTextParagData *data ) 1976inline void QTextParagraph::setExtraData( QTextParagraphData *data )
2097{ 1977{
2098 eData = data; 1978 eData = data;
2099} 1979}
2100 1980
2101inline QTextParagData *QTextParag::extraData() const 1981inline QTextParagraphData *QTextParagraph::extraData() const
2102{ 1982{
2103 return eData; 1983 return eData;
2104} 1984}
2105 1985
2106inline void QTextParag::setNewLinesAllowed( bool b )
2107{
2108 newLinesAllowed = b;
2109}
2110
2111inline bool QTextParag::isNewLinesAllowed() const
2112{
2113 return newLinesAllowed;
2114}
2115
2116// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1986// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2117 1987
2118inline void QTextFormatCollection::setDefaultFormat( QTextFormat *f ) 1988inline void QTextFormatCollection::setDefaultFormat( QTextFormat *f )
2119{ 1989{
2120 defFormat = f; 1990 defFormat = f;
2121} 1991}
2122 1992
2123inline QTextFormat *QTextFormatCollection::defaultFormat() const 1993inline QTextFormat *QTextFormatCollection::defaultFormat() const
2124{ 1994{
2125 return defFormat; 1995 return defFormat;
2126} 1996}
2127 1997
2128// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1998// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2129 1999
2130inline QTextFormat *QTextStringChar::format() const 2000inline QTextFormat *QTextStringChar::format() const
2131{ 2001{
2132 return (type == Regular) ? d.format : d.custom->format; 2002 return (type == Regular) ? d.format : d.custom->format;
2133} 2003}
2134 2004
2135 2005
2136inline QTextCustomItem *QTextStringChar::customItem() const 2006inline QTextCustomItem *QTextStringChar::customItem() const
2137{ 2007{
2138 return isCustom() ? d.custom->custom : 0; 2008 return isCustom() ? d.custom->custom : 0;
2139} 2009}
2140 2010
2141inline int QTextStringChar::height() const 2011inline int QTextStringChar::height() const
2142{ 2012{
2143 return !isCustom() ? format()->height() : ( customItem()->placement() == QTextCustomItem::PlaceInline ? customItem()->height : 0 ); 2013 return !isCustom() ? format()->height() : ( customItem()->placement() == QTextCustomItem::PlaceInline ? customItem()->height : 0 );
2144} 2014}
2145 2015
2146inline int QTextStringChar::ascent() const 2016inline int QTextStringChar::ascent() const
2147{ 2017{
diff --git a/noncore/apps/opie-write/qstylesheet.cpp b/noncore/apps/opie-write/qstylesheet.cpp
index 7ab9ec6..67cd828 100644
--- a/noncore/apps/opie-write/qstylesheet.cpp
+++ b/noncore/apps/opie-write/qstylesheet.cpp
@@ -25,1451 +25,1539 @@
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 "qstylesheet.h" 38#include "qstylesheet.h"
39 39
40#include "qrichtext_p.h" 40#include "qrichtext_p.h"
41#include "qlayout.h" 41#include "qlayout.h"
42#include "qpainter.h" 42#include "qpainter.h"
43#include "qcleanuphandler.h" 43#include "qcleanuphandler.h"
44 44
45#include <stdio.h> 45#include <stdio.h>
46 46
47using namespace Qt3; 47using namespace Qt3;
48 48
49namespace Qt3 { 49namespace Qt3 {
50 50
51class QStyleSheetItemData 51class QStyleSheetItemData
52{ 52{
53public: 53public:
54 QStyleSheetItem::DisplayMode disp; 54 QStyleSheetItem::DisplayMode disp;
55 int fontitalic; 55 int fontitalic;
56 int fontunderline; 56 int fontunderline;
57 int fontstrikeout;
57 int fontweight; 58 int fontweight;
58 int fontsize; 59 int fontsize;
59 int fontsizelog; 60 int fontsizelog;
60 int fontsizestep; 61 int fontsizestep;
61 int lineSpacing; 62 int lineSpacing;
62 QString fontfamily; 63 QString fontfamily;
63 QStyleSheetItem *parentstyle; 64 QStyleSheetItem *parentstyle;
64 QString stylename; 65 QString stylename;
65 int ncolumns; 66 int ncolumns;
66 QColor col; 67 QColor col;
67 bool anchor; 68 bool anchor;
68 int align; 69 int align;
69 QStyleSheetItem::VerticalAlignment valign; 70 QStyleSheetItem::VerticalAlignment valign;
70 int margin[5]; 71 int margin[5];
71 QStyleSheetItem::ListStyle list; 72 QStyleSheetItem::ListStyle list;
72 QStyleSheetItem::WhiteSpaceMode whitespacemode; 73 QStyleSheetItem::WhiteSpaceMode whitespacemode;
73 QString contxt; 74 QString contxt;
74 bool selfnest; 75 bool selfnest;
75 QStyleSheet* sheet; 76 QStyleSheet* sheet;
76}; 77};
77 78
78} 79}
79 80
80/*! 81/*!
81 \class QStyleSheetItem qstylesheet.h 82 \class QStyleSheetItem qstylesheet.h
82 \ingroup text 83 \brief The QStyleSheetItem class provides an encapsulation of a set of text styles.
83 \brief The QStyleSheetItem class provides an encapsulation of a set of text styles. 84
84 85 \ingroup text
85 A style sheet item consists of a name and a set of attributes that 86
86 specifiy its font, color, etc. When used in a \link QStyleSheet 87 A style sheet item consists of a name and a set of attributes that
87 style sheet\endlink (see styleSheet()), items define the name() of a 88 specifiy its font, color, etc. When used in a \link QStyleSheet
88 rich text tag and the display property changes associated with it. 89 style sheet\endlink (see styleSheet()), items define the name() of
89 90 a rich text tag and the display property changes associated with
90 The \link QStyleSheetItem::DisplayMode display mode\endlink 91 it.
91 attribute indicates whether the item is a block, an inline element 92
92 or a list element; see setDisplayMode(). The treatment of whitespace 93 The \link QStyleSheetItem::DisplayMode display mode\endlink
93 is controlled by the \link QStyleSheetItem::WhiteSpaceMode white 94 attribute indicates whether the item is a block, an inline element
94 space mode\endlink; see setWhiteSpaceMode(). An item's margins are 95 or a list element; see setDisplayMode(). The treatment of
95 set with setMargin(), and line spacing is set with setLineSpacing(). 96 whitespace is controlled by the \link
96 In the case of list items, the list style is set with 97 QStyleSheetItem::WhiteSpaceMode white space mode\endlink; see
97 setListStyle(). An item may be a hypertext link anchor; see 98 setWhiteSpaceMode(). An item's margins are set with setMargin(),
98 setAnchor(). Other attributes are set with setAlignment(), 99 In the case of list items, the list style is set with
99 setVerticalAlignment(), setFontFamily(), setFontSize(), 100 setListStyle(). An item may be a hypertext link anchor; see
100 setFontWeight(), setFontItalic(), setFontUnderline() and setColor(). 101 setAnchor(). Other attributes are set with setAlignment(),
102 setVerticalAlignment(), setFontFamily(), setFontSize(),
103 setFontWeight(), setFontItalic(), setFontUnderline(),
104 setFontStrikeOut and setColor().
101*/ 105*/
102 106
103/*! \enum QStyleSheetItem::AdditionalStyleValues 107/*! \enum QStyleSheetItem::AdditionalStyleValues
104 \internal 108 \internal
105*/ 109*/
106 110
107/*! \enum QStyleSheetItem::WhiteSpaceMode 111/*!
112 \enum QStyleSheetItem::WhiteSpaceMode
108 113
109 This enum defines the ways in which QStyleSheet can treat whitespace. There are three values at present: 114 This enum defines the ways in which QStyleSheet can treat
115 whitespace.
110 116
111 \value WhiteSpaceNormal any sequence of whitespace (including 117 \value WhiteSpaceNormal any sequence of whitespace (including
112 line-breaks) is equivalent to a single space. 118 line-breaks) is equivalent to a single space.
113 119
114 \value WhiteSpacePre whitespace must be output exactly as given 120 \value WhiteSpacePre whitespace must be output exactly as given
115 in the input. 121 in the input.
116 122
117 \value WhiteSpaceNoWrap multiple spaces are collapsed as with 123 \value WhiteSpaceNoWrap multiple spaces are collapsed as with
118 WhiteSpaceNormal, but no automatic line-breaks occur. To break lines manually, 124 WhiteSpaceNormal, but no automatic line-breaks occur. To break
119 use the \c{<br>} tag. 125 lines manually, use the \c{<br>} tag.
120 126
121*/ 127*/
122 128
123/*! \enum QStyleSheetItem::Margin 129/*!
124 130 \enum QStyleSheetItem::Margin
125 \value MarginLeft left margin 131
126 \value MarginRight right margin 132 \value MarginLeft left margin
127 \value MarginTop top margin 133 \value MarginRight right margin
128 \value MarginBottom bottom margin 134 \value MarginTop top margin
129 \value MarginAll all margins (left, right, top and bottom) 135 \value MarginBottom bottom margin
130 \value MarginVertical top and bottom margins 136 \value MarginAll all margins (left, right, top and bottom)
131 \value MarginHorizontal left and right margins 137 \value MarginVertical top and bottom margins
132 \value MarginFirstLine margin (indentation) of the first line of a paragarph (in addition to the MarginLeft of the paragraph) 138 \value MarginHorizontal left and right margins
139 \value MarginFirstLine margin (indentation) of the first line of
140 a paragarph (in addition to the MarginLeft of the paragraph)
133*/ 141*/
134 142
135/*! 143/*!
136 Constructs a new style named \a name for the stylesheet \a parent. 144 Constructs a new style called \a name for the stylesheet \a
145 parent.
137 146
138 All properties in QStyleSheetItem are initially in the "do not change" state, 147 All properties in QStyleSheetItem are initially in the "do not
139 except \link QStyleSheetItem::DisplayMode display mode\endlink, which defaults 148 change" state, except \link QStyleSheetItem::DisplayMode display
140 to \c DisplayInline. 149 mode\endlink, which defaults to \c DisplayInline.
141*/ 150*/
142QStyleSheetItem::QStyleSheetItem( QStyleSheet* parent, const QString& name ) 151QStyleSheetItem::QStyleSheetItem( QStyleSheet* parent, const QString& name )
143{ 152{
144 d = new QStyleSheetItemData; 153 d = new QStyleSheetItemData;
145 d->stylename = name.lower(); 154 d->stylename = name.lower();
146 d->sheet = parent; 155 d->sheet = parent;
147 init(); 156 init();
148 if (parent) 157 if (parent)
149 parent->insert( this ); 158 parent->insert( this );
150} 159}
151 160
152/*! 161/*!
153 Copy constructor. Constructs a copy of \a other that is 162 Copy constructor. Constructs a copy of \a other that is not bound
154 not bound to any style sheet. 163 to any style sheet.
155 */ 164*/
156QStyleSheetItem::QStyleSheetItem( const QStyleSheetItem & other ) 165QStyleSheetItem::QStyleSheetItem( const QStyleSheetItem & other )
157{ 166{
158 d = new QStyleSheetItemData; 167 d = new QStyleSheetItemData;
159 *d = *other.d; 168 *d = *other.d;
160} 169}
161 170
162 171
163/*! 172/*!
164 Destroys the style. Note that QStyleSheetItem objects become owned 173 Destroys the style. Note that QStyleSheetItem objects become
165 by QStyleSheet when they are created. 174 owned by QStyleSheet when they are created.
166 */ 175*/
167QStyleSheetItem::~QStyleSheetItem() 176QStyleSheetItem::~QStyleSheetItem()
168{ 177{
169 delete d; 178 delete d;
170} 179}
171 180
172 181
173 182
174/*! 183/*!
175 Returns the style sheet this item is in. 184 Returns the style sheet this item is in.
176 */ 185*/
177QStyleSheet* QStyleSheetItem::styleSheet() 186QStyleSheet* QStyleSheetItem::styleSheet()
178{ 187{
179 return d->sheet; 188 return d->sheet;
180} 189}
181 190
182/*! 191/*!
183 \overload 192 \overload
184 Returns the style sheet this item is in. 193
185 */ 194 Returns the style sheet this item is in.
195*/
186const QStyleSheet* QStyleSheetItem::styleSheet() const 196const QStyleSheet* QStyleSheetItem::styleSheet() const
187{ 197{
188 return d->sheet; 198 return d->sheet;
189} 199}
190 200
191/*! 201/*!
192 \internal 202 \internal
193 Internal initialization 203 Internal initialization
194 */ 204 */
195void QStyleSheetItem::init() 205void QStyleSheetItem::init()
196{ 206{
197 d->disp = DisplayInline; 207 d->disp = DisplayInline;
198 208
199 d->fontitalic = Undefined; 209 d->fontitalic = Undefined;
200 d->fontunderline = Undefined; 210 d->fontunderline = Undefined;
211 d->fontstrikeout = Undefined;
201 d->fontweight = Undefined; 212 d->fontweight = Undefined;
202 d->fontsize = Undefined; 213 d->fontsize = Undefined;
203 d->fontsizelog = Undefined; 214 d->fontsizelog = Undefined;
204 d->fontsizestep = 0; 215 d->fontsizestep = 0;
205 d->ncolumns = Undefined; 216 d->ncolumns = Undefined;
206 d->col = QColor(); // !isValid() 217 d->col = QColor(); // !isValid()
207 d->anchor = FALSE; 218 d->anchor = FALSE;
208 d->align = Undefined; 219 d->align = Undefined;
209 d->valign = VAlignBaseline; 220 d->valign = VAlignBaseline;
210 d->margin[0] = Undefined; 221 d->margin[0] = Undefined;
211 d->margin[1] = Undefined; 222 d->margin[1] = Undefined;
212 d->margin[2] = Undefined; 223 d->margin[2] = Undefined;
213 d->margin[3] = Undefined; 224 d->margin[3] = Undefined;
214 d->margin[4] = Undefined; 225 d->margin[4] = Undefined;
215 d->list = QStyleSheetItem::ListDisc; 226 d->list = (ListStyle) Undefined;
216 d->whitespacemode = QStyleSheetItem::WhiteSpaceNormal; 227 d->whitespacemode = (WhiteSpaceMode) Undefined;
217 d->selfnest = TRUE; 228 d->selfnest = TRUE;
218 d->lineSpacing = Undefined; 229 d->lineSpacing = Undefined;
219} 230}
220 231
221/*! 232/*!
222 Returns the name of the style item. 233 Returns the name of the style item.
223*/ 234*/
224QString QStyleSheetItem::name() const 235QString QStyleSheetItem::name() const
225{ 236{
226 return d->stylename; 237 return d->stylename;
227} 238}
228 239
229/*! 240/*!
230 Returns the \link QStyleSheetItem::DisplayMode display mode\endlink 241 Returns the \link QStyleSheetItem::DisplayMode display
231 of the style. 242 mode\endlink of the style.
232 243
233 \sa setDisplayMode() 244 \sa setDisplayMode()
234 */ 245*/
235QStyleSheetItem::DisplayMode QStyleSheetItem::displayMode() const 246QStyleSheetItem::DisplayMode QStyleSheetItem::displayMode() const
236{ 247{
237 return d->disp; 248 return d->disp;
238} 249}
239 250
240/*! \enum QStyleSheetItem::DisplayMode 251/*!
252 \enum QStyleSheetItem::DisplayMode
241 253
242 This enum type defines the way adjacent elements are displayed. The possible values are: 254 This enum type defines the way adjacent elements are displayed.
243 255
244 \value DisplayBlock elements are displayed as a rectangular block 256 \value DisplayBlock elements are displayed as a rectangular block
245 (e.g. \c{<p>...</p>}). 257 (e.g. \c{<p>...</p>}).
246 258
247 \value DisplayInline elements are displayed in a horizontally flowing 259 \value DisplayInline elements are displayed in a horizontally
248 sequence (e.g. \c{<em>...</em>}). 260 flowing sequence (e.g. \c{<em>...</em>}).
249 261
250 \value DisplayListItem elements are displayed in a vertical sequence 262 \value DisplayListItem elements are displayed in a vertical
251 (e.g. \c{<li>...</li>}). 263 sequence (e.g. \c{<li>...</li>}).
252 264
253 \value DisplayNone elements are not displayed at all. 265 \value DisplayNone elements are not displayed at all.
254*/ 266*/
255 267
256/*! 268/*!
257 Sets the display mode of the style to \a m. 269 Sets the display mode of the style to \a m.
258 270
259 \sa displayMode() 271 \sa displayMode()
260 */ 272 */
261void QStyleSheetItem::setDisplayMode(DisplayMode m) 273void QStyleSheetItem::setDisplayMode(DisplayMode m)
262{ 274{
263 d->disp=m; 275 d->disp=m;
264} 276}
265 277
266 278
267/*! 279/*!
268 Returns the alignment of this style. Possible values are AlignAuto, AlignLeft, 280 Returns the alignment of this style. Possible values are \c
269 AlignRight, AlignCenter and AlignJustify. 281 AlignAuto, \c AlignLeft, \c AlignRight, \c AlignCenter or \c
282 AlignJustify.
270 283
271 \sa setAlignment(), Qt::AlignmentFlags 284 \sa setAlignment(), Qt::AlignmentFlags
272 */ 285*/
273int QStyleSheetItem::alignment() const 286int QStyleSheetItem::alignment() const
274{ 287{
275 return d->align; 288 return d->align;
276} 289}
277 290
278/*! 291/*!
279 Sets the alignment to \a f. This only makes sense for styles with a 292 Sets the alignment to \a f. This only makes sense for styles with
280 \link QStyleSheetItem::DisplayMode display mode\endlink of 293 a \link QStyleSheetItem::DisplayMode display mode\endlink of
281 DisplayBlock. Possible values are AlignAuto, AlignLeft, AlignRight, 294 DisplayBlock. Possible values are \c AlignAuto, \c AlignLeft,
282 AlignCenter and AlignJustify. 295 \c AlignRight, \c AlignCenter or \c AlignJustify.
283 296
284 \sa alignment(), displayMode(), Qt::AlignmentFlags 297 \sa alignment(), displayMode(), Qt::AlignmentFlags
285 */ 298*/
286void QStyleSheetItem::setAlignment( int f ) 299void QStyleSheetItem::setAlignment( int f )
287{ 300{
288 d->align = f; 301 d->align = f;
289} 302}
290 303
291 304
292/*! 305/*!
293 Returns the vertical alignment of the style. Possible values are 306 Returns the vertical alignment of the style. Possible values are
294 VAlignBaseline, VAlignSub and VAlignSuper. 307 \c VAlignBaseline, \c VAlignSub or \c VAlignSuper.
295 308
296 psa setVerticalAlignment() 309 \sa setVerticalAlignment()
297 */ 310*/
298QStyleSheetItem::VerticalAlignment QStyleSheetItem::verticalAlignment() const 311QStyleSheetItem::VerticalAlignment QStyleSheetItem::verticalAlignment() const
299{ 312{
300 return d->valign; 313 return d->valign;
301} 314}
302 315
303/*! \enum QStyleSheetItem::VerticalAlignment 316/*!
317 \enum QStyleSheetItem::VerticalAlignment
304 318
305 This enum type defines the way elements are aligned vertically. This 319 This enum type defines the way elements are aligned vertically.
306 is supported for text elements only. The possible values are: 320 This is only supported for text elements.
307 321
308 \value VAlignBaseline align the baseline of the element (or the 322 \value VAlignBaseline align the baseline of the element (or the
309 bottom, if the element doesn't have a baseline) with the baseline of 323 bottom, if the element doesn't have a baseline) with the
310 the parent 324 baseline of the parent
311 325
312 \value VAlignSub subscript the element 326 \value VAlignSub subscript the element
313 327
314 \value VAlignSuper superscript the element 328 \value VAlignSuper superscript the element
315 329
316*/ 330*/
317 331
318 332
319/*! 333/*!
320 Sets the vertical alignment to \a valign. Possible values are 334 Sets the vertical alignment to \a valign. Possible values are
321 VAlignBaseline, VAlignSub and VAlignSuper. 335 \c VAlignBaseline, \c VAlignSub or \c VAlignSuper.
322 336
323 The vertical alignment property is not inherited. 337 The vertical alignment property is not inherited.
324 338
325 \sa verticalAlignment() 339 \sa verticalAlignment()
326 */ 340*/
327void QStyleSheetItem::setVerticalAlignment( VerticalAlignment valign ) 341void QStyleSheetItem::setVerticalAlignment( VerticalAlignment valign )
328{ 342{
329 d->valign = valign; 343 d->valign = valign;
330} 344}
331 345
332 346
333/*! 347/*!
334 Returns TRUE if the style sets an italic font; otherwise returns FALSE. 348 Returns TRUE if the style sets an italic font; otherwise returns
349 FALSE.
335 350
336 \sa setFontItalic(), definesFontItalic() 351 \sa setFontItalic(), definesFontItalic()
337 */ 352*/
338bool QStyleSheetItem::fontItalic() const 353bool QStyleSheetItem::fontItalic() const
339{ 354{
340 return d->fontitalic > 0; 355 return d->fontitalic > 0;
341} 356}
342 357
343/*! 358/*!
344 If \a italic is TRUE sets italic for the style; otherwise sets 359 If \a italic is TRUE sets italic for the style; otherwise sets
345 upright. 360 upright.
346 361
347 \sa fontItalic(), definesFontItalic() 362 \sa fontItalic(), definesFontItalic()
348 */ 363*/
349void QStyleSheetItem::setFontItalic(bool italic) 364void QStyleSheetItem::setFontItalic(bool italic)
350{ 365{
351 d->fontitalic = italic?1:0; 366 d->fontitalic = italic?1:0;
352} 367}
353 368
354/*! 369/*!
355 Returns whether the style defines a font shape. A style 370 Returns TRUE if the style defines a font shape; otherwise returns
356 does not define any shape until setFontItalic() is called. 371 FALSE. A style does not define any shape until setFontItalic() is
372 called.
357 373
358 \sa setFontItalic(), fontItalic() 374 \sa setFontItalic(), fontItalic()
359 */ 375*/
360bool QStyleSheetItem::definesFontItalic() const 376bool QStyleSheetItem::definesFontItalic() const
361{ 377{
362 return d->fontitalic != Undefined; 378 return d->fontitalic != Undefined;
363} 379}
364 380
365/*! 381/*!
366 Returns TRUE if the style sets an underlined font; otherwise returns FALSE. 382 Returns TRUE if the style sets an underlined font; otherwise
383 returns FALSE.
367 384
368 \sa setFontUnderline(), definesFontUnderline() 385 \sa setFontUnderline(), definesFontUnderline()
369 */ 386*/
370bool QStyleSheetItem::fontUnderline() const 387bool QStyleSheetItem::fontUnderline() const
371{ 388{
372 return d->fontunderline > 0; 389 return d->fontunderline > 0;
373} 390}
374 391
375/*! 392/*!
376 If \a underline is TRUE sets underline for the style; otherwise sets 393 If \a underline is TRUE, sets underline for the style; otherwise
377 no underline. 394 sets no underline.
378 395
379 \sa fontUnderline(), definesFontUnderline() 396 \sa fontUnderline(), definesFontUnderline()
380 */ 397*/
381void QStyleSheetItem::setFontUnderline(bool underline) 398void QStyleSheetItem::setFontUnderline(bool underline)
382{ 399{
383 d->fontunderline = underline?1:0; 400 d->fontunderline = underline?1:0;
384} 401}
385 402
386/*! 403/*!
387 Returns whether the style defines a setting for the underline 404 Returns TRUE if the style defines a setting for the underline
388 property of the font. A style does not define this until 405 property of the font; otherwise returns FALSE. A style does not
389 setFontUnderline() is called. 406 define this until setFontUnderline() is called.
390 407
391 \sa setFontUnderline(), fontUnderline() */ 408 \sa setFontUnderline(), fontUnderline()
409*/
392bool QStyleSheetItem::definesFontUnderline() const 410bool QStyleSheetItem::definesFontUnderline() const
393{ 411{
394 return d->fontunderline != Undefined; 412 return d->fontunderline != Undefined;
395} 413}
396 414
397 415
398/*! 416/*!
399 Returns the font weight setting of the style. This is either a 417 Returns TRUE if the style sets a strike out font; otherwise
400 valid QFont::Weight or the value QStyleSheetItem::Undefined. 418 returns FALSE.
401 419
402 \sa setFontWeight(), QFont 420 \sa setFontStrikeOut(), definesFontStrikeOut()
403 */ 421*/
422bool QStyleSheetItem::fontStrikeOut() const
423{
424 return d->fontstrikeout > 0;
425}
426
427/*!
428 If \a strikeOut is TRUE, sets strike out for the style; otherwise
429 sets no strike out.
430
431 \sa fontStrikeOut(), definesFontStrikeOut()
432*/
433void QStyleSheetItem::setFontStrikeOut(bool strikeOut)
434{
435 d->fontstrikeout = strikeOut?1:0;
436}
437
438/*!
439 Returns TRUE if the style defines a setting for the strikeOut
440 property of the font; otherwise returns FALSE. A style does not
441 define this until setFontStrikeOut() is called.
442
443 \sa setFontStrikeOut(), fontStrikeOut()
444*/
445bool QStyleSheetItem::definesFontStrikeOut() const
446{
447 return d->fontstrikeout != Undefined;
448}
449
450
451/*!
452 Returns the font weight setting of the style. This is either a
453 valid \c QFont::Weight or the value \c QStyleSheetItem::Undefined.
454
455 \sa setFontWeight(), QFont
456*/
404int QStyleSheetItem::fontWeight() const 457int QStyleSheetItem::fontWeight() const
405{ 458{
406 return d->fontweight; 459 return d->fontweight;
407} 460}
408 461
409/*! 462/*!
410 Sets the font weight setting of the style to \a w. Valid values are 463 Sets the font weight setting of the style to \a w. Valid values
411 those defined by QFont::Weight. 464 are those defined by \c QFont::Weight.
412 465
413 \sa QFont, fontWeight() 466 \sa QFont, fontWeight()
414 */ 467*/
415void QStyleSheetItem::setFontWeight(int w) 468void QStyleSheetItem::setFontWeight(int w)
416{ 469{
417 d->fontweight = w; 470 d->fontweight = w;
418} 471}
419 472
420/*! 473/*!
421 Returns the logical font size setting of the style. This is either a valid 474 Returns the logical font size setting of the style. This is either
422 size between 1 and 7 or QStyleSheetItem::Undefined. 475 a valid size between 1 and 7 or \c QStyleSheetItem::Undefined.
423 476
424 \sa setLogicalFontSize(), setLogicalFontSizeStep(), QFont::pointSize(), QFont::setPointSize() 477 \sa setLogicalFontSize(), setLogicalFontSizeStep(), QFont::pointSize(), QFont::setPointSize()
425 */ 478*/
426int QStyleSheetItem::logicalFontSize() const 479int QStyleSheetItem::logicalFontSize() const
427{ 480{
428 return d->fontsizelog; 481 return d->fontsizelog;
429} 482}
430 483
431 484
432/*! 485/*!
433 Sets the logical font size setting of the style to \a s. 486 Sets the logical font size setting of the style to \a s. Valid
434 Valid logical sizes are 1 to 7. 487 logical sizes are 1 to 7.
435 488
436 \sa logicalFontSize(), QFont::pointSize(), QFont::setPointSize() 489 \sa logicalFontSize(), QFont::pointSize(), QFont::setPointSize()
437 */ 490*/
438void QStyleSheetItem::setLogicalFontSize(int s) 491void QStyleSheetItem::setLogicalFontSize(int s)
439{ 492{
440 d->fontsizelog = s; 493 d->fontsizelog = s;
441} 494}
442 495
443/*! 496/*!
444 Returns the logical font size step of this style. 497 Returns the logical font size step of this style.
445 498
446 The default is 0. Tags such as \c big define \c +1; \c small defines 499 The default is 0. Tags such as \c big define \c +1; \c small
447 \c -1. 500 defines \c -1.
448 501
449 \sa setLogicalFontSizeStep() 502 \sa setLogicalFontSizeStep()
450 */ 503*/
451int QStyleSheetItem::logicalFontSizeStep() const 504int QStyleSheetItem::logicalFontSizeStep() const
452{ 505{
453 return d->fontsizestep; 506 return d->fontsizestep;
454} 507}
455 508
456/*! 509/*!
457 Sets the logical font size step of this style to \a s. 510 Sets the logical font size step of this style to \a s.
458 511
459 \sa logicalFontSizeStep() 512 \sa logicalFontSizeStep()
460 */ 513*/
461void QStyleSheetItem::setLogicalFontSizeStep( int s ) 514void QStyleSheetItem::setLogicalFontSizeStep( int s )
462{ 515{
463 d->fontsizestep = s; 516 d->fontsizestep = s;
464} 517}
465 518
466 519
467 520
468/*! 521/*!
469 Sets the font size setting of the style to \a s points. 522 Sets the font size setting of the style to \a s points.
470 523
471 \sa fontSize(), QFont::pointSize(), QFont::setPointSize() 524 \sa fontSize(), QFont::pointSize(), QFont::setPointSize()
472 */ 525*/
473void QStyleSheetItem::setFontSize(int s) 526void QStyleSheetItem::setFontSize(int s)
474{ 527{
475 d->fontsize = s; 528 d->fontsize = s;
476} 529}
477 530
478/*! 531/*!
479 Returns the font size setting of the style. This is either a valid 532 Returns the font size setting of the style. This is either a valid
480 point size or QStyleSheetItem::Undefined. 533 point size or \c QStyleSheetItem::Undefined.
481 534
482 \sa setFontSize(), QFont::pointSize(), QFont::setPointSize() 535 \sa setFontSize(), QFont::pointSize(), QFont::setPointSize()
483 */ 536*/
484int QStyleSheetItem::fontSize() const 537int QStyleSheetItem::fontSize() const
485{ 538{
486 return d->fontsize; 539 return d->fontsize;
487} 540}
488 541
489 542
490/*! 543/*!
491 Returns the font family setting of the style. This is either a valid 544 Returns the font family setting of the style. This is either a
492 font family or QString::null if no family has been set. 545 valid font family or QString::null if no family has been set.
493 546
494 \sa setFontFamily(), QFont::family(), QFont::setFamily() 547 \sa setFontFamily(), QFont::family(), QFont::setFamily()
495 */ 548*/
496QString QStyleSheetItem::fontFamily() const 549QString QStyleSheetItem::fontFamily() const
497{ 550{
498 return d->fontfamily; 551 return d->fontfamily;
499} 552}
500 553
501/*! 554/*!
502 Sets the font family setting of the style to \a fam. 555 Sets the font family setting of the style to \a fam.
503 556
504 \sa fontFamily(), QFont::family(), QFont::setFamily() 557 \sa fontFamily(), QFont::family(), QFont::setFamily()
505 */ 558*/
506void QStyleSheetItem::setFontFamily( const QString& fam) 559void QStyleSheetItem::setFontFamily( const QString& fam)
507{ 560{
508 d->fontfamily = fam; 561 d->fontfamily = fam;
509} 562}
510 563
511 564
512/*!\obsolete 565/*!\obsolete
513 Returns the number of columns for this style. 566 Returns the number of columns for this style.
514 567
515 \sa setNumberOfColumns(), displayMode(), setDisplayMode() 568 \sa setNumberOfColumns(), displayMode(), setDisplayMode()
516 569
517 */ 570 */
518int QStyleSheetItem::numberOfColumns() const 571int QStyleSheetItem::numberOfColumns() const
519{ 572{
520 return d->ncolumns; 573 return d->ncolumns;
521} 574}
522 575
523 576
524/*!\obsolete 577/*!\obsolete
525 Sets the number of columns for this style. Elements in the style 578 Sets the number of columns for this style. Elements in the style
526 are divided into columns. 579 are divided into columns.
527 580
528 This makes sense only if the style uses a block display mode 581 This makes sense only if the style uses a block display mode
529 (see QStyleSheetItem::DisplayMode). 582 (see QStyleSheetItem::DisplayMode).
530 583
531 \sa numberOfColumns() 584 \sa numberOfColumns()
532 */ 585 */
533void QStyleSheetItem::setNumberOfColumns(int ncols) 586void QStyleSheetItem::setNumberOfColumns(int ncols)
534{ 587{
535 if (ncols > 0) 588 if (ncols > 0)
536 d->ncolumns = ncols; 589 d->ncolumns = ncols;
537} 590}
538 591
539 592
540/*! 593/*!
541 Returns the text color of this style or an invalid color 594 Returns the text color of this style or an invalid color if no
542 if no color has been set. 595 color has been set.
543 596
544 \sa setColor() QColor::isValid() 597 \sa setColor() QColor::isValid()
545 */ 598*/
546QColor QStyleSheetItem::color() const 599QColor QStyleSheetItem::color() const
547{ 600{
548 return d->col; 601 return d->col;
549} 602}
550 603
551/*! 604/*!
552 Sets the text color of this style to \a c. 605 Sets the text color of this style to \a c.
553 606
554 \sa color() 607 \sa color()
555 */ 608*/
556void QStyleSheetItem::setColor( const QColor &c) 609void QStyleSheetItem::setColor( const QColor &c)
557{ 610{
558 d->col = c; 611 d->col = c;
559} 612}
560 613
561/*! 614/*!
562 Returns whether this style is an anchor. 615 Returns whether this style is an anchor.
563 616
564 \sa setAnchor() 617 \sa setAnchor()
565 */ 618*/
566bool QStyleSheetItem::isAnchor() const 619bool QStyleSheetItem::isAnchor() const
567{ 620{
568 return d->anchor; 621 return d->anchor;
569} 622}
570 623
571/*! 624/*!
572 If \a anc is TRUE sets this style to be an anchor (hypertext link); 625 If \a anc is TRUE, sets this style to be an anchor (hypertext
573 otherwise sets it to not be an anchor. Elements in this style have 626 link); otherwise sets it to not be an anchor. Elements in this
574 connections to other documents or anchors. 627 style link to other documents or anchors.
575 628
576 \sa isAnchor() 629 \sa isAnchor()
577 */ 630*/
578void QStyleSheetItem::setAnchor(bool anc) 631void QStyleSheetItem::setAnchor(bool anc)
579{ 632{
580 d->anchor = anc; 633 d->anchor = anc;
581} 634}
582 635
583 636
584/*! 637/*!
585 Returns the whitespace mode. 638 Returns the whitespace mode.
586 639
587 \sa setWhiteSpaceMode() WhiteSpaceMode 640 \sa setWhiteSpaceMode() WhiteSpaceMode
588 */ 641*/
589QStyleSheetItem::WhiteSpaceMode QStyleSheetItem::whiteSpaceMode() const 642QStyleSheetItem::WhiteSpaceMode QStyleSheetItem::whiteSpaceMode() const
590{ 643{
591 return d->whitespacemode; 644 return d->whitespacemode;
592} 645}
593 646
594/*! 647/*!
595 Sets the whitespace mode to \a m. 648 Sets the whitespace mode to \a m.
596 \sa WhiteSpaceMode 649
597 */ 650 \sa WhiteSpaceMode
651*/
598void QStyleSheetItem::setWhiteSpaceMode(WhiteSpaceMode m) 652void QStyleSheetItem::setWhiteSpaceMode(WhiteSpaceMode m)
599{ 653{
600 d->whitespacemode = m; 654 d->whitespacemode = m;
601} 655}
602 656
603 657
604/*! 658/*!
605 Returns the width of margin \a m in pixels. 659 Returns the width of margin \a m in pixels.
606 660
607 The margin, \a m, can be \c MarginLeft, \c MarginRight, 661 The margin, \a m, can be \c MarginLeft, \c MarginRight, \c
608 \c MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c 662 MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c
609 MarginHorizontal. 663 MarginHorizontal.
610 664
611 \sa setMargin() Margin 665 \sa setMargin() Margin
612 */ 666*/
613int QStyleSheetItem::margin(Margin m) const 667int QStyleSheetItem::margin(Margin m) const
614{ 668{
615 return d->margin[m]; 669 return d->margin[m];
616} 670}
617 671
618 672
619/*! 673/*!
620 Sets the width of margin \a m to \a v pixels. 674 Sets the width of margin \a m to \a v pixels.
621 675
622 The margin, \a m, can be \c MarginLeft, \c MarginRight, 676 The margin, \a m, can be \c MarginLeft, \c MarginRight, \c
623 \c MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c 677 MarginTop, \c MarginBottom, \c MarginAll, \c MarginVertical or \c
624 MarginHorizontal. The value \a v must be >= 0. 678 MarginHorizontal. The value \a v must be >= 0.
625 679
626 \sa margin() 680 \sa margin()
627 */ 681*/
628void QStyleSheetItem::setMargin(Margin m, int v) 682void QStyleSheetItem::setMargin(Margin m, int v)
629{ 683{
630 if (m == MarginAll ) { 684 if (m == MarginAll ) {
631 d->margin[0] = v; 685 d->margin[0] = v;
632 d->margin[1] = v; 686 d->margin[1] = v;
633 d->margin[2] = v; 687 d->margin[2] = v;
634 d->margin[3] = v; 688 d->margin[3] = v;
635 d->margin[4] = v; 689 d->margin[4] = v;
636 } else if (m == MarginVertical ) { 690 } else if (m == MarginVertical ) {
637 d->margin[MarginTop] = v; 691 d->margin[MarginTop] = v;
638 d->margin[MarginBottom] = v; 692 d->margin[MarginBottom] = v;
639 } else if (m == MarginHorizontal ) { 693 } else if (m == MarginHorizontal ) {
640 d->margin[MarginLeft] = v; 694 d->margin[MarginLeft] = v;
641 d->margin[MarginRight] = v; 695 d->margin[MarginRight] = v;
642 } else { 696 } else {
643 d->margin[m] = v; 697 d->margin[m] = v;
644 } 698 }
645} 699}
646 700
647 701
648/*! 702/*!
649 Returns the list style of the style. 703 Returns the list style of the style.
650 704
651 \sa setListStyle() ListStyle 705 \sa setListStyle() ListStyle
652 */ 706 */
653QStyleSheetItem::ListStyle QStyleSheetItem::listStyle() const 707QStyleSheetItem::ListStyle QStyleSheetItem::listStyle() const
654{ 708{
655 return d->list; 709 return d->list;
656} 710}
657 711
658/*! \enum QStyleSheetItem::ListStyle 712/*!
713 \enum QStyleSheetItem::ListStyle
659 714
660 This enum type defines how the items in a list are prefixed when 715 This enum type defines how the items in a list are prefixed when
661 displayed. The currently defined values are: 716 displayed.
662 717
663 \value ListDisc a filled circle (i.e. a bullet) 718 \value ListDisc a filled circle (i.e. a bullet)
664 \value ListCircle an unfilled circle 719 \value ListCircle an unfilled circle
665 \value ListSquare a filled square 720 \value ListSquare a filled square
666 \value ListDecimal an integer in base 10: \e 1, \e 2, \e 3, ... 721 \value ListDecimal an integer in base 10: \e 1, \e 2, \e 3, ...
667 \value ListLowerAlpha a lowercase letter: \e a, \e b, \e c, ... 722 \value ListLowerAlpha a lowercase letter: \e a, \e b, \e c, ...
668 \value ListUpperAlpha an uppercase letter: \e A, \e B, \e C, ... 723 \value ListUpperAlpha an uppercase letter: \e A, \e B, \e C, ...
669*/ 724*/
725
670/*! 726/*!
671 Sets the list style of the style to \a s. 727 Sets the list style of the style to \a s.
672 728
673 This is used by nested elements that have a display mode of 729 This is used by nested elements that have a display mode of \c
674 \c DisplayListItem. 730 DisplayListItem.
675 731
676 \sa listStyle() DisplayMode ListStyle 732 \sa listStyle() DisplayMode ListStyle
677 */ 733*/
678void QStyleSheetItem::setListStyle(ListStyle s) 734void QStyleSheetItem::setListStyle(ListStyle s)
679{ 735{
680 d->list=s; 736 d->list=s;
681} 737}
682 738
683 739
684/*! Returns a space-separated list of names of styles that may 740/*!
685 contain elements of this style. If nothing has been set, contexts() 741 Returns a space-separated list of names of styles that may contain
686 returns an empty string, which indicates that this style can be 742 elements of this style. If nothing has been set, contexts()
687 nested everywhere. 743 returns an empty string, which indicates that this style can be
744 nested everywhere.
688 745
689 \sa setContexts() 746 \sa setContexts()
690 */ 747*/
691QString QStyleSheetItem::contexts() const 748QString QStyleSheetItem::contexts() const
692{ 749{
693 return d->contxt; 750 return d->contxt;
694} 751}
695 752
696/*! 753/*!
697 Sets a space-separated list of names of styles that may contain 754 Sets a space-separated list of names of styles that may contain
698 elements of this style. If \a c is empty, the style can be nested 755 elements of this style. If \a c is empty, the style can be nested
699 everywhere. 756 everywhere.
700 757
701 \sa contexts() 758 \sa contexts()
702 */ 759*/
703void QStyleSheetItem::setContexts( const QString& c) 760void QStyleSheetItem::setContexts( const QString& c)
704{ 761{
705 d->contxt = QChar(' ') + c + QChar(' '); 762 d->contxt = QChar(' ') + c + QChar(' ');
706} 763}
707 764
708/*! 765/*!
709 Returns TRUE if this style can be nested into an element 766 Returns TRUE if this style can be nested into an element of style
710 of style \a s; otherwise returns FALSE. 767 \a s; otherwise returns FALSE.
711 768
712 \sa contexts(), setContexts() 769 \sa contexts(), setContexts()
713 */ 770*/
714bool QStyleSheetItem::allowedInContext( const QStyleSheetItem* s) const 771bool QStyleSheetItem::allowedInContext( const QStyleSheetItem* s) const
715{ 772{
716 if ( d->contxt.isEmpty() ) 773 if ( d->contxt.isEmpty() )
717 return TRUE; 774 return TRUE;
718 return d->contxt.find( QChar(' ')+s->name()+QChar(' ')) != -1; 775 return d->contxt.find( QChar(' ')+s->name()+QChar(' ')) != -1;
719} 776}
720 777
721 778
722/*! 779/*!
723 Returns TRUE if this style has self-nesting enabled; otherwise 780 Returns TRUE if this style has self-nesting enabled; otherwise
724 returns FALSE. 781 returns FALSE.
725 782
726 \sa setSelfNesting() 783 \sa setSelfNesting()
727 */ 784*/
728bool QStyleSheetItem::selfNesting() const 785bool QStyleSheetItem::selfNesting() const
729{ 786{
730 return d->selfnest; 787 return d->selfnest;
731} 788}
732 789
733/*! 790/*!
734 Sets the self-nesting property for this style to \a nesting. 791 Sets the self-nesting property for this style to \a nesting.
735 792
736 In order to support "dirty" HTML, paragraphs \c{<p>} and list items 793 In order to support "dirty" HTML, paragraphs \c{<p>} and list
737 \c{<li>} are not self-nesting. This means that starting a new 794 items \c{<li>} are not self-nesting. This means that starting a
738 paragraph or list item automatically closes the previous one. 795 new paragraph or list item automatically closes the previous one.
739 796
740 \sa selfNesting() 797 \sa selfNesting()
741 */ 798*/
742void QStyleSheetItem::setSelfNesting( bool nesting ) 799void QStyleSheetItem::setSelfNesting( bool nesting )
743{ 800{
744 d->selfnest = nesting; 801 d->selfnest = nesting;
745} 802}
746 803
747/*! Sets the linespacing to be \a ls pixels */ 804/*
805 Sets the linespacing to be at least \a ls pixels.
806
807 For compatibility with previous Qt releases, small values get
808 treated differently: If \a ls is smaller than the default font
809 line spacing in pixels at parse time, the resulting line spacing
810 is the sum of the default line spacing plus \a ls. We recommend
811 not relying on this behavior.
812*/
748 813
749void QStyleSheetItem::setLineSpacing( int ls ) 814void QStyleSheetItem::setLineSpacing( int ls )
750{ 815{
751 d->lineSpacing = ls; 816 d->lineSpacing = ls;
752} 817}
753 818
754/*! Returns the linespacing */ 819/*!
820 \obsolete
821
822 Returns the linespacing
823*/
755 824
756int QStyleSheetItem::lineSpacing() const 825int QStyleSheetItem::lineSpacing() const
757{ 826{
758 return d->lineSpacing; 827 return d->lineSpacing;
759} 828}
760 829
761//************************************************************************ 830//************************************************************************
762 831
763 832
764 833
765 834
766//************************************************************************ 835//************************************************************************
767 836
768 837
769/*! 838/*!
770 \class QStyleSheet qstylesheet.h 839 \class QStyleSheet qstylesheet.h
771 \ingroup text 840 \ingroup text
772 \brief The QStyleSheet class is a collection of styles for rich text 841 \brief The QStyleSheet class is a collection of styles for rich text
773 rendering and a generator of tags. 842 rendering and a generator of tags.
774 843
775 \ingroup graphics 844 \ingroup graphics
776 \ingroup helpsystem 845 \ingroup helpsystem
777 846
778 By creating QStyleSheetItem objects for a style sheet you build a 847 By creating QStyleSheetItem objects for a style sheet you build a
779 definition of a set of tags. This definition will be used by the 848 definition of a set of tags. This definition will be used by the
780 internal rich text rendering system to parse and display text 849 internal rich text rendering system to parse and display text
781 documents to which the style sheet applies. Rich text is normally 850 documents to which the style sheet applies. Rich text is normally
782 visualized in a QTextView or a QTextBrowser. However, QLabel, 851 visualized in a QTextView or a QTextBrowser. However, QLabel,
783 QWhatsThis and QMessageBox also support it, and other classes are 852 QWhatsThis and QMessageBox also support it, and other classes are
784 likely to follow. With QSimpleRichText it is possible to use the 853 likely to follow. With QSimpleRichText it is possible to use the
785 rich text renderer for custom widgets as well. 854 rich text renderer for custom widgets as well.
786 855
787 The default QStyleSheet object has the following style bindings, 856 The default QStyleSheet object has the following style bindings,
788 sorted by structuring bindings, anchors, character style bindings 857 sorted by structuring bindings, anchors, character style bindings
789 (i.e. inline styles), special elements such as horizontal lines or 858 (i.e. inline styles), special elements such as horizontal lines or
790 images, and other tags. In addition, rich text supports simple HTML 859 images, and other tags. In addition, rich text supports simple
791 tables. 860 HTML tables.
792 861
793 The structuring tags are 862 The structuring tags are
794 \list 863 \table
795 \i \c{<qt>}...\c{</qt>} 864 \header \i Structuring tags \i Notes
796 - A Qt rich text document. It understands the following attributes: 865 \row \i \c{<qt>}...\c{</qt>}
797 \list 866 \i A Qt rich text document. It understands the following
798 \i title 867 attributes:
799 - The caption of the document. This attribute is easily accessible with 868 \list
800 QTextView::documentTitle(). 869 \i \c title -- The caption of the document. This attribute is
801 \i type 870 easily accessible with QTextView::documentTitle().
802 - The type of the document. The default type is \c page . It 871 \i \c type -- The type of the document. The default type is \c
803 indicates that the document is displayed in a page of its 872 page. It indicates that the document is displayed in a
804 own. Another style is \c detail, which can be used to 873 page of its own. Another style is \c detail, which can be
805 explain certain expressions in more detail in a few 874 used to explain certain expressions in more detail in a
806 sentences. The QTextBrowser will then keep the current page 875 few sentences. For \c detail, QTextBrowser will then keep
807 and display the new document in a small popup similar to 876 the current page and display the new document in a small
808 QWhatsThis. Note that links will not work in documents with 877 popup similar to QWhatsThis. Note that links will not work
809 \c{<qt type="detail">...</qt>}. 878 in documents with \c{<qt type="detail">...</qt>}.
810 \i bgcolor 879 \i \c bgcolor -- The background color, for example \c
811 - The background color, for example \c bgcolor="yellow" or \c 880 bgcolor="yellow" or \c bgcolor="#0000FF".
812 bgcolor="#0000FF". 881 \i \c background -- The background pixmap, for example \c
813 \i background 882 background="granite.xpm". The pixmap name will be resolved
814 - The background pixmap, for example \c 883 by a QMimeSourceFactory().
815 background="granit.xpm". The pixmap name will be resolved by 884 \i \c text -- The default text color, for example \c text="red".
816 a QMimeSourceFactory(). 885 \i \c link -- The link color, for example \c link="green".
817 \i text 886 \endlist
818 - The default text color, for example \c text="red". 887 \row \i \c{<h1>...</h1>}
819 \i link 888 \i A top-level heading.
820 - The link color, for example \c link="green". 889 \row \i \c{<h2>...</h2>}
821 \endlist 890 \i A sublevel heading.
822 \i \c{<h1>...</h1>} 891 \row \i \c{<h3>...</h3>}
823 - A top-level heading. 892 \i A sub-sublevel heading.
824 \i \c{<h2>...</h2>} 893 \row \i \c{<p>...</p>}
825 - A sublevel heading. 894 \i A left-aligned paragraph. Adjust the alignment with the \c
826 \i \c{<h3>...</h3>} 895 align attribute. Possible values are \c left, \c right and
827 - A sub-sublevel heading. 896 \c center.
828 \i \c{<p>...</p>} 897 \row \i \c{<center>...}<br>\c{</center>}
829 - A left-aligned paragraph. Adjust the alignment with 898 \i A centered paragraph.
830 the \c align attribute. Possible values are 899 \row \i \c{<blockquote>...}<br>\c{</blockquote>}
831 \c left, \c right and \c center. 900 \i An indented paragraph that is useful for quotes.
832 \i \c{<center>...</center>} 901 \row \i \c{<ul>...</ul>}
833 - A centered paragraph. 902 \i An unordered list. You can also pass a type argument to
834 \i \c{<blockquote>...</blockquote>} 903 define the bullet style. The default is \c type=disc;
835 - An indented paragraph that is useful for quotes. 904 other types are \c circle and \c square.
836 \i \c{<ul>...</ul>} 905 \row \i \c{<ol>...</ol>}
837 - An unordered list. You can also pass a type argument to 906 \i An ordered list. You can also pass a type argument to
838 define the bullet style. The default is \c type=disc; other 907 define the enumeration label style. The default is \c
839 types are \c circle and \c square. 908 type="1"; other types are \c "a" and \c "A".
840 \i \c{<ol>...</ol>} 909 \row \i \c{<li>...</li>}
841 - An ordered list. You can also pass a type argument to define 910 \i A list item. This tag can be used only within the context
842 the enumeration label style. The default is \c type="1"; other 911 of \c{<ol>} or \c{<ul>}.
843 types are \c "a" and \c "A". 912 \row \i \c{<pre>...</pre>}
844 \i <tt>&lt;li&gt;</tt>...<tt>&lt;/li&gt;</tt> 913 \i For larger chunks of code. Whitespaces in the contents are
845 - A list item. This tag can be used only within the context of 914 preserved. For small bits of code use the inline-style \c
846 \c ol or \c ul. 915 code.
847 \i \c{<pre>...</pre>} 916 \endtable
848 - For larger chunks of code. Whitespaces in the contents are preserved. 917
849 For small bits of code use the inline-style \c code. 918 Anchors and links are done with a single tag:
850 \endlist 919 \table
851 920 \header \i Anchor tags \i Notes
852 Anchors and links are done with a single tag: 921 \row \i \c{<a>...</a>}
853 \list 922 \i An anchor or link.
854 \i \c{<a>...</a>} 923 \list
855 - An anchor or link. The reference target is defined in the \c 924 \i A link is created by using an \c href
856 href attribute of the tag as in \c{<a 925 attribute, for example
857 href="target.qml">...</a>}. You can also specify an 926 <br>\c{<a href="target.qml">Link Text</a>}. Links to
858 additional anchor within the specified target document, for 927 targets within a document are achieved in the same way
859 example \c{<a href="target.qml#123">...</a>}. If \c a is 928 as for HTML, e.g.
860 meant to be an anchor, the reference source is given in the 929 <br>\c{<a href="target.qml#subtitle">Link Text</a>}.
861 \c name attribute. 930 \i A target is created by using a \c name
862 \endlist 931 attribute, for example
863 932 <br>\c{<a name="subtitle"><h2>Sub Title</h2></a>}.
864 The default character style bindings are 933 \endlist
865 \list 934 \endtable
866 \i \c{<em>...</em>} 935
867 - Emphasized. By default this is the same as 936 The default character style bindings are
868 \c{<i>...</i>} (italic). 937 \table
869 \i \c{<strong>...</strong>} 938 \header \i Style tags \i Notes
870 - Strong. By default this is the same as 939 \row \i \c{<em>...</em>}
871 \c{<b>...</b>} (bold). 940 \i Emphasized. By default this is the same as \c{<i>...</i>}
872 \i \c{<i>...</i>} 941 (italic).
873 - Italic font style. 942 \row \i \c{<strong>...</strong>}
874 \i \c{<b>...</b>} 943 \i Strong. By default this is the same as \c{<b>...</b>}
875 - Bold font style. 944 (bold).
876 \i \c{<u>...</u>} 945 \row \i \c{<i>...</i>}
877 - Underlined font style. 946 \i Italic font style.
878 \i \c{<big>...</big>} 947 \row \i \c{<b>...</b>}
879 - A larger font size. 948 \i Bold font style.
880 \i \c{<small>...</small>} 949 \row \i \c{<u>...</u>}
881 - A smaller font size. 950 \i Underlined font style.
882 \i \c{<code>...</code>} 951 \row \i \c{<s>...</s>}
883 - Indicates code. By default this is the same as 952 \i Strike out font style.
884 \c{<tt>...</tt>} (typewriter). For 953 \row \i \c{<big>...</big>}
885 larger junks of code use the block-tag \c pre. 954 \i A larger font size.
886 \i \c{<tt>...</tt>} 955 \row \i \c{<small>...</small>}
887 - Typewriter font style. 956 \i A smaller font size.
888 \i \c{<font>...</font>} 957 \row \i \c{<code>...</code>}
889 - Customizes the font size, family and text color. The tag understands 958 \i Indicates code. By default this is the same as
890 the following attributes: 959 \c{<tt>...</tt>} (typewriter). For larger junks of code
891 \list 960 use the block-tag \c{<}\c{pre>}.
892 \i color 961 \row \i \c{<tt>...</tt>}
893 - The text color, for example \c color="red" or \c color="#FF0000". 962 \i Typewriter font style.
894 \i size 963 \row \i \c{<font>...</font>}
895 - The logical size of the font. Logical sizes 1 to 7 are supported. 964 \i Customizes the font size, family and text color. The tag
896 The value may either be absolute (for example, 965 understands the following attributes:
897 \c size=3) or relative (\c size=-2). In the latter case the sizes 966 \list
898 are simply added. 967 \i \c color -- The text color, for example \c color="red" or
899 \i face 968 \c color="#FF0000".
900 - The family of the font, for example \c face=times. 969 \i \c size -- The logical size of the font. Logical sizes 1
901 \endlist 970 to 7 are supported. The value may either be absolute
902 \endlist 971 (for example, \c size=3) or relative (\c size=-2). In
903 972 the latter case the sizes are simply added.
904 Special elements are: 973 \i \c face -- The family of the font, for example \c face=times.
905 \list 974 \endlist
906 \i \c{<img>} 975 \endtable
907 - An image. The image name for the mime source 976
908 factory is given in the source attribute, for example 977 Special elements are:
909 \c{<img src="qt.xpm">} 978 \table
910 The image tag also understands the attributes \c width and \c 979 \header \i Special tags \i Notes
911 height that determine the size of the image. If the pixmap 980 \row \i \c{<img>}
912 does not fit the specified size it will be scaled 981 \i An image. The image name for the mime source factory is
913 automatically (by using QImage::smoothScale()). 982 given in the source attribute, for example
914 983 \c{<img src="qt.xpm">} The image tag also understands the
915 The \c align attribute determines where the image is 984 attributes \c width and \c height that determine the size
916 placed. By default, an image is placed inline just like a 985 of the image. If the pixmap does not fit the specified
917 normal character. Specify \c left or \c right to place the 986 size it will be scaled automatically (by using
918 image at the respective side. 987 QImage::smoothScale()).
919 \i \c{<hr>} 988 <br>
920 - A horizonal line. 989 The \c align attribute determines where the image is
921 \i \c{<br>} 990 placed. By default, an image is placed inline just like a
922 - A line break. 991 normal character. Specify \c left or \c right to place the
923 \endlist 992 image at the respective side.
924 993 \row \i \c{<hr>}
925 Another tag not in any of the above cathegories is 994 \i A horizonal line.
926 \list 995 \row \i \c{<br>}
927 \i \c{<nobr>...</nobr>} 996 \i A line break.
928 - No break. Prevents word wrap. 997 \row \i \c{<nobr>...</nobr>}
929 \endlist 998 \i No break. Prevents word wrap.
930 999 \endtable
931 In addition, rich text supports simple HTML tables. A table consists 1000
932 of one or more rows each of which contains one or more cells. Cells 1001 In addition, rich text supports simple HTML tables. A table
933 are either data cells or header cells, depending on their 1002 consists of one or more rows each of which contains one or more
934 content. Cells which span rows and columns are supported. 1003 cells. Cells are either data cells or header cells, depending on
935 1004 their content. Cells which span rows and columns are supported.
936 \list 1005
937 \i \c{<table>...</table>} 1006 \table
938 - A table. Tables support the following attributes: 1007 \header \i Table tags \i Notes
939 \list 1008 \row \i \c{<table>...</table>}
940 \i bgcolor 1009 \i A table. Tables support the following attributes:
941 - The background color. 1010 \list
942 \i width 1011 \i \c bgcolor -- The background color.
943 - The table width. This is either an absolute pixel width or a relative 1012 \i \c width -- The table width. This is either an absolute
944 percentage of the table's width, for example \c width=80%. 1013 pixel width or a relative percentage of the table's
945 \i border 1014 width, for example \c width=80%.
946 - The width of the table border. The default is 0 (= no border). 1015 \i \c border -- The width of the table border. The default is
947 \i cellspacing 1016 0 (= no border).
948 - Additional space around the table cells. The default is 2. 1017 \i \c cellspacing -- Additional space around the table cells.
949 \i cellpadding 1018 The default is 2.
950 - Additional space around the contents of table cells. The default is 1. 1019 \i \c cellpadding -- Additional space around the contents of
951 \endlist 1020 table cells. The default is 1.
952 \i \c{<tr>...</tr>} 1021 \endlist
953 - A table row. This is only valid within a \c table. Rows support 1022 \row \i \c{<tr>...</tr>}
954 the following attribute: 1023 \i A table row. This is only valid within a \c table. Rows
955 \list 1024 support the following attribute:
956 \i bgcolor 1025 \list
957 - The background color. 1026 \i \c bgcolor -- The background color.
958 \endlist 1027 \endlist
959 \i \c{<th>...</th>} 1028 \row \i \c{<th>...</th>}
960 - A table header cell. Similar to \c td, but defaults to center alignment 1029 \i A table header cell. Similar to \c td, but defaults to
961 and a bold font. 1030 center alignment and a bold font.
962 \i \c{<td>...</td>} 1031 \row \i \c{<td>...</td>}
963 - A table data cell. This is only valid within a \c tr. Cells 1032 \i A table data cell. This is only valid within a \c tr.
964 support the following attributes: 1033 Cells support the following attributes:
965 \list 1034 \list
966 \i bgcolor 1035 \i \c bgcolor -- The background color.
967 - The background color. 1036 \i \c width -- The cell width. This is either an absolute
968 \i width 1037 pixel width or a relative percentage of table's width,
969 - The cell width. This is either an absolute pixel width or a relative 1038 for example \c width=50%.
970 percentage of table's width, for example \c width=50%. 1039 \i \c colspan -- Specifies how many columns this cell spans.
971 \i colspan 1040 The default is 1.
972 - Specifies how many columns this cell spans. The default is 1. 1041 \i \c rowspan -- Specifies how many rows this cell spans. The
973 \i rowspan 1042 default is 1.
974 - Specifies how many rows this cell spans. The default is 1. 1043 \i \c align -- Alignment; possible values are \c left, \c
975 \i align 1044 right, and \c center. The default is left.
976 - Alignment; possible values are \c left, \c right, and \c center. The 1045 \endlist
977 default is left. 1046 \endtable
978 \endlist 1047*/
979 \endlist 1048
980*/ 1049/*!
981 1050 Creates a style sheet called \a name, with parent \a parent. Like
982/*! 1051 any QObject it will be deleted when its parent is destroyed (if
983 Creates a style sheet with parent \a parent and name \a name. Like 1052 the child still exists).
984 any QObject it will be deleted when its parent is 1053
985 destroyed (if the child still exists). 1054 By default the style sheet has the tag definitions defined above.
986
987 By default the style sheet has the tag definitions defined above.
988*/ 1055*/
989QStyleSheet::QStyleSheet( QObject *parent, const char *name ) 1056QStyleSheet::QStyleSheet( QObject *parent, const char *name )
990 : QObject( parent, name ) 1057 : QObject( parent, name )
991{ 1058{
992 init(); 1059 init();
993} 1060}
994 1061
995/*! 1062/*!
996 Destroys the style sheet. All styles inserted into the style sheet 1063 Destroys the style sheet. All styles inserted into the style sheet
997 will be deleted. 1064 will be deleted.
998*/ 1065*/
999QStyleSheet::~QStyleSheet() 1066QStyleSheet::~QStyleSheet()
1000{ 1067{
1001} 1068}
1002 1069
1003/*! 1070/*!
1004 \internal 1071 \internal
1005 Initialized the style sheet to the basic Qt style. 1072 Initialized the style sheet to the basic Qt style.
1006*/ 1073*/
1007void QStyleSheet::init() 1074void QStyleSheet::init()
1008{ 1075{
1009 styles.setAutoDelete( TRUE ); 1076 styles.setAutoDelete( TRUE );
1010 1077
1011 nullstyle = new QStyleSheetItem( this, 1078 nullstyle = new QStyleSheetItem( this,
1012 QString::fromLatin1("") ); 1079 QString::fromLatin1("") );
1013 1080
1014 QStyleSheetItem* style; 1081 QStyleSheetItem* style;
1015 1082
1016 style = new QStyleSheetItem( this, "qml" ); // compatibility 1083 style = new QStyleSheetItem( this, "qml" ); // compatibility
1017 style->setDisplayMode( QStyleSheetItem::DisplayBlock ); 1084 style->setDisplayMode( QStyleSheetItem::DisplayBlock );
1018 1085
1019 style = new QStyleSheetItem( this, QString::fromLatin1("qt") ); 1086 style = new QStyleSheetItem( this, QString::fromLatin1("qt") );
1020 style->setDisplayMode( QStyleSheetItem::DisplayBlock ); 1087 style->setDisplayMode( QStyleSheetItem::DisplayBlock );
1021 //style->setMargin( QStyleSheetItem::MarginAll, 4 );
1022 1088
1023 style = new QStyleSheetItem( this, QString::fromLatin1("a") ); 1089 style = new QStyleSheetItem( this, QString::fromLatin1("a") );
1024 style->setAnchor( TRUE ); 1090 style->setAnchor( TRUE );
1025 1091
1026 style = new QStyleSheetItem( this, QString::fromLatin1("em") ); 1092 style = new QStyleSheetItem( this, QString::fromLatin1("em") );
1027 style->setFontItalic( TRUE ); 1093 style->setFontItalic( TRUE );
1028 1094
1029 style = new QStyleSheetItem( this, QString::fromLatin1("i") ); 1095 style = new QStyleSheetItem( this, QString::fromLatin1("i") );
1030 style->setFontItalic( TRUE ); 1096 style->setFontItalic( TRUE );
1031 1097
1032 style = new QStyleSheetItem( this, QString::fromLatin1("big") ); 1098 style = new QStyleSheetItem( this, QString::fromLatin1("big") );
1033 style->setLogicalFontSizeStep( 1 ); 1099 style->setLogicalFontSizeStep( 1 );
1034 style = new QStyleSheetItem( this, QString::fromLatin1("large") ); // compatibility 1100 style = new QStyleSheetItem( this, QString::fromLatin1("large") ); // compatibility
1035 style->setLogicalFontSizeStep( 1 ); 1101 style->setLogicalFontSizeStep( 1 );
1036 1102
1037 style = new QStyleSheetItem( this, QString::fromLatin1("small") ); 1103 style = new QStyleSheetItem( this, QString::fromLatin1("small") );
1038 style->setLogicalFontSizeStep( -1 ); 1104 style->setLogicalFontSizeStep( -1 );
1039 1105
1040 style = new QStyleSheetItem( this, QString::fromLatin1("strong") ); 1106 style = new QStyleSheetItem( this, QString::fromLatin1("strong") );
1041 style->setFontWeight( QFont::Bold); 1107 style->setFontWeight( QFont::Bold);
1042 1108
1043 style = new QStyleSheetItem( this, QString::fromLatin1("b") ); 1109 style = new QStyleSheetItem( this, QString::fromLatin1("b") );
1044 style->setFontWeight( QFont::Bold); 1110 style->setFontWeight( QFont::Bold);
1045 1111
1046 style = new QStyleSheetItem( this, QString::fromLatin1("h1") ); 1112 style = new QStyleSheetItem( this, QString::fromLatin1("h1") );
1047 style->setFontWeight( QFont::Bold); 1113 style->setFontWeight( QFont::Bold);
1048 style->setLogicalFontSize(6); 1114 style->setLogicalFontSize(6);
1049 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1115 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1050 style-> setMargin(QStyleSheetItem::MarginTop, 12); 1116 style-> setMargin(QStyleSheetItem::MarginTop, 18);
1051 style-> setMargin(QStyleSheetItem::MarginBottom, 6); 1117 style-> setMargin(QStyleSheetItem::MarginBottom, 12);
1052 1118
1053 style = new QStyleSheetItem( this, QString::fromLatin1("h2") ); 1119 style = new QStyleSheetItem( this, QString::fromLatin1("h2") );
1054 style->setFontWeight( QFont::Bold); 1120 style->setFontWeight( QFont::Bold);
1055 style->setLogicalFontSize(5); 1121 style->setLogicalFontSize(5);
1056 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1122 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1057 style-> setMargin(QStyleSheetItem::MarginTop, 10); 1123 style-> setMargin(QStyleSheetItem::MarginTop, 16);
1058 style-> setMargin(QStyleSheetItem::MarginBottom, 5); 1124 style-> setMargin(QStyleSheetItem::MarginBottom, 12);
1059 1125
1060 style = new QStyleSheetItem( this, QString::fromLatin1("h3") ); 1126 style = new QStyleSheetItem( this, QString::fromLatin1("h3") );
1061 style->setFontWeight( QFont::Bold); 1127 style->setFontWeight( QFont::Bold);
1062 style->setLogicalFontSize(4); 1128 style->setLogicalFontSize(4);
1063 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1129 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1064 style-> setMargin(QStyleSheetItem::MarginTop, 8); 1130 style-> setMargin(QStyleSheetItem::MarginTop, 14);
1065 style-> setMargin(QStyleSheetItem::MarginBottom, 4); 1131 style-> setMargin(QStyleSheetItem::MarginBottom, 12);
1066 1132
1067 style = new QStyleSheetItem( this, QString::fromLatin1("h4") ); 1133 style = new QStyleSheetItem( this, QString::fromLatin1("h4") );
1068 style->setFontWeight( QFont::Bold); 1134 style->setFontWeight( QFont::Bold);
1069 style->setLogicalFontSize(3); 1135 style->setLogicalFontSize(3);
1070 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1136 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1071 style-> setMargin(QStyleSheetItem::MarginTop, 8); 1137 style-> setMargin(QStyleSheetItem::MarginVertical, 12);
1072 style-> setMargin(QStyleSheetItem::MarginBottom, 4);
1073 1138
1074 style = new QStyleSheetItem( this, QString::fromLatin1("h5") ); 1139 style = new QStyleSheetItem( this, QString::fromLatin1("h5") );
1075 style->setFontWeight( QFont::Bold); 1140 style->setFontWeight( QFont::Bold);
1076 style->setLogicalFontSize(2); 1141 style->setLogicalFontSize(2);
1077 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1142 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1078 style-> setMargin(QStyleSheetItem::MarginTop, 8); 1143 style-> setMargin(QStyleSheetItem::MarginTop, 12);
1079 style-> setMargin(QStyleSheetItem::MarginBottom, 4); 1144 style-> setMargin(QStyleSheetItem::MarginBottom, 4);
1080 1145
1081 style = new QStyleSheetItem( this, QString::fromLatin1("p") ); 1146 style = new QStyleSheetItem( this, QString::fromLatin1("p") );
1082 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1147 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1083 style-> setMargin(QStyleSheetItem::MarginVertical, 8); 1148 style-> setMargin(QStyleSheetItem::MarginVertical, 12);
1084 style->setSelfNesting( FALSE ); 1149 style->setSelfNesting( FALSE );
1085 1150
1086 style = new QStyleSheetItem( this, QString::fromLatin1("center") ); 1151 style = new QStyleSheetItem( this, QString::fromLatin1("center") );
1087 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1152 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1088 style->setAlignment( AlignCenter ); 1153 style->setAlignment( AlignCenter );
1089 1154
1090 style = new QStyleSheetItem( this, QString::fromLatin1("twocolumn") ); 1155 style = new QStyleSheetItem( this, QString::fromLatin1("twocolumn") );
1091 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1156 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1092 style->setNumberOfColumns( 2 ); 1157 style->setNumberOfColumns( 2 );
1093 1158
1094 style = new QStyleSheetItem( this, QString::fromLatin1("multicol") ); 1159 style = new QStyleSheetItem( this, QString::fromLatin1("multicol") );
1095 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1160 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1096 (void) new QStyleSheetItem( this, QString::fromLatin1("font") ); 1161 (void) new QStyleSheetItem( this, QString::fromLatin1("font") );
1097 1162
1098 style = new QStyleSheetItem( this, QString::fromLatin1("ul") ); 1163 style = new QStyleSheetItem( this, QString::fromLatin1("ul") );
1099 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1164 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1100 style-> setMargin(QStyleSheetItem::MarginVertical, 4); 1165 style->setListStyle( QStyleSheetItem::ListDisc );
1166 style-> setMargin(QStyleSheetItem::MarginVertical, 12);
1167 style->setMargin( QStyleSheetItem::MarginLeft, 40 );
1101 1168
1102 style = new QStyleSheetItem( this, QString::fromLatin1("ol") ); 1169 style = new QStyleSheetItem( this, QString::fromLatin1("ol") );
1103 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1170 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1104 style->setListStyle( QStyleSheetItem::ListDecimal ); 1171 style->setListStyle( QStyleSheetItem::ListDecimal );
1105 style-> setMargin(QStyleSheetItem::MarginVertical, 4); 1172 style-> setMargin(QStyleSheetItem::MarginVertical, 12);
1173 style->setMargin( QStyleSheetItem::MarginLeft, 40 );
1106 1174
1107 style = new QStyleSheetItem( this, QString::fromLatin1("li") ); 1175 style = new QStyleSheetItem( this, QString::fromLatin1("li") );
1108 style->setDisplayMode(QStyleSheetItem::DisplayListItem); 1176 style->setDisplayMode(QStyleSheetItem::DisplayListItem);
1109 style->setSelfNesting( FALSE ); 1177 style->setSelfNesting( FALSE );
1110 style->setContexts(QString::fromLatin1("ol ul"));
1111 style-> setMargin(QStyleSheetItem::MarginVertical, 4);
1112 1178
1113 style = new QStyleSheetItem( this, QString::fromLatin1("code") ); 1179 style = new QStyleSheetItem( this, QString::fromLatin1("code") );
1114 style->setFontFamily( QString::fromLatin1("courier") ); 1180 style->setFontFamily( QString::fromLatin1("courier") );
1115 1181
1116 style = new QStyleSheetItem( this, QString::fromLatin1("tt") ); 1182 style = new QStyleSheetItem( this, QString::fromLatin1("tt") );
1117 style->setFontFamily( QString::fromLatin1("courier") ); 1183 style->setFontFamily( QString::fromLatin1("courier") );
1118 1184
1119 new QStyleSheetItem(this, QString::fromLatin1("img")); 1185 new QStyleSheetItem(this, QString::fromLatin1("img"));
1120 new QStyleSheetItem(this, QString::fromLatin1("br")); 1186 new QStyleSheetItem(this, QString::fromLatin1("br"));
1121 new QStyleSheetItem(this, QString::fromLatin1("hr")); 1187 new QStyleSheetItem(this, QString::fromLatin1("hr"));
1188
1122 style = new QStyleSheetItem(this, QString::fromLatin1("sub")); 1189 style = new QStyleSheetItem(this, QString::fromLatin1("sub"));
1123 style->setVerticalAlignment( QStyleSheetItem::VAlignSub ); 1190 style->setVerticalAlignment( QStyleSheetItem::VAlignSub );
1124 style = new QStyleSheetItem(this, QString::fromLatin1("sup")); 1191 style = new QStyleSheetItem(this, QString::fromLatin1("sup"));
1125 style->setVerticalAlignment( QStyleSheetItem::VAlignSuper ); 1192 style->setVerticalAlignment( QStyleSheetItem::VAlignSuper );
1126 1193
1127 style = new QStyleSheetItem( this, QString::fromLatin1("pre") ); 1194 style = new QStyleSheetItem( this, QString::fromLatin1("pre") );
1128 style->setFontFamily( QString::fromLatin1("courier") ); 1195 style->setFontFamily( QString::fromLatin1("courier") );
1129 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1196 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1130 style->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre); 1197 style->setWhiteSpaceMode(QStyleSheetItem::WhiteSpacePre);
1131 1198
1132 style = new QStyleSheetItem( this, QString::fromLatin1("blockquote") ); 1199 style = new QStyleSheetItem( this, QString::fromLatin1("blockquote") );
1133 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1200 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1134 style->setMargin(QStyleSheetItem::MarginHorizontal, 40 ); 1201 style->setMargin(QStyleSheetItem::MarginHorizontal, 40 );
1135 1202
1136 style = new QStyleSheetItem( this, QString::fromLatin1("head") ); 1203 style = new QStyleSheetItem( this, QString::fromLatin1("head") );
1137 style->setDisplayMode(QStyleSheetItem::DisplayNone); 1204 style->setDisplayMode(QStyleSheetItem::DisplayNone);
1205 style = new QStyleSheetItem( this, QString::fromLatin1("body") );
1206 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1138 style = new QStyleSheetItem( this, QString::fromLatin1("div") ); 1207 style = new QStyleSheetItem( this, QString::fromLatin1("div") );
1139 style->setDisplayMode(QStyleSheetItem::DisplayBlock) ; 1208 style->setDisplayMode(QStyleSheetItem::DisplayBlock) ;
1209 style = new QStyleSheetItem( this, QString::fromLatin1("span") );
1140 style = new QStyleSheetItem( this, QString::fromLatin1("dl") ); 1210 style = new QStyleSheetItem( this, QString::fromLatin1("dl") );
1211 style-> setMargin(QStyleSheetItem::MarginVertical, 8);
1141 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1212 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1142 style = new QStyleSheetItem( this, QString::fromLatin1("dt") ); 1213 style = new QStyleSheetItem( this, QString::fromLatin1("dt") );
1143 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1214 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1144 style->setContexts(QString::fromLatin1("dl") ); 1215 style->setContexts(QString::fromLatin1("dl") );
1145 style = new QStyleSheetItem( this, QString::fromLatin1("dd") ); 1216 style = new QStyleSheetItem( this, QString::fromLatin1("dd") );
1146 style->setDisplayMode(QStyleSheetItem::DisplayBlock); 1217 style->setDisplayMode(QStyleSheetItem::DisplayBlock);
1147 style->setMargin(QStyleSheetItem::MarginLeft, 30); 1218 style->setMargin(QStyleSheetItem::MarginLeft, 30);
1148 style->setContexts(QString::fromLatin1("dt dl") ); 1219 style->setContexts(QString::fromLatin1("dt dl") );
1149 style = new QStyleSheetItem( this, QString::fromLatin1("u") ); 1220 style = new QStyleSheetItem( this, QString::fromLatin1("u") );
1150 style->setFontUnderline( TRUE); 1221 style->setFontUnderline( TRUE);
1222 style = new QStyleSheetItem( this, QString::fromLatin1("s") );
1223 style->setFontStrikeOut( TRUE);
1151 style = new QStyleSheetItem( this, QString::fromLatin1("nobr") ); 1224 style = new QStyleSheetItem( this, QString::fromLatin1("nobr") );
1152 style->setWhiteSpaceMode( QStyleSheetItem::WhiteSpaceNoWrap ); 1225 style->setWhiteSpaceMode( QStyleSheetItem::WhiteSpaceNoWrap );
1153 style = new QStyleSheetItem( this, QString::fromLatin1("wsp") ); // qt extension for QTextEdit 1226
1154 style->setWhiteSpaceMode( (QStyleSheetItem::WhiteSpaceMode) 3 ); // WhiteSpaceModeNoCompression 1227 // compatibily with some minor 3.0.x Qt versions that had an
1228 // undocumented <wsp> tag. ### Remove 3.1
1229 style = new QStyleSheetItem( this, QString::fromLatin1("wsp") );
1230 style->setWhiteSpaceMode( QStyleSheetItem::WhiteSpacePre );
1155 1231
1156 // tables 1232 // tables
1157 style = new QStyleSheetItem( this, QString::fromLatin1("table") ); 1233 style = new QStyleSheetItem( this, QString::fromLatin1("table") );
1158 style = new QStyleSheetItem( this, QString::fromLatin1("tr") ); 1234 style = new QStyleSheetItem( this, QString::fromLatin1("tr") );
1159 style->setContexts(QString::fromLatin1("table")); 1235 style->setContexts(QString::fromLatin1("table"));
1160 style = new QStyleSheetItem( this, QString::fromLatin1("td") ); 1236 style = new QStyleSheetItem( this, QString::fromLatin1("td") );
1161 style->setContexts(QString::fromLatin1("tr")); 1237 style->setContexts(QString::fromLatin1("tr"));
1162 style = new QStyleSheetItem( this, QString::fromLatin1("th") ); 1238 style = new QStyleSheetItem( this, QString::fromLatin1("th") );
1163 style->setFontWeight( QFont::Bold ); 1239 style->setFontWeight( QFont::Bold );
1164 style->setAlignment( Qt::AlignCenter ); 1240 style->setAlignment( Qt::AlignCenter );
1165 style->setContexts(QString::fromLatin1("tr")); 1241 style->setContexts(QString::fromLatin1("tr"));
1166 1242
1167 style = new QStyleSheetItem( this, QString::fromLatin1("html") ); 1243 style = new QStyleSheetItem( this, QString::fromLatin1("html") );
1168} 1244}
1169 1245
1170 1246
1171 1247
1172static QStyleSheet* defaultsheet = 0; 1248static QStyleSheet* defaultsheet = 0;
1173static QSingleCleanupHandler<QStyleSheet> qt_cleanup_stylesheet; 1249static QSingleCleanupHandler<QStyleSheet> qt_cleanup_stylesheet;
1174 1250
1175/*! 1251/*!
1176 Returns the application-wide default style sheet. This style sheet is 1252 Returns the application-wide default style sheet. This style sheet
1177 used by rich text rendering classes such as QSimpleRichText, 1253 is used by rich text rendering classes such as QSimpleRichText,
1178 QWhatsThis and QMessageBox to define the rendering style and 1254 QWhatsThis and QMessageBox to define the rendering style and
1179 available tags within rich text documents. It serves also as initial 1255 available tags within rich text documents. It also serves as the
1180 style sheet for the more complex render widgets QTextEdit and 1256 initial style sheet for the more complex render widgets, QTextEdit
1181 QTextBrowser. 1257 and QTextBrowser.
1182 1258
1183 \sa setDefaultSheet() 1259 \sa setDefaultSheet()
1184*/ 1260*/
1185QStyleSheet* QStyleSheet::defaultSheet() 1261QStyleSheet* QStyleSheet::defaultSheet()
1186{ 1262{
1187 if (!defaultsheet) { 1263 if (!defaultsheet) {
1188 defaultsheet = new QStyleSheet(); 1264 defaultsheet = new QStyleSheet();
1189 qt_cleanup_stylesheet.set( &defaultsheet ); 1265 qt_cleanup_stylesheet.set( &defaultsheet );
1190 } 1266 }
1191 return defaultsheet; 1267 return defaultsheet;
1192} 1268}
1193 1269
1194/*! 1270/*!
1195 Sets the application-wide default style sheet to \a sheet, deleting 1271 Sets the application-wide default style sheet to \a sheet,
1196 any style sheet previously set. The ownership is transferred to 1272 deleting any style sheet previously set. The ownership is
1197 QStyleSheet. 1273 transferred to QStyleSheet.
1198 1274
1199 \sa defaultSheet() 1275 \sa defaultSheet()
1200*/ 1276*/
1201void QStyleSheet::setDefaultSheet( QStyleSheet* sheet) 1277void QStyleSheet::setDefaultSheet( QStyleSheet* sheet)
1202{ 1278{
1203 if ( defaultsheet != sheet ) { 1279 if ( defaultsheet != sheet ) {
1204 if ( defaultsheet ) 1280 if ( defaultsheet )
1205 qt_cleanup_stylesheet.reset(); 1281 qt_cleanup_stylesheet.reset();
1206 delete defaultsheet; 1282 delete defaultsheet;
1207 } 1283 }
1208 defaultsheet = sheet; 1284 defaultsheet = sheet;
1209 if ( defaultsheet ) 1285 if ( defaultsheet )
1210 qt_cleanup_stylesheet.set( &defaultsheet ); 1286 qt_cleanup_stylesheet.set( &defaultsheet );
1211} 1287}
1212 1288
1213/*!\internal 1289/*!\internal
1214 Inserts \a style. Any tags generated after this time will be 1290 Inserts \a style. Any tags generated after this time will be
1215 bound to this style. Note that \a style becomes owned by the 1291 bound to this style. Note that \a style becomes owned by the
1216 style sheet and will be deleted when the style sheet is destroyed. 1292 style sheet and will be deleted when the style sheet is destroyed.
1217*/ 1293*/
1218void QStyleSheet::insert( QStyleSheetItem* style ) 1294void QStyleSheet::insert( QStyleSheetItem* style )
1219{ 1295{
1220 styles.insert(style->name(), style); 1296 styles.insert(style->name(), style);
1221} 1297}
1222 1298
1223 1299
1224/*! 1300/*!
1225 Returns the style with name \a name or 0 if there is no such style. 1301 Returns the style called \a name or 0 if there is no such style.
1226 */ 1302*/
1227QStyleSheetItem* QStyleSheet::item( const QString& name) 1303QStyleSheetItem* QStyleSheet::item( const QString& name)
1228{ 1304{
1229 if ( name.isNull() ) 1305 if ( name.isNull() )
1230 return 0; 1306 return 0;
1231 return styles[name]; 1307 return styles[name];
1232} 1308}
1233 1309
1234/*! 1310/*!
1235 \overload 1311 \overload
1236 Returns the style with name \a name or 0 if there is no such style (const version) 1312
1237 */ 1313 Returns the style called \a name or 0 if there is no such style
1314 (const version)
1315*/
1238const QStyleSheetItem* QStyleSheet::item( const QString& name) const 1316const QStyleSheetItem* QStyleSheet::item( const QString& name) const
1239{ 1317{
1240 if ( name.isNull() ) 1318 if ( name.isNull() )
1241 return 0; 1319 return 0;
1242 return styles[name]; 1320 return styles[name];
1243} 1321}
1244 1322
1245 1323
1246/*! 1324/*!
1247 \preliminary 1325 \preliminary
1248 Generates an internal object for the tag called \a name, given the
1249 attributes \a attr, and using additional information provided
1250 by the mime source factory \a factory.
1251 1326
1252 \a context is the optional context of the document, i.e. the path to 1327 Generates an internal object for the tag called \a name, given the
1253 look for relative links. This becomes important if the text contains 1328 attributes \a attr, and using additional information provided by
1254 relative references, for example within image tags. QSimpleRichText 1329 the mime source factory \a factory.
1255 always uses the default mime source factory (see
1256 \l{QMimeSourceFactory::defaultFactory()}) to resolve these references.
1257 The context will then be used to calculate the absolute path. See
1258 QMimeSourceFactory::makeAbsolute() for details.
1259 1330
1260 \a emptyTag and \a doc are for internal use only. 1331 \a context is the optional context of the document, i.e. the path
1332 to look for relative links. This becomes important if the text
1333 contains relative references, for example within image tags.
1334 QSimpleRichText always uses the default mime source factory (see
1335 \l{QMimeSourceFactory::defaultFactory()}) to resolve these
1336 references. The context will then be used to calculate the
1337 absolute path. See QMimeSourceFactory::makeAbsolute() for details.
1261 1338
1262 This function should not (yet) be used in application code. 1339 \a emptyTag and \a doc are for internal use only.
1340
1341 This function should not be used in application code.
1263*/ 1342*/
1264QTextCustomItem* QStyleSheet::tag( const QString& name, 1343QTextCustomItem* QStyleSheet::tag( const QString& name,
1265 const QMap<QString, QString> &attr, 1344 const QMap<QString, QString> &attr,
1266 const QString& context, 1345 const QString& context,
1267 const QMimeSourceFactory& factory, 1346 const QMimeSourceFactory& factory,
1268 bool /*emptyTag */, QTextDocument *doc ) const 1347 bool /*emptyTag */, QTextDocument *doc ) const
1269{ 1348{
1270 static QString s_img = QString::fromLatin1("img");
1271 static QString s_hr = QString::fromLatin1("hr");
1272
1273 const QStyleSheetItem* style = item( name ); 1349 const QStyleSheetItem* style = item( name );
1274 // first some known tags 1350 // first some known tags
1275 if ( !style ) 1351 if ( !style )
1276 return 0; 1352 return 0;
1277 if ( style->name() == s_img ) 1353 if ( style->name() == "img" )
1278 return new QTextImage( doc, attr, context, (QMimeSourceFactory&)factory ); 1354 return new QTextImage( doc, attr, context, (QMimeSourceFactory&)factory );
1279 if ( style->name() == s_hr ) 1355 if ( style->name() == "hr" )
1280 return new QTextHorizontalLine( doc, attr, context, (QMimeSourceFactory&)factory ); 1356 return new QTextHorizontalLine( doc, attr, context, (QMimeSourceFactory&)factory );
1281 return 0; 1357 return 0;
1282} 1358}
1283 1359
1284 1360
1285/*! 1361/*! Auxiliary function. Converts the plain text string \a plain to a
1286 Auxiliary function. Converts the plain text string \a plain to a 1362 rich text formatted paragraph while preserving most of its look.
1287 rich text formatted paragraph while preserving its look.
1288 1363
1289 \a mode defines the whitespace mode. Possible values are \c 1364 \a mode defines the whitespace mode. Possible values are \c
1290 QStyleSheetItem::WhiteSpacePre (no wrapping, all whitespaces 1365 QStyleSheetItem::WhiteSpacePre (no wrapping, all whitespaces
1291 preserved) and \c QStyleSheetItem::WhiteSpaceNormal (wrapping, 1366 preserved) and \c QStyleSheetItem::WhiteSpaceNormal (wrapping,
1292 simplified whitespaces). 1367 simplified whitespaces).
1293 1368
1294 \sa escape() 1369 \sa escape()
1295 */ 1370*/
1296QString QStyleSheet::convertFromPlainText( const QString& plain, QStyleSheetItem::WhiteSpaceMode mode ) 1371QString QStyleSheet::convertFromPlainText( const QString& plain, QStyleSheetItem::WhiteSpaceMode mode )
1297{ 1372{
1298 int col = 0; 1373 int col = 0;
1299 QString rich; 1374 QString rich;
1300 rich += "<p>"; 1375 rich += "<p>";
1301 for ( int i = 0; i < int(plain.length()); ++i ) { 1376 for ( int i = 0; i < int(plain.length()); ++i ) {
1302 if ( plain[i] == '\n' ){ 1377 if ( plain[i] == '\n' ){
1303 if ( col == 1 ) 1378 int c = 1;
1304 rich += "<p></p>"; 1379 while ( i+1 < int(plain.length()) && plain[i+1] == '\n' ) {
1305 else 1380 i++;
1306 rich += "<br>"; 1381 c++;
1382 }
1383 if ( c == 1)
1384 rich += "<br>\n";
1385 else {
1386 rich += "</p>\n";
1387 while ( --c > 1 )
1388 rich += "<br>\n";
1389 rich += "<p>";
1390 }
1307 col = 0; 1391 col = 0;
1308 } 1392 } else {
1309 else if ( mode == QStyleSheetItem::WhiteSpacePre && plain[i] == '\t' ){ 1393 if ( mode == QStyleSheetItem::WhiteSpacePre && plain[i] == '\t' ){
1310 rich += 0x00a0U;
1311 while ( col % 4 ) {
1312 rich += 0x00a0U; 1394 rich += 0x00a0U;
1313 ++col; 1395 ++col;
1396 while ( col % 8 ) {
1397 rich += 0x00a0U;
1398 ++col;
1399 }
1314 } 1400 }
1401 else if ( mode == QStyleSheetItem::WhiteSpacePre && plain[i].isSpace() )
1402 rich += 0x00a0U;
1403 else if ( plain[i] == '<' )
1404 rich +="&lt;";
1405 else if ( plain[i] == '>' )
1406 rich +="&gt;";
1407 else if ( plain[i] == '&' )
1408 rich +="&amp;";
1409 else
1410 rich += plain[i];
1411 ++col;
1315 } 1412 }
1316 else if ( mode == QStyleSheetItem::WhiteSpacePre && plain[i].isSpace() )
1317 rich += 0x00a0U;
1318 else if ( plain[i] == '<' )
1319 rich +="&lt;";
1320 else if ( plain[i] == '>' )
1321 rich +="&gt;";
1322 else if ( plain[i] == '&' )
1323 rich +="&amp;";
1324 else
1325 rich += plain[i];
1326 ++col;
1327 } 1413 }
1328 rich += "</p>"; 1414 if ( col != 0 )
1415 rich += "</p>";
1329 return rich; 1416 return rich;
1330} 1417}
1331 1418
1332/*! 1419/*!
1333 Auxiliary function. Converts the plain text string \a plain to a 1420 Auxiliary function. Converts the plain text string \a plain to a
1334 rich text formatted string with any HTML meta-characters escaped. 1421 rich text formatted string with any HTML meta-characters escaped.
1335 1422
1336 \sa convertFromPlainText() 1423 \sa convertFromPlainText()
1337 */ 1424*/
1338QString QStyleSheet::escape( const QString& plain) 1425QString QStyleSheet::escape( const QString& plain)
1339{ 1426{
1340 QString rich; 1427 QString rich;
1341 for ( int i = 0; i < int(plain.length()); ++i ) { 1428 for ( int i = 0; i < int(plain.length()); ++i ) {
1342 if ( plain[i] == '<' ) 1429 if ( plain[i] == '<' )
1343 rich +="&lt;"; 1430 rich +="&lt;";
1344 else if ( plain[i] == '>' ) 1431 else if ( plain[i] == '>' )
1345 rich +="&gt;"; 1432 rich +="&gt;";
1346 else if ( plain[i] == '&' ) 1433 else if ( plain[i] == '&' )
1347 rich +="&amp;"; 1434 rich +="&amp;";
1348 else 1435 else
1349 rich += plain[i]; 1436 rich += plain[i];
1350 } 1437 }
1351 return rich; 1438 return rich;
1352} 1439}
1353 1440
1354// Must doc this enum somewhere, and it is logically related to QStyleSheet 1441// Must doc this enum somewhere, and it is logically related to QStyleSheet
1355 1442
1356/*! 1443/*!
1357 \enum Qt::TextFormat 1444 \enum Qt::TextFormat
1358 1445
1359 This enum is used in widgets that can display both plain text and 1446 This enum is used in widgets that can display both plain text and
1360 rich text, e.g. QLabel. It is used for deciding whether a text 1447 rich text, e.g. QLabel. It is used for deciding whether a text
1361 string should be interpreted as one or the other. This is 1448 string should be interpreted as one or the other. This is normally
1362 normally done by passing one of the enum values to a setTextFormat() 1449 done by passing one of the enum values to a setTextFormat()
1363 function. 1450 function.
1364 1451
1365 \value PlainText The text string is interpreted as a plain text string. 1452 \value PlainText The text string is interpreted as a plain text
1453 string.
1366 1454
1367 \value RichText The text string is interpreted as a rich text string 1455 \value RichText The text string is interpreted as a rich text
1368 using the current QStyleSheet::defaultSheet(). 1456 string using the current QStyleSheet::defaultSheet().
1369 1457
1370 \value AutoText The text string is interpreted as for \c RichText if 1458 \value AutoText The text string is interpreted as for \c RichText
1371 QStyleSheet::mightBeRichText() returns TRUE, otherwise as for \c 1459 if QStyleSheet::mightBeRichText() returns TRUE, otherwise as
1372 PlainText. 1460 \c PlainText.
1373*/ 1461*/
1374 1462
1375/*! 1463/*!
1376 Returns TRUE if the string \a text is likely to be rich text; 1464 Returns TRUE if the string \a text is likely to be rich text;
1377 otherwise returns FALSE. 1465 otherwise returns FALSE.
1378 1466
1379 Note: The function uses a fast and therefore simple heuristic. It 1467 This function uses a fast and therefore simple heuristic. It
1380 mainly checks whether there is something that looks like a tag 1468 mainly checks whether there is something that looks like a tag
1381 before the first line break. Although the result may be correct for 1469 before the first line break. Although the result may be correct
1382 most common cases, there is no guarantee. 1470 for common cases, there is no guarantee.
1383*/ 1471*/
1384bool QStyleSheet::mightBeRichText( const QString& text) 1472bool QStyleSheet::mightBeRichText( const QString& text)
1385{ 1473{
1386 if ( text.isEmpty() ) 1474 if ( text.isEmpty() )
1387 return FALSE; 1475 return FALSE;
1388 if ( text.left(5).lower() == "<!doc" ) 1476 if ( text.left(5).lower() == "<!doc" )
1389 return TRUE; 1477 return TRUE;
1390 int open = 0; 1478 int open = 0;
1391 while ( open < int(text.length()) && text[open] != '<' 1479 while ( open < int(text.length()) && text[open] != '<'
1392 && text[open] != '\n' && text[open] != '&') 1480 && text[open] != '\n' && text[open] != '&')
1393 ++open; 1481 ++open;
1394 if ( text[open] == '&' ) { 1482 if ( text[open] == '&' ) {
1395 if ( text.mid(open+1,3) == "lt;" ) 1483 if ( text.mid(open+1,3) == "lt;" )
1396 return TRUE; // support desperate attempt of user to see <...> 1484 return TRUE; // support desperate attempt of user to see <...>
1397 } else if ( text[open] == '<' ) { 1485 } else if ( text[open] == '<' ) {
1398 int close = text.find('>', open); 1486 int close = text.find('>', open);
1399 if ( close > -1 ) { 1487 if ( close > -1 ) {
1400 QString tag; 1488 QString tag;
1401 for (int i = open+1; i < close; ++i) { 1489 for (int i = open+1; i < close; ++i) {
1402 if ( text[i].isDigit() || text[i].isLetter() ) 1490 if ( text[i].isDigit() || text[i].isLetter() )
1403 tag += text[i]; 1491 tag += text[i];
1404 else if ( !tag.isEmpty() && text[i].isSpace() ) 1492 else if ( !tag.isEmpty() && text[i].isSpace() )
1405 break; 1493 break;
1406 else if ( !text[i].isSpace() && (!tag.isEmpty() || text[i] != '!' ) ) 1494 else if ( !text[i].isSpace() && (!tag.isEmpty() || text[i] != '!' ) )
1407 return FALSE; // that's not a tag 1495 return FALSE; // that's not a tag
1408 } 1496 }
1409 return defaultSheet()->item( tag.lower() ) != 0; 1497 return defaultSheet()->item( tag.lower() ) != 0;
1410 } 1498 }
1411 } 1499 }
1412 return FALSE; 1500 return FALSE;
1413} 1501}
1414 1502
1415 1503
1416/*! \fn void QStyleSheet::error( const QString& msg) const 1504/*!
1505 \fn void QStyleSheet::error( const QString& msg) const
1417 1506
1418 This virtual function is called when an error occurs when 1507 This virtual function is called when an error occurs when
1419 processing rich text. Reimplement it if you need to catch 1508 processing rich text. Reimplement it if you need to catch error
1420 error messages. 1509 messages.
1421 1510
1422 Errors might occur if some rich text strings contain tags that are 1511 Errors might occur if some rich text strings contain tags that are
1423 not understood by the stylesheet, if some tags are nested incorrectly, or 1512 not understood by the stylesheet, if some tags are nested
1424 if tags are not closed properly. 1513 incorrectly, or if tags are not closed properly.
1425 1514
1426 \a msg is the error message. 1515 \a msg is the error message.
1427*/ 1516*/
1428void QStyleSheet::error( const QString& ) const 1517void QStyleSheet::error( const QString& ) const
1429{ 1518{
1430} 1519}
1431 1520
1432 1521
1433/*! 1522/*!
1434 Scales the font \a font to the appropriate physical point size 1523 Scales the font \a font to the appropriate physical point size
1435 corresponding to the logical font size \a logicalSize. 1524 corresponding to the logical font size \a logicalSize.
1436 1525
1437 When calling this function, \a font has a point size corresponding to 1526 When calling this function, \a font has a point size corresponding
1438 the logical font size 3. 1527 to the logical font size 3.
1439 1528
1440 Logical font sizes range from 1 to 7, with 1 being the smallest. 1529 Logical font sizes range from 1 to 7, with 1 being the smallest.
1441 1530
1442 \sa QStyleSheetItem::logicalFontSize(), 1531 \sa QStyleSheetItem::logicalFontSize(), QStyleSheetItem::logicalFontSizeStep(), QFont::setPointSize()
1443 QStyleSheetItem::logicalFontSizeStep(), QFont::setPointSize()
1444 */ 1532 */
1445void QStyleSheet::scaleFont( QFont& font, int logicalSize ) const 1533void QStyleSheet::scaleFont( QFont& font, int logicalSize ) const
1446{ 1534{
1447 if ( logicalSize < 1 ) 1535 if ( logicalSize < 1 )
1448 logicalSize = 1; 1536 logicalSize = 1;
1449 if ( logicalSize > 7 ) 1537 if ( logicalSize > 7 )
1450 logicalSize = 7; 1538 logicalSize = 7;
1451 int baseSize = font.pointSize(); 1539 int baseSize = font.pointSize();
1452 bool pixel = FALSE; 1540 bool pixel = FALSE;
1453 if ( baseSize == -1 ) { 1541 if ( baseSize == -1 ) {
1454 baseSize = font.pixelSize(); 1542 baseSize = font.pixelSize();
1455 pixel = TRUE; 1543 pixel = TRUE;
1456 } 1544 }
1457 int s; 1545 int s;
1458 switch ( logicalSize ) { 1546 switch ( logicalSize ) {
1459 case 1: 1547 case 1:
1460 s = baseSize/2; 1548 s = baseSize/2;
1461 break; 1549 break;
1462 case 2: 1550 case 2:
1463 s = (8 * baseSize) / 10; 1551 s = (8 * baseSize) / 10;
1464 break; 1552 break;
1465 case 4: 1553 case 4:
1466 s = (12 * baseSize) / 10; 1554 s = (12 * baseSize) / 10;
1467 break; 1555 break;
1468 case 5: 1556 case 5:
1469 s = (15 * baseSize) / 10; 1557 s = (15 * baseSize) / 10;
1470 break; 1558 break;
1471 case 6: 1559 case 6:
1472 s = 2 * baseSize; 1560 s = 2 * baseSize;
1473 break; 1561 break;
1474 case 7: 1562 case 7:
1475 s = (24 * baseSize) / 10; 1563 s = (24 * baseSize) / 10;
diff --git a/noncore/apps/opie-write/qstylesheet.h b/noncore/apps/opie-write/qstylesheet.h
index bb209fa..cb786f5 100644
--- a/noncore/apps/opie-write/qstylesheet.h
+++ b/noncore/apps/opie-write/qstylesheet.h
@@ -52,158 +52,162 @@ template<class Key, class T> class QMap;
52namespace Qt3 { 52namespace Qt3 {
53 53
54class QStyleSheet; 54class QStyleSheet;
55class QTextDocument; 55class QTextDocument;
56class QStyleSheetItemData; 56class QStyleSheetItemData;
57 57
58class Q_EXPORT QStyleSheetItem : public Qt 58class Q_EXPORT QStyleSheetItem : public Qt
59{ 59{
60public: 60public:
61 QStyleSheetItem( QStyleSheet* parent, const QString& name ); 61 QStyleSheetItem( QStyleSheet* parent, const QString& name );
62 QStyleSheetItem( const QStyleSheetItem & ); 62 QStyleSheetItem( const QStyleSheetItem & );
63 ~QStyleSheetItem(); 63 ~QStyleSheetItem();
64 64
65 QString name() const; 65 QString name() const;
66 66
67 QStyleSheet* styleSheet(); 67 QStyleSheet* styleSheet();
68 const QStyleSheet* styleSheet() const; 68 const QStyleSheet* styleSheet() const;
69 69
70 enum AdditionalStyleValues { Undefined = - 1}; 70 enum AdditionalStyleValues { Undefined = - 1};
71 71
72 enum DisplayMode { 72 enum DisplayMode {
73 DisplayBlock, 73 DisplayBlock,
74 DisplayInline, 74 DisplayInline,
75 DisplayListItem, 75 DisplayListItem,
76 DisplayNone 76 DisplayNone
77 }; 77 };
78 78
79 DisplayMode displayMode() const; 79 DisplayMode displayMode() const;
80 void setDisplayMode(DisplayMode m); 80 void setDisplayMode(DisplayMode m);
81 81
82 int alignment() const; 82 int alignment() const;
83 void setAlignment( int f); 83 void setAlignment( int f);
84 84
85 enum VerticalAlignment { 85 enum VerticalAlignment {
86 VAlignBaseline, 86 VAlignBaseline,
87 VAlignSub, 87 VAlignSub,
88 VAlignSuper 88 VAlignSuper
89 }; 89 };
90 90
91 VerticalAlignment verticalAlignment() const; 91 VerticalAlignment verticalAlignment() const;
92 void setVerticalAlignment( VerticalAlignment valign ); 92 void setVerticalAlignment( VerticalAlignment valign );
93 93
94 int fontWeight() const; 94 int fontWeight() const;
95 void setFontWeight(int w); 95 void setFontWeight(int w);
96 96
97 int logicalFontSize() const; 97 int logicalFontSize() const;
98 void setLogicalFontSize(int s); 98 void setLogicalFontSize(int s);
99 99
100 int logicalFontSizeStep() const; 100 int logicalFontSizeStep() const;
101 void setLogicalFontSizeStep( int s ); 101 void setLogicalFontSizeStep( int s );
102 102
103 int fontSize() const; 103 int fontSize() const;
104 void setFontSize(int s); 104 void setFontSize(int s);
105 105
106 QString fontFamily() const; 106 QString fontFamily() const;
107 void setFontFamily( const QString& ); 107 void setFontFamily( const QString& );
108 108
109 int numberOfColumns() const; 109 int numberOfColumns() const;
110 void setNumberOfColumns(int ncols); 110 void setNumberOfColumns(int ncols);
111 111
112 QColor color() const; 112 QColor color() const;
113 void setColor( const QColor &); 113 void setColor( const QColor &);
114 114
115 bool fontItalic() const; 115 bool fontItalic() const;
116 void setFontItalic( bool ); 116 void setFontItalic( bool );
117 bool definesFontItalic() const; 117 bool definesFontItalic() const;
118 118
119 bool fontUnderline() const; 119 bool fontUnderline() const;
120 void setFontUnderline( bool ); 120 void setFontUnderline( bool );
121 bool definesFontUnderline() const; 121 bool definesFontUnderline() const;
122 122
123 bool fontStrikeOut() const;
124 void setFontStrikeOut( bool );
125 bool definesFontStrikeOut() const;
126
123 bool isAnchor() const; 127 bool isAnchor() const;
124 void setAnchor(bool anc); 128 void setAnchor(bool anc);
125 129
126 enum WhiteSpaceMode { WhiteSpaceNormal, WhiteSpacePre, WhiteSpaceNoWrap }; 130 enum WhiteSpaceMode { WhiteSpaceNormal, WhiteSpacePre, WhiteSpaceNoWrap };
127 WhiteSpaceMode whiteSpaceMode() const; 131 WhiteSpaceMode whiteSpaceMode() const;
128 void setWhiteSpaceMode(WhiteSpaceMode m); 132 void setWhiteSpaceMode(WhiteSpaceMode m);
129 133
130 enum Margin { 134 enum Margin {
131 MarginLeft, 135 MarginLeft,
132 MarginRight, 136 MarginRight,
133 MarginTop, 137 MarginTop,
134 MarginBottom, 138 MarginBottom,
135 MarginFirstLine, 139 MarginFirstLine,
136 MarginAll, 140 MarginAll,
137 MarginVertical, 141 MarginVertical,
138 MarginHorizontal 142 MarginHorizontal
139 }; 143 };
140 144
141 int margin( Margin m) const; 145 int margin( Margin m) const;
142 void setMargin( Margin, int); 146 void setMargin( Margin, int);
143 147
144 enum ListStyle { 148 enum ListStyle {
145 ListDisc, 149 ListDisc,
146 ListCircle, 150 ListCircle,
147 ListSquare, 151 ListSquare,
148 ListDecimal, 152 ListDecimal,
149 ListLowerAlpha, 153 ListLowerAlpha,
150 ListUpperAlpha 154 ListUpperAlpha
151 }; 155 };
152 156
153 ListStyle listStyle() const; 157 ListStyle listStyle() const;
154 void setListStyle( ListStyle ); 158 void setListStyle( ListStyle );
155 159
156 QString contexts() const; 160 QString contexts() const;
157 void setContexts( const QString& ); 161 void setContexts( const QString& );
158 bool allowedInContext( const QStyleSheetItem* ) const; 162 bool allowedInContext( const QStyleSheetItem* ) const;
159 163
160 bool selfNesting() const; 164 bool selfNesting() const;
161 void setSelfNesting( bool ); 165 void setSelfNesting( bool );
162 166
163 void setLineSpacing( int ls ); 167 void setLineSpacing( int ls );
164 int lineSpacing() const; 168 int lineSpacing() const;
165 169
166private: 170private:
167 void init(); 171 void init();
168 QStyleSheetItemData* d; 172 QStyleSheetItemData* d;
169}; 173};
170 174
171 175
172#if defined(Q_TEMPLATEDLL) 176#if defined(Q_TEMPLATEDLL)
173// MOC_SKIP_BEGIN 177// MOC_SKIP_BEGIN
174template class Q_EXPORT QDict<QStyleSheetItem>; 178Q_TEMPLATE_EXTERN template class Q_EXPORT QDict<QStyleSheetItem>;
175template class Q_EXPORT QValueList< QPtrVector<QStyleSheetItem> >; 179Q_TEMPLATE_EXTERN template class Q_EXPORT QValueList< QPtrVector<QStyleSheetItem> >;
176template class Q_EXPORT QPtrVector<QStyleSheetItem>; 180Q_TEMPLATE_EXTERN template class Q_EXPORT QPtrVector<QStyleSheetItem>;
177template class Q_EXPORT QValueList<QStyleSheetItem::ListStyle>; 181Q_TEMPLATE_EXTERN template class Q_EXPORT QValueList<QStyleSheetItem::ListStyle>;
178// MOC_SKIP_END 182// MOC_SKIP_END
179#endif 183#endif
180 184
181class QTextCustomItem; 185class QTextCustomItem;
182 186
183class Q_EXPORT QStyleSheet : public QObject 187class Q_EXPORT QStyleSheet : public QObject
184{ 188{
185 Q_OBJECT 189 Q_OBJECT
186public: 190public:
187 QStyleSheet( QObject *parent=0, const char *name=0 ); 191 QStyleSheet( QObject *parent=0, const char *name=0 );
188 virtual ~QStyleSheet(); 192 virtual ~QStyleSheet();
189 193
190 static QStyleSheet* defaultSheet(); 194 static QStyleSheet* defaultSheet();
191 static void setDefaultSheet( QStyleSheet* ); 195 static void setDefaultSheet( QStyleSheet* );
192 196
193 197
194 QStyleSheetItem* item( const QString& name); 198 QStyleSheetItem* item( const QString& name);
195 const QStyleSheetItem* item( const QString& name) const; 199 const QStyleSheetItem* item( const QString& name) const;
196 200
197 void insert( QStyleSheetItem* item); 201 void insert( QStyleSheetItem* item);
198 202
199 virtual QTextCustomItem* tag( const QString& name, 203 virtual QTextCustomItem* tag( const QString& name,
200 const QMap<QString, QString> &attr, 204 const QMap<QString, QString> &attr,
201 const QString& context, 205 const QString& context,
202 const QMimeSourceFactory& factory, 206 const QMimeSourceFactory& factory,
203 bool emptyTag, QTextDocument *doc ) const; 207 bool emptyTag, QTextDocument *doc ) const;
204 208
205 static QString escape( const QString& ); 209 static QString escape( const QString& );
206 static QString convertFromPlainText( const QString&, QStyleSheetItem::WhiteSpaceMode mode = QStyleSheetItem::WhiteSpacePre ); 210 static QString convertFromPlainText( const QString&, QStyleSheetItem::WhiteSpaceMode mode = QStyleSheetItem::WhiteSpacePre );
207 static bool mightBeRichText( const QString& ); 211 static bool mightBeRichText( const QString& );
208 212
209 virtual void scaleFont( QFont& font, int logicalSize ) const; 213 virtual void scaleFont( QFont& font, int logicalSize ) const;
diff --git a/noncore/apps/opie-write/qt3namespace.h b/noncore/apps/opie-write/qt3namespace.h
index 81c5020..557131a 100644
--- a/noncore/apps/opie-write/qt3namespace.h
+++ b/noncore/apps/opie-write/qt3namespace.h
@@ -1,28 +1,29 @@
1#ifndef QT3NAMESPACE_H 1#ifndef QT3NAMESPACE_H
2#define QT3NAMESPACE_H 2#define QT3NAMESPACE_H
3 3
4#include <qnamespace.h> 4#include <qnamespace.h>
5#include <qstring.h>
5 6
6#define Q_ASSERT ASSERT 7#define Q_ASSERT ASSERT
7#define Q_WS_QWS 8#define Q_WS_QWS
8 9
9#define QMemArray QArray 10#define QMemArray QArray
10#define QPtrList QList 11#define QPtrList QList
11#define QPtrListIterator QListIterator 12#define QPtrListIterator QListIterator
12#define QPtrVector QVector 13#define QPtrVector QVector
13 14
14namespace Qt3 { 15namespace Qt3 {
15 16
16enum NewAlignmentFlags { 17enum NewAlignmentFlags {
17 AlignAuto = 0x0000, 18 AlignAuto = 0x0000,
18 AlignJustify = 0x0080, 19 AlignJustify = 0x0080,
19 AlignHorizontal_Mask = Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | AlignJustify 20 AlignHorizontal_Mask = Qt::AlignLeft | Qt::AlignRight | Qt::AlignHCenter | AlignJustify
20}; 21};
21 22
22enum NewWidgetFlags { 23enum NewWidgetFlags {
23 WStaticContents = Qt::WNorthWestGravity 24 WStaticContents = Qt::WNorthWestGravity
24}; 25};
25 26
26} 27}
27 28
28#endif // QT3NAMESPACE_H 29#endif // QT3NAMESPACE_H
diff --git a/noncore/apps/opie-write/qtextedit.cpp b/noncore/apps/opie-write/qtextedit.cpp
index 9c5ea79..82401c6 100644
--- a/noncore/apps/opie-write/qtextedit.cpp
+++ b/noncore/apps/opie-write/qtextedit.cpp
@@ -37,330 +37,401 @@
37 37
38#include "qtextedit.h" 38#include "qtextedit.h"
39 39
40#include "qrichtext_p.h" 40#include "qrichtext_p.h"
41#include "qpainter.h" 41#include "qpainter.h"
42#include "qpen.h" 42#include "qpen.h"
43#include "qbrush.h" 43#include "qbrush.h"
44#include "qpixmap.h" 44#include "qpixmap.h"
45#include "qfont.h" 45#include "qfont.h"
46#include "qcolor.h" 46#include "qcolor.h"
47#include "qstyle.h" 47#include "qstyle.h"
48#include "qsize.h" 48#include "qsize.h"
49#include "qevent.h" 49#include "qevent.h"
50#include "qtimer.h" 50#include "qtimer.h"
51#include "qapplication.h" 51#include "qapplication.h"
52#include "qlistbox.h" 52#include "qlistbox.h"
53#include "qvbox.h" 53#include "qvbox.h"
54#include "qapplication.h" 54#include "qapplication.h"
55#include "qclipboard.h" 55#include "qclipboard.h"
56#include "qcolordialog.h" 56#include "qcolordialog.h"
57#include "qfontdialog.h" 57#include "qfontdialog.h"
58#include "qstylesheet.h" 58#include "qstylesheet.h"
59#include "qdragobject.h" 59#include "qdragobject.h"
60#include "qurl.h" 60#include "qurl.h"
61#include "qcursor.h" 61#include "qcursor.h"
62#include "qregexp.h" 62#include "qregexp.h"
63#include "qpopupmenu.h" 63#include "qpopupmenu.h"
64 64
65#define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k) 65#define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k)
66 66
67using namespace Qt3; 67using namespace Qt3;
68 68
69static bool qt_enable_richtext_copy = FALSE;
70
69struct QUndoRedoInfoPrivate 71struct QUndoRedoInfoPrivate
70{ 72{
71 QTextString text; 73 QTextString text;
72}; 74};
73 75
74namespace Qt3 { 76namespace Qt3 {
75 77
76class QTextEditPrivate 78class QTextEditPrivate
77{ 79{
78public: 80public:
79 QTextEditPrivate() 81 QTextEditPrivate()
80 :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) {} 82 :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE)
83 {
84 for ( int i=0; i<7; i++ )
85 id[i] = 0;
86 }
81 int id[ 7 ]; 87 int id[ 7 ];
82 int preeditStart; 88 int preeditStart;
83 int preeditLength; 89 int preeditLength;
84 bool ensureCursorVisibleInShowEvent; 90 bool ensureCursorVisibleInShowEvent;
91 QString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized
85}; 92};
86 93
87} 94}
88 95
89static bool block_set_alignment = FALSE; 96static bool block_set_alignment = FALSE;
90 97
91/*! 98/*!
92 \class QTextEdit qtextedit.h 99 \class QTextEdit qtextedit.h
93 \brief The QTextEdit widget provides a sophisticated single-page rich text editor. 100 \brief The QTextEdit widget provides a powerful single-page rich text editor.
94 101
95 \ingroup basic 102 \ingroup basic
96 \ingroup text 103 \ingroup text
97 \mainclass 104 \mainclass
98 105
99 QTextEdit is an advanced WYSIWYG editor supporting rich text 106 \tableofcontents
100 formatting. It is optimized to handle large documents and to 107
101 respond quickly to user input. 108 \section1 Introduction and Concepts
109
110 QTextEdit is an advanced WYSIWYG viewer/editor supporting rich
111 text formatting using HTML-style tags. It is optimized to handle
112 large documents and to respond quickly to user input.
113
114 QTextEdit has three modes of operation:
115 \table
116 \header \i Mode \i Command \i Notes
117 \row \i Plain Text Editor \i setTextFormat(PlainText)
118 \i Set text with setText(); text() returns plain text. Text
119 attributes (e.g. colors) can be set, but plain text is always
120 returned.<sup>1.</sup>
121 \row \i Rich Text Editor \i setTextFormat(RichText)
122 \i Set text with setText(); text() returns rich text. Rich
123 text editing is fairly limited. You can't set margins or
124 insert images for example (although you can read and
125 correctly display files that have margins set and that
126 include images). This mode is mostly useful for editing small
127 amounts of rich text. <sup>2.</sup>
128 \row \i Text Viewer<sup>3.</sup> \i setReadOnly(TRUE)
129 \i Set text with setText() or append() (which has no undo
130 history so is faster and uses less memory); text() returns
131 plain or rich text depending on the textFormat(). This mode
132 can correctly display a large subset of HTML tags.
133 \endtable
134
135 <sup>1.</sup><small>We do \e not recommend using QTextEdit to
136 create syntax highlighting editors because the current API is
137 insufficient for this purpose. We hope to release a more complete
138 API that will support syntax highlighting in a later
139 release.</small>
140
141 <sup>2.</sup><small>A more complete API that supports setting
142 margins, images, etc., is planned for a later Qt release.</small>
143
144 <sup>3.</sup><small>Qt 3.1 will provide a Log Viewer mode which is
145 optimised for the fast and memory efficient display of large
146 amounts of read only text.</small>
147
148 We recommend that you always call setTextFormat() to set the mode
149 you want to use. If you use \c AutoText then setText() and
150 append() will try to determine whether the text they are given is
151 plain text or rich text. If you use \c RichText then setText() and
152 append() will assume that the text they are given is rich text.
153 insert() simply inserts the text it is given.
102 154
103 QTextEdit works on paragraphs and characters. A paragraph is a 155 QTextEdit works on paragraphs and characters. A paragraph is a
104 formatted string which is word-wrapped to fit into the width of 156 formatted string which is word-wrapped to fit into the width of
105 the widget. A document consists of zero or more paragraphs, 157 the widget. By default when reading plain text, two newlines
106 indexed from 0. Characters are indexed on a per-paragraph basis, 158 signify a paragraph. A document consists of zero or more
107 also indexed from 0. The words in the paragraph are aligned in 159 paragraphs, indexed from 0. Characters are indexed on a
108 accordance with the paragraph's alignment(). Paragraphs are 160 per-paragraph basis, also indexed from 0. The words in the
109 separated by hard line breaks. Each character within a paragraph 161 paragraph are aligned in accordance with the paragraph's
110 has its own attributes, for example, font and color. 162 alignment(). Paragraphs are separated by hard line breaks. Each
163 character within a paragraph has its own attributes, for example,
164 font and color.
165
166 The text edit documentation uses the following concepts:
167 \list
168 \i \e{current format} --
169 this is the format at the current cursor position, \e and it
170 is the format of the selected text if any.
171 \i \e{current paragraph} -- the paragraph which contains the
172 cursor.
173 \endlist
111 174
112 QTextEdit can display images (using QMimeSourceFactory), lists and 175 QTextEdit can display images (using QMimeSourceFactory), lists and
113 tables. If the text is too large to view within the text edit's 176 tables. If the text is too large to view within the text edit's
114 viewport, scrollbars will appear. The text edit can load both 177 viewport, scrollbars will appear. The text edit can load both
115 plain text and HTML files (a subset of HTML 3.2 and 4). The 178 plain text and HTML files (a subset of HTML 3.2 and 4). The
116 rendering style and the set of valid tags are defined by a 179 rendering style and the set of valid tags are defined by a
117 styleSheet(). Change the style sheet with \l{setStyleSheet()}; see 180 styleSheet(). Custom tags can be created and placed in a custom
181 style sheet. Change the style sheet with \l{setStyleSheet()}; see
118 QStyleSheet for details. The images identified by image tags are 182 QStyleSheet for details. The images identified by image tags are
119 displayed if they can be interpreted using the text edit's 183 displayed if they can be interpreted using the text edit's
120 \l{QMimeSourceFactory}; see setMimeSourceFactory(). 184 \l{QMimeSourceFactory}; see setMimeSourceFactory().
121 185
122 If you want a text browser with more navigation use QTextBrowser. 186 If you want a text browser with more navigation use QTextBrowser.
123 If you just need to display a small piece of rich text use QLabel 187 If you just need to display a small piece of rich text use QLabel
124 or QSimpleRichText. 188 or QSimpleRichText.
125 189
126 If you create a new QTextEdit, and want to allow the user to edit 190 If you create a new QTextEdit, and want to allow the user to edit
127 rich text, call setTextFormat(Qt::RichText) to ensure that the 191 rich text, call setTextFormat(Qt::RichText) to ensure that the
128 text is treated as rich text. (Rich text uses HTML tags to set 192 text is treated as rich text. (Rich text uses HTML tags to set
129 text formatting attributes. See QStyleSheet for information on the 193 text formatting attributes. See QStyleSheet for information on the
130 HTML tags that are supported.). If you don't call setTextFormat() 194 HTML tags that are supported.). If you don't call setTextFormat()
131 explicitly the text edit will guess from the text itself whether 195 explicitly the text edit will guess from the text itself whether
132 it is rich text or plain text. This means that if the text looks 196 it is rich text or plain text. This means that if the text looks
133 like HTML or XML it will probably be interpreted as rich text, so 197 like HTML or XML it will probably be interpreted as rich text, so
134 you should call setTextFormat(Qt::PlainText) to preserve such 198 you should call setTextFormat(Qt::PlainText) to preserve such
135 text. 199 text.
136 200
137 The text edit documentation uses the following concepts: 201 Note that we do not intend to add a full-featured web browser
138 \list 202 widget to Qt (because that would easily double Qt's size and only
139 \i <i>current format</i> -- 203 a few applications would benefit from it). The rich
140 this is the format at the current cursor position, \e and it 204 text support in Qt is designed to provide a fast, portable and
141 is the format of the selected text if any. 205 efficient way to add reasonable online help facilities to
142 \i <i>current paragraph</i> -- the paragraph which contains the 206 applications, and to provide a basis for rich text editors.
143 cursor. 207 \section1 Using QTextEdit as a Display Widget
144 \endlist 208
209 QTextEdit can display a large HTML subset, including tables and
210 images.
145 211
146 The text is set or replaced using setText() which deletes any 212 The text is set or replaced using setText() which deletes any
147 existing text and replaces it with the text passed in the 213 existing text and replaces it with the text passed in the
148 setText() call. Text can be inserted with insert(), paste() and 214 setText() call. If you call setText() with legacy HTML (with
149 pasteSubType(). Text can also be cut(). The entire text is deleted 215 setTextFormat(RichText) in force), and then call text(), the text
150 with clear() and the selected text is deleted with 216 that is returned may have different markup, but will render the
151 removeSelectedText(). Selected (marked) text can also be deleted 217 same. Text can be inserted with insert(), paste(), pasteSubType()
152 with del() (which will delete the character to the right of the 218 and append(). Text that is appended does not go into the undo
153 cursor if no text is selected). 219 history; this makes append() faster and consumes less memory. Text
154 220 can also be cut(). The entire text is deleted with clear() and the
155 The current format's attributes are set with setItalic(), 221 selected text is deleted with removeSelectedText(). Selected
156 setBold(), setUnderline(), setFamily() (font family), 222 (marked) text can also be deleted with del() (which will delete
157 setPointSize(), setColor() and setCurrentFont(). The current 223 the character to the right of the cursor if no text is selected).
158 paragraph's style is set with setParagType() and its alignment is
159 set with setAlignment().
160
161 Use setSelection() to select text. The setSelectionAttributes()
162 function is used to indicate how selected text should be
163 displayed. Use hasSelectedText() to find out if any text is
164 selected. The currently selected text's position is available
165 using getSelection() and the selected text itself is returned by
166 selectedText(). The selection can be copied to the clipboard with
167 copy(), or cut to the clipboard with cut(). It can be deleted with
168 removeSelectedText(). The entire text can be selected (or
169 unselected) using selectAll(). QTextEdit supports multiple
170 selections. Most of the selection functions operate on the default
171 selection, selection 0. If the user presses a non-selecting key,
172 e.g. a cursor key without also holding down Shift, all selections
173 are cleared.
174
175 Set and get the position of the cursor with setCursorPosition()
176 and getCursorPosition() respectively. When the cursor is moved,
177 the signals currentFontChanged(), currentColorChanged() and
178 currentAlignmentChanged() are emitted to reflect the font, color
179 and alignment at the new cursor position.
180
181 If the text changes, the textChanged() signal is emitted, and if
182 the user inserts a new line by pressing Return or Enter,
183 returnPressed() is emitted. The isModified() function will return
184 TRUE if the text has been modified.
185
186 QTextEdit provides command-based undo and redo. To set the depth
187 of the command history use setUndoDepth() which defaults to 100
188 steps. To undo or redo the last operation call undo() or redo().
189 The signals undoAvailable() and redoAvailable() indicate whether
190 the undo and redo operations can be executed.
191
192 The indent() function is used to reindent a paragraph. It is
193 useful for code editors, for example in <em>Qt Designer</em>'s
194 code editor \e{Ctrl+I} invokes the indent() function.
195 224
196 Loading and saving text is achieved using setText() and text(), 225 Loading and saving text is achieved using setText() and text(),
197 for example: 226 for example:
198 \code 227 \code
199 QFile file( fileName ); // Read the text from a file 228 QFile file( fileName ); // Read the text from a file
200 if ( file.open( IO_ReadOnly ) ) { 229 if ( file.open( IO_ReadOnly ) ) {
201 QTextStream ts( &file ); 230 QTextStream ts( &file );
202 textEdit->setText( ts.read() ); 231 textEdit->setText( ts.read() );
203 } 232 }
204 \endcode 233 \endcode
205 \code 234 \code
206 QFile file( fileName ); // Write the text to a file 235 QFile file( fileName ); // Write the text to a file
207 if ( file.open( IO_WriteOnly ) ) { 236 if ( file.open( IO_WriteOnly ) ) {
208 QTextStream ts( &file ); 237 QTextStream ts( &file );
209 ts << textEdit->text(); 238 ts << textEdit->text();
210 textEdit->setModified( FALSE ); 239 textEdit->setModified( FALSE );
211 } 240 }
212 \endcode 241 \endcode
213 242
214 By default the text edit wraps words at whitespace to fit within 243 By default the text edit wraps words at whitespace to fit within
215 the text edit widget. The setWordWrap() function is used to 244 the text edit widget. The setWordWrap() function is used to
216 specify the kind of word wrap you want, or \c NoWrap if you don't 245 specify the kind of word wrap you want, or \c NoWrap if you don't
217 want any wrapping. Call setWordWrap() to set a fixed pixel width 246 want any wrapping. Call setWordWrap() to set a fixed pixel width
218 \c FixedPixelWidth, or character column (e.g. 80 column) \c 247 \c FixedPixelWidth, or character column (e.g. 80 column) \c
219 FixedColumnWidth with the pixels or columns specified with 248 FixedColumnWidth with the pixels or columns specified with
220 setWrapColumnOrWidth(). If you use word wrap to the widget's width 249 setWrapColumnOrWidth(). If you use word wrap to the widget's width
221 \c WidgetWidth, you can specify whether to break on whitespace or 250 \c WidgetWidth, you can specify whether to break on whitespace or
222 anywhere with setWrapPolicy(). 251 anywhere with setWrapPolicy().
223 252
224 The background color is set differently than other widgets, using 253 The background color is set differently than other widgets, using
225 setPaper(). You specify a brush style which could be a plain color 254 setPaper(). You specify a brush style which could be a plain color
226 or a complex pixmap. 255 or a complex pixmap.
227 256
228 Hypertext links are automatically underlined; this can be changed 257 Hypertext links are automatically underlined; this can be changed
229 with setLinkUnderline(). The tab stop width is set with 258 with setLinkUnderline(). The tab stop width is set with
230 setTabStopWidth(). 259 setTabStopWidth().
231 260
232 The zoomIn() and zoomOut() functions can be used to resize the 261 The zoomIn() and zoomOut() functions can be used to resize the
233 text by increasing (decreasing for zoomOut()) the point size used. 262 text by increasing (decreasing for zoomOut()) the point size used.
234 Images are not affected by the zoom functions. 263 Images are not affected by the zoom functions.
235 264
236 The lines() function returns the number of lines in the text and 265 The lines() function returns the number of lines in the text and
237 paragraphs() returns the number of paragraphs. The number of lines 266 paragraphs() returns the number of paragraphs. The number of lines
238 within a particular paragraph is returned by linesOfParagraph(). 267 within a particular paragraph is returned by linesOfParagraph().
239 The length of the entire text in characters is returned by 268 The length of the entire text in characters is returned by
240 length(). 269 length().
241 270
242 You can scroll to an anchor in the text, e.g. \c{<a 271 You can scroll to an anchor in the text, e.g. \c{<a
243 name="anchor">} with scrollToAnchor(). The find() function can be 272 name="anchor">} with scrollToAnchor(). The find() function can be
244 used to find and select a given string within the text. 273 used to find and select a given string within the text.
245 274
275 A read-only QTextEdit provides the same functionality as the
276 (obsolete) QTextView. (QTextView is still supplied for
277 compatibility with old code.)
278
279 \section2 Read-only key bindings
280
281 When QTextEdit is used read-only the key-bindings are limited to
282 navigation, and text may only be selected with the mouse:
283 \table
284 \header \i Keypresses \i Action
285 \row \i \e{UpArrow} \i Move one line up
286 \row \i \e{DownArrow} \i Move one line down
287 \row \i \e{LeftArrow} \i Move one character left
288 \row \i \e{RightArrow} \i Move one character right
289 \row \i \e{PageUp} \i Move one (viewport) page up
290 \row \i \e{PageDown} \i Move one (viewport) page down
291 \row \i \e{Home} \i Move to the beginning of the text
292 \row \i \e{End} \i Move to the end of the text
293 \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel)
294 \row \i \e{Ctrl+Wheel} \i Zoom the text
295 \endtable
296
297 The text edit may be able to provide some meta-information. For
298 example, the documentTitle() function will return the text from
299 within HTML \c{<title>} tags.
300
301 The text displayed in a text edit has a \e context. The context is
302 a path which the text edit's QMimeSourceFactory uses to resolve
303 the locations of files and images. It is passed to the
304 mimeSourceFactory() when quering data. (See QTextEdit() and
305 \l{context()}.)
306
307 \section1 Using QTextEdit as an Editor
308
309 All the information about using QTextEdit as a display widget also
310 applies here.
311
312 The current format's attributes are set with setItalic(),
313 setBold(), setUnderline(), setFamily() (font family),
314 setPointSize(), setColor() and setCurrentFont(). The current
315 paragraph's alignment is set with setAlignment().
316
317 Use setSelection() to select text. The setSelectionAttributes()
318 function is used to indicate how selected text should be
319 displayed. Use hasSelectedText() to find out if any text is
320 selected. The currently selected text's position is available
321 using getSelection() and the selected text itself is returned by
322 selectedText(). The selection can be copied to the clipboard with
323 copy(), or cut to the clipboard with cut(). It can be deleted with
324 removeSelectedText(). The entire text can be selected (or
325 unselected) using selectAll(). QTextEdit supports multiple
326 selections. Most of the selection functions operate on the default
327 selection, selection 0. If the user presses a non-selecting key,
328 e.g. a cursor key without also holding down Shift, all selections
329 are cleared.
330
331 Set and get the position of the cursor with setCursorPosition()
332 and getCursorPosition() respectively. When the cursor is moved,
333 the signals currentFontChanged(), currentColorChanged() and
334 currentAlignmentChanged() are emitted to reflect the font, color
335 and alignment at the new cursor position.
336
337 If the text changes, the textChanged() signal is emitted, and if
338 the user inserts a new line by pressing Return or Enter,
339 returnPressed() is emitted. The isModified() function will return
340 TRUE if the text has been modified.
341
342 QTextEdit provides command-based undo and redo. To set the depth
343 of the command history use setUndoDepth() which defaults to 100
344 steps. To undo or redo the last operation call undo() or redo().
345 The signals undoAvailable() and redoAvailable() indicate whether
346 the undo and redo operations can be executed.
347
348 The indent() function is used to reindent a paragraph. It is
349 useful for code editors, for example in <em>Qt Designer</em>'s
350 code editor \e{Ctrl+I} invokes the indent() function.
351
352 \section2 Editing key bindings
353
246 The list of key-bindings which are implemented for editing: 354 The list of key-bindings which are implemented for editing:
247 \table 355 \table
248 \header \i Keypresses \i Action 356 \header \i Keypresses \i Action
249 \row \i \e{Backspace} \i Delete the character to the left of the cursor 357 \row \i \e{Backspace} \i Delete the character to the left of the cursor
250 \row \i \e{Delete} \i Delete the character to the right of the cursor 358 \row \i \e{Delete} \i Delete the character to the right of the cursor
251 \row \i \e{Ctrl+A} \i Move the cursor to the beginning of the line 359 \row \i \e{Ctrl+A} \i Move the cursor to the beginning of the line
252 \row \i \e{Ctrl+B} \i Move the cursor one character left 360 \row \i \e{Ctrl+B} \i Move the cursor one character left
253 \row \i \e{Ctrl+C} \i Copy the marked text to the clipboard (also 361 \row \i \e{Ctrl+C} \i Copy the marked text to the clipboard (also
254 \e{Ctrl+Insert} under Windows) 362 \e{Ctrl+Insert} under Windows)
255 \row \i \e{Ctrl+D} \i Delete the character to the right of the cursor 363 \row \i \e{Ctrl+D} \i Delete the character to the right of the cursor
256 \row \i \e{Ctrl+E} \i Move the cursor to the end of the line 364 \row \i \e{Ctrl+E} \i Move the cursor to the end of the line
257 \row \i \e{Ctrl+F} \i Move the cursor one character right 365 \row \i \e{Ctrl+F} \i Move the cursor one character right
258 \row \i \e{Ctrl+H} \i Delete the character to the left of the cursor 366 \row \i \e{Ctrl+H} \i Delete the character to the left of the cursor
259 \row \i \e{Ctrl+K} \i Delete to end of line 367 \row \i \e{Ctrl+K} \i Delete to end of line
260 \row \i \e{Ctrl+N} \i Move the cursor one line down 368 \row \i \e{Ctrl+N} \i Move the cursor one line down
261 \row \i \e{Ctrl+P} \i Move the cursor one line up 369 \row \i \e{Ctrl+P} \i Move the cursor one line up
262 \row \i \e{Ctrl+V} \i Paste the clipboard text into line edit 370 \row \i \e{Ctrl+V} \i Paste the clipboard text into line edit
263 (also \e{Shift+Insert} under Windows) 371 (also \e{Shift+Insert} under Windows)
264 \row \i \e{Ctrl+X} \i Cut the marked text, copy to clipboard 372 \row \i \e{Ctrl+X} \i Cut the marked text, copy to clipboard
265 (also \e{Shift+Delete} under Windows) 373 (also \e{Shift+Delete} under Windows)
266 \row \i \e{Ctrl+Z} \i Undo the last operation 374 \row \i \e{Ctrl+Z} \i Undo the last operation
267 \row \i \e{Ctrl+Y} \i Redo the last operation 375 \row \i \e{Ctrl+Y} \i Redo the last operation
268 \row \i \e{LeftArrow} \i Move the cursor one character left 376 \row \i \e{LeftArrow} \i Move the cursor one character left
269 \row \i \e{Ctrl+LeftArrow} \i Move the cursor one word left 377 \row \i \e{Ctrl+LeftArrow} \i Move the cursor one word left
270 \row \i \e{RightArrow} \i Move the cursor one character right 378 \row \i \e{RightArrow} \i Move the cursor one character right
271 \row \i \e{Ctrl+RightArrow} \i Move the cursor one word right 379 \row \i \e{Ctrl+RightArrow} \i Move the cursor one word right
272 \row \i \e{UpArrow} \i Move the cursor one line up 380 \row \i \e{UpArrow} \i Move the cursor one line up
273 \row \i \e{Ctrl+UpArrow} \i Move the cursor one word up 381 \row \i \e{Ctrl+UpArrow} \i Move the cursor one word up
274 \row \i \e{DownArrow} \i Move the cursor one line down 382 \row \i \e{DownArrow} \i Move the cursor one line down
275 \row \i \e{Ctrl+Down Arrow} \i Move the cursor one word down 383 \row \i \e{Ctrl+Down Arrow} \i Move the cursor one word down
276 \row \i \e{PageUp} \i Move the cursor one page up 384 \row \i \e{PageUp} \i Move the cursor one page up
277 \row \i \e{PageDown} \i Move the cursor one page down 385 \row \i \e{PageDown} \i Move the cursor one page down
278 \row \i \e{Home} \i Move the cursor to the beginning of the line 386 \row \i \e{Home} \i Move the cursor to the beginning of the line
279 \row \i \e{Ctrl+Home} \i Move the cursor to the beginning of the text 387 \row \i \e{Ctrl+Home} \i Move the cursor to the beginning of the text
280 \row \i \e{End} \i Move the cursor to the end of the line 388 \row \i \e{End} \i Move the cursor to the end of the line
281 \row \i \e{Ctrl+End} \i Move the cursor to the end of the text 389 \row \i \e{Ctrl+End} \i Move the cursor to the end of the text
282 \row \i \e{Shift+Wheel} \i Scroll the page horizontally 390 \row \i \e{Shift+Wheel} \i Scroll the page horizontally
283 (the Wheel is the mouse wheel) 391 (the Wheel is the mouse wheel)
284 \row \i \e{Ctrl+Wheel} \i Zoom the text 392 \row \i \e{Ctrl+Wheel} \i Zoom the text
285 \endtable 393 \endtable
286 394
287 To select (mark) text hold down the Shift key whilst pressing one 395 To select (mark) text hold down the Shift key whilst pressing one
288 of the movement keystrokes, for example, <i>Shift+Right Arrow</i> 396 of the movement keystrokes, for example, <i>Shift+Right Arrow</i>
289 will select the character to the right, and <i>Shift+Ctrl+Right 397 will select the character to the right, and <i>Shift+Ctrl+Right
290 Arrow</i> will select the word to the right, etc. 398 Arrow</i> will select the word to the right, etc.
291 399
292 By default the text edit widget operates in insert mode so all 400 By default the text edit widget operates in insert mode so all
293 text that the user enters is inserted into the text edit and any 401 text that the user enters is inserted into the text edit and any
294 text to the right of the cursor is moved out of the way. The mode 402 text to the right of the cursor is moved out of the way. The mode
295 can be changed to overwrite, where new text overwrites any text to 403 can be changed to overwrite, where new text overwrites any text to
296 the right of the cursor, using setOverwriteMode(). 404 the right of the cursor, using setOverwriteMode().
297 405
298 QTextEdit can also be used as read-only text viewer. Call
299 setReadOnly( TRUE ) to disable editing. A read-only QTextEdit
300 provides the same functionality as the (obsolete) QTextView.
301 (QTextView is still supplied for compatibility with old code.)
302
303 When QTextEdit is used read-only the key-bindings are limited to
304 navigation, and text may only be selected with the mouse:
305 \table
306 \header \i Keypresses \i Action
307 \row \i \e{UpArrow} \i Move one line up
308 \row \i \e{DownArrow} \i Move one line down
309 \row \i \e{LeftArrow} \i Move one character left
310 \row \i \e{RightArrow} \i Move one character right
311 \row \i \e{PageUp} \i Move one (viewport) page up
312 \row \i \e{PageDown} \i Move one (viewport) page down
313 \row \i \e{Home} \i Move to the beginning of the text
314 \row \i \e{End} \i Move to the end of the text
315 \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel)
316 \row \i \e{Ctrl+Wheel} \i Zoom the text
317 \endtable
318
319 The text edit may be able to provide some meta-information. For
320 example, the documentTitle() function will return the text from
321 within HTML \c{<title>} tags.
322
323 The text displayed in a text edit has a \e context. The context is
324 a path which the text edit's QMimeSourceFactory uses to resolve
325 the locations of files and images. It is passed to the
326 mimeSourceFactory() when quering data. (See QTextEdit() and
327 \l{context()}.)
328
329 Note that we do not intend to add a full-featured web browser
330 widget to Qt (because that would easily double Qt's size and only
331 a few applications would benefit from it). The rich
332 text support in Qt is designed to provide a fast, portable and
333 efficient way to add reasonable online help facilities to
334 applications, and to provide a basis for rich text editors.
335*/ 406*/
336 407
337/*! \enum QTextEdit::KeyboardAction 408/*! \enum QTextEdit::KeyboardAction
338 409
339 This enum is used by doKeyboardAction() to specify which action 410 This enum is used by doKeyboardAction() to specify which action
340 should be executed: 411 should be executed:
341 412
342 \value ActionBackspace Delete the character to the left of the 413 \value ActionBackspace Delete the character to the left of the
343 cursor. 414 cursor.
344 415
345 \value ActionDelete Delete the character to the right of the cursor. 416 \value ActionDelete Delete the character to the right of the cursor.
346 417
347 \value ActionReturn Split the paragraph at the cursor position. 418 \value ActionReturn Split the paragraph at the cursor position.
348 419
349 \value ActionKill If the cursor is not at the end of the paragraph, 420 \value ActionKill If the cursor is not at the end of the paragraph,
350 delete the text from the cursor position until the end of the 421 delete the text from the cursor position until the end of the
351 paragraph. If the cursor is at the end of the paragraph, delete the 422 paragraph. If the cursor is at the end of the paragraph, delete the
352 hard line break at the end of the paragraph - this will cause this 423 hard line break at the end of the paragraph - this will cause this
353 paragraph to be joined with the following paragraph. 424 paragraph to be joined with the following paragraph.
354*/ 425*/
355 426
356/*! \enum QTextEdit::VerticalAlignment 427/*! \enum QTextEdit::VerticalAlignment
357 428
358 This enum is used to set the vertical alignment of the text. 429 This enum is used to set the vertical alignment of the text.
359 430
360 \value AlignNormal Normal alignment 431 \value AlignNormal Normal alignment
361 \value AlignSuperScript Superscript 432 \value AlignSuperScript Superscript
362 \value AlignSubScript Subscript 433 \value AlignSubScript Subscript
363*/ 434*/
364 435
365/*! \fn void QTextEdit::copyAvailable (bool yes) 436/*! \fn void QTextEdit::copyAvailable (bool yes)
366 437
@@ -611,141 +682,143 @@ QTextEdit::QTextEdit( const QString& text, const QString& context,
611/*! \reimp */ 682/*! \reimp */
612 683
613QTextEdit::~QTextEdit() 684QTextEdit::~QTextEdit()
614{ 685{
615 delete undoRedoInfo.d; 686 delete undoRedoInfo.d;
616 undoRedoInfo.d = 0; 687 undoRedoInfo.d = 0;
617 delete cursor; 688 delete cursor;
618 delete doc; 689 delete doc;
619 delete d; 690 delete d;
620} 691}
621 692
622void QTextEdit::init() 693void QTextEdit::init()
623{ 694{
624 setFrameStyle( Sunken ); 695 setFrameStyle( Sunken );
625 undoEnabled = TRUE; 696 undoEnabled = TRUE;
626 readonly = TRUE; 697 readonly = TRUE;
627 setReadOnly( FALSE ); 698 setReadOnly( FALSE );
628 d = new QTextEditPrivate; 699 d = new QTextEditPrivate;
629 connect( doc, SIGNAL( minimumWidthChanged( int ) ), 700 connect( doc, SIGNAL( minimumWidthChanged( int ) ),
630 this, SLOT( documentWidthChanged( int ) ) ); 701 this, SLOT( documentWidthChanged( int ) ) );
631 702
632 mousePressed = FALSE; 703 mousePressed = FALSE;
633 inDoubleClick = FALSE; 704 inDoubleClick = FALSE;
634 modified = FALSE; 705 modified = FALSE;
635 onLink = QString::null; 706 onLink = QString::null;
636 overWrite = FALSE; 707 overWrite = FALSE;
637 wrapMode = WidgetWidth; 708 wrapMode = WidgetWidth;
638 wrapWidth = -1; 709 wrapWidth = -1;
639 wPolicy = AtWhiteSpace; 710 wPolicy = AtWhiteSpace;
640 inDnD = FALSE; 711 inDnD = FALSE;
641 712
642 doc->setFormatter( new QTextFormatterBreakWords ); 713 doc->setFormatter( new QTextFormatterBreakWords );
714 doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() );
715 doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( QColorGroup::Text ) );
643 currentFormat = doc->formatCollection()->defaultFormat(); 716 currentFormat = doc->formatCollection()->defaultFormat();
644 currentAlignment = Qt3::AlignAuto; 717 currentAlignment = Qt3::AlignAuto;
645 718
646 viewport()->setBackgroundMode( PaletteBase ); 719 viewport()->setBackgroundMode( PaletteBase );
647 viewport()->setAcceptDrops( TRUE ); 720 viewport()->setAcceptDrops( TRUE );
648 resizeContents( 0, doc->lastParag() ? 721 resizeContents( 0, doc->lastParagraph() ?
649 ( doc->lastParag()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); 722 ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 );
650 723
651 setKeyCompression( TRUE ); 724 setKeyCompression( TRUE );
652 viewport()->setMouseTracking( TRUE ); 725 viewport()->setMouseTracking( TRUE );
653#ifndef QT_NO_CURSOR 726#ifndef QT_NO_CURSOR
654 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 727 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
655#endif 728#endif
656 cursor = new QTextCursor( doc ); 729 cursor = new QTextCursor( doc );
657 730
658 formatTimer = new QTimer( this ); 731 formatTimer = new QTimer( this );
659 connect( formatTimer, SIGNAL( timeout() ), 732 connect( formatTimer, SIGNAL( timeout() ),
660 this, SLOT( formatMore() ) ); 733 this, SLOT( formatMore() ) );
661 lastFormatted = doc->firstParag(); 734 lastFormatted = doc->firstParagraph();
662 735
663 scrollTimer = new QTimer( this ); 736 scrollTimer = new QTimer( this );
664 connect( scrollTimer, SIGNAL( timeout() ), 737 connect( scrollTimer, SIGNAL( timeout() ),
665 this, SLOT( autoScrollTimerDone() ) ); 738 this, SLOT( autoScrollTimerDone() ) );
666 739
667 interval = 0; 740 interval = 0;
668 changeIntervalTimer = new QTimer( this ); 741 changeIntervalTimer = new QTimer( this );
669 connect( changeIntervalTimer, SIGNAL( timeout() ), 742 connect( changeIntervalTimer, SIGNAL( timeout() ),
670 this, SLOT( doChangeInterval() ) ); 743 this, SLOT( doChangeInterval() ) );
671 744
672 cursorVisible = TRUE; 745 cursorVisible = TRUE;
673 blinkTimer = new QTimer( this ); 746 blinkTimer = new QTimer( this );
674 connect( blinkTimer, SIGNAL( timeout() ), 747 connect( blinkTimer, SIGNAL( timeout() ),
675 this, SLOT( blinkCursor() ) ); 748 this, SLOT( blinkCursor() ) );
676 749
677#ifndef QT_NO_DRAGANDDROP 750#ifndef QT_NO_DRAGANDDROP
678 dragStartTimer = new QTimer( this ); 751 dragStartTimer = new QTimer( this );
679 connect( dragStartTimer, SIGNAL( timeout() ), 752 connect( dragStartTimer, SIGNAL( timeout() ),
680 this, SLOT( startDrag() ) ); 753 this, SLOT( startDrag() ) );
681#endif 754#endif
682 755
683 756
684 formatMore(); 757 formatMore();
685 758
686 blinkCursorVisible = FALSE; 759 blinkCursorVisible = FALSE;
687 760
688 viewport()->setFocusProxy( this ); 761 viewport()->setFocusProxy( this );
689 viewport()->setFocusPolicy( WheelFocus ); 762 viewport()->setFocusPolicy( WheelFocus );
690 viewport()->installEventFilter( this ); 763 viewport()->installEventFilter( this );
691 installEventFilter( this ); 764 installEventFilter( this );
692} 765}
693 766
694void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw, int ch ) 767void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw, int ch )
695{ 768{
696 bool drawCur = hasFocus() || viewport()->hasFocus(); 769 bool drawCur = hasFocus() || viewport()->hasFocus();
697 if ( hasSelectedText() || isReadOnly() || !cursorVisible ) 770 if ( hasSelectedText() || isReadOnly() || !cursorVisible )
698 drawCur = FALSE; 771 drawCur = FALSE;
699 QColorGroup g = colorGroup(); 772 QColorGroup g = colorGroup();
700 if ( doc->paper() ) 773 if ( doc->paper() )
701 g.setBrush( QColorGroup::Base, *doc->paper() ); 774 g.setBrush( QColorGroup::Base, *doc->paper() );
702 775
703 if ( contentsY() < doc->y() ) { 776 if ( contentsY() < doc->y() ) {
704 p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(), 777 p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(),
705 g.brush( QColorGroup::Base ) ); 778 g.brush( QColorGroup::Base ) );
706 } 779 }
707 if ( drawAll && doc->width() - contentsX() < cx + cw ) { 780 if ( drawAll && doc->width() - contentsX() < cx + cw ) {
708 p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch, 781 p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch,
709 g.brush( QColorGroup::Base ) ); 782 g.brush( QColorGroup::Base ) );
710 } 783 }
711 784
712 p->setBrushOrigin( -contentsX(), -contentsY() ); 785 p->setBrushOrigin( -contentsX(), -contentsY() );
713 786
714 lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); 787 lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor );
715 788
716 if ( lastFormatted == doc->lastParag() ) 789 if ( lastFormatted == doc->lastParagraph() )
717 resizeContents( contentsWidth(), doc->height() ); 790 resizeContents( contentsWidth(), doc->height() );
718 791
719 if ( contentsHeight() < visibleHeight() && ( !doc->lastParag() || doc->lastParag()->isValid() ) && drawAll ) 792 if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll )
720 p->fillRect( 0, contentsHeight(), visibleWidth(), 793 p->fillRect( 0, contentsHeight(), visibleWidth(),
721 visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) ); 794 visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) );
722} 795}
723 796
724/*! \reimp */ 797/*! \reimp */
725 798
726void QTextEdit::drawContents( QPainter *p, int cx, int cy, int cw, int ch ) 799void QTextEdit::drawContents( QPainter *p, int cx, int cy, int cw, int ch )
727{ 800{
728 paintDocument( TRUE, p, cx, cy, cw, ch ); 801 paintDocument( TRUE, p, cx, cy, cw, ch );
729 int v; 802 int v;
730 p->setPen( foregroundColor() ); 803 p->setPen( foregroundColor() );
731 if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) { 804 if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) {
732 int l = int(cy / v) * v; 805 int l = int(cy / v) * v;
733 while ( l < cy + ch ) { 806 while ( l < cy + ch ) {
734 p->drawLine( cx, l, cx + cw - 1, l ); 807 p->drawLine( cx, l, cx + cw - 1, l );
735 l += v; 808 l += v;
736 } 809 }
737 } 810 }
738 811
739} 812}
740 813
741/*! \reimp */ 814/*! \reimp */
742 815
743void QTextEdit::drawContents( QPainter * ) 816void QTextEdit::drawContents( QPainter * )
744{ 817{
745} 818}
746 819
747/*! \reimp */ 820/*! \reimp */
748 821
749bool QTextEdit::event( QEvent *e ) 822bool QTextEdit::event( QEvent *e )
750{ 823{
751 if ( e->type() == QEvent::AccelOverride && !isReadOnly() ) { 824 if ( e->type() == QEvent::AccelOverride && !isReadOnly() ) {
@@ -784,883 +857,837 @@ bool QTextEdit::event( QEvent *e )
784 case Key_C: 857 case Key_C:
785 case Key_V: 858 case Key_V:
786 case Key_X: 859 case Key_X:
787 case Key_Y: 860 case Key_Y:
788 case Key_Z: 861 case Key_Z:
789 case Key_Left: 862 case Key_Left:
790 case Key_Right: 863 case Key_Right:
791 case Key_Up: 864 case Key_Up:
792 case Key_Down: 865 case Key_Down:
793 case Key_Home: 866 case Key_Home:
794 case Key_End: 867 case Key_End:
795 case Key_Tab: 868 case Key_Tab:
796#if defined (Q_WS_WIN) 869#if defined (Q_WS_WIN)
797 case Key_Insert: 870 case Key_Insert:
798 case Key_Delete: 871 case Key_Delete:
799#endif 872#endif
800 ke->accept(); 873 ke->accept();
801 default: 874 default:
802 break; 875 break;
803 } 876 }
804 } else { 877 } else {
805 switch ( ke->key() ) { 878 switch ( ke->key() ) {
806#if defined (Q_WS_WIN) 879#if defined (Q_WS_WIN)
807 case Key_Insert: 880 case Key_Insert:
808 ke->accept(); 881 ke->accept();
809#endif 882#endif
810 default: 883 default:
811 break; 884 break;
812 } 885 }
813 } 886 }
814 } 887 }
815 888
816 if ( e->type() == QEvent::Show && d->ensureCursorVisibleInShowEvent ) { 889 if ( e->type() == QEvent::Show ) {
817 sync(); 890 if ( d->ensureCursorVisibleInShowEvent ) {
818 ensureCursorVisible(); 891 sync();
819 d->ensureCursorVisibleInShowEvent = FALSE; 892 ensureCursorVisible();
893 d->ensureCursorVisibleInShowEvent = FALSE;
894 }
895 if ( !d->scrollToAnchor.isEmpty() ) {
896 scrollToAnchor( d->scrollToAnchor );
897 d->scrollToAnchor = QString::null;
898 }
820 } 899 }
821 return QWidget::event( e ); 900 return QWidget::event( e );
822} 901}
823 902
824/*! 903/*!
825 Processes the key event, \a e. 904 Processes the key event, \a e.
826 By default key events are used to provide keyboard navigation and 905 By default key events are used to provide keyboard navigation and
827 text editing. 906 text editing.
828*/ 907*/
829 908
830void QTextEdit::keyPressEvent( QKeyEvent *e ) 909void QTextEdit::keyPressEvent( QKeyEvent *e )
831{ 910{
832 changeIntervalTimer->stop(); 911 changeIntervalTimer->stop();
833 interval = 10; 912 interval = 10;
834 bool unknown = FALSE; 913 bool unknown = FALSE;
835 if ( isReadOnly() ) { 914 if ( isReadOnly() ) {
836 if ( !handleReadOnlyKeyEvent( e ) ) 915 if ( !handleReadOnlyKeyEvent( e ) )
837 QScrollView::keyPressEvent( e ); 916 QScrollView::keyPressEvent( e );
838 changeIntervalTimer->start( 100, TRUE ); 917 changeIntervalTimer->start( 100, TRUE );
839 return; 918 return;
840 } 919 }
841 920
842 921
843 bool selChanged = FALSE; 922 bool selChanged = FALSE;
844 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection 923 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection
845 selChanged = doc->removeSelection( i ) || selChanged; 924 selChanged = doc->removeSelection( i ) || selChanged;
846 925
847 if ( selChanged ) { 926 if ( selChanged ) {
848 cursor->parag()->document()->nextDoubleBuffered = TRUE; 927 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
849 repaintChanged(); 928 repaintChanged();
850 } 929 }
851 930
852 bool clearUndoRedoInfo = TRUE; 931 bool clearUndoRedoInfo = TRUE;
853 932
854 933
855 switch ( e->key() ) { 934 switch ( e->key() ) {
856 case Key_Left: 935 case Key_Left:
857 case Key_Right: { 936 case Key_Right: {
858 // a bit hacky, but can't change this without introducing new enum values for move and keeping the 937 // a bit hacky, but can't change this without introducing new enum values for move and keeping the
859 // correct semantics and movement for BiDi and non BiDi text. 938 // correct semantics and movement for BiDi and non BiDi text.
860 CursorAction a; 939 CursorAction a;
861 if ( cursor->parag()->string()->isRightToLeft() == (e->key() == Key_Right) ) 940 if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) )
862 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; 941 a = e->state() & ControlButton ? MoveWordBackward : MoveBackward;
863 else 942 else
864 a = e->state() & ControlButton ? MoveWordForward : MoveForward; 943 a = e->state() & ControlButton ? MoveWordForward : MoveForward;
865 moveCursor( a, e->state() & ShiftButton ); 944 moveCursor( a, e->state() & ShiftButton );
866 break; 945 break;
867 } 946 }
868 case Key_Up: 947 case Key_Up:
869 moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton ); 948 moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton );
870 break; 949 break;
871 case Key_Down: 950 case Key_Down:
872 moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton ); 951 moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton );
873 break; 952 break;
874 case Key_Home: 953 case Key_Home:
875 moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton ); 954 moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton );
876 break; 955 break;
877 case Key_End: 956 case Key_End:
878 moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton ); 957 moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton );
879 break; 958 break;
880 case Key_Prior: 959 case Key_Prior:
881 moveCursor( MovePgUp, e->state() & ShiftButton ); 960 moveCursor( MovePgUp, e->state() & ShiftButton );
882 break; 961 break;
883 case Key_Next: 962 case Key_Next:
884 moveCursor( MovePgDown, e->state() & ShiftButton ); 963 moveCursor( MovePgDown, e->state() & ShiftButton );
885 break; 964 break;
886 case Key_Return: case Key_Enter: 965 case Key_Return: case Key_Enter:
887 if ( doc->hasSelection( QTextDocument::Standard, FALSE ) ) 966 if ( doc->hasSelection( QTextDocument::Standard, FALSE ) )
888 removeSelectedText(); 967 removeSelectedText();
968 if ( textFormat() == Qt::RichText && ( e->state() & ControlButton ) ) {
969 // Ctrl-Enter inserts a line break in rich text mode
970 insert( QString( QChar( 0x2028) ), TRUE, FALSE, TRUE );
971 } else {
889#ifndef QT_NO_CURSOR 972#ifndef QT_NO_CURSOR
890 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 973 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
891#endif 974#endif
892 clearUndoRedoInfo = FALSE; 975 clearUndoRedoInfo = FALSE;
893 doKeyboardAction( ActionReturn ); 976 doKeyboardAction( ActionReturn );
894 emit returnPressed(); 977 emit returnPressed();
978 }
895 break; 979 break;
896 case Key_Delete: 980 case Key_Delete:
897#if defined (Q_WS_WIN) 981#if defined (Q_WS_WIN)
898 if ( e->state() & ShiftButton ) { 982 if ( e->state() & ShiftButton ) {
899 cut(); 983 cut();
900 break; 984 break;
901 } else 985 } else
902#endif 986#endif
903 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { 987 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) {
904 removeSelectedText(); 988 removeSelectedText();
905 break; 989 break;
906 } 990 }
907 doKeyboardAction( ActionDelete ); 991 doKeyboardAction( ActionDelete );
908 clearUndoRedoInfo = FALSE; 992 clearUndoRedoInfo = FALSE;
909 993
910 break; 994 break;
911 case Key_Insert: 995 case Key_Insert:
912 if ( e->state() & ShiftButton ) 996 if ( e->state() & ShiftButton )
913 paste(); 997 paste();
998#if defined (Q_WS_WIN)
999 else if ( e->state() & ControlButton )
1000 copy();
1001#endif
914 break; 1002 break;
915 case Key_Backspace: 1003 case Key_Backspace:
916 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { 1004 if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) {
917 removeSelectedText(); 1005 removeSelectedText();
918 break; 1006 break;
919 } 1007 }
920 1008
921 if ( !cursor->parag()->prev() &&
922 cursor->atParagStart() )
923 break;
924
925 doKeyboardAction( ActionBackspace ); 1009 doKeyboardAction( ActionBackspace );
926 clearUndoRedoInfo = FALSE; 1010 clearUndoRedoInfo = FALSE;
927 1011
928 break; 1012 break;
929 case Key_F16: // Copy key on Sun keyboards 1013 case Key_F16: // Copy key on Sun keyboards
930 copy(); 1014 copy();
931 break; 1015 break;
932 case Key_F18: // Paste key on Sun keyboards 1016 case Key_F18: // Paste key on Sun keyboards
933 paste(); 1017 paste();
934 break; 1018 break;
935 case Key_F20: // Cut key on Sun keyboards 1019 case Key_F20: // Cut key on Sun keyboards
936 cut(); 1020 cut();
937 break; 1021 break;
938 default: { 1022 default: {
939 if ( e->text().length() && 1023 if ( e->text().length() &&
940 ( !( e->state() & ControlButton ) && 1024 ( !( e->state() & ControlButton ) &&
941 !( e->state() & AltButton ) || 1025 !( e->state() & AltButton ) ||
942 ( ( e->state() & ControlButton | AltButton ) == (ControlButton|AltButton) ) ) && 1026 ( ( e->state() & ControlButton | AltButton ) == (ControlButton|AltButton) ) ) &&
943 ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) { 1027 ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) {
944 clearUndoRedoInfo = FALSE; 1028 clearUndoRedoInfo = FALSE;
945 if ( e->key() == Key_Tab ) { 1029 if ( e->key() == Key_Tab ) {
946 if ( textFormat() == Qt::RichText && 1030 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() ) {
947 cursor->index() == 0 && cursor->parag()->style() && 1031 clearUndoRedo();
948 cursor->parag()->style()->displayMode() == 1032 undoRedoInfo.type = UndoRedoInfo::Style;
949 QStyleSheetItem::DisplayListItem ) { 1033 undoRedoInfo.id = cursor->paragraph()->paragId();
950 cursor->parag()->incDepth(); 1034 undoRedoInfo.eid = undoRedoInfo.id;
1035 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
1036 cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 );
1037 clearUndoRedo();
951 drawCursor( FALSE ); 1038 drawCursor( FALSE );
952 repaintChanged(); 1039 repaintChanged();
953 drawCursor( TRUE ); 1040 drawCursor( TRUE );
954 break; 1041 break;
955 } 1042 }
956 } 1043 }
957 if ( textFormat() == Qt::RichText && ( !cursor->parag()->style() || 1044
958 cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayBlock ) && 1045 if ( textFormat() == Qt::RichText && !cursor->paragraph()->isListItem() ) {
959 cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { 1046 if ( cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) {
960 setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); 1047 clearUndoRedo();
961 cursor->parag()->incDepth(); 1048 undoRedoInfo.type = UndoRedoInfo::Style;
962 drawCursor( FALSE ); 1049 undoRedoInfo.id = cursor->paragraph()->paragId();
963 repaintChanged(); 1050 undoRedoInfo.eid = undoRedoInfo.id;
964 drawCursor( TRUE ); 1051 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
965 } else { 1052 setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc );
966 if ( overWrite && !cursor->atParagEnd() ) 1053 clearUndoRedo();
967 cursor->remove(); 1054 drawCursor( FALSE );
968 QString t = e->text(); 1055 repaintChanged();
969 QTextParag *p = cursor->parag(); 1056 drawCursor( TRUE );
970 if ( p && p->string() && p->string()->isRightToLeft() ) { 1057 break;
971 QChar *c = (QChar *)t.unicode(); 1058 }
972 int l = t.length(); 1059 }
973 while( l-- ) { 1060 if ( overWrite && !cursor->atParagEnd() )
974 if ( c->mirrored() ) 1061 cursor->remove();
975 *c = c->mirroredChar(); 1062 QString t = e->text();
976 c++; 1063 QTextParagraph *p = cursor->paragraph();
977 } 1064 if ( p && p->string() && p->string()->isRightToLeft() ) {
1065 QChar *c = (QChar *)t.unicode();
1066 int l = t.length();
1067 while( l-- ) {
1068 if ( c->mirrored() )
1069 *c = c->mirroredChar();
1070 c++;
978 } 1071 }
979 insert( t, TRUE, FALSE, TRUE );
980 } 1072 }
1073 insert( t, TRUE, FALSE, TRUE );
981 break; 1074 break;
982 } else if ( e->state() & ControlButton ) { 1075 } else if ( e->state() & ControlButton ) {
983 switch ( e->key() ) { 1076 switch ( e->key() ) {
984 case Key_C: case Key_F16: // Copy key on Sun keyboards 1077 case Key_C: case Key_F16: // Copy key on Sun keyboards
985 copy(); 1078 copy();
986 break; 1079 break;
987 case Key_V: 1080 case Key_V:
988 paste(); 1081 paste();
989 break; 1082 break;
990 case Key_X: 1083 case Key_X:
991 cut(); 1084 cut();
992 break; 1085 break;
993 case Key_I: case Key_T: case Key_Tab: 1086 case Key_I: case Key_T: case Key_Tab:
994 indent(); 1087 indent();
995 break; 1088 break;
996 case Key_A: 1089 case Key_A:
997#if defined(Q_WS_X11) 1090#if defined(Q_WS_X11)
998 moveCursor( MoveLineStart, e->state() & ShiftButton ); 1091 moveCursor( MoveLineStart, e->state() & ShiftButton );
999#else 1092#else
1000 selectAll( TRUE ); 1093 selectAll( TRUE );
1001#endif 1094#endif
1002 break; 1095 break;
1003 case Key_B: 1096 case Key_B:
1004 moveCursor( MoveBackward, e->state() & ShiftButton ); 1097 moveCursor( MoveBackward, e->state() & ShiftButton );
1005 break; 1098 break;
1006 case Key_F: 1099 case Key_F:
1007 moveCursor( MoveForward, e->state() & ShiftButton ); 1100 moveCursor( MoveForward, e->state() & ShiftButton );
1008 break; 1101 break;
1009 case Key_D: 1102 case Key_D:
1010 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1103 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1011 removeSelectedText(); 1104 removeSelectedText();
1012 break; 1105 break;
1013 } 1106 }
1014 doKeyboardAction( ActionDelete ); 1107 doKeyboardAction( ActionDelete );
1015 clearUndoRedoInfo = FALSE; 1108 clearUndoRedoInfo = FALSE;
1016 break; 1109 break;
1017 case Key_H: 1110 case Key_H:
1018 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1111 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1019 removeSelectedText(); 1112 removeSelectedText();
1020 break; 1113 break;
1021 } 1114 }
1022 if ( !cursor->parag()->prev() && 1115 if ( !cursor->paragraph()->prev() &&
1023 cursor->atParagStart() ) 1116 cursor->atParagStart() )
1024 break; 1117 break;
1025 1118
1026 doKeyboardAction( ActionBackspace ); 1119 doKeyboardAction( ActionBackspace );
1027 clearUndoRedoInfo = FALSE; 1120 clearUndoRedoInfo = FALSE;
1028 break; 1121 break;
1029 case Key_E: 1122 case Key_E:
1030 moveCursor( MoveLineEnd, e->state() & ShiftButton ); 1123 moveCursor( MoveLineEnd, e->state() & ShiftButton );
1031 break; 1124 break;
1032 case Key_N: 1125 case Key_N:
1033 moveCursor( MoveDown, e->state() & ShiftButton ); 1126 moveCursor( MoveDown, e->state() & ShiftButton );
1034 break; 1127 break;
1035 case Key_P: 1128 case Key_P:
1036 moveCursor( MoveUp, e->state() & ShiftButton ); 1129 moveCursor( MoveUp, e->state() & ShiftButton );
1037 break; 1130 break;
1038 case Key_Z: 1131 case Key_Z:
1039 undo(); 1132 if(e->state() & ShiftButton)
1133 redo();
1134 else
1135 undo();
1040 break; 1136 break;
1041 case Key_Y: 1137 case Key_Y:
1042 redo(); 1138 redo();
1043 break; 1139 break;
1044 case Key_K: 1140 case Key_K:
1045 doKeyboardAction( ActionKill ); 1141 doKeyboardAction( ActionKill );
1046 break; 1142 break;
1047#if defined(Q_WS_WIN) 1143#if defined(Q_WS_WIN)
1048 case Key_Insert: 1144 case Key_Insert:
1049 copy(); 1145 copy();
1050 break; 1146 break;
1051 case Key_Delete: 1147 case Key_Delete:
1052 del(); 1148 del();
1053 break; 1149 break;
1054#endif 1150#endif
1055 default: 1151 default:
1056 unknown = FALSE; 1152 unknown = FALSE;
1057 break; 1153 break;
1058 } 1154 }
1059 } else { 1155 } else {
1060 unknown = TRUE; 1156 unknown = TRUE;
1061 } 1157 }
1062 } 1158 }
1063 } 1159 }
1064 1160
1065 emit cursorPositionChanged( cursor ); 1161 emit cursorPositionChanged( cursor );
1066 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 1162 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
1067 if ( clearUndoRedoInfo ) 1163 if ( clearUndoRedoInfo )
1068 clearUndoRedo(); 1164 clearUndoRedo();
1069 changeIntervalTimer->start( 100, TRUE ); 1165 changeIntervalTimer->start( 100, TRUE );
1070 if ( unknown ) 1166 if ( unknown )
1071 e->ignore(); 1167 e->ignore();
1072} 1168}
1073 1169
1074/*! 1170/*!
1075 Executes keyboard action \a action. This is normally called by 1171 Executes keyboard action \a action. This is normally called by
1076 a key event handler. 1172 a key event handler.
1077*/ 1173*/
1078 1174
1079void QTextEdit::doKeyboardAction( KeyboardAction action ) 1175void QTextEdit::doKeyboardAction( KeyboardAction action )
1080{ 1176{
1081 if ( isReadOnly() ) 1177 if ( isReadOnly() )
1082 return; 1178 return;
1083 1179
1084 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough 1180 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough
1085 return; 1181 return;
1086 1182
1087 lastFormatted = cursor->parag(); 1183 lastFormatted = cursor->paragraph();
1088 drawCursor( FALSE ); 1184 drawCursor( FALSE );
1089 bool doUpdateCurrentFormat = TRUE; 1185 bool doUpdateCurrentFormat = TRUE;
1090 1186
1091 switch ( action ) { 1187 switch ( action ) {
1092 case ActionDelete: { 1188 case ActionDelete:
1093 checkUndoRedoInfo( UndoRedoInfo::Delete ); 1189 if ( !cursor->atParagEnd() ) {
1094 if ( !undoRedoInfo.valid() ) { 1190 checkUndoRedoInfo( UndoRedoInfo::Delete );
1095 undoRedoInfo.id = cursor->parag()->paragId(); 1191 if ( !undoRedoInfo.valid() ) {
1096 undoRedoInfo.index = cursor->index(); 1192 undoRedoInfo.id = cursor->paragraph()->paragId();
1097 undoRedoInfo.d->text = QString::null; 1193 undoRedoInfo.index = cursor->index();
1098 } 1194 undoRedoInfo.d->text = QString::null;
1099 undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; 1195 }
1100 if ( cursor->parag()->at( cursor->index() )->format() ) { 1196 undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( cursor->index() ), TRUE );
1101 cursor->parag()->at( cursor->index() )->format()->addRef(); 1197 cursor->remove();
1102 undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); 1198 } else {
1103 } 1199 clearUndoRedo();
1104 QTextParag *old = cursor->parag(); 1200 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1105 if ( cursor->remove() ) { 1201 cursor->gotoNextLetter();
1106 if ( old != cursor->parag() && lastFormatted == old ) 1202 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1107 lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; 1203 removeSelectedText( QTextDocument::Temp );
1108 undoRedoInfo.d->text += "\n";
1109 } 1204 }
1110 } break; 1205 break;
1111 case ActionBackspace: 1206 case ActionBackspace:
1112 if ( textFormat() == Qt::RichText && 1207 if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() && cursor->index() == 0 ) {
1113 cursor->parag()->style() && 1208 clearUndoRedo();
1114 cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayListItem && 1209 undoRedoInfo.type = UndoRedoInfo::Style;
1115 cursor->index() == 0 ) { 1210 undoRedoInfo.id = cursor->paragraph()->paragId();
1116 cursor->parag()->decDepth(); 1211 undoRedoInfo.eid = undoRedoInfo.id;
1117 lastFormatted = cursor->parag(); 1212 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
1213 int ldepth = cursor->paragraph()->listDepth();
1214 ldepth = QMAX( ldepth-1, 0 );
1215 cursor->paragraph()->setListDepth( ldepth );
1216 if ( ldepth == 0 )
1217 cursor->paragraph()->setListItem( FALSE );
1218 clearUndoRedo();
1219 lastFormatted = cursor->paragraph();
1118 repaintChanged(); 1220 repaintChanged();
1119 drawCursor( TRUE ); 1221 drawCursor( TRUE );
1120 return; 1222 return;
1121 } 1223 }
1122 checkUndoRedoInfo( UndoRedoInfo::Delete ); 1224 if ( !cursor->atParagStart() ) {
1123 if ( !undoRedoInfo.valid() ) { 1225 checkUndoRedoInfo( UndoRedoInfo::Delete );
1124 undoRedoInfo.id = cursor->parag()->paragId(); 1226 if ( !undoRedoInfo.valid() ) {
1125 undoRedoInfo.index = cursor->index(); 1227 undoRedoInfo.id = cursor->paragraph()->paragId();
1126 undoRedoInfo.d->text = QString::null; 1228 undoRedoInfo.index = cursor->index();
1127 } 1229 undoRedoInfo.d->text = QString::null;
1128 cursor->gotoPreviousLetter(); 1230 }
1129 undoRedoInfo.d->text.prepend( QString( cursor->parag()->at( cursor->index() )->c ) ); 1231 cursor->gotoPreviousLetter();
1130 if ( cursor->parag()->at( cursor->index() )->format() ) { 1232 undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index() ), TRUE );
1131 cursor->parag()->at( cursor->index() )->format()->addRef();
1132 undoRedoInfo.d->text.at( 0 ).setFormat( cursor->parag()->at( cursor->index() )->format() );
1133 }
1134 undoRedoInfo.index = cursor->index();
1135 if ( cursor->remove() ) {
1136 undoRedoInfo.d->text.remove( 0, 1 );
1137 undoRedoInfo.d->text.prepend( "\n" );
1138 undoRedoInfo.index = cursor->index(); 1233 undoRedoInfo.index = cursor->index();
1139 undoRedoInfo.id = cursor->parag()->paragId(); 1234 cursor->remove();
1235 lastFormatted = cursor->paragraph();
1236 } else if ( cursor->paragraph()->prev() ){
1237 clearUndoRedo();
1238 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1239 cursor->gotoPreviousLetter();
1240 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1241 removeSelectedText( QTextDocument::Temp );
1140 } 1242 }
1141 lastFormatted = cursor->parag();
1142 break; 1243 break;
1143 case ActionReturn: { 1244 case ActionReturn:
1144 checkUndoRedoInfo( UndoRedoInfo::Return ); 1245 checkUndoRedoInfo( UndoRedoInfo::Return );
1145 if ( !undoRedoInfo.valid() ) { 1246 if ( !undoRedoInfo.valid() ) {
1146 undoRedoInfo.id = cursor->parag()->paragId(); 1247 undoRedoInfo.id = cursor->paragraph()->paragId();
1147 undoRedoInfo.index = cursor->index(); 1248 undoRedoInfo.index = cursor->index();
1148 undoRedoInfo.d->text = QString::null; 1249 undoRedoInfo.d->text = QString::null;
1149 } 1250 }
1150 undoRedoInfo.d->text += "\n"; 1251 undoRedoInfo.d->text += "\n";
1151 cursor->splitAndInsertEmptyParag(); 1252 cursor->splitAndInsertEmptyParagraph();
1152 if ( cursor->parag()->prev() ) { 1253 if ( cursor->paragraph()->prev() ) {
1153 lastFormatted = cursor->parag()->prev(); 1254 lastFormatted = cursor->paragraph()->prev();
1154 lastFormatted->invalidate( 0 ); 1255 lastFormatted->invalidate( 0 );
1155 } 1256 }
1156 doUpdateCurrentFormat = FALSE; 1257 doUpdateCurrentFormat = FALSE;
1157 } break;
1158 case ActionKill:
1159 checkUndoRedoInfo( UndoRedoInfo::Delete );
1160 if ( !undoRedoInfo.valid() ) {
1161 undoRedoInfo.id = cursor->parag()->paragId();
1162 undoRedoInfo.index = cursor->index();
1163 undoRedoInfo.d->text = QString::null;
1164 }
1165 if ( cursor->atParagEnd() ) {
1166 undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c;
1167 if ( cursor->parag()->at( cursor->index() )->format() ) {
1168 cursor->parag()->at( cursor->index() )->format()->addRef();
1169 undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() );
1170 }
1171 QTextParag *old = cursor->parag();
1172 if ( cursor->remove() ) {
1173 if ( old != cursor->parag() && lastFormatted == old )
1174 lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0;
1175 undoRedoInfo.d->text += "\n";
1176 }
1177 } else {
1178 int oldLen = undoRedoInfo.d->text.length();
1179 undoRedoInfo.d->text += cursor->parag()->string()->toString().mid( cursor->index() );
1180 for ( int i = cursor->index(); i < cursor->parag()->length(); ++i ) {
1181 if ( cursor->parag()->at( i )->format() ) {
1182 cursor->parag()->at( i )->format()->addRef();
1183 undoRedoInfo.d->text.at( oldLen + i - cursor->index() ).setFormat( cursor->parag()->at( i )->format() );
1184 }
1185 }
1186 undoRedoInfo.d->text.remove( undoRedoInfo.d->text.length() - 1, 1 );
1187 cursor->killLine();
1188 }
1189 break; 1258 break;
1259 case ActionKill:
1260 clearUndoRedo();
1261 doc->setSelectionStart( QTextDocument::Temp, *cursor );
1262 if ( cursor->atParagEnd() )
1263 cursor->gotoNextLetter();
1264 else
1265 cursor->setIndex( cursor->paragraph()->length() - 1 );
1266 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
1267 removeSelectedText( QTextDocument::Temp );
1268 break;
1190 } 1269 }
1191 1270
1192 formatMore(); 1271 formatMore();
1193 repaintChanged(); 1272 repaintChanged();
1194 ensureCursorVisible(); 1273 ensureCursorVisible();
1195 drawCursor( TRUE ); 1274 drawCursor( TRUE );
1196 1275 updateMicroFocusHint();
1197 if ( hasFocus() || viewport()->hasFocus() ) {
1198 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1199 if ( !readonly ) {
1200 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1201 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1202 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1203 }
1204 }
1205
1206 if ( doUpdateCurrentFormat ) 1276 if ( doUpdateCurrentFormat )
1207 updateCurrentFormat(); 1277 updateCurrentFormat();
1208 setModified(); 1278 setModified();
1209 emit textChanged(); 1279 emit textChanged();
1210} 1280}
1211 1281
1212void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles ) 1282void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles )
1213{ 1283{
1284 QDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly );
1214 c2.restoreState(); 1285 c2.restoreState();
1215 c1.restoreState(); 1286 c1.restoreState();
1216 if ( c1.parag() == c2.parag() ) { 1287 int lastIndex = text.length();
1217 for ( int i = c1.index(); i < c2.index(); ++i ) { 1288 if ( c1.paragraph() == c2.paragraph() ) {
1218 if ( c1.parag()->at( i )->format() ) { 1289 for ( int i = c1.index(); i < c2.index(); ++i )
1219 c1.parag()->at( i )->format()->addRef(); 1290 text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE );
1220 text.at( oldLen + i - c1.index() ).setFormat( c1.parag()->at( i )->format() );
1221 }
1222 }
1223 if ( fillStyles ) { 1291 if ( fillStyles ) {
1224 undoRedoInfo.oldAligns[ 0 ] = c1.parag()->alignment(); 1292 styleStream << (int) 1;
1225 undoRedoInfo.oldStyles << c1.parag()->styleSheetItems(); 1293 c1.paragraph()->writeStyleInformation( styleStream );
1226 undoRedoInfo.oldListStyles << c1.parag()->listStyle();
1227 } 1294 }
1228 } else { 1295 } else {
1229 int lastIndex = oldLen;
1230 int i; 1296 int i;
1231 for ( i = c1.index(); i < c1.parag()->length(); ++i ) { 1297 for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i )
1232 if ( c1.parag()->at( i )->format() ) { 1298 text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE );
1233 c1.parag()->at( i )->format()->addRef(); 1299 int num = 2; // start and end, being different
1234 text.at( lastIndex ).setFormat( c1.parag()->at( i )->format() ); 1300 text += "\n"; lastIndex++;
1235 lastIndex++; 1301 QTextParagraph *p = c1.paragraph()->next();
1236 } 1302 while ( p && p != c2.paragraph() ) {
1237 } 1303 for ( i = 0; i < p->length()-1; ++i )
1238 QTextParag *p = c1.parag()->next(); 1304 text.insert( lastIndex++ , p->at( i ), TRUE );
1239 while ( p && p != c2.parag() ) { 1305 text += "\n"; num++; lastIndex++;
1240 for ( int i = 0; i < p->length(); ++i ) {
1241 if ( p->at( i )->format() ) {
1242 p->at( i )->format()->addRef();
1243 text.at( i + lastIndex ).setFormat( p->at( i )->format() );
1244 }
1245 }
1246 lastIndex += p->length();
1247 p = p->next(); 1306 p = p->next();
1248 } 1307 }
1249 for ( i = 0; i < c2.index(); ++i ) { 1308 for ( i = 0; i < c2.index(); ++i )
1250 if ( c2.parag()->at( i )->format() ) { 1309 text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE );
1251 c2.parag()->at( i )->format()->addRef();
1252 text.at( i + lastIndex ).setFormat( c2.parag()->at( i )->format() );
1253 }
1254 }
1255 if ( fillStyles ) { 1310 if ( fillStyles ) {
1256 QTextParag *p = c1.parag(); 1311 styleStream << num;
1257 i = 0; 1312 for ( QTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() )
1258 while ( p ) { 1313 p->writeStyleInformation( styleStream );
1259 if ( i < (int)undoRedoInfo.oldAligns.size() )
1260 undoRedoInfo.oldAligns[ i ] = p->alignment();
1261 undoRedoInfo.oldStyles << p->styleSheetItems();
1262 undoRedoInfo.oldListStyles << p->listStyle();
1263 if ( p == c2.parag() )
1264 break;
1265 p = p->next();
1266 ++i;
1267 }
1268 } 1314 }
1269 } 1315 }
1270} 1316}
1271 1317
1272/*! Removes the selection \a selNum (by default 0). This does not 1318/*! Removes the selection \a selNum (by default 0). This does not
1273 remove the selected text. 1319 remove the selected text.
1274 1320
1275 \sa removeSelectedText() 1321 \sa removeSelectedText()
1276*/ 1322*/
1277 1323
1278void QTextEdit::removeSelection( int selNum ) 1324void QTextEdit::removeSelection( int selNum )
1279{ 1325{
1280 doc->removeSelection( selNum ); 1326 doc->removeSelection( selNum );
1281 repaintChanged(); 1327 repaintChanged();
1282} 1328}
1283 1329
1284/*! Deletes the selected text (i.e. the default selection's text) of 1330/*! Deletes the selected text (i.e. the default selection's text) of
1285 the selection \a selNum (by default, 0). If there is no selected text 1331 the selection \a selNum (by default, 0). If there is no selected text
1286 nothing happens. 1332 nothing happens.
1287 1333
1288 \sa selectedText removeSelection() 1334 \sa selectedText removeSelection()
1289*/ 1335*/
1290 1336
1291void QTextEdit::removeSelectedText( int selNum ) 1337void QTextEdit::removeSelectedText( int selNum )
1292{ 1338{
1293 if ( isReadOnly() ) 1339 if ( isReadOnly() )
1294 return; 1340 return;
1295 1341
1296 QTextCursor c1 = doc->selectionStartCursor( selNum ); 1342 QTextCursor c1 = doc->selectionStartCursor( selNum );
1343 c1.restoreState();
1297 QTextCursor c2 = doc->selectionEndCursor( selNum ); 1344 QTextCursor c2 = doc->selectionEndCursor( selNum );
1345 c2.restoreState();
1298 1346
1299 // ### no support for editing tables yet 1347 // ### no support for editing tables yet, plus security for broken selections
1300 if ( c1.nestedDepth() || c2.nestedDepth() ) 1348 if ( c1.nestedDepth() || c2.nestedDepth() )
1301 return; 1349 return;
1302 1350
1303 for ( int i = 0; i < (int)doc->numSelections(); ++i ) { 1351 for ( int i = 0; i < (int)doc->numSelections(); ++i ) {
1304 if ( i == selNum ) 1352 if ( i == selNum )
1305 continue; 1353 continue;
1306 doc->removeSelection( i ); 1354 doc->removeSelection( i );
1307 } 1355 }
1308 1356
1309 drawCursor( FALSE ); 1357 drawCursor( FALSE );
1310 checkUndoRedoInfo( UndoRedoInfo::RemoveSelected ); 1358 checkUndoRedoInfo( UndoRedoInfo::RemoveSelected );
1311 if ( !undoRedoInfo.valid() ) { 1359 if ( !undoRedoInfo.valid() ) {
1312 doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); 1360 doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index );
1313 undoRedoInfo.d->text = QString::null; 1361 undoRedoInfo.d->text = QString::null;
1314 } 1362 }
1315 int oldLen = undoRedoInfo.d->text.length(); 1363 readFormats( c1, c2, undoRedoInfo.d->text, TRUE );
1316 undoRedoInfo.d->text = doc->selectedText( selNum, FALSE ); 1364
1317 undoRedoInfo.oldAligns.resize( undoRedoInfo.oldAligns.size() + QMAX( 0, c2.parag()->paragId() - c1.parag()->paragId() + 1 ) ); 1365
1318 readFormats( c1, c2, oldLen, undoRedoInfo.d->text, TRUE );
1319 doc->removeSelectedText( selNum, cursor ); 1366 doc->removeSelectedText( selNum, cursor );
1320 if ( cursor->isValid() ) { 1367 if ( cursor->isValid() ) {
1321 ensureCursorVisible(); 1368 ensureCursorVisible();
1322 lastFormatted = cursor->parag(); 1369 lastFormatted = cursor->paragraph();
1323 formatMore(); 1370 formatMore();
1324 repaintChanged(); 1371 repaintChanged();
1325 ensureCursorVisible(); 1372 ensureCursorVisible();
1326 drawCursor( TRUE ); 1373 drawCursor( TRUE );
1327 clearUndoRedo(); 1374 clearUndoRedo();
1328#if defined(Q_WS_WIN) 1375#if defined(Q_WS_WIN)
1329 // there seems to be a problem with repainting or erasing the area 1376 // there seems to be a problem with repainting or erasing the area
1330 // of the scrollview which is not the contents on windows 1377 // of the scrollview which is not the contents on windows
1331 if ( contentsHeight() < visibleHeight() ) 1378 if ( contentsHeight() < visibleHeight() )
1332 viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE ); 1379 viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE );
1333#endif 1380#endif
1334#ifndef QT_NO_CURSOR 1381#ifndef QT_NO_CURSOR
1335 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1382 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1336#endif 1383#endif
1337 if ( hasFocus() || viewport()->hasFocus() ) { 1384 updateMicroFocusHint();
1338 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1339 if ( !readonly ) {
1340 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1341 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1342 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1343 }
1344 }
1345 } else { 1385 } else {
1346 cursor->setDocument( doc ); 1386 delete cursor;
1347 cursor->setParag( doc->firstParag() ); 1387 cursor = new QTextCursor( doc );
1348 cursor->setIndex( 0 );
1349 drawCursor( TRUE ); 1388 drawCursor( TRUE );
1350 viewport()->repaint( TRUE ); 1389 viewport()->repaint( TRUE );
1351 } 1390 }
1352 setModified(); 1391 setModified();
1353 emit textChanged(); 1392 emit textChanged();
1354 emit selectionChanged(); 1393 emit selectionChanged();
1355} 1394}
1356 1395
1357/*! Moves the text cursor according to \a action. This is normally 1396/*! Moves the text cursor according to \a action. This is normally
1358 used by some key event handler. \a select specifies whether the text 1397 used by some key event handler. \a select specifies whether the text
1359 between the current cursor position and the new position should be 1398 between the current cursor position and the new position should be
1360 selected. 1399 selected.
1361*/ 1400*/
1362 1401
1363void QTextEdit::moveCursor( CursorAction action, bool select ) 1402void QTextEdit::moveCursor( CursorAction action, bool select )
1364{ 1403{
1365 drawCursor( FALSE ); 1404 drawCursor( FALSE );
1366 if ( select ) { 1405 if ( select ) {
1367 if ( !doc->hasSelection( QTextDocument::Standard ) ) 1406 if ( !doc->hasSelection( QTextDocument::Standard ) )
1368 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1407 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1369 moveCursor( action ); 1408 moveCursor( action );
1370 if ( doc->setSelectionEnd( QTextDocument::Standard, cursor ) ) { 1409 if ( doc->setSelectionEnd( QTextDocument::Standard, *cursor ) ) {
1371 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1410 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1372 repaintChanged(); 1411 repaintChanged();
1373 } else { 1412 } else {
1374 drawCursor( TRUE ); 1413 drawCursor( TRUE );
1375 } 1414 }
1376 ensureCursorVisible(); 1415 ensureCursorVisible();
1377 emit selectionChanged(); 1416 emit selectionChanged();
1378 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 1417 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
1379 } else { 1418 } else {
1380 bool redraw = doc->removeSelection( QTextDocument::Standard ); 1419 bool redraw = doc->removeSelection( QTextDocument::Standard );
1381 moveCursor( action ); 1420 moveCursor( action );
1382 if ( !redraw ) { 1421 if ( !redraw ) {
1383 ensureCursorVisible(); 1422 ensureCursorVisible();
1384 drawCursor( TRUE ); 1423 drawCursor( TRUE );
1385 } else { 1424 } else {
1386 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1425 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1387 repaintChanged(); 1426 repaintChanged();
1388 ensureCursorVisible(); 1427 ensureCursorVisible();
1389 drawCursor( TRUE ); 1428 drawCursor( TRUE );
1390#ifndef QT_NO_CURSOR 1429#ifndef QT_NO_CURSOR
1391 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1430 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1392#endif 1431#endif
1393 } 1432 }
1394 if ( redraw ) { 1433 if ( redraw ) {
1395 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 1434 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
1396 emit selectionChanged(); 1435 emit selectionChanged();
1397 } 1436 }
1398 } 1437 }
1399 1438
1400 drawCursor( TRUE ); 1439 drawCursor( TRUE );
1401 updateCurrentFormat(); 1440 updateCurrentFormat();
1402 if ( hasFocus() || viewport()->hasFocus() ) { 1441 updateMicroFocusHint();
1403 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1404 if ( !readonly ) {
1405 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1406 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1407 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1408 }
1409 }
1410} 1442}
1411 1443
1412/*! \overload 1444/*! \overload
1413*/ 1445*/
1414 1446
1415void QTextEdit::moveCursor( CursorAction action ) 1447void QTextEdit::moveCursor( CursorAction action )
1416{ 1448{
1417 switch ( action ) { 1449 switch ( action ) {
1418 case MoveBackward: 1450 case MoveBackward:
1419 cursor->gotoPreviousLetter(); 1451 cursor->gotoPreviousLetter();
1420 break; 1452 break;
1421 case MoveWordBackward: 1453 case MoveWordBackward:
1422 cursor->gotoPreviousWord(); 1454 cursor->gotoPreviousWord();
1423 break; 1455 break;
1424 case MoveForward: 1456 case MoveForward:
1425 cursor->gotoNextLetter(); 1457 cursor->gotoNextLetter();
1426 break; 1458 break;
1427 case MoveWordForward: 1459 case MoveWordForward:
1428 cursor->gotoNextWord(); 1460 cursor->gotoNextWord();
1429 break; 1461 break;
1430 case MoveUp: 1462 case MoveUp:
1431 cursor->gotoUp(); 1463 cursor->gotoUp();
1432 break; 1464 break;
1433 case MovePgUp: 1465 case MovePgUp:
1434 cursor->gotoPageUp( visibleHeight() ); 1466 cursor->gotoPageUp( visibleHeight() );
1435 break; 1467 break;
1436 case MoveDown: 1468 case MoveDown:
1437 cursor->gotoDown(); 1469 cursor->gotoDown();
1438 break; 1470 break;
1439 case MovePgDown: 1471 case MovePgDown:
1440 cursor->gotoPageDown( visibleHeight() ); 1472 cursor->gotoPageDown( visibleHeight() );
1441 break; 1473 break;
1442 case MoveLineStart: 1474 case MoveLineStart:
1443 cursor->gotoLineStart(); 1475 cursor->gotoLineStart();
1444 break; 1476 break;
1445 case MoveHome: 1477 case MoveHome:
1446 cursor->gotoHome(); 1478 cursor->gotoHome();
1447 break; 1479 break;
1448 case MoveLineEnd: 1480 case MoveLineEnd:
1449 cursor->gotoLineEnd(); 1481 cursor->gotoLineEnd();
1450 break; 1482 break;
1451 case MoveEnd: 1483 case MoveEnd:
1452 ensureFormatted( doc->lastParag() ); 1484 ensureFormatted( doc->lastParagraph() );
1453 cursor->gotoEnd(); 1485 cursor->gotoEnd();
1454 break; 1486 break;
1455 } 1487 }
1456 1488 updateMicroFocusHint();
1457 if ( hasFocus() || viewport()->hasFocus() ) {
1458 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
1459 if ( !readonly ) {
1460 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
1461 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
1462 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1463 }
1464 }
1465 updateCurrentFormat(); 1489 updateCurrentFormat();
1466} 1490}
1467 1491
1468/*! \reimp */ 1492/*! \reimp */
1469 1493
1470void QTextEdit::resizeEvent( QResizeEvent *e ) 1494void QTextEdit::resizeEvent( QResizeEvent *e )
1471{ 1495{
1472 QScrollView::resizeEvent( e ); 1496 QScrollView::resizeEvent( e );
1497 if ( doc->visibleWidth() == 0 )
1498 doResize();
1473} 1499}
1474 1500
1475/*! \reimp */ 1501/*! \reimp */
1476 1502
1477void QTextEdit::viewportResizeEvent( QResizeEvent *e ) 1503void QTextEdit::viewportResizeEvent( QResizeEvent *e )
1478{ 1504{
1479 QScrollView::viewportResizeEvent( e ); 1505 QScrollView::viewportResizeEvent( e );
1480 if ( e->oldSize().width() != e->size().width() ) 1506 if ( e->oldSize().width() != e->size().width() ) {
1507 bool stayAtBottom = e->oldSize().height() != e->size().height() &&
1508 contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height();
1481 doResize(); 1509 doResize();
1510 if ( stayAtBottom )
1511 scrollToBottom();
1512 }
1482} 1513}
1483 1514
1484static bool blockEnsureCursorVisible = FALSE;
1485
1486/*! 1515/*!
1487 Ensures that the cursor is visible by scrolling the text edit if 1516 Ensures that the cursor is visible by scrolling the text edit if
1488 necessary. 1517 necessary.
1489 1518
1490 \sa setCursorPosition() 1519 \sa setCursorPosition()
1491*/ 1520*/
1492 1521
1493void QTextEdit::ensureCursorVisible() 1522void QTextEdit::ensureCursorVisible()
1494{ 1523{
1495 if ( blockEnsureCursorVisible )
1496 return;
1497 if ( !isVisible() ) { 1524 if ( !isVisible() ) {
1498 d->ensureCursorVisibleInShowEvent = TRUE; 1525 d->ensureCursorVisibleInShowEvent = TRUE;
1499 return; 1526 return;
1500 } 1527 }
1501 lastFormatted = cursor->parag(); 1528 lastFormatted = cursor->paragraph();
1502 formatMore(); 1529 formatMore();
1503 QTextStringChar *chr = cursor->parag()->at( cursor->index() ); 1530 QTextStringChar *chr = cursor->paragraph()->at( cursor->index() );
1504 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 1531 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
1505 int x = cursor->parag()->rect().x() + chr->x + cursor->offsetX(); 1532 int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX();
1506 int y = 0; int dummy; 1533 int y = 0; int dummy;
1507 cursor->parag()->lineHeightOfChar( cursor->index(), &dummy, &y ); 1534 cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y );
1508 y += cursor->parag()->rect().y() + cursor->offsetY(); 1535 y += cursor->paragraph()->rect().y() + cursor->offsetY();
1509 int w = 1; 1536 int w = 1;
1510 ensureVisible( x, y + h / 2, w, h / 2 + 2 ); 1537 ensureVisible( x, y + h / 2, w, h / 2 + 2 );
1511} 1538}
1512 1539
1513/*! 1540/*!
1514 \internal 1541 \internal
1515*/ 1542*/
1516void QTextEdit::drawCursor( bool visible ) 1543void QTextEdit::drawCursor( bool visible )
1517{ 1544{
1518 if ( !isUpdatesEnabled() || 1545 if ( !isUpdatesEnabled() ||
1519 !viewport()->isUpdatesEnabled() || 1546 !viewport()->isUpdatesEnabled() ||
1520 !cursor->parag() || 1547 !cursor->paragraph() ||
1521 !cursor->parag()->isValid() || 1548 !cursor->paragraph()->isValid() ||
1522 !selectedText().isEmpty() || 1549 !selectedText().isEmpty() ||
1523 ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || 1550 ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) ||
1524 isReadOnly() ) 1551 isReadOnly() )
1525 return; 1552 return;
1526 1553
1527 QPainter p( viewport() ); 1554 QPainter p( viewport() );
1528 QRect r( cursor->topParag()->rect() ); 1555 QRect r( cursor->topParagraph()->rect() );
1529 cursor->parag()->setChanged( TRUE ); 1556 cursor->paragraph()->setChanged( TRUE );
1530 p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); 1557 p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() );
1531 QPixmap *pix = 0; 1558 QPixmap *pix = 0;
1532 QColorGroup cg( colorGroup() ); 1559 QColorGroup cg( colorGroup() );
1533 if ( cursor->parag()->background() ) 1560 if ( cursor->paragraph()->background() )
1534 cg.setBrush( QColorGroup::Base, *cursor->parag()->background() ); 1561 cg.setBrush( QColorGroup::Base, *cursor->paragraph()->background() );
1535 else if ( doc->paper() ) 1562 else if ( doc->paper() )
1536 cg.setBrush( QColorGroup::Base, *doc->paper() ); 1563 cg.setBrush( QColorGroup::Base, *doc->paper() );
1537 p.setBrushOrigin( -contentsX(), -contentsY() ); 1564 p.setBrushOrigin( -contentsX(), -contentsY() );
1538 cursor->parag()->document()->nextDoubleBuffered = TRUE; 1565 cursor->paragraph()->document()->nextDoubleBuffered = TRUE;
1539 if ( !cursor->nestedDepth() ) { 1566 if ( !cursor->nestedDepth() ) {
1540 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 1567 int h = cursor->paragraph()->lineHeightOfChar( cursor->index() );
1541 int dist = 5; 1568 int dist = 5;
1542 if ( ( cursor->parag()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) 1569 if ( ( cursor->paragraph()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify )
1543 dist = 50; 1570 dist = 50;
1544 int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; 1571 int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist;
1545 x = QMAX( x, 0 ); 1572 x = QMAX( x, 0 );
1546 p.setClipRect( QRect( x - contentsX(), 1573 p.setClipRect( QRect( x - contentsX(),
1547 r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); 1574 r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) );
1548 doc->drawParag( &p, cursor->parag(), x, 1575 doc->drawParagraph( &p, cursor->paragraph(), x,
1549 r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); 1576 r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor );
1550 } else { 1577 } else {
1551 doc->drawParag( &p, cursor->parag(), r.x() - cursor->totalOffsetX(), 1578 doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(),
1552 r.y() - cursor->totalOffsetY(), r.width(), r.height(), 1579 r.y() - cursor->totalOffsetY(), r.width(), r.height(),
1553 pix, cg, visible, cursor ); 1580 pix, cg, visible, cursor );
1554 } 1581 }
1555 cursorVisible = visible; 1582 cursorVisible = visible;
1556} 1583}
1557 1584
1558enum { 1585enum {
1559 IdUndo = 0, 1586 IdUndo = 0,
1560 IdRedo = 1, 1587 IdRedo = 1,
1561 IdCut = 2, 1588 IdCut = 2,
1562 IdCopy = 3, 1589 IdCopy = 3,
1563 IdPaste = 4, 1590 IdPaste = 4,
1564 IdClear = 5, 1591 IdClear = 5,
1565 IdSelectAll = 6 1592 IdSelectAll = 6
1566}; 1593};
1567 1594
1568/*! \reimp */ 1595/*! \reimp */
1569#ifndef QT_NO_WHEELEVENT 1596#ifndef QT_NO_WHEELEVENT
1570void QTextEdit::contentsWheelEvent( QWheelEvent *e ) 1597void QTextEdit::contentsWheelEvent( QWheelEvent *e )
1571{ 1598{
1572 if ( isReadOnly() ) { 1599 if ( isReadOnly() ) {
1573 if ( e->state() & ControlButton ) { 1600 if ( e->state() & ControlButton ) {
1574 if ( e->delta() > 0 ) 1601 if ( e->delta() > 0 )
1575 zoomOut(); 1602 zoomOut();
1576 else if ( e->delta() < 0 ) 1603 else if ( e->delta() < 0 )
1577 zoomIn(); 1604 zoomIn();
1578 return; 1605 return;
1579 } 1606 }
1580 } 1607 }
1581 QScrollView::contentsWheelEvent( e ); 1608 QScrollView::contentsWheelEvent( e );
1582} 1609}
1583#endif 1610#endif
1584 1611
1585/*! \reimp */ 1612/*! \reimp */
1586 1613
1587void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) 1614void QTextEdit::contentsMousePressEvent( QMouseEvent *e )
1588{ 1615{
1589 clearUndoRedo(); 1616 clearUndoRedo();
1590 QTextCursor oldCursor = *cursor; 1617 QTextCursor oldCursor = *cursor;
1591 QTextCursor c = *cursor; 1618 QTextCursor c = *cursor;
1592 mousePos = e->pos(); 1619 mousePos = e->pos();
1593 mightStartDrag = FALSE; 1620 mightStartDrag = FALSE;
1594 pressedLink = QString::null; 1621 pressedLink = QString::null;
1595 1622
1596 if ( e->button() == LeftButton ) { 1623 if ( e->button() == LeftButton ) {
1597 mousePressed = TRUE; 1624 mousePressed = TRUE;
1598 drawCursor( FALSE ); 1625 drawCursor( FALSE );
1599 placeCursor( e->pos() ); 1626 placeCursor( e->pos() );
1600 ensureCursorVisible(); 1627 ensureCursorVisible();
1601 1628
1602 if ( isReadOnly() && linksEnabled() ) { 1629 if ( isReadOnly() && linksEnabled() ) {
1603 QTextCursor c = *cursor; 1630 QTextCursor c = *cursor;
1604 placeCursor( e->pos(), &c, TRUE ); 1631 placeCursor( e->pos(), &c, TRUE );
1605 if ( c.parag() && c.parag()->at( c.index() ) && 1632 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
1606 c.parag()->at( c.index() )->isAnchor() ) { 1633 c.paragraph()->at( c.index() )->isAnchor() ) {
1607 pressedLink = c.parag()->at( c.index() )->anchorHref(); 1634 pressedLink = c.paragraph()->at( c.index() )->anchorHref();
1608 } 1635 }
1609 } 1636 }
1610 1637
1611#ifndef QT_NO_DRAGANDDROP 1638#ifndef QT_NO_DRAGANDDROP
1612 if ( doc->inSelection( QTextDocument::Standard, e->pos() ) ) { 1639 if ( doc->inSelection( QTextDocument::Standard, e->pos() ) ) {
1613 mightStartDrag = TRUE; 1640 mightStartDrag = TRUE;
1614 drawCursor( TRUE ); 1641 drawCursor( TRUE );
1615 dragStartTimer->start( QApplication::startDragTime(), TRUE ); 1642 dragStartTimer->start( QApplication::startDragTime(), TRUE );
1616 dragStartPos = e->pos(); 1643 dragStartPos = e->pos();
1617 return; 1644 return;
1618 } 1645 }
1619#endif 1646#endif
1620 1647
1621 bool redraw = FALSE; 1648 bool redraw = FALSE;
1622 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1649 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1623 if ( !( e->state() & ShiftButton ) ) { 1650 if ( !( e->state() & ShiftButton ) ) {
1624 redraw = doc->removeSelection( QTextDocument::Standard ); 1651 redraw = doc->removeSelection( QTextDocument::Standard );
1625 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1652 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1626 } else { 1653 } else {
1627 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1654 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1628 } 1655 }
1629 } else { 1656 } else {
1630 if ( isReadOnly() || !( e->state() & ShiftButton ) ) { 1657 if ( isReadOnly() || !( e->state() & ShiftButton ) ) {
1631 doc->setSelectionStart( QTextDocument::Standard, cursor ); 1658 doc->setSelectionStart( QTextDocument::Standard, *cursor );
1632 } else { 1659 } else {
1633 doc->setSelectionStart( QTextDocument::Standard, &c ); 1660 doc->setSelectionStart( QTextDocument::Standard, c );
1634 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1661 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1635 } 1662 }
1636 } 1663 }
1637 1664
1638 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection 1665 for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection
1639 redraw = doc->removeSelection( i ) || redraw; 1666 redraw = doc->removeSelection( i ) || redraw;
1640 1667
1641 if ( !redraw ) { 1668 if ( !redraw ) {
1642 drawCursor( TRUE ); 1669 drawCursor( TRUE );
1643 } else { 1670 } else {
1644 repaintChanged(); 1671 repaintChanged();
1645#ifndef QT_NO_CURSOR 1672#ifndef QT_NO_CURSOR
1646 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1673 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1647#endif 1674#endif
1648 } 1675 }
1649 } else if ( e->button() == MidButton ) { 1676 } else if ( e->button() == MidButton ) {
1650 bool redraw = doc->removeSelection( QTextDocument::Standard ); 1677 bool redraw = doc->removeSelection( QTextDocument::Standard );
1651 if ( !redraw ) { 1678 if ( !redraw ) {
1652 drawCursor( TRUE ); 1679 drawCursor( TRUE );
1653 } else { 1680 } else {
1654 repaintChanged(); 1681 repaintChanged();
1655#ifndef QT_NO_CURSOR 1682#ifndef QT_NO_CURSOR
1656 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1683 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1657#endif 1684#endif
1658 } 1685 }
1659 } 1686 }
1660 1687
1661 if ( *cursor != oldCursor ) 1688 if ( *cursor != oldCursor )
1662 updateCurrentFormat(); 1689 updateCurrentFormat();
1663} 1690}
1664 1691
1665/*! \reimp */ 1692/*! \reimp */
1666 1693
@@ -1685,967 +1712,949 @@ void QTextEdit::contentsMouseMoveEvent( QMouseEvent *e )
1685 } 1712 }
1686 1713
1687#ifndef QT_NO_CURSOR 1714#ifndef QT_NO_CURSOR
1688 if ( !isReadOnly() && !mousePressed ) { 1715 if ( !isReadOnly() && !mousePressed ) {
1689 if ( doc->hasSelection( QTextDocument::Standard ) && doc->inSelection( QTextDocument::Standard, e->pos() ) ) 1716 if ( doc->hasSelection( QTextDocument::Standard ) && doc->inSelection( QTextDocument::Standard, e->pos() ) )
1690 viewport()->setCursor( arrowCursor ); 1717 viewport()->setCursor( arrowCursor );
1691 else 1718 else
1692 viewport()->setCursor( ibeamCursor ); 1719 viewport()->setCursor( ibeamCursor );
1693 } 1720 }
1694#endif 1721#endif
1695 updateCursor( e->pos() ); 1722 updateCursor( e->pos() );
1696} 1723}
1697 1724
1698/*! \reimp */ 1725/*! \reimp */
1699 1726
1700void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e ) 1727void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e )
1701{ 1728{
1702 QTextCursor oldCursor = *cursor; 1729 QTextCursor oldCursor = *cursor;
1703 if ( scrollTimer->isActive() ) 1730 if ( scrollTimer->isActive() )
1704 scrollTimer->stop(); 1731 scrollTimer->stop();
1705#ifndef QT_NO_DRAGANDDROP 1732#ifndef QT_NO_DRAGANDDROP
1706 if ( dragStartTimer->isActive() ) 1733 if ( dragStartTimer->isActive() )
1707 dragStartTimer->stop(); 1734 dragStartTimer->stop();
1708 if ( mightStartDrag ) { 1735 if ( mightStartDrag ) {
1709 selectAll( FALSE ); 1736 selectAll( FALSE );
1710 mousePressed = FALSE; 1737 mousePressed = FALSE;
1711 } 1738 }
1712#endif 1739#endif
1713 if ( mousePressed ) { 1740 if ( mousePressed ) {
1714 mousePressed = FALSE; 1741 mousePressed = FALSE;
1715 } 1742 }
1716 emit cursorPositionChanged( cursor ); 1743 emit cursorPositionChanged( cursor );
1717 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 1744 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
1718 if ( oldCursor != *cursor ) 1745 if ( oldCursor != *cursor )
1719 updateCurrentFormat(); 1746 updateCurrentFormat();
1720 inDoubleClick = FALSE; 1747 inDoubleClick = FALSE;
1721 1748
1722#ifndef QT_NO_NETWORKPROTOCOL 1749#ifndef QT_NO_NETWORKPROTOCOL
1723 if ( !onLink.isEmpty() && onLink == pressedLink && linksEnabled() ) { 1750 if ( !onLink.isEmpty() && onLink == pressedLink && linksEnabled() ) {
1724 QUrl u( doc->context(), onLink, TRUE ); 1751 QUrl u( doc->context(), onLink, TRUE );
1725 emitLinkClicked( u.toString( FALSE, FALSE ) ); 1752 emitLinkClicked( u.toString( FALSE, FALSE ) );
1726 1753
1727 // emitting linkClicked() may result in that the cursor winds 1754 // emitting linkClicked() may result in that the cursor winds
1728 // up hovering over a different valid link - check this and 1755 // up hovering over a different valid link - check this and
1729 // set the appropriate cursor shape 1756 // set the appropriate cursor shape
1730 updateCursor( e->pos() ); 1757 updateCursor( e->pos() );
1731 } 1758 }
1732#endif 1759#endif
1733 drawCursor( TRUE ); 1760 drawCursor( TRUE );
1734 if ( !doc->hasSelection( QTextDocument::Standard, TRUE ) ) 1761 if ( !doc->hasSelection( QTextDocument::Standard, TRUE ) )
1735 doc->removeSelection( QTextDocument::Standard ); 1762 doc->removeSelection( QTextDocument::Standard );
1736 1763
1737 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 1764 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
1738 emit selectionChanged(); 1765 emit selectionChanged();
1739} 1766}
1740 1767
1741/*! \reimp */ 1768/*! \reimp */
1742 1769
1743void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * ) 1770void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * )
1744{ 1771{
1745 QTextCursor c1 = *cursor; 1772 QTextCursor c1 = *cursor;
1746 QTextCursor c2 = *cursor; 1773 QTextCursor c2 = *cursor;
1747 if ( cursor->index() > 0 && !cursor->parag()->at( cursor->index()-1 )->c.isSpace() ) 1774 if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() )
1748 c1.gotoPreviousWord(); 1775 c1.gotoPreviousWord();
1749 if ( !cursor->parag()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) 1776 if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() )
1750 c2.gotoNextWord(); 1777 c2.gotoNextWord();
1751 1778
1752 doc->setSelectionStart( QTextDocument::Standard, &c1 ); 1779 doc->setSelectionStart( QTextDocument::Standard, c1 );
1753 doc->setSelectionEnd( QTextDocument::Standard, &c2 ); 1780 doc->setSelectionEnd( QTextDocument::Standard, c2 );
1754 1781
1755 *cursor = c2; 1782 *cursor = c2;
1756 1783
1757 repaintChanged(); 1784 repaintChanged();
1758 1785
1759 inDoubleClick = TRUE; 1786 inDoubleClick = TRUE;
1760 mousePressed = TRUE; 1787 mousePressed = TRUE;
1761} 1788}
1762 1789
1763#ifndef QT_NO_DRAGANDDROP 1790#ifndef QT_NO_DRAGANDDROP
1764 1791
1765/*! \reimp */ 1792/*! \reimp */
1766 1793
1767void QTextEdit::contentsDragEnterEvent( QDragEnterEvent *e ) 1794void QTextEdit::contentsDragEnterEvent( QDragEnterEvent *e )
1768{ 1795{
1769 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) { 1796 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) {
1770 e->ignore(); 1797 e->ignore();
1771 return; 1798 return;
1772 } 1799 }
1773 e->acceptAction(); 1800 e->acceptAction();
1774 inDnD = TRUE; 1801 inDnD = TRUE;
1775} 1802}
1776 1803
1777/*! \reimp */ 1804/*! \reimp */
1778 1805
1779void QTextEdit::contentsDragMoveEvent( QDragMoveEvent *e ) 1806void QTextEdit::contentsDragMoveEvent( QDragMoveEvent *e )
1780{ 1807{
1781 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) { 1808 if ( isReadOnly() || !QTextDrag::canDecode( e ) ) {
1782 e->ignore(); 1809 e->ignore();
1783 return; 1810 return;
1784 } 1811 }
1785 drawCursor( FALSE ); 1812 drawCursor( FALSE );
1786 placeCursor( e->pos(), cursor ); 1813 placeCursor( e->pos(), cursor );
1787 drawCursor( TRUE ); 1814 drawCursor( TRUE );
1788 e->acceptAction(); 1815 e->acceptAction();
1789} 1816}
1790 1817
1791/*! \reimp */ 1818/*! \reimp */
1792 1819
1793void QTextEdit::contentsDragLeaveEvent( QDragLeaveEvent * ) 1820void QTextEdit::contentsDragLeaveEvent( QDragLeaveEvent * )
1794{ 1821{
1795 inDnD = FALSE; 1822 inDnD = FALSE;
1796} 1823}
1797 1824
1798/*! \reimp */ 1825/*! \reimp */
1799 1826
1800void QTextEdit::contentsDropEvent( QDropEvent *e ) 1827void QTextEdit::contentsDropEvent( QDropEvent *e )
1801{ 1828{
1802 if ( isReadOnly() ) 1829 if ( isReadOnly() )
1803 return; 1830 return;
1804 inDnD = FALSE; 1831 inDnD = FALSE;
1805 e->acceptAction(); 1832 e->acceptAction();
1806 QString text; 1833 QString text;
1807 bool intern = FALSE; 1834 bool intern = FALSE;
1808 if ( QTextDrag::decode( e, text ) ) { 1835 if ( QTextDrag::decode( e, text ) ) {
1809 if ( ( e->source() == this || 1836 bool hasSel = doc->hasSelection( QTextDocument::Standard );
1810 e->source() == viewport() ) && 1837 bool internalDrag = e->source() == this || e->source() == viewport();
1811 e->action() == QDropEvent::Move ) { 1838 int dropId, dropIndex;
1839 QTextCursor insertCursor = *cursor;
1840 dropId = cursor->paragraph()->paragId();
1841 dropIndex = cursor->index();
1842 if ( hasSel && internalDrag ) {
1843 QTextCursor c1, c2;
1844 int selStartId, selStartIndex;
1845 int selEndId, selEndIndex;
1846 c1 = doc->selectionStartCursor( QTextDocument::Standard );
1847 c1.restoreState();
1848 c2 = doc->selectionEndCursor( QTextDocument::Standard );
1849 c2.restoreState();
1850 selStartId = c1.paragraph()->paragId();
1851 selStartIndex = c1.index();
1852 selEndId = c2.paragraph()->paragId();
1853 selEndIndex = c2.index();
1854 if ( ( ( dropId > selStartId ) ||
1855 ( dropId == selStartId && dropIndex > selStartIndex ) ) &&
1856 ( ( dropId < selEndId ) ||
1857 ( dropId == selEndId && dropIndex <= selEndIndex ) ) )
1858 insertCursor = c1;
1859 if ( dropId == selEndId && dropIndex > selEndIndex ) {
1860 insertCursor = c1;
1861 if ( selStartId == selEndId ) {
1862 insertCursor.setIndex( dropIndex -
1863 ( selEndIndex - selStartIndex ) );
1864 } else {
1865 insertCursor.setIndex( dropIndex - selEndIndex +
1866 selStartIndex );
1867 }
1868 }
1869 }
1870
1871 if ( internalDrag && e->action() == QDropEvent::Move ) {
1812 removeSelectedText(); 1872 removeSelectedText();
1813 intern = TRUE; 1873 intern = TRUE;
1814 } else { 1874 } else {
1815 doc->removeSelection( QTextDocument::Standard ); 1875 doc->removeSelection( QTextDocument::Standard );
1816#ifndef QT_NO_CURSOR 1876#ifndef QT_NO_CURSOR
1817 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 1877 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
1818#endif 1878#endif
1819 } 1879 }
1820 drawCursor( FALSE ); 1880 drawCursor( FALSE );
1821 placeCursor( e->pos(), cursor ); 1881 cursor->setParagraph( insertCursor.paragraph() );
1882 cursor->setIndex( insertCursor.index() );
1822 drawCursor( TRUE ); 1883 drawCursor( TRUE );
1823 if ( !cursor->nestedDepth() ) { 1884 if ( !cursor->nestedDepth() ) {
1824 insert( text, FALSE, TRUE, FALSE ); 1885 insert( text, FALSE, TRUE, FALSE );
1825 } else { 1886 } else {
1826 if ( intern ) 1887 if ( intern )
1827 undo(); 1888 undo();
1828 e->ignore(); 1889 e->ignore();
1829 } 1890 }
1830 } 1891 }
1831} 1892}
1832 1893
1833#endif 1894#endif
1834 1895
1835void QTextEdit::autoScrollTimerDone() 1896void QTextEdit::autoScrollTimerDone()
1836{ 1897{
1837 if ( mousePressed ) 1898 if ( mousePressed )
1838 handleMouseMove( viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ) ); 1899 handleMouseMove( viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ) );
1839} 1900}
1840 1901
1841void QTextEdit::handleMouseMove( const QPoint& pos ) 1902void QTextEdit::handleMouseMove( const QPoint& pos )
1842{ 1903{
1843 if ( !mousePressed ) 1904 if ( !mousePressed )
1844 return; 1905 return;
1845 1906
1846 if ( !scrollTimer->isActive() && pos.y() < contentsY() || pos.y() > contentsY() + visibleHeight() ) 1907 if ( !scrollTimer->isActive() && pos.y() < contentsY() || pos.y() > contentsY() + visibleHeight() )
1847 scrollTimer->start( 100, FALSE ); 1908 scrollTimer->start( 100, FALSE );
1848 else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() ) 1909 else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() )
1849 scrollTimer->stop(); 1910 scrollTimer->stop();
1850 1911
1851 drawCursor( FALSE ); 1912 drawCursor( FALSE );
1852 QTextCursor oldCursor = *cursor; 1913 QTextCursor oldCursor = *cursor;
1853 1914
1854 placeCursor( pos ); 1915 placeCursor( pos );
1855 1916
1856 if ( inDoubleClick ) { 1917 if ( inDoubleClick ) {
1857 QTextCursor cl = *cursor; 1918 QTextCursor cl = *cursor;
1858 cl.gotoPreviousWord(); 1919 cl.gotoPreviousWord();
1859 QTextCursor cr = *cursor; 1920 QTextCursor cr = *cursor;
1860 cr.gotoNextWord(); 1921 cr.gotoNextWord();
1861 1922
1862 int diff = QABS( oldCursor.parag()->at( oldCursor.index() )->x - mousePos.x() ); 1923 int diff = QABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() );
1863 int ldiff = QABS( cl.parag()->at( cl.index() )->x - mousePos.x() ); 1924 int ldiff = QABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() );
1864 int rdiff = QABS( cr.parag()->at( cr.index() )->x - mousePos.x() ); 1925 int rdiff = QABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() );
1865 1926
1866 1927
1867 if ( cursor->parag()->lineStartOfChar( cursor->index() ) != 1928 if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) !=
1868 oldCursor.parag()->lineStartOfChar( oldCursor.index() ) ) 1929 oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) )
1869 diff = 0xFFFFFF; 1930 diff = 0xFFFFFF;
1870 1931
1871 if ( rdiff < diff && rdiff < ldiff ) 1932 if ( rdiff < diff && rdiff < ldiff )
1872 *cursor = cr; 1933 *cursor = cr;
1873 else if ( ldiff < diff && ldiff < rdiff ) 1934 else if ( ldiff < diff && ldiff < rdiff )
1874 *cursor = cl; 1935 *cursor = cl;
1875 else 1936 else
1876 *cursor = oldCursor; 1937 *cursor = oldCursor;
1877 1938
1878 } 1939 }
1879 ensureCursorVisible(); 1940 ensureCursorVisible();
1880 1941
1881 bool redraw = FALSE; 1942 bool redraw = FALSE;
1882 if ( doc->hasSelection( QTextDocument::Standard ) ) { 1943 if ( doc->hasSelection( QTextDocument::Standard ) ) {
1883 redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; 1944 redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw;
1884 } 1945 }
1885 1946
1886 if ( !redraw ) { 1947 if ( !redraw ) {
1887 drawCursor( TRUE ); 1948 drawCursor( TRUE );
1888 } else { 1949 } else {
1889 repaintChanged(); 1950 repaintChanged();
1890 drawCursor( TRUE ); 1951 drawCursor( TRUE );
1891 } 1952 }
1892 1953
1893 if ( currentFormat && currentFormat->key() != cursor->parag()->at( cursor->index() )->format()->key() ) { 1954 if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) {
1894 currentFormat->removeRef(); 1955 currentFormat->removeRef();
1895 currentFormat = doc->formatCollection()->format( cursor->parag()->at( cursor->index() )->format() ); 1956 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() );
1896 if ( currentFormat->isMisspelled() ) { 1957 if ( currentFormat->isMisspelled() ) {
1897 currentFormat->removeRef(); 1958 currentFormat->removeRef();
1898 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 1959 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
1899 } 1960 }
1900 emit currentFontChanged( currentFormat->font() ); 1961 emit currentFontChanged( currentFormat->font() );
1901 emit currentColorChanged( currentFormat->color() ); 1962 emit currentColorChanged( currentFormat->color() );
1902 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 1963 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
1903 } 1964 }
1904 1965
1905 if ( currentAlignment != cursor->parag()->alignment() ) { 1966 if ( currentAlignment != cursor->paragraph()->alignment() ) {
1906 currentAlignment = cursor->parag()->alignment(); 1967 currentAlignment = cursor->paragraph()->alignment();
1907 block_set_alignment = TRUE; 1968 block_set_alignment = TRUE;
1908 emit currentAlignmentChanged( currentAlignment ); 1969 emit currentAlignmentChanged( currentAlignment );
1909 block_set_alignment = FALSE; 1970 block_set_alignment = FALSE;
1910 } 1971 }
1911} 1972}
1912 1973
1913/*! 1974/*!
1914 \fn void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) 1975 \fn void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c )
1915 Places the cursor \a c at the character which is closest to position 1976 Places the cursor \a c at the character which is closest to position
1916 \a pos (in contents coordinates). If \a c is 0, the default text 1977 \a pos (in contents coordinates). If \a c is 0, the default text
1917 cursor is used. 1978 cursor is used.
1918 1979
1919 \sa setCursorPosition() 1980 \sa setCursorPosition()
1920*/ 1981*/
1921 1982
1922void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link ) 1983void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link )
1923{ 1984{
1924 if ( !c ) 1985 if ( !c )
1925 c = cursor; 1986 c = cursor;
1926 1987
1927 c->restoreState(); 1988 c->restoreState();
1928 QTextParag *s = doc->firstParag(); 1989 QTextParagraph *s = doc->firstParagraph();
1929 c->place( pos, s, link ); 1990 c->place( pos, s, link );
1991 updateMicroFocusHint();
1992}
1993
1994
1995void QTextEdit::updateMicroFocusHint()
1996{
1997 QTextCursor c( *cursor );
1998 if ( d->preeditStart != -1 )
1999 c.setIndex( d->preeditStart );
2000
1930 if ( hasFocus() || viewport()->hasFocus() ) { 2001 if ( hasFocus() || viewport()->hasFocus() ) {
1931 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 2002 int h = c.paragraph()->lineHeightOfChar( cursor->index() );
1932 if ( !readonly ) { 2003 if ( !readonly ) {
1933 QFont f = cursor->parag()->at( cursor->index() )->format()->font(); 2004 QFont f = c.paragraph()->at( c.index() )->format()->font();
1934 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), 2005 setMicroFocusHint( c.x() - contentsX() + frameWidth(),
1935 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); 2006 c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
1936 } 2007 }
1937 } 2008 }
1938} 2009}
1939 2010
2011
2012
1940void QTextEdit::formatMore() 2013void QTextEdit::formatMore()
1941{ 2014{
1942 if ( !lastFormatted ) 2015 if ( !lastFormatted )
1943 return; 2016 return;
1944 2017
1945 int bottom = contentsHeight(); 2018 int bottom = contentsHeight();
1946 int lastBottom = -1; 2019 int lastBottom = -1;
1947 int to = !sender() ? 2 : 20; 2020 int to = 20;
1948 bool firstVisible = FALSE; 2021 bool firstVisible = FALSE;
1949 QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2022 QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
1950 for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) { 2023 for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) {
1951 lastFormatted->format(); 2024 lastFormatted->format();
1952 if ( i == 0 ) 2025 if ( i == 0 )
1953 firstVisible = lastFormatted->rect().intersects( cr ); 2026 firstVisible = lastFormatted->rect().intersects( cr );
1954 else if ( firstVisible ) 2027 else if ( firstVisible )
1955 firstVisible = lastFormatted->rect().intersects( cr ); 2028 firstVisible = lastFormatted->rect().intersects( cr );
1956 bottom = QMAX( bottom, lastFormatted->rect().top() + 2029 bottom = QMAX( bottom, lastFormatted->rect().top() +
1957 lastFormatted->rect().height() ); 2030 lastFormatted->rect().height() );
1958 lastBottom = lastFormatted->rect().top() + lastFormatted->rect().height(); 2031 lastBottom = lastFormatted->rect().top() + lastFormatted->rect().height();
1959 lastFormatted = lastFormatted->next(); 2032 lastFormatted = lastFormatted->next();
1960 if ( lastFormatted ) 2033 if ( lastFormatted )
1961 lastBottom = -1; 2034 lastBottom = -1;
1962 } 2035 }
1963 2036
1964 if ( bottom > contentsHeight() ) 2037 if ( bottom > contentsHeight() ) {
1965 resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) ); 2038 resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) );
1966 else if ( lastBottom != -1 && lastBottom < contentsHeight() ) 2039 } else if ( lastBottom != -1 && lastBottom < contentsHeight() ) {
1967 resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); 2040 resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) );
2041 if ( contentsHeight() < visibleHeight() )
2042 updateContents( 0, contentsHeight(), visibleWidth(),
2043 visibleHeight() - contentsHeight() );
2044 }
1968 2045
1969 if ( lastFormatted ) 2046 if ( lastFormatted )
1970 formatTimer->start( interval, TRUE ); 2047 formatTimer->start( interval, TRUE );
1971 else 2048 else
1972 interval = QMAX( 0, interval ); 2049 interval = QMAX( 0, interval );
1973} 2050}
1974 2051
1975void QTextEdit::doResize() 2052void QTextEdit::doResize()
1976{ 2053{
1977 if ( wrapMode == FixedPixelWidth ) 2054 if ( wrapMode == FixedPixelWidth )
1978 return; 2055 return;
1979 doc->setMinimumWidth( -1 ); 2056 doc->setMinimumWidth( -1 );
1980 resizeContents( 0, 0 ); 2057 resizeContents( 0, 0 );
1981 doc->setWidth( visibleWidth() ); 2058 doc->setWidth( visibleWidth() );
1982 doc->invalidate(); 2059 doc->invalidate();
1983 lastFormatted = doc->firstParag(); 2060 lastFormatted = doc->firstParagraph();
1984 interval = 0; 2061 interval = 0;
1985 formatMore(); 2062 formatMore();
1986 repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE ); 2063 repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE );
1987} 2064}
1988 2065
1989/*! \internal */ 2066/*! \internal */
1990 2067
1991void QTextEdit::doChangeInterval() 2068void QTextEdit::doChangeInterval()
1992{ 2069{
1993 interval = 0; 2070 interval = 0;
1994} 2071}
1995 2072
1996/*! \reimp */ 2073/*! \reimp */
1997 2074
1998bool QTextEdit::eventFilter( QObject *o, QEvent *e ) 2075bool QTextEdit::eventFilter( QObject *o, QEvent *e )
1999{ 2076{
2000 if ( o == this || o == viewport() ) { 2077 if ( o == this || o == viewport() ) {
2001 if ( e->type() == QEvent::FocusIn ) { 2078 if ( e->type() == QEvent::FocusIn ) {
2002 blinkTimer->start( QApplication::cursorFlashTime() / 2 ); 2079 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
2003 drawCursor( TRUE ); 2080 drawCursor( TRUE );
2004 2081 updateMicroFocusHint();
2005 if ( !readonly ) {
2006 // make sure the micro focus hint is updated...
2007 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2008 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2009 cursor->y() + cursor->parag()->rect().y() -
2010 contentsY() + frameWidth(), 0,
2011 cursor->parag()->lineHeightOfChar( cursor->index() ),
2012 TRUE );
2013 }
2014 } else if ( e->type() == QEvent::FocusOut ) { 2082 } else if ( e->type() == QEvent::FocusOut ) {
2015 blinkTimer->stop(); 2083 blinkTimer->stop();
2016 drawCursor( FALSE ); 2084 drawCursor( FALSE );
2017 } 2085 }
2018 } 2086 }
2019 2087
2020 return QScrollView::eventFilter( o, e ); 2088 return QScrollView::eventFilter( o, e );
2021} 2089}
2022 2090
2023/*! 2091/*! Inserts \a text at the current cursor position. If \a indent is
2024 Inserts \a text at the current cursor position. If \a indent is TRUE, 2092 TRUE, the paragraph is re-indented. If \a checkNewLine is TRUE,
2025 the paragraph is re-indented. If \a checkNewLine is TRUE, newline 2093 newline characters in \a text result in hard line breaks (i.e. new
2026 characters in \a text result in hard line breaks (i.e. new 2094 paragraphs). If \a checkNewLine is FALSE and there are newlines in
2027 paragraphs). If \a checkNewLine is FALSE the behaviour of the editor 2095 \a text, the behavior is undefined. If \a checkNewLine is FALSE the
2028 is undefined if the \a text contains newlines. If \a removeSelected is 2096 behaviour of the editor is undefined if the \a text contains
2029 TRUE, any selected text (in selection 0) is removed before the text is 2097 newlines. If \a removeSelected is TRUE, any selected text (in
2030 inserted. 2098 selection 0) is removed before the text is inserted.
2031 2099
2032 \sa paste() pasteSubType() 2100 \sa paste() pasteSubType()
2033*/ 2101*/
2034 2102
2035void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected ) 2103void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected )
2036{ 2104{
2037 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough 2105 if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough
2038 return; 2106 return;
2039 QString txt( text ); 2107 QString txt( text );
2040 drawCursor( FALSE ); 2108 drawCursor( FALSE );
2041 if ( !isReadOnly() && doc->hasSelection( QTextDocument::Standard ) && removeSelected ) 2109 if ( !isReadOnly() && doc->hasSelection( QTextDocument::Standard ) && removeSelected )
2042 removeSelectedText(); 2110 removeSelectedText();
2043 QTextCursor c2 = *cursor; 2111 QTextCursor c2 = *cursor;
2044 int oldLen = 0; 2112 int oldLen = 0;
2045 2113
2046 if ( undoEnabled && !isReadOnly() ) { 2114 if ( undoEnabled && !isReadOnly() ) {
2047 checkUndoRedoInfo( UndoRedoInfo::Insert ); 2115 checkUndoRedoInfo( UndoRedoInfo::Insert );
2048 if ( !undoRedoInfo.valid() ) { 2116 if ( !undoRedoInfo.valid() ) {
2049 undoRedoInfo.id = cursor->parag()->paragId(); 2117 undoRedoInfo.id = cursor->paragraph()->paragId();
2050 undoRedoInfo.index = cursor->index(); 2118 undoRedoInfo.index = cursor->index();
2051 undoRedoInfo.d->text = QString::null; 2119 undoRedoInfo.d->text = QString::null;
2052 } 2120 }
2053 oldLen = undoRedoInfo.d->text.length(); 2121 oldLen = undoRedoInfo.d->text.length();
2054 } 2122 }
2055 2123
2056 lastFormatted = checkNewLine && cursor->parag()->prev() ? 2124 lastFormatted = checkNewLine && cursor->paragraph()->prev() ?
2057 cursor->parag()->prev() : cursor->parag(); 2125 cursor->paragraph()->prev() : cursor->paragraph();
2058 QTextCursor oldCursor = *cursor; 2126 QTextCursor oldCursor = *cursor;
2059 cursor->insert( txt, checkNewLine ); 2127 cursor->insert( txt, checkNewLine );
2060 if ( doc->useFormatCollection() ) { 2128 if ( doc->useFormatCollection() ) {
2061 doc->setSelectionStart( QTextDocument::Temp, &oldCursor ); 2129 doc->setSelectionStart( QTextDocument::Temp, oldCursor );
2062 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 2130 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
2063 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); 2131 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
2064 doc->removeSelection( QTextDocument::Temp ); 2132 doc->removeSelection( QTextDocument::Temp );
2065 } 2133 }
2066 2134
2067 if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) ) 2135 if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) )
2068 cursor->indent(); 2136 cursor->indent();
2069 formatMore(); 2137 formatMore();
2070 repaintChanged(); 2138 repaintChanged();
2071 ensureCursorVisible(); 2139 ensureCursorVisible();
2072 drawCursor( TRUE ); 2140 drawCursor( TRUE );
2073 2141
2074 if ( undoEnabled && !isReadOnly() ) { 2142 if ( undoEnabled && !isReadOnly() ) {
2075 undoRedoInfo.d->text += txt; 2143 undoRedoInfo.d->text += txt;
2076 if ( !doc->preProcessor() ) { 2144 if ( !doc->preProcessor() ) {
2077 for ( int i = 0; i < (int)txt.length(); ++i ) { 2145 for ( int i = 0; i < (int)txt.length(); ++i ) {
2078 if ( txt[ i ] != '\n' && c2.parag()->at( c2.index() )->format() ) { 2146 if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) {
2079 c2.parag()->at( c2.index() )->format()->addRef(); 2147 c2.paragraph()->at( c2.index() )->format()->addRef();
2080 undoRedoInfo.d->text.setFormat( oldLen + i, c2.parag()->at( c2.index() )->format(), TRUE ); 2148 undoRedoInfo.d->text.setFormat( oldLen + i, c2.paragraph()->at( c2.index() )->format(), TRUE );
2081 } 2149 }
2082 c2.gotoNextLetter(); 2150 c2.gotoNextLetter();
2083 } 2151 }
2084 } 2152 }
2085 } 2153 }
2086 2154
2087 setModified();
2088 emit textChanged();
2089 if ( !removeSelected ) { 2155 if ( !removeSelected ) {
2090 doc->setSelectionStart( QTextDocument::Standard, &oldCursor ); 2156 doc->setSelectionStart( QTextDocument::Standard, oldCursor );
2091 doc->setSelectionEnd( QTextDocument::Standard, cursor ); 2157 doc->setSelectionEnd( QTextDocument::Standard, *cursor );
2092 repaintChanged(); 2158 repaintChanged();
2093 } 2159 }
2094 if ( hasFocus() || viewport()->hasFocus() ) { 2160 updateMicroFocusHint();
2095 int h = cursor->parag()->lineHeightOfChar( cursor->index() ); 2161 setModified();
2096 if ( !readonly ) { 2162 emit textChanged();
2097 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2098 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2099 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2100 }
2101 }
2102} 2163}
2103 2164
2104/*! Inserts \a text in the paragraph \a para and position \a index */ 2165/*! Inserts \a text in the paragraph \a para and position \a index */
2105 2166
2106void QTextEdit::insertAt( const QString &text, int para, int index ) 2167void QTextEdit::insertAt( const QString &text, int para, int index )
2107{ 2168{
2108 QTextParag *p = doc->paragAt( para ); 2169 removeSelection( QTextDocument::Standard );
2170 QTextParagraph *p = doc->paragAt( para );
2109 if ( !p ) 2171 if ( !p )
2110 return; 2172 return;
2111 QTextCursor tmp = *cursor; 2173 QTextCursor tmp = *cursor;
2112 cursor->setParag( p ); 2174 cursor->setParagraph( p );
2113 cursor->setIndex( index ); 2175 cursor->setIndex( index );
2114 insert( text, FALSE, TRUE, FALSE ); 2176 insert( text, FALSE, TRUE, FALSE );
2115 *cursor = tmp; 2177 *cursor = tmp;
2116 removeSelection( QTextDocument::Standard ); 2178 removeSelection( QTextDocument::Standard );
2117} 2179}
2118 2180
2119/*! Inserts \a text as the paragraph at position \a para. If \a para 2181/*! Inserts \a text as the paragraph at position \a para. If \a para
2120 is -1, the text is appended. 2182 is -1, the text is appended.
2121*/ 2183*/
2122 2184
2123void QTextEdit::insertParagraph( const QString &text, int para ) 2185void QTextEdit::insertParagraph( const QString &text, int para )
2124{ 2186{
2125 QTextParag *p = doc->paragAt( para ); 2187 QTextParagraph *p = doc->paragAt( para );
2126 if ( p ) { 2188 if ( p ) {
2127 QTextCursor tmp( doc ); 2189 QTextCursor tmp( doc );
2128 tmp.setParag( p ); 2190 tmp.setParagraph( p );
2129 tmp.setIndex( 0 ); 2191 tmp.setIndex( 0 );
2130 tmp.insert( text, TRUE ); 2192 tmp.insert( text, TRUE );
2131 tmp.splitAndInsertEmptyParag(); 2193 tmp.splitAndInsertEmptyParagraph();
2132 repaintChanged(); 2194 repaintChanged();
2133 } else { 2195 } else {
2134 append( text ); 2196 append( text );
2135 } 2197 }
2136} 2198}
2137 2199
2138/*! Removes the paragraph \a para */ 2200/*! Removes the paragraph \a para */
2139 2201
2140void QTextEdit::removeParagraph( int para ) 2202void QTextEdit::removeParagraph( int para )
2141{ 2203{
2142 QTextParag *p = doc->paragAt( para ); 2204 QTextParagraph *p = doc->paragAt( para );
2143 if ( !p ) 2205 if ( !p )
2144 return; 2206 return;
2145 for ( int i = 0; i < doc->numSelections(); ++i ) 2207 for ( int i = 0; i < doc->numSelections(); ++i )
2146 doc->removeSelection( i ); 2208 doc->removeSelection( i );
2147 2209
2148 if ( p == doc->firstParag() && p == doc->lastParag() ) { 2210 if ( p == doc->firstParagraph() && p == doc->lastParagraph() ) {
2149 p->remove( 0, p->length() - 1 ); 2211 p->remove( 0, p->length() - 1 );
2150 repaintChanged(); 2212 repaintChanged();
2151 return; 2213 return;
2152 } 2214 }
2153 drawCursor( FALSE ); 2215 drawCursor( FALSE );
2154 bool resetCursor = cursor->parag() == p; 2216 bool resetCursor = cursor->paragraph() == p;
2155 if ( p->prev() ) 2217 if ( p->prev() )
2156 p->prev()->setNext( p->next() ); 2218 p->prev()->setNext( p->next() );
2157 else 2219 else
2158 doc->setFirstParag( p->next() ); 2220 doc->setFirstParagraph( p->next() );
2159 if ( p->next() ) 2221 if ( p->next() )
2160 p->next()->setPrev( p->prev() ); 2222 p->next()->setPrev( p->prev() );
2161 else 2223 else
2162 doc->setLastParag( p->prev() ); 2224 doc->setLastParagraph( p->prev() );
2163 QTextParag *start = p->next(); 2225 QTextParagraph *start = p->next();
2164 int h = p->rect().height(); 2226 int h = p->rect().height();
2165 delete p; 2227 delete p;
2166 p = start; 2228 p = start;
2167 int dy = -h; 2229 int dy = -h;
2168 while ( p ) { 2230 while ( p ) {
2169 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); 2231 p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 );
2170 p->move( dy ); 2232 p->move( dy );
2171 p->invalidate( 0 ); 2233 p->invalidate( 0 );
2172 p->setEndState( -1 ); 2234 p->setEndState( -1 );
2173 p = p->next(); 2235 p = p->next();
2174 } 2236 }
2175 2237
2176 if ( resetCursor ) { 2238 if ( resetCursor ) {
2177 cursor->setParag( doc->firstParag() ); 2239 cursor->setParagraph( doc->firstParagraph() );
2178 cursor->setIndex( 0 ); 2240 cursor->setIndex( 0 );
2179 } 2241 }
2180 repaintChanged(); 2242 repaintChanged();
2181 drawCursor( TRUE ); 2243 drawCursor( TRUE );
2182} 2244}
2183 2245
2184/*! 2246/*!
2185 Undoes the last operation. 2247 Undoes the last operation.
2186 2248
2187 If there is no operation to undo, e.g. there is no undo step in the 2249 If there is no operation to undo, e.g. there is no undo step in the
2188 undo/redo history, nothing happens. 2250 undo/redo history, nothing happens.
2189 2251
2190 \sa undoAvailable() redo() undoDepth() 2252 \sa undoAvailable() redo() undoDepth()
2191*/ 2253*/
2192 2254
2193void QTextEdit::undo() 2255void QTextEdit::undo()
2194{ 2256{
2195 // XXX FIXME The next line is here because there may be a command 2257 // XXX FIXME The next line is here because there may be a command
2196 // that needs to be 'flushed'. The FIXME is because I am not 2258 // that needs to be 'flushed'. The FIXME is because I am not
2197 // 100% certain this is the right call to do this. 2259 // 100% certain this is the right call to do this.
2198 clearUndoRedo(); 2260 clearUndoRedo();
2199 if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled ) 2261 if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled )
2200 return; 2262 return;
2201 2263
2202 for ( int i = 0; i < (int)doc->numSelections(); ++i ) 2264 for ( int i = 0; i < (int)doc->numSelections(); ++i )
2203 doc->removeSelection( i ); 2265 doc->removeSelection( i );
2204 2266
2205#ifndef QT_NO_CURSOR 2267#ifndef QT_NO_CURSOR
2206 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 2268 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
2207#endif 2269#endif
2208 2270
2209 clearUndoRedo(); 2271 clearUndoRedo();
2210 drawCursor( FALSE ); 2272 drawCursor( FALSE );
2211 QTextCursor *c = doc->undo( cursor ); 2273 QTextCursor *c = doc->undo( cursor );
2212 if ( !c ) { 2274 if ( !c ) {
2213 drawCursor( TRUE ); 2275 drawCursor( TRUE );
2214 return; 2276 return;
2215 } 2277 }
2216 lastFormatted = 0; 2278 lastFormatted = 0;
2217 ensureCursorVisible(); 2279 ensureCursorVisible();
2218 repaintChanged(); 2280 repaintChanged();
2219 drawCursor( TRUE ); 2281 drawCursor( TRUE );
2282 updateMicroFocusHint();
2220 setModified(); 2283 setModified();
2221 emit textChanged(); 2284 emit textChanged();
2222 if ( hasFocus() || viewport()->hasFocus() ) {
2223 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2224 if ( !readonly ) {
2225 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2226 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2227 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2228 }
2229 }
2230} 2285}
2231 2286
2232/*! 2287/*!
2233 Redoes the last operation. 2288 Redoes the last operation.
2234 2289
2235 If there is no operation to redo, e.g. there is no redo step in the 2290 If there is no operation to redo, e.g. there is no redo step in the
2236 undo/redo history, nothing happens. 2291 undo/redo history, nothing happens.
2237 2292
2238 \sa redoAvailable() undo() undoDepth() 2293 \sa redoAvailable() undo() undoDepth()
2239*/ 2294*/
2240 2295
2241void QTextEdit::redo() 2296void QTextEdit::redo()
2242{ 2297{
2243 if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled ) 2298 if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled )
2244 return; 2299 return;
2245 2300
2246 for ( int i = 0; i < (int)doc->numSelections(); ++i ) 2301 for ( int i = 0; i < (int)doc->numSelections(); ++i )
2247 doc->removeSelection( i ); 2302 doc->removeSelection( i );
2248 2303
2249#ifndef QT_NO_CURSOR 2304#ifndef QT_NO_CURSOR
2250 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 2305 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
2251#endif 2306#endif
2252 2307
2253 clearUndoRedo(); 2308 clearUndoRedo();
2254 drawCursor( FALSE ); 2309 drawCursor( FALSE );
2255 QTextCursor *c = doc->redo( cursor ); 2310 QTextCursor *c = doc->redo( cursor );
2256 if ( !c ) { 2311 if ( !c ) {
2257 drawCursor( TRUE ); 2312 drawCursor( TRUE );
2258 return; 2313 return;
2259 } 2314 }
2260 lastFormatted = 0; 2315 lastFormatted = 0;
2261 ensureCursorVisible(); 2316 ensureCursorVisible();
2262 repaintChanged(); 2317 repaintChanged();
2263 ensureCursorVisible(); 2318 ensureCursorVisible();
2264 drawCursor( TRUE ); 2319 drawCursor( TRUE );
2320 updateMicroFocusHint();
2265 setModified(); 2321 setModified();
2266 emit textChanged(); 2322 emit textChanged();
2267 if ( hasFocus() || viewport()->hasFocus() ) {
2268 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2269 if ( !readonly ) {
2270 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2271 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2272 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2273 }
2274 }
2275} 2323}
2276 2324
2277/*! 2325/*!
2278 Pastes the text from the clipboard into the text edit at the current 2326 Pastes the text from the clipboard into the text edit at the current
2279 cursor position. Only plain text is pasted. 2327 cursor position. Only plain text is pasted.
2280 2328
2281 If there is no text in the clipboard nothing happens. 2329 If there is no text in the clipboard nothing happens.
2282 2330
2283 \sa pasteSubType() cut() QTextEdit::copy() 2331 \sa pasteSubType() cut() QTextEdit::copy()
2284*/ 2332*/
2285 2333
2286void QTextEdit::paste() 2334void QTextEdit::paste()
2287{ 2335{
2288#ifndef QT_NO_CLIPBOARD 2336#ifndef QT_NO_CLIPBOARD
2289 if ( isReadOnly() ) 2337 if ( isReadOnly() )
2290 return; 2338 return;
2291 pasteSubType( "plain" ); 2339 pasteSubType( "plain" );
2292 if ( hasFocus() || viewport()->hasFocus() ) { 2340 updateMicroFocusHint();
2293 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2294 if ( !readonly ) {
2295 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2296 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2297 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2298 }
2299 }
2300#endif 2341#endif
2301} 2342}
2302 2343
2303void QTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t ) 2344void QTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t )
2304{ 2345{
2305 if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) { 2346 if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) {
2306 clearUndoRedo(); 2347 clearUndoRedo();
2307 } 2348 }
2308 undoRedoInfo.type = t; 2349 undoRedoInfo.type = t;
2309} 2350}
2310 2351
2311/*! Repaints any paragraphs that have changed. 2352/*! Repaints any paragraphs that have changed.
2312 2353
2313 Although used extensively internally you shouldn't need to call this 2354 Although used extensively internally you shouldn't need to call this
2314 yourself. 2355 yourself.
2315*/ 2356*/
2316 2357
2317void QTextEdit::repaintChanged() 2358void QTextEdit::repaintChanged()
2318{ 2359{
2319 if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() ) 2360 if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() )
2320 return; 2361 return;
2321 QPainter p( viewport() ); 2362 QPainter p( viewport() );
2322 p.translate( -contentsX(), -contentsY() ); 2363 p.translate( -contentsX(), -contentsY() );
2323 paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2364 paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() );
2324} 2365}
2325 2366
2326/*! 2367/*!
2327 Copies the selected text (from selection 0) to the clipboard and 2368 Copies the selected text (from selection 0) to the clipboard and
2328 deletes it from the text edit. 2369 deletes it from the text edit.
2329 2370
2330 If there is no selected text (in selection 0) nothing happens. 2371 If there is no selected text (in selection 0) nothing happens.
2331 2372
2332 \sa QTextEdit::copy() paste() pasteSubType() 2373 \sa QTextEdit::copy() paste() pasteSubType()
2333*/ 2374*/
2334 2375
2335void QTextEdit::cut() 2376void QTextEdit::cut()
2336{ 2377{
2337 if ( isReadOnly() ) 2378 if ( isReadOnly() )
2338 return; 2379 return;
2339 2380
2340 if ( doc->hasSelection( QTextDocument::Standard ) ) { 2381 QString t;
2341 doc->copySelectedText( QTextDocument::Standard ); 2382 if ( doc->hasSelection( QTextDocument::Standard ) &&
2383 !( t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ) ).isEmpty() ) {
2384 QApplication::clipboard()->setText( t );
2342 removeSelectedText(); 2385 removeSelectedText();
2343 } 2386 }
2344 if ( hasFocus() || viewport()->hasFocus() ) { 2387 updateMicroFocusHint();
2345 int h = cursor->parag()->lineHeightOfChar( cursor->index() );
2346 if ( !readonly ) {
2347 QFont f = cursor->parag()->at( cursor->index() )->format()->font();
2348 setMicroFocusHint( cursor->x() - contentsX() + frameWidth(),
2349 cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE );
2350 }
2351 }
2352} 2388}
2353 2389
2354/*! Copies any selected text (from selection 0) to the clipboard. 2390/*! Copies any selected text (from selection 0) to the clipboard.
2355 2391
2356 \sa hasSelectedText() copyAvailable() 2392 \sa hasSelectedText() copyAvailable()
2357 */ 2393 */
2358 2394
2359void QTextEdit::copy() 2395void QTextEdit::copy()
2360{ 2396{
2361 if ( !doc->selectedText( QTextDocument::Standard ).isEmpty() ) 2397 QString t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy );
2362 doc->copySelectedText( QTextDocument::Standard ); 2398 if ( doc->hasSelection( QTextDocument::Standard ) &&
2399 !t.isEmpty() && t.simplifyWhiteSpace() != "<selstart/>" )
2400 QApplication::clipboard()->setText( t );
2363} 2401}
2364 2402
2365/*! 2403/*!
2366 Re-indents the current paragraph. 2404 Re-indents the current paragraph.
2367*/ 2405*/
2368 2406
2369void QTextEdit::indent() 2407void QTextEdit::indent()
2370{ 2408{
2371 if ( isReadOnly() ) 2409 if ( isReadOnly() )
2372 return; 2410 return;
2373 2411
2374 drawCursor( FALSE ); 2412 drawCursor( FALSE );
2375 if ( !doc->hasSelection( QTextDocument::Standard ) ) 2413 if ( !doc->hasSelection( QTextDocument::Standard ) )
2376 cursor->indent(); 2414 cursor->indent();
2377 else 2415 else
2378 doc->indentSelection( QTextDocument::Standard ); 2416 doc->indentSelection( QTextDocument::Standard );
2379 repaintChanged(); 2417 repaintChanged();
2380 drawCursor( TRUE ); 2418 drawCursor( TRUE );
2381 setModified(); 2419 setModified();
2382 emit textChanged(); 2420 emit textChanged();
2383} 2421}
2384 2422
2385/*! Reimplemented to allow tabbing through links. 2423/*! Reimplemented to allow tabbing through links.
2386 If \a n is TRUE the tab moves the focus to the next child; if \a n 2424 If \a n is TRUE the tab moves the focus to the next child; if \a n
2387 is FALSE the tab moves the focus to the previous child. 2425 is FALSE the tab moves the focus to the previous child.
2388 Returns TRUE if the focus was moved; otherwise returns FALSE. 2426 Returns TRUE if the focus was moved; otherwise returns FALSE.
2389 */ 2427 */
2390 2428
2391bool QTextEdit::focusNextPrevChild( bool n ) 2429bool QTextEdit::focusNextPrevChild( bool n )
2392{ 2430{
2393 if ( !isReadOnly() || !linksEnabled() ) 2431 if ( !isReadOnly() || !linksEnabled() )
2394 return FALSE; 2432 return FALSE;
2395 bool b = doc->focusNextPrevChild( n ); 2433 bool b = doc->focusNextPrevChild( n );
2396 repaintChanged(); 2434 repaintChanged();
2397 if ( b ) 2435 if ( b )
2398 //##### this does not work with tables. The focusIndicator 2436 //##### this does not work with tables. The focusIndicator
2399 //should really be a QTextCursor. Fix 3.1 2437 //should really be a QTextCursor. Fix 3.1
2400 makeParagVisible( doc->focusIndicator.parag ); 2438 makeParagVisible( doc->focusIndicator.parag );
2401 return b; 2439 return b;
2402} 2440}
2403 2441
2404/*! 2442/*!
2405 \internal 2443 \internal
2406 2444
2407 This functions sets the current format to \a f. Only the fields of \a 2445 This functions sets the current format to \a f. Only the fields of \a
2408 f which are specified by the \a flags are used. 2446 f which are specified by the \a flags are used.
2409*/ 2447*/
2410 2448
2411void QTextEdit::setFormat( QTextFormat *f, int flags ) 2449void QTextEdit::setFormat( QTextFormat *f, int flags )
2412{ 2450{
2413 if ( doc->hasSelection( QTextDocument::Standard ) ) { 2451 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2414 drawCursor( FALSE ); 2452 drawCursor( FALSE );
2415 QString str = doc->selectedText( QTextDocument::Standard );
2416 QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard ); 2453 QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard );
2454 c1.restoreState();
2417 QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard ); 2455 QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard );
2456 c2.restoreState();
2418 clearUndoRedo(); 2457 clearUndoRedo();
2419 undoRedoInfo.type = UndoRedoInfo::Format; 2458 undoRedoInfo.type = UndoRedoInfo::Format;
2420 undoRedoInfo.id = c1.parag()->paragId(); 2459 undoRedoInfo.id = c1.paragraph()->paragId();
2421 undoRedoInfo.index = c1.index(); 2460 undoRedoInfo.index = c1.index();
2422 undoRedoInfo.eid = c2.parag()->paragId(); 2461 undoRedoInfo.eid = c2.paragraph()->paragId();
2423 undoRedoInfo.eindex = c2.index(); 2462 undoRedoInfo.eindex = c2.index();
2424 undoRedoInfo.d->text = str; 2463 readFormats( c1, c2, undoRedoInfo.d->text );
2425 readFormats( c1, c2, 0, undoRedoInfo.d->text );
2426 undoRedoInfo.format = f; 2464 undoRedoInfo.format = f;
2427 undoRedoInfo.flags = flags; 2465 undoRedoInfo.flags = flags;
2428 clearUndoRedo(); 2466 clearUndoRedo();
2429 doc->setFormat( QTextDocument::Standard, f, flags ); 2467 doc->setFormat( QTextDocument::Standard, f, flags );
2430 repaintChanged(); 2468 repaintChanged();
2431 formatMore(); 2469 formatMore();
2432 drawCursor( TRUE ); 2470 drawCursor( TRUE );
2433 setModified(); 2471 setModified();
2434 emit textChanged(); 2472 emit textChanged();
2435 } 2473 }
2436 if ( currentFormat && currentFormat->key() != f->key() ) { 2474 if ( currentFormat && currentFormat->key() != f->key() ) {
2437 currentFormat->removeRef(); 2475 currentFormat->removeRef();
2438 currentFormat = doc->formatCollection()->format( f ); 2476 currentFormat = doc->formatCollection()->format( f );
2439 if ( currentFormat->isMisspelled() ) { 2477 if ( currentFormat->isMisspelled() ) {
2440 currentFormat->removeRef(); 2478 currentFormat->removeRef();
2441 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 2479 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
2442 } 2480 }
2443 emit currentFontChanged( currentFormat->font() ); 2481 emit currentFontChanged( currentFormat->font() );
2444 emit currentColorChanged( currentFormat->color() ); 2482 emit currentColorChanged( currentFormat->color() );
2445 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 2483 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
2446 if ( cursor->index() == cursor->parag()->length() - 1 ) { 2484 if ( cursor->index() == cursor->paragraph()->length() - 1 ) {
2447 currentFormat->addRef(); 2485 currentFormat->addRef();
2448 cursor->parag()->string()->setFormat( cursor->index(), currentFormat, TRUE ); 2486 cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE );
2449 if ( cursor->parag()->length() == 1 ) { 2487 if ( cursor->paragraph()->length() == 1 ) {
2450 cursor->parag()->invalidate( 0 ); 2488 cursor->paragraph()->invalidate( 0 );
2451 cursor->parag()->format(); 2489 cursor->paragraph()->format();
2452 repaintChanged(); 2490 repaintChanged();
2453 } 2491 }
2454 } 2492 }
2455 } 2493 }
2456} 2494}
2457 2495
2458/*! \reimp */ 2496/*! \reimp */
2459 2497
2460void QTextEdit::setPalette( const QPalette &p ) 2498void QTextEdit::setPalette( const QPalette &p )
2461{ 2499{
2462 QScrollView::setPalette( p ); 2500 QScrollView::setPalette( p );
2463 if ( textFormat() == PlainText ) { 2501 if ( textFormat() == PlainText ) {
2464 QTextFormat *f = doc->formatCollection()->defaultFormat(); 2502 QTextFormat *f = doc->formatCollection()->defaultFormat();
2465 f->setColor( colorGroup().text() ); 2503 f->setColor( colorGroup().text() );
2466 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2504 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
2467 } 2505 }
2468} 2506}
2469 2507
2470/*! 2508/*! \internal
2509
2510 \warning In Qt 3.1 we will provide a cleaer API for the
2511 functionality which is provided by this function and in Qt 4.0 this
2512 function will go away.
2513
2471 Sets the paragraph style of the current paragraph 2514 Sets the paragraph style of the current paragraph
2472 to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the 2515 to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the
2473 type of the list item is set to \a listStyle. 2516 type of the list item is set to \a listStyle.
2474 2517
2475 \sa setAlignment() 2518 \sa setAlignment()
2476*/ 2519*/
2477 2520
2478void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle ) 2521void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle )
2479{ 2522{
2480 if ( isReadOnly() ) 2523 if ( isReadOnly() )
2481 return; 2524 return;
2482 2525
2483 drawCursor( FALSE ); 2526 drawCursor( FALSE );
2484 if ( !doc->hasSelection( QTextDocument::Standard ) ) { 2527 QTextParagraph *start = cursor->paragraph();
2485 clearUndoRedo(); 2528 QTextParagraph *end = start;
2486 undoRedoInfo.type = UndoRedoInfo::ParagType; 2529 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2487 QValueList< QPtrVector<QStyleSheetItem> > oldStyles; 2530 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
2488 undoRedoInfo.oldStyles.clear(); 2531 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
2489 undoRedoInfo.oldStyles << cursor->parag()->styleSheetItems(); 2532 if ( end->paragId() < start->paragId() )
2490 undoRedoInfo.oldListStyles.clear(); 2533 return; // do not trust our selections
2491 undoRedoInfo.oldListStyles << cursor->parag()->listStyle(); 2534 }
2492 undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; 2535
2493 undoRedoInfo.listStyle = listStyle; 2536 clearUndoRedo();
2494 undoRedoInfo.id = cursor->parag()->paragId(); 2537 undoRedoInfo.type = UndoRedoInfo::Style;
2495 undoRedoInfo.eid = cursor->parag()->paragId(); 2538 undoRedoInfo.id = start->paragId();
2496 undoRedoInfo.d->text = " "; 2539 undoRedoInfo.eid = end->paragId();
2497 undoRedoInfo.index = 1; 2540 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
2498 clearUndoRedo(); 2541
2499 cursor->parag()->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); 2542 while ( start != end->next() ) {
2500 repaintChanged(); 2543 start->setListStyle( listStyle );
2501 } else { 2544 if ( dm == QStyleSheetItem::DisplayListItem ) {
2502 QTextParag *start = doc->selectionStart( QTextDocument::Standard ); 2545 start->setListItem( TRUE );
2503 QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); 2546 if( start->listDepth() == 0 )
2504 lastFormatted = start; 2547 start->setListDepth( 1 );
2505 clearUndoRedo(); 2548 } else if ( start->isListItem() ) {
2506 undoRedoInfo.type = UndoRedoInfo::ParagType; 2549 start->setListItem( FALSE );
2507 undoRedoInfo.id = start->paragId(); 2550 start->setListDepth( QMAX( start->listDepth()-1, 0 ) );
2508 undoRedoInfo.eid = end->paragId();
2509 undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem;
2510 undoRedoInfo.listStyle = listStyle;
2511 undoRedoInfo.oldStyles.clear();
2512 undoRedoInfo.oldListStyles.clear();
2513 while ( start ) {
2514 undoRedoInfo.oldStyles << start->styleSheetItems();
2515 undoRedoInfo.oldListStyles << start->listStyle();
2516 start->setList( dm == QStyleSheetItem::DisplayListItem, listStyle );
2517 if ( start == end )
2518 break;
2519 start = start->next();
2520 } 2551 }
2521 undoRedoInfo.d->text = " "; 2552 start = start->next();
2522 undoRedoInfo.index = 1;
2523 clearUndoRedo();
2524 repaintChanged();
2525 formatMore();
2526 } 2553 }
2554
2555 clearUndoRedo();
2556 repaintChanged();
2557 formatMore();
2527 drawCursor( TRUE ); 2558 drawCursor( TRUE );
2528 setModified(); 2559 setModified();
2529 emit textChanged(); 2560 emit textChanged();
2530} 2561}
2531 2562
2532/*! 2563/*!
2533 Sets the alignment of the current paragraph to \a a. Valid alignments 2564 Sets the alignment of the current paragraph to \a a. Valid alignments
2534 are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and 2565 are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and
2535 Qt::AlignCenter (which centers horizontally). 2566 Qt::AlignCenter (which centers horizontally).
2536 2567
2537 \sa setParagType()
2538*/ 2568*/
2539 2569
2540void QTextEdit::setAlignment( int a ) 2570void QTextEdit::setAlignment( int a )
2541{ 2571{
2542 if ( isReadOnly() || block_set_alignment ) 2572 if ( isReadOnly() || block_set_alignment )
2543 return; 2573 return;
2544 2574
2545 drawCursor( FALSE ); 2575 drawCursor( FALSE );
2546 if ( !doc->hasSelection( QTextDocument::Standard ) ) { 2576 QTextParagraph *start = cursor->paragraph();
2547 if ( cursor->parag()->alignment() != a ) { 2577 QTextParagraph *end = start;
2548 clearUndoRedo(); 2578 if ( doc->hasSelection( QTextDocument::Standard ) ) {
2549 undoRedoInfo.type = UndoRedoInfo::Alignment; 2579 start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph();
2550 QMemArray<int> oa( 1 ); 2580 end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph();
2551 oa[ 0 ] = cursor->parag()->alignment(); 2581 if ( end->paragId() < start->paragId() )
2552 undoRedoInfo.oldAligns = oa; 2582 return; // do not trust our selections
2553 undoRedoInfo.newAlign = a;
2554 undoRedoInfo.id = cursor->parag()->paragId();
2555 undoRedoInfo.eid = cursor->parag()->paragId();
2556 undoRedoInfo.d->text = " ";
2557 undoRedoInfo.index = 1;
2558 clearUndoRedo();
2559 cursor->parag()->setAlignment( a );
2560 repaintChanged();
2561 }
2562 } else {
2563 QTextParag *start = doc->selectionStart( QTextDocument::Standard );
2564 QTextParag *end = doc->selectionEnd( QTextDocument::Standard );
2565 lastFormatted = start;
2566 int len = end->paragId() - start->paragId() + 1;
2567 clearUndoRedo();
2568 undoRedoInfo.type = UndoRedoInfo::Alignment;
2569 undoRedoInfo.id = start->paragId();
2570 undoRedoInfo.eid = end->paragId();
2571 QMemArray<int> oa( QMAX( 0, len ) );
2572 int i = 0;
2573 while ( start ) {
2574 if ( i < (int)oa.size() )
2575 oa[ i ] = start->alignment();
2576 start->setAlignment( a );
2577 if ( start == end )
2578 break;
2579 start = start->next();
2580 ++i;
2581 }
2582 undoRedoInfo.oldAligns = oa;
2583 undoRedoInfo.newAlign = a;
2584 undoRedoInfo.d->text = " ";
2585 undoRedoInfo.index = 1;
2586 clearUndoRedo();
2587 repaintChanged();
2588 formatMore();
2589 } 2583 }
2584
2585 clearUndoRedo();
2586 undoRedoInfo.type = UndoRedoInfo::Style;
2587 undoRedoInfo.id = start->paragId();
2588 undoRedoInfo.eid = end->paragId();
2589 undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid );
2590
2591 while ( start != end->next() ) {
2592 start->setAlignment( a );
2593 start = start->next();
2594 }
2595
2596 clearUndoRedo();
2597 repaintChanged();
2598 formatMore();
2590 drawCursor( TRUE ); 2599 drawCursor( TRUE );
2591 if ( currentAlignment != a ) { 2600 if ( currentAlignment != a ) {
2592 currentAlignment = a; 2601 currentAlignment = a;
2593 emit currentAlignmentChanged( currentAlignment ); 2602 emit currentAlignmentChanged( currentAlignment );
2594 } 2603 }
2595 setModified(); 2604 setModified();
2596 emit textChanged(); 2605 emit textChanged();
2597} 2606}
2598 2607
2599void QTextEdit::updateCurrentFormat() 2608void QTextEdit::updateCurrentFormat()
2600{ 2609{
2601 int i = cursor->index(); 2610 int i = cursor->index();
2602 if ( i > 0 ) 2611 if ( i > 0 )
2603 --i; 2612 --i;
2604 if ( doc->useFormatCollection() && 2613 if ( doc->useFormatCollection() &&
2605 ( !currentFormat || currentFormat->key() != cursor->parag()->at( i )->format()->key() ) ) { 2614 ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) {
2606 if ( currentFormat ) 2615 if ( currentFormat )
2607 currentFormat->removeRef(); 2616 currentFormat->removeRef();
2608 currentFormat = doc->formatCollection()->format( cursor->parag()->at( i )->format() ); 2617 currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() );
2609 if ( currentFormat->isMisspelled() ) { 2618 if ( currentFormat->isMisspelled() ) {
2610 currentFormat->removeRef(); 2619 currentFormat->removeRef();
2611 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); 2620 currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() );
2612 } 2621 }
2613 emit currentFontChanged( currentFormat->font() ); 2622 emit currentFontChanged( currentFormat->font() );
2614 emit currentColorChanged( currentFormat->color() ); 2623 emit currentColorChanged( currentFormat->color() );
2615 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); 2624 emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() );
2616 } 2625 }
2617 2626
2618 if ( currentAlignment != cursor->parag()->alignment() ) { 2627 if ( currentAlignment != cursor->paragraph()->alignment() ) {
2619 currentAlignment = cursor->parag()->alignment(); 2628 currentAlignment = cursor->paragraph()->alignment();
2620 block_set_alignment = TRUE; 2629 block_set_alignment = TRUE;
2621 emit currentAlignmentChanged( currentAlignment ); 2630 emit currentAlignmentChanged( currentAlignment );
2622 block_set_alignment = FALSE; 2631 block_set_alignment = FALSE;
2623 } 2632 }
2624} 2633}
2625 2634
2626/*! 2635/*!
2627 If \a b is TRUE sets the current format to italic; otherwise sets 2636 If \a b is TRUE sets the current format to italic; otherwise sets
2628 the current format to non-italic. 2637 the current format to non-italic.
2629 2638
2630 \sa italic() 2639 \sa italic()
2631*/ 2640*/
2632 2641
2633void QTextEdit::setItalic( bool b ) 2642void QTextEdit::setItalic( bool b )
2634{ 2643{
2635 QTextFormat f( *currentFormat ); 2644 QTextFormat f( *currentFormat );
2636 f.setItalic( b ); 2645 f.setItalic( b );
2637 QTextFormat *f2 = doc->formatCollection()->format( &f ); 2646 QTextFormat *f2 = doc->formatCollection()->format( &f );
2638 setFormat( f2, QTextFormat::Italic ); 2647 setFormat( f2, QTextFormat::Italic );
2639} 2648}
2640 2649
2641/*! 2650/*!
2642 If \a b is TRUE sets the current format to bold; otherwise sets the 2651 If \a b is TRUE sets the current format to bold; otherwise sets the
2643 current format to non-bold. 2652 current format to non-bold.
2644 2653
2645 \sa bold() 2654 \sa bold()
2646*/ 2655*/
2647 2656
2648void QTextEdit::setBold( bool b ) 2657void QTextEdit::setBold( bool b )
2649{ 2658{
2650 QTextFormat f( *currentFormat ); 2659 QTextFormat f( *currentFormat );
2651 f.setBold( b ); 2660 f.setBold( b );
@@ -2749,265 +2758,287 @@ QString QTextEdit::text() const
2749 2758
2750 If textFormat() is \c RichText the text will contain HTML 2759 If textFormat() is \c RichText the text will contain HTML
2751 formatting tags. 2760 formatting tags.
2752*/ 2761*/
2753 2762
2754QString QTextEdit::text( int para ) const 2763QString QTextEdit::text( int para ) const
2755{ 2764{
2756 return doc->text( para ); 2765 return doc->text( para );
2757} 2766}
2758 2767
2759/*! 2768/*!
2760 \overload 2769 \overload
2761 2770
2762 Changes the text of the text edit to the string \a text and the 2771 Changes the text of the text edit to the string \a text and the
2763 context to \a context. Any previous text is removed. 2772 context to \a context. Any previous text is removed.
2764 2773
2765 \a text may be interpreted either as plain text or as rich text, 2774 \a text may be interpreted either as plain text or as rich text,
2766 depending on the textFormat(). The default setting is \c AutoText, 2775 depending on the textFormat(). The default setting is \c AutoText,
2767 i.e. the text edit autodetects the format from \a text. 2776 i.e. the text edit autodetects the format from \a text.
2768 2777
2769 The optional \a context is a path which the text edit's 2778 The optional \a context is a path which the text edit's
2770 QMimeSourceFactory uses to resolve the locations of files and images. 2779 QMimeSourceFactory uses to resolve the locations of files and images.
2771 (See \l{QTextEdit::QTextEdit()}.) It is passed to the text edit's 2780 (See \l{QTextEdit::QTextEdit()}.) It is passed to the text edit's
2772 QMimeSourceFactory when quering data. 2781 QMimeSourceFactory when quering data.
2773 2782
2774 Note that the undo/redo history is cleared by this function. 2783 Note that the undo/redo history is cleared by this function.
2775 2784
2776 \sa text(), setTextFormat() 2785 \sa text(), setTextFormat()
2777*/ 2786*/
2778 2787
2779void QTextEdit::setText( const QString &text, const QString &context ) 2788void QTextEdit::setText( const QString &text, const QString &context )
2780{ 2789{
2781 if ( !isModified() && this->context() == context && this->text() == text ) 2790 if ( !isModified() && isReadOnly() &&
2791 this->context() == context && this->text() == text )
2782 return; 2792 return;
2783 2793
2784 emit undoAvailable( FALSE ); 2794 emit undoAvailable( FALSE );
2785 emit redoAvailable( FALSE ); 2795 emit redoAvailable( FALSE );
2786 undoRedoInfo.clear(); 2796 undoRedoInfo.clear();
2787 doc->commands()->clear(); 2797 doc->commands()->clear();
2788 2798
2789 lastFormatted = 0; 2799 lastFormatted = 0;
2790 cursor->restoreState(); 2800 cursor->restoreState();
2791 doc->setText( text, context ); 2801 doc->setText( text, context );
2792 2802
2793 if ( wrapMode == FixedPixelWidth ) { 2803 if ( wrapMode == FixedPixelWidth ) {
2794 resizeContents( wrapWidth, 0 ); 2804 resizeContents( wrapWidth, 0 );
2795 doc->setWidth( wrapWidth ); 2805 doc->setWidth( wrapWidth );
2796 doc->setMinimumWidth( wrapWidth ); 2806 doc->setMinimumWidth( wrapWidth );
2797 } else { 2807 } else {
2798 doc->setMinimumWidth( -1 ); 2808 doc->setMinimumWidth( -1 );
2799 resizeContents( 0, 0 ); 2809 resizeContents( 0, 0 );
2800 } 2810 }
2801 2811
2802 cursor->setDocument( doc ); 2812 lastFormatted = doc->firstParagraph();
2803 lastFormatted = doc->firstParag(); 2813 delete cursor;
2804 cursor->setParag( doc->firstParag() ); 2814 cursor = new QTextCursor( doc );
2805 cursor->setIndex( 0 );
2806 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 2815 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
2807 2816
2808 if ( isModified() ) 2817 if ( isModified() )
2809 setModified( FALSE ); 2818 setModified( FALSE );
2810 emit textChanged(); 2819 emit textChanged();
2811 formatMore(); 2820 formatMore();
2812 updateCurrentFormat(); 2821 updateCurrentFormat();
2822 d->scrollToAnchor = QString::null;
2813} 2823}
2814 2824
2815/*! 2825/*!
2816 \property QTextEdit::text 2826 \property QTextEdit::text
2817 \brief the text edit's text 2827 \brief the text edit's text
2818 2828
2819 There is no default text. 2829 There is no default text.
2820 2830
2821 On setting, any previous text is deleted. 2831 On setting, any previous text is deleted.
2822 2832
2823 The text may be interpreted either as plain text or as rich text, 2833 The text may be interpreted either as plain text or as rich text,
2824 depending on the textFormat(). The default setting is \c AutoText, 2834 depending on the textFormat(). The default setting is \c AutoText,
2825 i.e. the text edit autodetects the format of the text. 2835 i.e. the text edit autodetects the format of the text.
2826 2836
2827 For richtext, calling text() on an editable QTextEdit will cause the text 2837 For richtext, calling text() on an editable QTextEdit will cause the text
2828 to be regenerated from the textedit. This may mean that the QString returned 2838 to be regenerated from the textedit. This may mean that the QString returned
2829 may not be exactly the same as the one that was set. 2839 may not be exactly the same as the one that was set.
2830 2840
2831 \sa textFormat 2841 \sa textFormat
2832*/ 2842*/
2833 2843
2834 2844
2835/*! 2845/*!
2836 \property QTextEdit::readOnly 2846 \property QTextEdit::readOnly
2837 \brief whether the text edit is read-only 2847 \brief whether the text edit is read-only
2838 2848
2839 In a read-only text edit the user can only navigate through the text 2849 In a read-only text edit the user can only navigate through the text
2840 and select text; modifying the text is not possible. 2850 and select text; modifying the text is not possible.
2841 2851
2842 This property's default is FALSE. 2852 This property's default is FALSE.
2843*/ 2853*/
2844 2854
2845/*! 2855/*!
2846 Finds the next occurrence of the string, \a expr. Returns TRUE if 2856 Finds the next occurrence of the string, \a expr. Returns TRUE if
2847 \a expr is found; otherwise returns FALSE. 2857 \a expr is found; otherwise returns FALSE.
2848 2858
2849 If \a para and \a index are both null the search begins from the 2859 If \a para and \a index are both null the search begins from the
2850 start of the text. If \a para and \a index are both not null, the 2860 current cursor position. If \a para and \a index are both not
2851 search begins from the \e *\a index character position in the \e 2861 null, the search begins from the \e *\a index character position
2852 *\a para paragraph. 2862 in the \e *\a para paragraph.
2853 2863
2854 If \a cs is TRUE the search is case sensitive, otherwise it is 2864 If \a cs is TRUE the search is case sensitive, otherwise it is
2855 case insensitive. If \a wo is TRUE the search looks for whole word 2865 case insensitive. If \a wo is TRUE the search looks for whole word
2856 matches only; otherwise it searches for any matching text. If \a 2866 matches only; otherwise it searches for any matching text. If \a
2857 forward is TRUE (the default) the search works forward from the 2867 forward is TRUE (the default) the search works forward from the
2858 starting position to the end of the text, otherwise it works 2868 starting position to the end of the text, otherwise it works
2859 backwards to the beginning of the text. 2869 backwards to the beginning of the text.
2860 2870
2861 If \a expr is found the function returns TRUE. If \a index and \a 2871 If \a expr is found the function returns TRUE. If \a index and \a
2862 para are not null, the number of the paragraph in which the first 2872 para are not null, the number of the paragraph in which the first
2863 character of the match was found is put into \e *\a para, and the 2873 character of the match was found is put into \e *\a para, and the
2864 index position of that character within the paragraph is put into 2874 index position of that character within the paragraph is put into
2865 \e *\a index. 2875 \e *\a index.
2866 2876
2867 If \a expr is not found the function returns FALSE. If \a index 2877 If \a expr is not found the function returns FALSE. If \a index
2868 and \a para are not null and \a expr is not found, \e *\a index 2878 and \a para are not null and \a expr is not found, \e *\a index
2869 and \e *\a para are undefined. 2879 and \e *\a para are undefined.
2870*/ 2880*/
2871 2881
2872bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward, 2882bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward,
2873 int *para, int *index ) 2883 int *para, int *index )
2874{ 2884{
2875 drawCursor( FALSE ); 2885 drawCursor( FALSE );
2876 doc->removeSelection( QTextDocument::Standard );
2877#ifndef QT_NO_CURSOR 2886#ifndef QT_NO_CURSOR
2878 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 2887 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
2879#endif 2888#endif
2880 bool found = doc->find( expr, cs, wo, forward, para, index, cursor ); 2889 QTextCursor findcur = *cursor;
2881 ensureCursorVisible(); 2890 if ( para && index ) {
2891 if ( doc->paragAt( *para ) )
2892 findcur.gotoPosition( doc->paragAt(*para), *index );
2893 else
2894 findcur.gotoEnd();
2895 } else if ( doc->hasSelection( QTextDocument::Standard ) ){
2896 // maks sure we do not find the same selection again
2897 if ( forward )
2898 findcur.gotoNextLetter();
2899 else
2900 findcur.gotoPreviousLetter();
2901 }
2902 removeSelection( QTextDocument::Standard );
2903 bool found = doc->find( findcur, expr, cs, wo, forward );
2904 if ( found ) {
2905 if ( para )
2906 *para = findcur.paragraph()->paragId();
2907 if ( index )
2908 *index = findcur.index();
2909 *cursor = findcur;
2910 repaintChanged();
2911 ensureCursorVisible();
2912 }
2882 drawCursor( TRUE ); 2913 drawCursor( TRUE );
2883 repaintChanged();
2884 return found; 2914 return found;
2885} 2915}
2886 2916
2887void QTextEdit::blinkCursor() 2917void QTextEdit::blinkCursor()
2888{ 2918{
2889 if ( !cursorVisible ) 2919 if ( !cursorVisible )
2890 return; 2920 return;
2891 bool cv = cursorVisible; 2921 bool cv = cursorVisible;
2892 blinkCursorVisible = !blinkCursorVisible; 2922 blinkCursorVisible = !blinkCursorVisible;
2893 drawCursor( blinkCursorVisible ); 2923 drawCursor( blinkCursorVisible );
2894 cursorVisible = cv; 2924 cursorVisible = cv;
2895} 2925}
2896 2926
2897/*! 2927/*!
2898 Sets the cursor to position \a index in paragraph \a para. 2928 Sets the cursor to position \a index in paragraph \a para.
2899 2929
2900 \sa getCursorPosition() 2930 \sa getCursorPosition()
2901*/ 2931*/
2902 2932
2903void QTextEdit::setCursorPosition( int para, int index ) 2933void QTextEdit::setCursorPosition( int para, int index )
2904{ 2934{
2905 QTextParag *p = doc->paragAt( para ); 2935 QTextParagraph *p = doc->paragAt( para );
2906 if ( !p ) 2936 if ( !p )
2907 return; 2937 return;
2908 2938
2909 if ( index > p->length() - 1 ) 2939 if ( index > p->length() - 1 )
2910 index = p->length() - 1; 2940 index = p->length() - 1;
2911 2941
2912 drawCursor( FALSE ); 2942 drawCursor( FALSE );
2913 cursor->setParag( p ); 2943 cursor->setParagraph( p );
2914 cursor->setIndex( index ); 2944 cursor->setIndex( index );
2915 ensureCursorVisible(); 2945 ensureCursorVisible();
2916 drawCursor( TRUE ); 2946 drawCursor( TRUE );
2947 updateCurrentFormat();
2917 emit cursorPositionChanged( cursor ); 2948 emit cursorPositionChanged( cursor );
2918 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 2949 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
2919} 2950}
2920 2951
2921/*! 2952/*!
2922 This function sets the \e *\a para and \e *\a index parameters to the 2953 This function sets the \e *\a para and \e *\a index parameters to the
2923 current cursor position. \a para and \a index must be non-null int 2954 current cursor position. \a para and \a index must be non-null int
2924 pointers. 2955 pointers.
2925 2956
2926 \sa setCursorPosition() 2957 \sa setCursorPosition()
2927 */ 2958 */
2928 2959
2929void QTextEdit::getCursorPosition( int *para, int *index ) const 2960void QTextEdit::getCursorPosition( int *para, int *index ) const
2930{ 2961{
2931 if ( !para || !index ) 2962 if ( !para || !index )
2932 return; 2963 return;
2933 *para = cursor->parag()->paragId(); 2964 *para = cursor->paragraph()->paragId();
2934 *index = cursor->index(); 2965 *index = cursor->index();
2935} 2966}
2936 2967
2937/*! Sets a selection which starts at position \a indexFrom in 2968/*! Sets a selection which starts at position \a indexFrom in
2938 paragraph \a paraFrom and ends at position \a indexTo in paragraph 2969 paragraph \a paraFrom and ends at position \a indexTo in paragraph
2939 \a paraTo. Existing selections which have a different id (selNum) 2970 \a paraTo. Existing selections which have a different id (selNum)
2940 are not removed, existing selections which have the same id as \a 2971 are not removed, existing selections which have the same id as \a
2941 selNum are removed. 2972 selNum are removed.
2942 2973
2943 Uses the selection settings of selection \a selNum. If \a selNum is 0, 2974 Uses the selection settings of selection \a selNum. If \a selNum is 0,
2944 this is the default selection. 2975 this is the default selection.
2945 2976
2946 The cursor is moved to the end of the selection if \a selNum is 0, 2977 The cursor is moved to the end of the selection if \a selNum is 0,
2947 otherwise the cursor position remains unchanged. 2978 otherwise the cursor position remains unchanged.
2948 2979
2949 \sa getSelection() selectedText 2980 \sa getSelection() selectedText
2950*/ 2981*/
2951 2982
2952void QTextEdit::setSelection( int paraFrom, int indexFrom, 2983void QTextEdit::setSelection( int paraFrom, int indexFrom,
2953 int paraTo, int indexTo, int selNum ) 2984 int paraTo, int indexTo, int selNum )
2954{ 2985{
2955 if ( doc->hasSelection( selNum ) ) { 2986 if ( doc->hasSelection( selNum ) ) {
2956 doc->removeSelection( selNum ); 2987 doc->removeSelection( selNum );
2957 repaintChanged(); 2988 repaintChanged();
2958 } 2989 }
2959 if ( selNum > doc->numSelections() - 1 ) 2990 if ( selNum > doc->numSelections() - 1 )
2960 doc->addSelection( selNum ); 2991 doc->addSelection( selNum );
2961 QTextParag *p1 = doc->paragAt( paraFrom ); 2992 QTextParagraph *p1 = doc->paragAt( paraFrom );
2962 if ( !p1 ) 2993 if ( !p1 )
2963 return; 2994 return;
2964 QTextParag *p2 = doc->paragAt( paraTo ); 2995 QTextParagraph *p2 = doc->paragAt( paraTo );
2965 if ( !p2 ) 2996 if ( !p2 )
2966 return; 2997 return;
2967 2998
2968 if ( indexFrom > p1->length() - 1 ) 2999 if ( indexFrom > p1->length() - 1 )
2969 indexFrom = p1->length() - 1; 3000 indexFrom = p1->length() - 1;
2970 if ( indexTo > p2->length() - 1 ) 3001 if ( indexTo > p2->length() - 1 )
2971 indexTo = p2->length() - 1; 3002 indexTo = p2->length() - 1;
2972 3003
2973 drawCursor( FALSE ); 3004 drawCursor( FALSE );
2974 QTextCursor c = *cursor; 3005 QTextCursor c = *cursor;
2975 QTextCursor oldCursor = *cursor; 3006 QTextCursor oldCursor = *cursor;
2976 c.setParag( p1 ); 3007 c.setParagraph( p1 );
2977 c.setIndex( indexFrom ); 3008 c.setIndex( indexFrom );
2978 cursor->setParag( p2 ); 3009 cursor->setParagraph( p2 );
2979 cursor->setIndex( indexTo ); 3010 cursor->setIndex( indexTo );
2980 doc->setSelectionStart( selNum, &c ); 3011 doc->setSelectionStart( selNum, c );
2981 doc->setSelectionEnd( selNum, cursor ); 3012 doc->setSelectionEnd( selNum, *cursor );
2982 repaintChanged(); 3013 repaintChanged();
2983 ensureCursorVisible(); 3014 ensureCursorVisible();
2984 if ( selNum != QTextDocument::Standard ) 3015 if ( selNum != QTextDocument::Standard )
2985 *cursor = oldCursor; 3016 *cursor = oldCursor;
2986 drawCursor( TRUE ); 3017 drawCursor( TRUE );
2987} 3018}
2988 3019
2989/*! 3020/*!
2990 If there is a selection, \e *\a paraFrom is set to the number of the 3021 If there is a selection, \e *\a paraFrom is set to the number of the
2991 paragraph in which the selection begins and \e *\a paraTo is set to 3022 paragraph in which the selection begins and \e *\a paraTo is set to
2992 the number of the paragraph in which the selection ends. (They could 3023 the number of the paragraph in which the selection ends. (They could
2993 be the same.) \e *\a indexFrom is set to the index at which the 3024 be the same.) \e *\a indexFrom is set to the index at which the
2994 selection begins within \e *\a paraFrom, and \e *\a indexTo is set to 3025 selection begins within \e *\a paraFrom, and \e *\a indexTo is set to
2995 the index at which the selection ends within \e *\a paraTo. 3026 the index at which the selection ends within \e *\a paraTo.
2996 3027
2997 If there is no selection, \e *\a paraFrom, \e *\a indexFrom, \e *\a 3028 If there is no selection, \e *\a paraFrom, \e *\a indexFrom, \e *\a
2998 paraTo and \e *\a indexTo are all set to -1. 3029 paraTo and \e *\a indexTo are all set to -1.
2999 3030
3000 \a paraFrom, \a indexFrom, \a paraTo and \a indexTo must be non-null 3031 \a paraFrom, \a indexFrom, \a paraTo and \a indexTo must be non-null
3001 int pointers. 3032 int pointers.
3002 3033
3003 The \a selNum is the number of the selection (multiple selections 3034 The \a selNum is the number of the selection (multiple selections
3004 are supported). It defaults to 0 (the default selection). 3035 are supported). It defaults to 0 (the default selection).
3005 3036
3006 \sa setSelection() selectedText 3037 \sa setSelection() selectedText
3007*/ 3038*/
3008 3039
3009void QTextEdit::getSelection( int *paraFrom, int *indexFrom, 3040void QTextEdit::getSelection( int *paraFrom, int *indexFrom,
3010 int *paraTo, int *indexTo, int selNum ) const 3041 int *paraTo, int *indexTo, int selNum ) const
3011{ 3042{
3012 if ( !paraFrom || !paraTo || !indexFrom || !indexTo ) 3043 if ( !paraFrom || !paraTo || !indexFrom || !indexTo )
3013 return; 3044 return;
@@ -3027,124 +3058,124 @@ void QTextEdit::getSelection( int *paraFrom, int *indexFrom,
3027 \property QTextEdit::textFormat 3058 \property QTextEdit::textFormat
3028 \brief the text format: rich text, plain text or auto text 3059 \brief the text format: rich text, plain text or auto text
3029 3060
3030 The text format is one of the following: 3061 The text format is one of the following:
3031 \list 3062 \list
3032 \i PlainText - all characters, except newlines, are displayed 3063 \i PlainText - all characters, except newlines, are displayed
3033 verbatim, including spaces. Whenever a newline appears in the text the 3064 verbatim, including spaces. Whenever a newline appears in the text the
3034 text edit inserts a hard line break and begins a new paragraph. 3065 text edit inserts a hard line break and begins a new paragraph.
3035 \i RichText - rich text rendering. The available styles are 3066 \i RichText - rich text rendering. The available styles are
3036 defined in the default stylesheet QStyleSheet::defaultSheet(). 3067 defined in the default stylesheet QStyleSheet::defaultSheet().
3037 \i AutoText - this is the default. The text edit autodetects 3068 \i AutoText - this is the default. The text edit autodetects
3038 which rendering style is best, \c PlainText or \c RichText. This is 3069 which rendering style is best, \c PlainText or \c RichText. This is
3039 done by using the QStyleSheet::mightBeRichText() function. 3070 done by using the QStyleSheet::mightBeRichText() function.
3040 \endlist 3071 \endlist
3041*/ 3072*/
3042 3073
3043void QTextEdit::setTextFormat( TextFormat format ) 3074void QTextEdit::setTextFormat( TextFormat format )
3044{ 3075{
3045 doc->setTextFormat( format ); 3076 doc->setTextFormat( format );
3046} 3077}
3047 3078
3048Qt::TextFormat QTextEdit::textFormat() const 3079Qt::TextFormat QTextEdit::textFormat() const
3049{ 3080{
3050 return doc->textFormat(); 3081 return doc->textFormat();
3051} 3082}
3052 3083
3053/*! 3084/*!
3054 Returns the number of paragraphs in the text; this could be 0. 3085 Returns the number of paragraphs in the text; this could be 0.
3055*/ 3086*/
3056 3087
3057int QTextEdit::paragraphs() const 3088int QTextEdit::paragraphs() const
3058{ 3089{
3059 return doc->lastParag()->paragId() + 1; 3090 return doc->lastParagraph()->paragId() + 1;
3060} 3091}
3061 3092
3062/*! 3093/*!
3063 Returns the number of lines in paragraph \a para, or -1 if there 3094 Returns the number of lines in paragraph \a para, or -1 if there
3064 is no paragraph with index \a para. 3095 is no paragraph with index \a para.
3065*/ 3096*/
3066 3097
3067int QTextEdit::linesOfParagraph( int para ) const 3098int QTextEdit::linesOfParagraph( int para ) const
3068{ 3099{
3069 QTextParag *p = doc->paragAt( para ); 3100 QTextParagraph *p = doc->paragAt( para );
3070 if ( !p ) 3101 if ( !p )
3071 return -1; 3102 return -1;
3072 return p->lines(); 3103 return p->lines();
3073} 3104}
3074 3105
3075/*! 3106/*!
3076 Returns the length of the paragraph \a para (number of 3107 Returns the length of the paragraph \a para (number of
3077 characters), or -1 if there is no paragraph with index \a para 3108 characters), or -1 if there is no paragraph with index \a para
3078*/ 3109*/
3079 3110
3080int QTextEdit::paragraphLength( int para ) const 3111int QTextEdit::paragraphLength( int para ) const
3081{ 3112{
3082 QTextParag *p = doc->paragAt( para ); 3113 QTextParagraph *p = doc->paragAt( para );
3083 if ( !p ) 3114 if ( !p )
3084 return -1; 3115 return -1;
3085 return p->length() - 1; 3116 return p->length() - 1;
3086} 3117}
3087 3118
3088/*! 3119/*!
3089 Returns the number of lines in the text edit; this could be 0. 3120 Returns the number of lines in the text edit; this could be 0.
3090 3121
3091 \warning This function may be slow. Lines change all the time 3122 \warning This function may be slow. Lines change all the time
3092 during word wrapping, so this function has to iterate over all the 3123 during word wrapping, so this function has to iterate over all the
3093 paragraphs and get the number of lines from each one individually. 3124 paragraphs and get the number of lines from each one individually.
3094*/ 3125*/
3095 3126
3096int QTextEdit::lines() const 3127int QTextEdit::lines() const
3097{ 3128{
3098 QTextParag *p = doc->firstParag(); 3129 QTextParagraph *p = doc->firstParagraph();
3099 int l = 0; 3130 int l = 0;
3100 while ( p ) { 3131 while ( p ) {
3101 l += p->lines(); 3132 l += p->lines();
3102 p = p->next(); 3133 p = p->next();
3103 } 3134 }
3104 3135
3105 return l; 3136 return l;
3106} 3137}
3107 3138
3108/*! 3139/*!
3109 Returns the line number of the line in paragraph \a para in which 3140 Returns the line number of the line in paragraph \a para in which
3110 the character at position \a index appears. The \a index position is 3141 the character at position \a index appears. The \a index position is
3111 relative to the beginning of the paragraph. If there is no such 3142 relative to the beginning of the paragraph. If there is no such
3112 paragraph or no such character at the \a index position (e.g. the 3143 paragraph or no such character at the \a index position (e.g. the
3113 index is out of range) -1 is returned. 3144 index is out of range) -1 is returned.
3114*/ 3145*/
3115 3146
3116int QTextEdit::lineOfChar( int para, int index ) 3147int QTextEdit::lineOfChar( int para, int index )
3117{ 3148{
3118 QTextParag *p = doc->paragAt( para ); 3149 QTextParagraph *p = doc->paragAt( para );
3119 if ( !p ) 3150 if ( !p )
3120 return -1; 3151 return -1;
3121 3152
3122 int idx, line; 3153 int idx, line;
3123 QTextStringChar *c = p->lineStartOfChar( index, &idx, &line ); 3154 QTextStringChar *c = p->lineStartOfChar( index, &idx, &line );
3124 if ( !c ) 3155 if ( !c )
3125 return -1; 3156 return -1;
3126 3157
3127 return line; 3158 return line;
3128} 3159}
3129 3160
3130void QTextEdit::setModified( bool m ) 3161void QTextEdit::setModified( bool m )
3131{ 3162{
3132 bool oldModified = modified; 3163 bool oldModified = modified;
3133 modified = m; 3164 modified = m;
3134 if ( modified && doc->oTextValid ) 3165 if ( modified && doc->oTextValid )
3135 doc->invalidateOriginalText(); 3166 doc->invalidateOriginalText();
3136 if ( oldModified != modified ) 3167 if ( oldModified != modified )
3137 emit modificationChanged( modified ); 3168 emit modificationChanged( modified );
3138} 3169}
3139 3170
3140/*! \property QTextEdit::modified 3171/*! \property QTextEdit::modified
3141 \brief whether the document has been modified by the user 3172 \brief whether the document has been modified by the user
3142*/ 3173*/
3143 3174
3144bool QTextEdit::isModified() const 3175bool QTextEdit::isModified() const
3145{ 3176{
3146 return modified; 3177 return modified;
3147} 3178}
3148 3179
3149void QTextEdit::setModified() 3180void QTextEdit::setModified()
3150{ 3181{
@@ -3219,157 +3250,155 @@ QColor QTextEdit::color() const
3219{ 3250{
3220 return currentFormat->color(); 3251 return currentFormat->color();
3221} 3252}
3222 3253
3223/*! 3254/*!
3224 Returns the font of the current format. 3255 Returns the font of the current format.
3225 3256
3226 \sa setCurrentFont() setFamily() setPointSize() 3257 \sa setCurrentFont() setFamily() setPointSize()
3227 3258
3228*/ 3259*/
3229 3260
3230QFont QTextEdit::font() const 3261QFont QTextEdit::font() const
3231{ 3262{
3232 return currentFormat->font(); 3263 return currentFormat->font();
3233} 3264}
3234 3265
3235/*! 3266/*!
3236 Returns the alignment of the current paragraph. 3267 Returns the alignment of the current paragraph.
3237 3268
3238 \sa setAlignment() 3269 \sa setAlignment()
3239*/ 3270*/
3240 3271
3241int QTextEdit::alignment() const 3272int QTextEdit::alignment() const
3242{ 3273{
3243 return currentAlignment; 3274 return currentAlignment;
3244} 3275}
3245 3276
3246void QTextEdit::startDrag() 3277void QTextEdit::startDrag()
3247{ 3278{
3248#ifndef QT_NO_DRAGANDDROP 3279#ifndef QT_NO_DRAGANDDROP
3249 mousePressed = FALSE; 3280 mousePressed = FALSE;
3250 inDoubleClick = FALSE; 3281 inDoubleClick = FALSE;
3251 QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard ), viewport() ); 3282 QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ), viewport() );
3252 if ( isReadOnly() ) { 3283 if ( isReadOnly() ) {
3253 drag->dragCopy(); 3284 drag->dragCopy();
3254 } else { 3285 } else {
3255 if ( drag->drag() && QDragObject::target() != this && QDragObject::target() != viewport() ) 3286 if ( drag->drag() && QDragObject::target() != this && QDragObject::target() != viewport() )
3256 removeSelectedText(); 3287 removeSelectedText();
3257 } 3288 }
3258#endif 3289#endif
3259} 3290}
3260 3291
3261/*! 3292/*!
3262 If \a select is TRUE (the default), all the text is selected as 3293 If \a select is TRUE (the default), all the text is selected as
3263 selection 0. 3294 selection 0.
3264 If \a select is FALSE any selected text is unselected, i.e., the 3295 If \a select is FALSE any selected text is unselected, i.e., the
3265 default selection (selection 0) is cleared. 3296 default selection (selection 0) is cleared.
3266 3297
3267 \sa selectedText 3298 \sa selectedText
3268*/ 3299*/
3269 3300
3270void QTextEdit::selectAll( bool select ) 3301void QTextEdit::selectAll( bool select )
3271{ 3302{
3272 if ( !select ) 3303 if ( !select )
3273 doc->removeSelection( QTextDocument::Standard ); 3304 doc->removeSelection( QTextDocument::Standard );
3274 else 3305 else
3275 doc->selectAll( QTextDocument::Standard ); 3306 doc->selectAll( QTextDocument::Standard );
3276 repaintChanged(); 3307 repaintChanged();
3277 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); 3308 emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) );
3278 emit selectionChanged(); 3309 emit selectionChanged();
3279#ifndef QT_NO_CURSOR 3310#ifndef QT_NO_CURSOR
3280 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 3311 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
3281#endif 3312#endif
3282} 3313}
3283 3314
3284void QTextEdit::UndoRedoInfo::clear() 3315void QTextEdit::UndoRedoInfo::clear()
3285{ 3316{
3286 if ( valid() ) { 3317 if ( valid() ) {
3287 if ( type == Insert || type == Return ) 3318 if ( type == Insert || type == Return )
3288 doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); 3319 doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) );
3289 else if ( type == Format ) 3320 else if ( type == Format )
3290 doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); 3321 doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) );
3291 else if ( type == Alignment ) 3322 else if ( type == Style )
3292 doc->addCommand( new QTextAlignmentCommand( doc, id, eid, newAlign, oldAligns ) ); 3323 doc->addCommand( new QTextStyleCommand( doc, id, eid, styleInformation ) );
3293 else if ( type == ParagType ) 3324 else if ( type != Invalid ) {
3294 doc->addCommand( new QTextParagTypeCommand( doc, id, eid, list, listStyle, oldStyles, oldListStyles ) ); 3325 doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) );
3295 else if ( type != Invalid ) 3326 }
3296 doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) );
3297 } 3327 }
3328 type = Invalid;
3298 d->text = QString::null; 3329 d->text = QString::null;
3299 id = -1; 3330 id = -1;
3300 index = -1; 3331 index = -1;
3301 oldStyles.clear(); 3332 styleInformation = QByteArray();
3302 oldListStyles.clear();
3303 oldAligns.resize( 0 );
3304} 3333}
3305 3334
3306 3335
3307/*! 3336/*!
3308 If there is some selected text (in selection 0) it is deleted. If 3337 If there is some selected text (in selection 0) it is deleted. If
3309 there is no selected text (in selection 0) the character to the 3338 there is no selected text (in selection 0) the character to the
3310 right of the text cursor is deleted. 3339 right of the text cursor is deleted.
3311 3340
3312 \sa removeSelectedText() cut() 3341 \sa removeSelectedText() cut()
3313 3342
3314*/ 3343*/
3315 3344
3316void QTextEdit::del() 3345void QTextEdit::del()
3317{ 3346{
3318 if ( doc->hasSelection( QTextDocument::Standard ) ) { 3347 if ( doc->hasSelection( QTextDocument::Standard ) ) {
3319 removeSelectedText(); 3348 removeSelectedText();
3320 return; 3349 return;
3321 } 3350 }
3322 3351
3323 doKeyboardAction( ActionDelete ); 3352 doKeyboardAction( ActionDelete );
3324} 3353}
3325 3354
3326 3355
3327QTextEdit::UndoRedoInfo::UndoRedoInfo( QTextDocument *dc ) 3356QTextEdit::UndoRedoInfo::UndoRedoInfo( QTextDocument *dc )
3328 : type( Invalid ), doc( dc ) 3357 : type( Invalid ), doc( dc )
3329{ 3358{
3330 d = new QUndoRedoInfoPrivate; 3359 d = new QUndoRedoInfoPrivate;
3331 d->text = QString::null; 3360 d->text = QString::null;
3332 id = -1; 3361 id = -1;
3333 index = -1; 3362 index = -1;
3334} 3363}
3335 3364
3336QTextEdit::UndoRedoInfo::~UndoRedoInfo() 3365QTextEdit::UndoRedoInfo::~UndoRedoInfo()
3337{ 3366{
3338 delete d; 3367 delete d;
3339} 3368}
3340 3369
3341bool QTextEdit::UndoRedoInfo::valid() const 3370bool QTextEdit::UndoRedoInfo::valid() const
3342{ 3371{
3343 return d->text.length() > 0 && id >= 0 && index >= 0; 3372 return id >= 0 && type != Invalid;
3344} 3373}
3345 3374
3346/*! 3375/*!
3347 \internal 3376 \internal
3348 3377
3349 Resets the current format to the default format. 3378 Resets the current format to the default format.
3350*/ 3379*/
3351 3380
3352void QTextEdit::resetFormat() 3381void QTextEdit::resetFormat()
3353{ 3382{
3354 setAlignment( Qt3::AlignAuto ); 3383 setAlignment( Qt3::AlignAuto );
3355 setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc ); 3384 setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc );
3356 setFormat( doc->formatCollection()->defaultFormat(), QTextFormat::Format ); 3385 setFormat( doc->formatCollection()->defaultFormat(), QTextFormat::Format );
3357} 3386}
3358 3387
3359/*! Returns the QStyleSheet which is currently used in this text edit. 3388/*! Returns the QStyleSheet which is currently used in this text edit.
3360 3389
3361 \sa setStyleSheet() 3390 \sa setStyleSheet()
3362 */ 3391 */
3363 3392
3364QStyleSheet* QTextEdit::styleSheet() const 3393QStyleSheet* QTextEdit::styleSheet() const
3365{ 3394{
3366 return doc->styleSheet(); 3395 return doc->styleSheet();
3367} 3396}
3368 3397
3369/*! Sets the stylesheet to use with this text edit to \a styleSheet. Changes 3398/*! Sets the stylesheet to use with this text edit to \a styleSheet. Changes
3370 will only take effect for new text added with setText() or append(). 3399 will only take effect for new text added with setText() or append().
3371 3400
3372 \sa styleSheet() 3401 \sa styleSheet()
3373 */ 3402 */
3374 3403
3375void QTextEdit::setStyleSheet( QStyleSheet* styleSheet ) 3404void QTextEdit::setStyleSheet( QStyleSheet* styleSheet )
@@ -3380,161 +3409,159 @@ void QTextEdit::setStyleSheet( QStyleSheet* styleSheet )
3380/*! 3409/*!
3381 \property QTextEdit::paper 3410 \property QTextEdit::paper
3382 \brief the background (paper) brush. 3411 \brief the background (paper) brush.
3383 3412
3384 The brush that is currently used to draw the background of the 3413 The brush that is currently used to draw the background of the
3385 text edit. The initial setting is an empty brush. 3414 text edit. The initial setting is an empty brush.
3386 */ 3415 */
3387 3416
3388void QTextEdit::setPaper( const QBrush& pap ) 3417void QTextEdit::setPaper( const QBrush& pap )
3389{ 3418{
3390 doc->setPaper( new QBrush( pap ) ); 3419 doc->setPaper( new QBrush( pap ) );
3391 viewport()->setBackgroundColor( pap.color() ); 3420 viewport()->setBackgroundColor( pap.color() );
3392 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3421 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3393} 3422}
3394 3423
3395QBrush QTextEdit::paper() const 3424QBrush QTextEdit::paper() const
3396{ 3425{
3397 if ( doc->paper() ) 3426 if ( doc->paper() )
3398 return *doc->paper(); 3427 return *doc->paper();
3399 return QBrush(); 3428 return QBrush();
3400} 3429}
3401 3430
3402/*! 3431/*!
3403 \property QTextEdit::linkUnderline 3432 \property QTextEdit::linkUnderline
3404 \brief whether hypertext links will be underlined 3433 \brief whether hypertext links will be underlined
3405 3434
3406 If TRUE (the default) hypertext links will be displayed underlined. 3435 If TRUE (the default) hypertext links will be displayed underlined.
3407 If FALSE links will not be displayed underlined. 3436 If FALSE links will not be displayed underlined.
3408*/ 3437*/
3409 3438
3410void QTextEdit::setLinkUnderline( bool b ) 3439void QTextEdit::setLinkUnderline( bool b )
3411{ 3440{
3412 if ( b == doc->underlineLinks() )
3413 return;
3414 doc->setUnderlineLinks( b ); 3441 doc->setUnderlineLinks( b );
3415 updateStyles();
3416} 3442}
3417 3443
3418bool QTextEdit::linkUnderline() const 3444bool QTextEdit::linkUnderline() const
3419{ 3445{
3420 return doc->underlineLinks(); 3446 return doc->underlineLinks();
3421} 3447}
3422 3448
3423/*! Sets the text edit's mimesource factory to \a factory. See 3449/*! Sets the text edit's mimesource factory to \a factory. See
3424 QMimeSourceFactory for further details. 3450 QMimeSourceFactory for further details.
3425 3451
3426 \sa mimeSourceFactory() 3452 \sa mimeSourceFactory()
3427 */ 3453 */
3428 3454
3429void QTextEdit::setMimeSourceFactory( QMimeSourceFactory* factory ) 3455void QTextEdit::setMimeSourceFactory( QMimeSourceFactory* factory )
3430{ 3456{
3431 doc->setMimeSourceFactory( factory ); 3457 doc->setMimeSourceFactory( factory );
3432} 3458}
3433 3459
3434/*! Returns the QMimeSourceFactory which is currently used by this 3460/*! Returns the QMimeSourceFactory which is currently used by this
3435 text edit. 3461 text edit.
3436 3462
3437 \sa setMimeSourceFactory() 3463 \sa setMimeSourceFactory()
3438*/ 3464*/
3439 3465
3440QMimeSourceFactory* QTextEdit::mimeSourceFactory() const 3466QMimeSourceFactory* QTextEdit::mimeSourceFactory() const
3441{ 3467{
3442 return doc->mimeSourceFactory(); 3468 return doc->mimeSourceFactory();
3443} 3469}
3444 3470
3445/*! 3471/*!
3446 Returns how many pixels high the text edit needs to be to display 3472 Returns how many pixels high the text edit needs to be to display
3447 all the text if the text edit is \a w pixels wide. 3473 all the text if the text edit is \a w pixels wide.
3448*/ 3474*/
3449 3475
3450int QTextEdit::heightForWidth( int w ) const 3476int QTextEdit::heightForWidth( int w ) const
3451{ 3477{
3452 int oldw = doc->width(); 3478 int oldw = doc->width();
3453 doc->doLayout( 0, w ); 3479 doc->doLayout( 0, w );
3454 int h = doc->height(); 3480 int h = doc->height();
3455 doc->setWidth( oldw ); 3481 doc->setWidth( oldw );
3456 doc->invalidate(); 3482 doc->invalidate();
3457 ( (QTextEdit*)this )->formatMore(); 3483 ( (QTextEdit*)this )->formatMore();
3458 return h; 3484 return h;
3459} 3485}
3460 3486
3461/*! Appends the text \a text to the end of the text edit. 3487/*! Appends the text \a text to the end of the text edit.
3462 Note that the undo/redo history is cleared by this function. 3488 Note that the undo/redo history is cleared by this function.
3463 */ 3489 */
3464 3490
3465void QTextEdit::append( const QString &text ) 3491void QTextEdit::append( const QString &text )
3466{ 3492{
3467 // flush and clear the undo/redo stack if necessary 3493 // flush and clear the undo/redo stack if necessary
3468 if ( isReadOnly() && undoRedoInfo.valid() ) { 3494 undoRedoInfo.clear();
3469 undoRedoInfo.clear(); 3495 doc->commands()->clear();
3470 doc->commands()->clear(); 3496
3471 }
3472 doc->removeSelection( QTextDocument::Standard ); 3497 doc->removeSelection( QTextDocument::Standard );
3473 TextFormat f = doc->textFormat(); 3498 TextFormat f = doc->textFormat();
3474 if ( f == AutoText ) { 3499 if ( f == AutoText ) {
3475 if ( QStyleSheet::mightBeRichText( text ) ) 3500 if ( QStyleSheet::mightBeRichText( text ) )
3476 f = RichText; 3501 f = RichText;
3477 else 3502 else
3478 f = PlainText; 3503 f = PlainText;
3479 } 3504 }
3480 if ( f == PlainText ) { 3505
3481 QTextCursor oldc( *cursor ); 3506 drawCursor( FALSE );
3482 ensureFormatted( doc->lastParag() ); 3507 QTextCursor oldc( *cursor );
3483 bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight() - 3508 ensureFormatted( doc->lastParagraph() );
3484 ( horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0 ); 3509 bool atBottom = contentsY() >= contentsHeight() - visibleHeight();
3485 if ( !scrollToEnd ) 3510 cursor->gotoEnd();
3486 blockEnsureCursorVisible = TRUE; 3511 if ( cursor->index() > 0 )
3487 cursor->gotoEnd(); 3512 cursor->splitAndInsertEmptyParagraph();
3488 if ( cursor->index() > 0 ) 3513 QTextCursor oldCursor2 = *cursor;
3489 cursor->splitAndInsertEmptyParag(); 3514
3490 QTextCursor oldCursor2 = *cursor; 3515 if ( f == Qt::PlainText ) {
3491 cursor->insert( text, TRUE ); 3516 cursor->insert( text, TRUE );
3492 if ( doc->useFormatCollection() && currentFormat != cursor->parag()->at( cursor->index() )->format() ) { 3517 if ( doc->useFormatCollection() &&
3493 doc->setSelectionStart( QTextDocument::Temp, &oldCursor2 ); 3518 currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) {
3494 doc->setSelectionEnd( QTextDocument::Temp, cursor ); 3519 doc->setSelectionStart( QTextDocument::Temp, oldCursor2 );
3520 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
3495 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); 3521 doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format );
3496 doc->removeSelection( QTextDocument::Temp ); 3522 doc->removeSelection( QTextDocument::Temp );
3497 } 3523 }
3498 formatMore(); 3524 } else {
3499 repaintChanged(); 3525 if ( cursor->paragraph()->prev() )
3500 ensureCursorVisible(); 3526 cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change
3501 drawCursor( TRUE );
3502 *cursor = oldc;
3503 if ( !scrollToEnd )
3504 blockEnsureCursorVisible = FALSE;
3505 } else if ( f == RichText ) {
3506 doc->setRichTextInternal( text ); 3527 doc->setRichTextInternal( text );
3507 repaintChanged();
3508 } 3528 }
3529 formatMore();
3530 repaintChanged();
3531 if ( atBottom )
3532 scrollToBottom();
3533 *cursor = oldc;
3534 if ( !isReadOnly() )
3535 cursorVisible = TRUE;
3509 setModified(); 3536 setModified();
3510 emit textChanged(); 3537 emit textChanged();
3511} 3538}
3512 3539
3513/*! \property QTextEdit::hasSelectedText 3540/*! \property QTextEdit::hasSelectedText
3514 \brief whether some text is selected in selection 0 3541 \brief whether some text is selected in selection 0
3515 */ 3542 */
3516 3543
3517bool QTextEdit::hasSelectedText() const 3544bool QTextEdit::hasSelectedText() const
3518{ 3545{
3519 return doc->hasSelection( QTextDocument::Standard ); 3546 return doc->hasSelection( QTextDocument::Standard );
3520} 3547}
3521 3548
3522/*!\property QTextEdit::selectedText 3549/*!\property QTextEdit::selectedText
3523 \brief The selected text (from selection 0) or an empty string if 3550 \brief The selected text (from selection 0) or an empty string if
3524 there is no currently selected text (in selection 0). 3551 there is no currently selected text (in selection 0).
3525 3552
3526 The text is always returned as \c PlainText regardless of the text 3553 The text is always returned as \c PlainText regardless of the text
3527 format. In a future version of Qt an HTML subset \e may be returned 3554 format. In a future version of Qt an HTML subset \e may be returned
3528 depending on the text format. 3555 depending on the text format.
3529 3556
3530 \sa hasSelectedText 3557 \sa hasSelectedText
3531 */ 3558 */
3532 3559
3533QString QTextEdit::selectedText() const 3560QString QTextEdit::selectedText() const
3534{ 3561{
3535 return doc->selectedText( QTextDocument::Standard ); 3562 return doc->selectedText( QTextDocument::Standard );
3536} 3563}
3537 3564
3538bool QTextEdit::handleReadOnlyKeyEvent( QKeyEvent *e ) 3565bool QTextEdit::handleReadOnlyKeyEvent( QKeyEvent *e )
3539{ 3566{
3540 switch( e->key() ) { 3567 switch( e->key() ) {
@@ -3588,151 +3615,202 @@ bool QTextEdit::handleReadOnlyKeyEvent( QKeyEvent *e )
3588 } 3615 }
3589 return FALSE; 3616 return FALSE;
3590 } 3617 }
3591 return TRUE; 3618 return TRUE;
3592} 3619}
3593 3620
3594/*! Returns the context of the edit. 3621/*! Returns the context of the edit.
3595 The context is a path which the text edit's QMimeSourceFactory 3622 The context is a path which the text edit's QMimeSourceFactory
3596 uses to resolve the locations of files and images. 3623 uses to resolve the locations of files and images.
3597 3624
3598 \sa text 3625 \sa text
3599*/ 3626*/
3600 3627
3601QString QTextEdit::context() const 3628QString QTextEdit::context() const
3602{ 3629{
3603 return doc->context(); 3630 return doc->context();
3604} 3631}
3605 3632
3606/*! 3633/*!
3607 \property QTextEdit::documentTitle 3634 \property QTextEdit::documentTitle
3608 \brief the title of the document parsed from the text. 3635 \brief the title of the document parsed from the text.
3609 3636
3610 For \c PlainText the title will be an empty string. For \c RichText 3637 For \c PlainText the title will be an empty string. For \c RichText
3611 the title will be the text between the \c{<title>} tags, if present, 3638 the title will be the text between the \c{<title>} tags, if present,
3612 otherwise an empty string. 3639 otherwise an empty string.
3613*/ 3640*/
3614 3641
3615QString QTextEdit::documentTitle() const 3642QString QTextEdit::documentTitle() const
3616{ 3643{
3617 return doc->attributes()[ "title" ]; 3644 return doc->attributes()[ "title" ];
3618} 3645}
3619 3646
3620void QTextEdit::makeParagVisible( QTextParag *p ) 3647void QTextEdit::makeParagVisible( QTextParagraph *p )
3621{ 3648{
3622 setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); 3649 setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) );
3623} 3650}
3624 3651
3625/*! Scrolls the text edit to make the text at the anchor called \a name 3652/*! Scrolls the text edit to make the text at the anchor called \a name
3626 visible, if it can be found in the document. If the anchor isn't found 3653 visible, if it can be found in the document. If the anchor isn't found
3627 no scrolling will occur. An anchor is defined using the HTML anchor 3654 no scrolling will occur. An anchor is defined using the HTML anchor
3628 tag, e.g. \c{<a name="target">}. 3655 tag, e.g. \c{<a name="target">}.
3629*/ 3656*/
3630 3657
3631void QTextEdit::scrollToAnchor( const QString& name ) 3658void QTextEdit::scrollToAnchor( const QString& name )
3632{ 3659{
3660 if ( !isVisible() ) {
3661 d->scrollToAnchor = name;
3662 return;
3663 }
3633 if ( name.isEmpty() ) 3664 if ( name.isEmpty() )
3634 return; 3665 return;
3635 sync(); 3666 sync();
3636 QTextCursor cursor( doc ); 3667 QTextCursor cursor( doc );
3637 QTextParag* last = doc->lastParag(); 3668 QTextParagraph* last = doc->lastParagraph();
3638 do { 3669 for (;;) {
3639 QTextStringChar* c = cursor.parag()->at( cursor.index() ); 3670 QTextStringChar* c = cursor.paragraph()->at( cursor.index() );
3640 if( c->isAnchor() ) { 3671 if( c->isAnchor() ) {
3641 QString a = c->anchorName(); 3672 QString a = c->anchorName();
3642 if ( a == name || 3673 if ( a == name ||
3643 (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) { 3674 (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) {
3644 setContentsPos( contentsX(), QMIN( cursor.parag()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); 3675 setContentsPos( contentsX(), QMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) );
3645 return; 3676 break;
3646 } 3677 }
3647 } 3678 }
3679 if ( cursor.paragraph() == last && cursor.atParagEnd() )
3680 break;
3648 cursor.gotoNextLetter(); 3681 cursor.gotoNextLetter();
3649 } while( cursor.parag() != last || !cursor.atParagEnd() ); 3682 }
3650} 3683}
3651 3684
3652/*! If there is an anchor at position \a pos (in contents 3685/*! If there is an anchor at position \a pos (in contents
3653 coordinates), its name is returned, otherwise an empty string is 3686 coordinates), its name is returned, otherwise an empty string is
3654 returned. 3687 returned.
3655*/ 3688*/
3656 3689
3657QString QTextEdit::anchorAt( const QPoint& pos ) 3690QString QTextEdit::anchorAt( const QPoint& pos )
3658{ 3691{
3659 QTextCursor c( doc ); 3692 QTextCursor c( doc );
3660 placeCursor( pos, &c ); 3693 placeCursor( pos, &c );
3661 return c.parag()->at( c.index() )->anchorHref(); 3694 return c.paragraph()->at( c.index() )->anchorHref();
3662} 3695}
3663 3696
3664void QTextEdit::documentWidthChanged( int w ) 3697void QTextEdit::documentWidthChanged( int w )
3665{ 3698{
3666 resizeContents( QMAX( visibleWidth(), w), contentsHeight() ); 3699 resizeContents( QMAX( visibleWidth(), w), contentsHeight() );
3667} 3700}
3668 3701
3669/*! 3702/*! \internal
3670 Updates all the rendering styles used to display the text. You will 3703
3671 probably want to call this function after calling setStyleSheet(). 3704 This function does nothing
3672*/ 3705*/
3673 3706
3674void QTextEdit::updateStyles() 3707void QTextEdit::updateStyles()
3675{ 3708{
3676 doc->updateStyles();
3677 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3678} 3709}
3679 3710
3680void QTextEdit::setDocument( QTextDocument *dc ) 3711void QTextEdit::setDocument( QTextDocument *dc )
3681{ 3712{
3682 if ( dc == doc ) 3713 if ( dc == doc )
3683 return; 3714 return;
3684 doc = dc; 3715 doc = dc;
3685 cursor->setDocument( doc ); 3716 delete cursor;
3717 cursor = new QTextCursor( doc );
3686 clearUndoRedo(); 3718 clearUndoRedo();
3719 undoRedoInfo.doc = doc;
3687 lastFormatted = 0; 3720 lastFormatted = 0;
3688} 3721}
3689 3722
3690#ifndef QT_NO_CLIPBOARD 3723#ifndef QT_NO_CLIPBOARD
3691 3724
3692/*! 3725/*!
3693 Pastes the text with format \a subtype from the clipboard into the 3726 Pastes the text with format \a subtype from the clipboard into the
3694 text edit at the current cursor position. The \a subtype can be 3727 text edit at the current cursor position. The \a subtype can be
3695 "plain" or "html". 3728 "plain" or "html".
3696 3729
3697 If there is no text with format \a subtype in the clipboard nothing 3730 If there is no text with format \a subtype in the clipboard nothing
3698 happens. 3731 happens.
3699 3732
3700 \sa paste() cut() QTextEdit::copy() 3733 \sa paste() cut() QTextEdit::copy()
3701*/ 3734*/
3702void QTextEdit::pasteSubType( const QCString& subtype ) 3735void QTextEdit::pasteSubType( const QCString& subtype )
3703{ 3736{
3704 QCString st = subtype; 3737 QCString st = subtype;
3705 QString t = QApplication::clipboard()->text(st); 3738 QString t = QApplication::clipboard()->text(st);
3739 if ( doc->hasSelection( QTextDocument::Standard ) )
3740 removeSelectedText();
3706 if ( !t.isEmpty() ) { 3741 if ( !t.isEmpty() ) {
3742 if ( t.startsWith( "<selstart/>" ) ) {
3743 t.remove( 0, 11 );
3744 QTextCursor oldC = *cursor;
3745 lastFormatted = cursor->paragraph();
3746 if ( lastFormatted->prev() )
3747 lastFormatted = lastFormatted->prev();
3748 doc->setRichTextInternal( t, cursor );
3749
3750 if ( undoEnabled && !isReadOnly() ) {
3751 doc->setSelectionStart( QTextDocument::Temp, oldC );
3752 doc->setSelectionEnd( QTextDocument::Temp, *cursor );
3753
3754 checkUndoRedoInfo( UndoRedoInfo::Insert );
3755 if ( !undoRedoInfo.valid() ) {
3756 undoRedoInfo.id = oldC.paragraph()->paragId();
3757 undoRedoInfo.index = oldC.index();
3758 undoRedoInfo.d->text = QString::null;
3759 }
3760 int oldLen = undoRedoInfo.d->text.length();
3761 if ( !doc->preProcessor() ) {
3762 QString txt = doc->selectedText( QTextDocument::Temp );
3763 undoRedoInfo.d->text += txt;
3764 for ( int i = 0; i < (int)txt.length(); ++i ) {
3765 if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) {
3766 oldC.paragraph()->at( oldC.index() )->format()->addRef();
3767 undoRedoInfo.d->text.
3768 setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE );
3769 }
3770 oldC.gotoNextLetter();
3771 }
3772 }
3773 undoRedoInfo.clear();
3774 removeSelection( QTextDocument::Temp );
3775 }
3776
3777 formatMore();
3778 setModified();
3779 emit textChanged();
3780 repaintChanged();
3781 ensureCursorVisible();
3782 return;
3783 }
3784
3707#if defined(Q_OS_WIN32) 3785#if defined(Q_OS_WIN32)
3708 // Need to convert CRLF to LF 3786 // Need to convert CRLF to LF
3709 int index = t.find( QString::fromLatin1("\r\n"), 0 ); 3787 int index = t.find( QString::fromLatin1("\r\n"), 0 );
3710 while ( index != -1 ) { 3788 while ( index != -1 ) {
3711 t.replace( index, 2, QChar('\n') ); 3789 t.replace( index, 2, QChar('\n') );
3712 index = t.find( "\r\n", index ); 3790 index = t.find( "\r\n", index );
3713 } 3791 }
3714#elif defined(Q_OS_MAC) 3792#elif defined(Q_OS_MAC)
3715 //need to convert CR to LF 3793 //need to convert CR to LF
3716 for( unsigned int index = 0; index < t.length(); index++ ) 3794 for( unsigned int index = 0; index < t.length(); index++ )
3717 if(t[index] == '\r') 3795 if(t[index] == '\r')
3718 t[index] = '\n'; 3796 t[index] = '\n';
3719#endif 3797#endif
3720 for ( int i=0; (uint) i<t.length(); i++ ) { 3798 for ( int i=0; (uint) i<t.length(); i++ ) {
3721 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' ) 3799 if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' )
3722 t[ i ] = ' '; 3800 t[ i ] = ' ';
3723 } 3801 }
3724 if ( !t.isEmpty() ) 3802 if ( !t.isEmpty() )
3725 insert( t, FALSE, TRUE, TRUE ); 3803 insert( t, FALSE, TRUE, TRUE );
3726 } 3804 }
3727} 3805}
3728 3806
3729#ifndef QT_NO_MIMECLIPBOARD 3807#ifndef QT_NO_MIMECLIPBOARD
3730/*! 3808/*!
3731 Prompts the user to choose a type from a list of text types available, 3809 Prompts the user to choose a type from a list of text types available,
3732 then copies text from the clipboard (if there is any) into the text 3810 then copies text from the clipboard (if there is any) into the text
3733 edit at the current text cursor position. Any selected text (in 3811 edit at the current text cursor position. Any selected text (in
3734 selection 0) is first deleted. 3812 selection 0) is first deleted.
3735*/ 3813*/
3736void QTextEdit::pasteSpecial( const QPoint& pt ) 3814void QTextEdit::pasteSpecial( const QPoint& pt )
3737{ 3815{
3738 QCString st = pickSpecial( QApplication::clipboard()->data(), TRUE, pt ); 3816 QCString st = pickSpecial( QApplication::clipboard()->data(), TRUE, pt );
@@ -3809,414 +3887,416 @@ QCString QTextEdit::pickSpecial( QMimeSource* ms, bool always_ask, const QPoint&
3809 80. 3887 80.
3810 3888
3811 \sa setWordWrap() wordWrap() 3889 \sa setWordWrap() wordWrap()
3812*/ 3890*/
3813 3891
3814/*! 3892/*!
3815 \property QTextEdit::wordWrap 3893 \property QTextEdit::wordWrap
3816 \brief the word wrap mode 3894 \brief the word wrap mode
3817 3895
3818 The default mode is \c WidgetWidth which causes words to be wrapped 3896 The default mode is \c WidgetWidth which causes words to be wrapped
3819 at the right edge of the text edit. Wrapping occurs at whitespace, 3897 at the right edge of the text edit. Wrapping occurs at whitespace,
3820 keeping whole words intact. If you want wrapping to occur within 3898 keeping whole words intact. If you want wrapping to occur within
3821 words use setWrapPolicy(). If you set a wrap mode of \c 3899 words use setWrapPolicy(). If you set a wrap mode of \c
3822 FixedPixelWidth or \c FixedColumnWidth you should also call 3900 FixedPixelWidth or \c FixedColumnWidth you should also call
3823 setWrapColumnOrWidth() with the width you want. 3901 setWrapColumnOrWidth() with the width you want.
3824 3902
3825 \sa WordWrap, wrapColumnOrWidth, wrapPolicy, 3903 \sa WordWrap, wrapColumnOrWidth, wrapPolicy,
3826*/ 3904*/
3827 3905
3828void QTextEdit::setWordWrap( WordWrap mode ) 3906void QTextEdit::setWordWrap( WordWrap mode )
3829{ 3907{
3830 if ( wrapMode == mode ) 3908 if ( wrapMode == mode )
3831 return; 3909 return;
3832 wrapMode = mode; 3910 wrapMode = mode;
3833 switch ( mode ) { 3911 switch ( mode ) {
3834 case NoWrap: 3912 case NoWrap:
3835 document()->formatter()->setWrapEnabled( FALSE ); 3913 document()->formatter()->setWrapEnabled( FALSE );
3836 document()->formatter()->setWrapAtColumn( -1 ); 3914 document()->formatter()->setWrapAtColumn( -1 );
3837 doc->setWidth( visibleWidth() ); 3915 doc->setWidth( visibleWidth() );
3838 doc->setMinimumWidth( -1 ); 3916 doc->setMinimumWidth( -1 );
3839 doc->invalidate(); 3917 doc->invalidate();
3840 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3918 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3841 lastFormatted = doc->firstParag(); 3919 lastFormatted = doc->firstParagraph();
3842 interval = 0; 3920 interval = 0;
3843 formatMore(); 3921 formatMore();
3844 break; 3922 break;
3845 case WidgetWidth: 3923 case WidgetWidth:
3846 document()->formatter()->setWrapEnabled( TRUE ); 3924 document()->formatter()->setWrapEnabled( TRUE );
3847 document()->formatter()->setWrapAtColumn( -1 ); 3925 document()->formatter()->setWrapAtColumn( -1 );
3848 doResize(); 3926 doResize();
3849 break; 3927 break;
3850 case FixedPixelWidth: 3928 case FixedPixelWidth:
3851 document()->formatter()->setWrapEnabled( TRUE ); 3929 document()->formatter()->setWrapEnabled( TRUE );
3852 document()->formatter()->setWrapAtColumn( -1 ); 3930 document()->formatter()->setWrapAtColumn( -1 );
3853 if ( wrapWidth < 0 ) 3931 if ( wrapWidth < 0 )
3854 wrapWidth = 200; 3932 wrapWidth = 200;
3855 setWrapColumnOrWidth( wrapWidth ); 3933 setWrapColumnOrWidth( wrapWidth );
3856 break; 3934 break;
3857 case FixedColumnWidth: 3935 case FixedColumnWidth:
3858 if ( wrapWidth < 0 ) 3936 if ( wrapWidth < 0 )
3859 wrapWidth = 80; 3937 wrapWidth = 80;
3860 document()->formatter()->setWrapEnabled( TRUE ); 3938 document()->formatter()->setWrapEnabled( TRUE );
3861 document()->formatter()->setWrapAtColumn( wrapWidth ); 3939 document()->formatter()->setWrapAtColumn( wrapWidth );
3862 setWrapColumnOrWidth( wrapWidth ); 3940 setWrapColumnOrWidth( wrapWidth );
3863 break; 3941 break;
3864 } 3942 }
3865} 3943}
3866 3944
3867QTextEdit::WordWrap QTextEdit::wordWrap() const 3945QTextEdit::WordWrap QTextEdit::wordWrap() const
3868{ 3946{
3869 return wrapMode; 3947 return wrapMode;
3870} 3948}
3871 3949
3872/*! 3950/*!
3873 \property QTextEdit::wrapColumnOrWidth 3951 \property QTextEdit::wrapColumnOrWidth
3874 \brief the position (in pixels or columns depending on the wrap mode) where text will be wrapped 3952 \brief the position (in pixels or columns depending on the wrap mode) where text will be wrapped
3875 3953
3876 If the wrap mode is \c FixedPixelWidth, the value is the number 3954 If the wrap mode is \c FixedPixelWidth, the value is the number
3877 of pixels from the left edge of the text edit at which text should 3955 of pixels from the left edge of the text edit at which text should
3878 be wrapped. If the wrap mode is \c FixedColumnWidth, the value is 3956 be wrapped. If the wrap mode is \c FixedColumnWidth, the value is
3879 the column number (in character columns) from the left edge of the 3957 the column number (in character columns) from the left edge of the
3880 text edit at which text should be wrapped. 3958 text edit at which text should be wrapped.
3881 3959
3882 \sa wordWrap 3960 \sa wordWrap
3883 */ 3961 */
3884void QTextEdit::setWrapColumnOrWidth( int value ) 3962void QTextEdit::setWrapColumnOrWidth( int value )
3885{ 3963{
3886 wrapWidth = value; 3964 wrapWidth = value;
3887 if ( wrapMode == FixedColumnWidth ) { 3965 if ( wrapMode == FixedColumnWidth ) {
3888 document()->formatter()->setWrapAtColumn( wrapWidth ); 3966 document()->formatter()->setWrapAtColumn( wrapWidth );
3889 resizeContents( 0, 0 ); 3967 resizeContents( 0, 0 );
3890 doc->setWidth( visibleWidth() ); 3968 doc->setWidth( visibleWidth() );
3891 doc->setMinimumWidth( -1 ); 3969 doc->setMinimumWidth( -1 );
3892 } else if (wrapMode == FixedPixelWidth ) { 3970 } else if (wrapMode == FixedPixelWidth ) {
3893 document()->formatter()->setWrapAtColumn( -1 ); 3971 document()->formatter()->setWrapAtColumn( -1 );
3894 resizeContents( wrapWidth, 0 ); 3972 resizeContents( wrapWidth, 0 );
3895 doc->setWidth( wrapWidth ); 3973 doc->setWidth( wrapWidth );
3896 doc->setMinimumWidth( wrapWidth ); 3974 doc->setMinimumWidth( wrapWidth );
3897 } else { 3975 } else {
3898 return; 3976 return;
3899 } 3977 }
3900 doc->invalidate(); 3978 doc->invalidate();
3901 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 3979 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3902 lastFormatted = doc->firstParag(); 3980 lastFormatted = doc->firstParagraph();
3903 interval = 0; 3981 interval = 0;
3904 formatMore(); 3982 formatMore();
3905} 3983}
3906 3984
3907int QTextEdit::wrapColumnOrWidth() const 3985int QTextEdit::wrapColumnOrWidth() const
3908{ 3986{
3909 if ( wrapMode == WidgetWidth ) 3987 if ( wrapMode == WidgetWidth )
3910 return visibleWidth(); 3988 return visibleWidth();
3911 return wrapWidth; 3989 return wrapWidth;
3912} 3990}
3913 3991
3914 3992
3915/*! \enum QTextEdit::WrapPolicy 3993/*! \enum QTextEdit::WrapPolicy
3916 3994
3917 This enum defines where text can be wrapped in word wrap mode. 3995 This enum defines where text can be wrapped in word wrap mode.
3918 3996
3919 The following values are valid: 3997 The following values are valid:
3920 \value AtWhiteSpace Break lines at whitespace, e.g. spaces or 3998 \value AtWhiteSpace Break lines at whitespace, e.g. spaces or
3921 newlines. 3999 newlines.
3922 \value Anywhere Break anywhere, including within words. 4000 \value Anywhere Break anywhere, including within words.
3923 \value AtWordBoundary Don't use this deprecated value (it is a 4001 \value AtWordBoundary Don't use this deprecated value (it is a
3924 synonym for AtWhiteSpace which you should use instead). 4002 synonym for AtWhiteSpace which you should use instead).
3925 4003
3926 \sa setWrapPolicy() 4004 \sa setWrapPolicy()
3927*/ 4005*/
3928 4006
3929/*! 4007/*!
3930 \property QTextEdit::wrapPolicy 4008 \property QTextEdit::wrapPolicy
3931 \brief the word wrap policy, at whitespace or anywhere 4009 \brief the word wrap policy, at whitespace or anywhere
3932 4010
3933 Defines where text can be wrapped when word wrap mode is not 4011 Defines where text can be wrapped when word wrap mode is not
3934 \c NoWrap. The choices are \c AtWhiteSpace (the default) and \c 4012 \c NoWrap. The choices are \c AtWhiteSpace (the default) and \c
3935 Anywhere. 4013 Anywhere.
3936 4014
3937 \sa wordWrap 4015 \sa wordWrap
3938 */ 4016 */
3939 4017
3940void QTextEdit::setWrapPolicy( WrapPolicy policy ) 4018void QTextEdit::setWrapPolicy( WrapPolicy policy )
3941{ 4019{
3942 if ( wPolicy == policy ) 4020 if ( wPolicy == policy )
3943 return; 4021 return;
3944 wPolicy = policy; 4022 wPolicy = policy;
3945 QTextFormatter *formatter; 4023 QTextFormatter *formatter;
3946 if ( policy == AtWhiteSpace ) 4024 if ( policy == AtWhiteSpace )
3947 formatter = new QTextFormatterBreakWords; 4025 formatter = new QTextFormatterBreakWords;
3948 else 4026 else
3949 formatter = new QTextFormatterBreakInWords; 4027 formatter = new QTextFormatterBreakInWords;
3950 formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() ); 4028 formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() );
3951 formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) ); 4029 formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) );
3952 document()->setFormatter( formatter ); 4030 document()->setFormatter( formatter );
3953 doc->invalidate(); 4031 doc->invalidate();
3954 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4032 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3955 lastFormatted = doc->firstParag(); 4033 lastFormatted = doc->firstParagraph();
3956 interval = 0; 4034 interval = 0;
3957 formatMore(); 4035 formatMore();
3958} 4036}
3959 4037
3960QTextEdit::WrapPolicy QTextEdit::wrapPolicy() const 4038QTextEdit::WrapPolicy QTextEdit::wrapPolicy() const
3961{ 4039{
3962 return wPolicy; 4040 return wPolicy;
3963} 4041}
3964 4042
3965/*! 4043/*!
3966 Deletes all the text in the text edit. 4044 Deletes all the text in the text edit.
3967 4045
3968 \sa cut() removeSelectedText() setText() 4046 \sa cut() removeSelectedText() setText()
3969 4047
3970*/ 4048*/
3971 4049
3972void QTextEdit::clear() 4050void QTextEdit::clear()
3973{ 4051{
3974 // make clear undoable 4052 // make clear undoable
3975 doc->selectAll( QTextDocument::Temp ); 4053 doc->selectAll( QTextDocument::Temp );
3976 removeSelectedText( QTextDocument::Temp ); 4054 removeSelectedText( QTextDocument::Temp );
3977 4055
3978 setContentsPos( 0, 0 ); 4056 setContentsPos( 0, 0 );
3979 if ( cursor->isValid() ) 4057 if ( cursor->isValid() )
3980 cursor->restoreState(); 4058 cursor->restoreState();
3981 doc->clear( TRUE ); 4059 doc->clear( TRUE );
3982 cursor->setDocument( doc ); 4060 delete cursor;
3983 cursor->setParag( doc->firstParag() ); 4061 cursor = new QTextCursor( doc );
3984 cursor->setIndex( 0 );
3985 lastFormatted = 0; 4062 lastFormatted = 0;
3986 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4063 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
3987 4064
3988 emit cursorPositionChanged( cursor ); 4065 emit cursorPositionChanged( cursor );
3989 emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); 4066 emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() );
3990} 4067}
3991 4068
3992int QTextEdit::undoDepth() const 4069int QTextEdit::undoDepth() const
3993{ 4070{
3994 return document()->undoDepth(); 4071 return document()->undoDepth();
3995} 4072}
3996 4073
3997/*! 4074/*!
3998 \property QTextEdit::length 4075 \property QTextEdit::length
3999 \brief the number of characters in the text 4076 \brief the number of characters in the text
4000 4077
4001*/ 4078*/
4002 4079
4003int QTextEdit::length() const 4080int QTextEdit::length() const
4004{ 4081{
4005 return document()->length(); 4082 return document()->length();
4006} 4083}
4007 4084
4008/*! 4085/*!
4009 \property QTextEdit::tabStopWidth 4086 \property QTextEdit::tabStopWidth
4010 \brief the tab stop width in pixels 4087 \brief the tab stop width in pixels
4011 4088
4012*/ 4089*/
4013 4090
4014int QTextEdit::tabStopWidth() const 4091int QTextEdit::tabStopWidth() const
4015{ 4092{
4016 return document()->tabStopWidth(); 4093 return document()->tabStopWidth();
4017} 4094}
4018 4095
4019void QTextEdit::setUndoDepth( int d ) 4096void QTextEdit::setUndoDepth( int d )
4020{ 4097{
4021 document()->setUndoDepth( d ); 4098 document()->setUndoDepth( d );
4022} 4099}
4023 4100
4024void QTextEdit::setTabStopWidth( int ts ) 4101void QTextEdit::setTabStopWidth( int ts )
4025{ 4102{
4026 document()->setTabStops( ts ); 4103 document()->setTabStops( ts );
4027 doc->invalidate(); 4104 doc->invalidate();
4028 lastFormatted = doc->firstParag(); 4105 lastFormatted = doc->firstParagraph();
4029 interval = 0; 4106 interval = 0;
4030 formatMore(); 4107 formatMore();
4031 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4108 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
4032} 4109}
4033 4110
4034/*! \reimp */ 4111/*! \reimp */
4035 4112
4036QSize QTextEdit::sizeHint() const 4113QSize QTextEdit::sizeHint() const
4037{ 4114{
4038 // ### calculate a reasonable one 4115 // ### calculate a reasonable one
4039 return QSize( 100, 100 ); 4116 return QSize( 100, 100 );
4040} 4117}
4041 4118
4042void QTextEdit::clearUndoRedo() 4119void QTextEdit::clearUndoRedo()
4043{ 4120{
4044 undoRedoInfo.clear(); 4121 undoRedoInfo.clear();
4045 emit undoAvailable( doc->commands()->isUndoAvailable() ); 4122 emit undoAvailable( doc->commands()->isUndoAvailable() );
4046 emit redoAvailable( doc->commands()->isRedoAvailable() ); 4123 emit redoAvailable( doc->commands()->isRedoAvailable() );
4047} 4124}
4048 4125
4049/*! This function gets the format of the character at position \a 4126/*! \internal
4127
4128 \warning In Qt 3.1 we will provide a cleaer API for the
4129 functionality which is provided by this function and in Qt 4.0 this
4130 function will go away.
4131
4132 This function gets the format of the character at position \a
4050 index in paragraph \a para. Sets \a font to the character's font, \a 4133 index in paragraph \a para. Sets \a font to the character's font, \a
4051 color to the character's color and \a verticalAlignment to the 4134 color to the character's color and \a verticalAlignment to the
4052 character's vertical alignment. 4135 character's vertical alignment.
4053 4136
4054 Returns FALSE if \a para or \a index is out of range otherwise 4137 Returns FALSE if \a para or \a index is out of range otherwise
4055 returns TRUE. 4138 returns TRUE.
4056*/ 4139*/
4057 4140
4058bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment ) 4141bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment )
4059{ 4142{
4060 if ( !font || !color ) 4143 if ( !font || !color )
4061 return FALSE; 4144 return FALSE;
4062 QTextParag *p = doc->paragAt( para ); 4145 QTextParagraph *p = doc->paragAt( para );
4063 if ( !p ) 4146 if ( !p )
4064 return FALSE; 4147 return FALSE;
4065 if ( index < 0 || index >= p->length() ) 4148 if ( index < 0 || index >= p->length() )
4066 return FALSE; 4149 return FALSE;
4067 *font = p->at( index )->format()->font(); 4150 *font = p->at( index )->format()->font();
4068 *color = p->at( index )->format()->color(); 4151 *color = p->at( index )->format()->color();
4069 *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign(); 4152 *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign();
4070 return TRUE; 4153 return TRUE;
4071} 4154}
4072 4155
4073/*! This function gets the format of the paragraph \a para. Sets \a 4156/*! \internal
4157
4158 \warning In Qt 3.1 we will provide a cleaer API for the
4159 functionality which is provided by this function and in Qt 4.0 this
4160 function will go away.
4161
4162 This function gets the format of the paragraph \a para. Sets \a
4074 font to the paragraphs's font, \a color to the paragraph's color, \a 4163 font to the paragraphs's font, \a color to the paragraph's color, \a
4075 verticalAlignment to the paragraph's vertical alignment, \a 4164 verticalAlignment to the paragraph's vertical alignment, \a
4076 alignment to the paragraph's alignment, \a displayMode to the 4165 alignment to the paragraph's alignment, \a displayMode to the
4077 paragraph's display mode, \a listStyle to the paragraph's list style 4166 paragraph's display mode, \a listStyle to the paragraph's list style
4078 (if the display mode is QStyleSheetItem::DisplayListItem) and \a 4167 (if the display mode is QStyleSheetItem::DisplayListItem) and \a
4079 listDepth to the depth of the list (if the display mode is 4168 listDepth to the depth of the list (if the display mode is
4080 QStyleSheetItem::DisplayListItem). 4169 QStyleSheetItem::DisplayListItem).
4081 4170
4082 Returns FALSE if \a para is out of range otherwise returns TRUE. 4171 Returns FALSE if \a para is out of range otherwise returns TRUE.
4083*/ 4172*/
4084 4173
4085bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color, 4174bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color,
4086 VerticalAlignment *verticalAlignment, int *alignment, 4175 VerticalAlignment *verticalAlignment, int *alignment,
4087 QStyleSheetItem::DisplayMode *displayMode, 4176 QStyleSheetItem::DisplayMode *displayMode,
4088 QStyleSheetItem::ListStyle *listStyle, 4177 QStyleSheetItem::ListStyle *listStyle,
4089 int *listDepth ) 4178 int *listDepth )
4090{ 4179{
4091 if ( !font || !color || !alignment || !displayMode || !listStyle ) 4180 if ( !font || !color || !alignment || !displayMode || !listStyle )
4092 return FALSE; 4181 return FALSE;
4093 QTextParag *p = doc->paragAt( para ); 4182 QTextParagraph *p = doc->paragAt( para );
4094 if ( !p ) 4183 if ( !p )
4095 return FALSE; 4184 return FALSE;
4096 *font = p->paragFormat()->font(); 4185 *font = p->at(0)->format()->font();
4097 *color = p->paragFormat()->color(); 4186 *color = p->at(0)->format()->color();
4098 *verticalAlignment = (VerticalAlignment)p->paragFormat()->vAlign(); 4187 *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign();
4099 *alignment = p->alignment(); 4188 *alignment = p->alignment();
4100 *displayMode = p->style() ? p->style()->displayMode() : QStyleSheetItem::DisplayBlock; 4189 *displayMode = p->isListItem() ? QStyleSheetItem::DisplayListItem : QStyleSheetItem::DisplayBlock;
4101 *listStyle = p->listStyle(); 4190 *listStyle = p->listStyle();
4102 *listDepth = p->listDepth(); 4191 *listDepth = p->listDepth();
4103 return TRUE; 4192 return TRUE;
4104} 4193}
4105 4194
4106 4195
4107 4196
4108/*! 4197/*!
4109 4198
4110 This function is called to create a right mouse button popup menu 4199 This function is called to create a right mouse button popup menu
4111 at the document position \a pos. If you want to create a custom 4200 at the document position \a pos. If you want to create a custom
4112 popup menu, reimplement this function and return the created 4201 popup menu, reimplement this function and return the created
4113 popup menu. Ownership of the popup menu is transferred to the 4202 popup menu. Ownership of the popup menu is transferred to the
4114 caller. 4203 caller.
4115*/ 4204*/
4116 4205
4117QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) 4206QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos )
4118{ 4207{
4119#ifndef QT_NO_POPUPMENU 4208#ifndef QT_NO_POPUPMENU
4120 QPopupMenu *popup = new QPopupMenu( this, "qt_edit_menu" ); 4209 QPopupMenu *popup = new QPopupMenu( this, "qt_edit_menu" );
4121 if ( !isReadOnly() ) { 4210 if ( !isReadOnly() ) {
4122 d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) ); 4211 d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) );
4123 d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) ); 4212 d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) );
4124 popup->insertSeparator(); 4213 popup->insertSeparator();
4125 } 4214 }
4126#ifndef QT_NO_CLIPBOARD 4215#ifndef QT_NO_CLIPBOARD
4127 if ( !isReadOnly() ) 4216 if ( !isReadOnly() )
4128 d->id[ IdCut ] = popup->insertItem( tr( "Cu&t" ) + ACCEL_KEY( X ) ); 4217 d->id[ IdCut ] = popup->insertItem( tr( "Cu&t" ) + ACCEL_KEY( X ) );
4129 d->id[ IdCopy ] = popup->insertItem( tr( "&Copy" ) + ACCEL_KEY( C ) ); 4218 d->id[ IdCopy ] = popup->insertItem( tr( "&Copy" ) + ACCEL_KEY( C ) );
4130 if ( !isReadOnly() ) 4219 if ( !isReadOnly() )
4131 d->id[ IdPaste ] = popup->insertItem( tr( "&Paste" ) + ACCEL_KEY( V ) ); 4220 d->id[ IdPaste ] = popup->insertItem( tr( "&Paste" ) + ACCEL_KEY( V ) );
4132#endif 4221#endif
4133 if ( !isReadOnly() ) { 4222 if ( !isReadOnly() ) {
4134 d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) ); 4223 d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) );
4135 popup->insertSeparator(); 4224 popup->insertSeparator();
4136 } 4225 }
4137#if defined(Q_WS_X11) 4226#if defined(Q_WS_X11)
4138 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) ); 4227 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) );
4139#else 4228#else
4140 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) ); 4229 d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) );
4141#endif 4230#endif
4142 popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() ); 4231 popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() );
4143 popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() ); 4232 popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() );
4144#ifndef QT_NO_CLIPBOARD 4233#ifndef QT_NO_CLIPBOARD
4145 popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( QTextDocument::Standard, TRUE ) ); 4234 popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( QTextDocument::Standard, TRUE ) );
4146 popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( QTextDocument::Standard, TRUE ) ); 4235 popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( QTextDocument::Standard, TRUE ) );
4147 popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !QApplication::clipboard()->text().isEmpty() ); 4236 popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
4148#endif 4237#endif
4149 popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !text().isEmpty() ); 4238 popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !text().isEmpty() );
4150 popup->setItemEnabled( d->id[ IdSelectAll ], (bool)text().length() ); 4239 popup->setItemEnabled( d->id[ IdSelectAll ], (bool)text().length() );
4151 return popup; 4240 return popup;
4152#else 4241#else
4153 return 0; 4242 return 0;
4154#endif 4243#endif
4155} 4244}
4156 4245
4157/*! \overload 4246/*! \overload
4247 \obsolete
4158 This function is called to create a right mouse button popup menu. 4248 This function is called to create a right mouse button popup menu.
4159 If you want to create a custom popup menu, reimplement this function 4249 If you want to create a custom popup menu, reimplement this function
4160 and return the created popup menu. Ownership of the popup menu is 4250 and return the created popup menu. Ownership of the popup menu is
4161 transferred to the caller. 4251 transferred to the caller.
4252
4253 This function is only called if createPopupMenu( const QPoint & )
4254 returns 0.
4162*/ 4255*/
4163 4256
4164QPopupMenu *QTextEdit::createPopupMenu() 4257QPopupMenu *QTextEdit::createPopupMenu()
4165{ 4258{
4166 return 0; 4259 return 0;
4167} 4260}
4168 4261
4169/*! \reimp */ 4262/*! \reimp */
4170 4263
4171void QTextEdit::setFont( const QFont &f ) 4264void QTextEdit::setFont( const QFont &f )
4172{ 4265{
4173 QFont old( QScrollView::font() ); 4266 QFont old( QScrollView::font() );
4174 QScrollView::setFont( f ); 4267 QScrollView::setFont( f );
4175 doc->setMinimumWidth( -1 ); 4268 doc->setMinimumWidth( -1 );
4176 4269 doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() );
4177 // ### that is a bit hacky 4270 lastFormatted = doc->firstParagraph();
4178 static short diff = 1;
4179 diff *= -1;
4180 doc->setWidth( visibleWidth() + diff );
4181
4182 int s = f.pointSize();
4183 bool usePixels = FALSE;
4184 if ( s == -1 ) {
4185 s = f.pixelSize();
4186 usePixels = TRUE;
4187 }
4188 doc->updateFontSizes( s, usePixels );
4189 doc->updateFontAttributes( f, old );
4190 lastFormatted = doc->firstParag();
4191 formatMore(); 4271 formatMore();
4192 repaintChanged(); 4272 repaintChanged();
4193} 4273}
4194 4274
4195/*! \fn QTextEdit::zoomIn() 4275/*! \fn QTextEdit::zoomIn()
4196 4276
4197 \overload 4277 \overload
4198 4278
4199 Zooms in on the text by by making the base font size one 4279 Zooms in on the text by by making the base font size one
4200 point larger and recalculating all font sizes. This does not change 4280 point larger and recalculating all font sizes. This does not change
4201 the size of any images. 4281 the size of any images.
4202 4282
4203 \sa zoomOut() 4283 \sa zoomOut()
4204 4284
4205*/ 4285*/
4206 4286
4207/*! \fn QTextEdit::zoomOut() 4287/*! \fn QTextEdit::zoomOut()
4208 4288
4209 \overload 4289 \overload
4210 4290
4211 Zooms out on the text by by making the base font size one 4291 Zooms out on the text by by making the base font size one
4212 point smaller and recalculating all font sizes. This does not change 4292 point smaller and recalculating all font sizes. This does not change
4213 the size of any images. 4293 the size of any images.
4214 4294
4215 \sa zoomIn() 4295 \sa zoomIn()
4216*/ 4296*/
4217 4297
4218 4298
4219/*! 4299/*!
4220 Zooms in on the text by by making the base font size \a range 4300 Zooms in on the text by by making the base font size \a range
4221 points larger and recalculating all font sizes. This does not change 4301 points larger and recalculating all font sizes. This does not change
4222 the size of any images. 4302 the size of any images.
@@ -4244,68 +4324,67 @@ void QTextEdit::zoomOut( int range )
4244 f.setPointSize( QMAX( 1, f.pointSize() - range ) ); 4324 f.setPointSize( QMAX( 1, f.pointSize() - range ) );
4245 setFont( f ); 4325 setFont( f );
4246} 4326}
4247 4327
4248/*! Zooms the text by making the base font size \a size points and 4328/*! Zooms the text by making the base font size \a size points and
4249 recalculating all font sizes. This does not change the size of any 4329 recalculating all font sizes. This does not change the size of any
4250 images. 4330 images.
4251*/ 4331*/
4252 4332
4253void QTextEdit::zoomTo( int size ) 4333void QTextEdit::zoomTo( int size )
4254{ 4334{
4255 QFont f( QScrollView::font() ); 4335 QFont f( QScrollView::font() );
4256 f.setPointSize( size ); 4336 f.setPointSize( size );
4257 setFont( f ); 4337 setFont( f );
4258} 4338}
4259 4339
4260/*! 4340/*!
4261 \internal 4341 \internal
4262 4342
4263 QTextEdit is optimized for large amounts text. One of its 4343 QTextEdit is optimized for large amounts text. One of its
4264 optimizations is to format only the visible text, formatting the rest 4344 optimizations is to format only the visible text, formatting the rest
4265 on demand, e.g. as the user scrolls, so you don't usually need to 4345 on demand, e.g. as the user scrolls, so you don't usually need to
4266 call this function. 4346 call this function.
4267 4347
4268 In some situations you may want to force the whole text 4348 In some situations you may want to force the whole text
4269 to be formatted. For example, if after calling setText(), you wanted 4349 to be formatted. For example, if after calling setText(), you wanted
4270 to know the height of the document (using contentsHeight()), you 4350 to know the height of the document (using contentsHeight()), you
4271 would call this function first. 4351 would call this function first.
4272*/ 4352*/
4273 4353
4274void QTextEdit::sync() 4354void QTextEdit::sync()
4275{ 4355{
4276 QTextParag *p = lastFormatted; 4356 while ( lastFormatted ) {
4277 while ( p ) { 4357 lastFormatted->format();
4278 p->format(); 4358 lastFormatted = lastFormatted->next();
4279 p = p->next();
4280 } 4359 }
4281 resizeContents( contentsWidth(), doc->height() ); 4360 resizeContents( contentsWidth(), doc->height() );
4282} 4361}
4283 4362
4284/*! \reimp */ 4363/*! \reimp */
4285 4364
4286void QTextEdit::setEnabled( bool b ) 4365void QTextEdit::setEnabled( bool b )
4287{ 4366{
4288 QScrollView::setEnabled( b ); 4367 QScrollView::setEnabled( b );
4289 if ( !b ) { 4368 if ( !b ) {
4290 blinkTimer->stop(); 4369 blinkTimer->stop();
4291 drawCursor( FALSE ); 4370 drawCursor( FALSE );
4292 } 4371 }
4293 if ( textFormat() == PlainText ) { 4372 if ( textFormat() == PlainText ) {
4294 QTextFormat *f = doc->formatCollection()->defaultFormat(); 4373 QTextFormat *f = doc->formatCollection()->defaultFormat();
4295 f->setColor( colorGroup().text() ); 4374 f->setColor( colorGroup().text() );
4296 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); 4375 updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
4297 } 4376 }
4298 if ( b ) { 4377 if ( b ) {
4299 blinkTimer->start( QApplication::cursorFlashTime() / 2 ); 4378 blinkTimer->start( QApplication::cursorFlashTime() / 2 );
4300 drawCursor( TRUE ); 4379 drawCursor( TRUE );
4301 } 4380 }
4302} 4381}
4303 4382
4304/*! 4383/*!
4305 Sets the background color of selection number \a selNum to \a back and 4384 Sets the background color of selection number \a selNum to \a back and
4306 specifies whether the text of this selection should be inverted with \a 4385 specifies whether the text of this selection should be inverted with \a
4307 invertText. 4386 invertText.
4308 4387
4309 This only works for \a selNum > 0. The default selection (\a selNum == 4388 This only works for \a selNum > 0. The default selection (\a selNum ==
4310 0) gets its attributes from the colorGroup() of this widget. 4389 0) gets its attributes from the colorGroup() of this widget.
4311*/ 4390*/
@@ -4331,186 +4410,186 @@ void QTextEdit::windowActivationChange( bool )
4331} 4410}
4332 4411
4333void QTextEdit::setReadOnly( bool b ) 4412void QTextEdit::setReadOnly( bool b )
4334{ 4413{
4335 if ( readonly == b ) 4414 if ( readonly == b )
4336 return; 4415 return;
4337 readonly = b; 4416 readonly = b;
4338#ifndef QT_NO_CURSOR 4417#ifndef QT_NO_CURSOR
4339 if ( readonly ) 4418 if ( readonly )
4340 viewport()->setCursor( arrowCursor ); 4419 viewport()->setCursor( arrowCursor );
4341 else 4420 else
4342 viewport()->setCursor( ibeamCursor ); 4421 viewport()->setCursor( ibeamCursor );
4343#endif 4422#endif
4344} 4423}
4345 4424
4346/*! Scrolls to the bottom of the document and does formatting if 4425/*! Scrolls to the bottom of the document and does formatting if
4347 required */ 4426 required */
4348 4427
4349void QTextEdit::scrollToBottom() 4428void QTextEdit::scrollToBottom()
4350{ 4429{
4351 sync(); 4430 sync();
4352 setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); 4431 setContentsPos( contentsX(), contentsHeight() - visibleHeight() );
4353} 4432}
4354 4433
4355/*! Returns the rectangle of the paragraph \a para in contents 4434/*! Returns the rectangle of the paragraph \a para in contents
4356 coordinates, or an invalid rectangle if \a para is out of range. 4435 coordinates, or an invalid rectangle if \a para is out of range.
4357*/ 4436*/
4358 4437
4359QRect QTextEdit::paragraphRect( int para ) const 4438QRect QTextEdit::paragraphRect( int para ) const
4360{ 4439{
4361 QTextEdit *that = (QTextEdit *)this; 4440 QTextEdit *that = (QTextEdit *)this;
4362 that->sync(); 4441 that->sync();
4363 QTextParag *p = doc->paragAt( para ); 4442 QTextParagraph *p = doc->paragAt( para );
4364 if ( !p ) 4443 if ( !p )
4365 return QRect( -1, -1, -1, -1 ); 4444 return QRect( -1, -1, -1, -1 );
4366 return p->rect(); 4445 return p->rect();
4367} 4446}
4368 4447
4369/*! 4448/*!
4370 Returns the paragraph which is at position \a pos (in contents 4449 Returns the paragraph which is at position \a pos (in contents
4371 coordinates), or -1 if there is no paragraph with index \a pos. 4450 coordinates), or -1 if there is no paragraph with index \a pos.
4372*/ 4451*/
4373 4452
4374int QTextEdit::paragraphAt( const QPoint &pos ) const 4453int QTextEdit::paragraphAt( const QPoint &pos ) const
4375{ 4454{
4376 QTextCursor c( doc ); 4455 QTextCursor c( doc );
4377 c.place( pos, doc->firstParag() ); 4456 c.place( pos, doc->firstParagraph() );
4378 if ( c.parag() ) 4457 if ( c.paragraph() )
4379 return c.parag()->paragId(); 4458 return c.paragraph()->paragId();
4380 return -1; 4459 return -1;
4381} 4460}
4382 4461
4383/*! 4462/*!
4384 Returns the index of the character (relative to its paragraph) at 4463 Returns the index of the character (relative to its paragraph) at
4385 position \a pos (in contents coordinates). If \a para is not null, 4464 position \a pos (in contents coordinates). If \a para is not null,
4386 \e *\a para is set to this paragraph. If there is no character at 4465 \e *\a para is set to this paragraph. If there is no character at
4387 \a pos, -1 is returned. 4466 \a pos, -1 is returned.
4388*/ 4467*/
4389 4468
4390int QTextEdit::charAt( const QPoint &pos, int *para ) const 4469int QTextEdit::charAt( const QPoint &pos, int *para ) const
4391{ 4470{
4392 QTextCursor c( doc ); 4471 QTextCursor c( doc );
4393 c.place( pos, doc->firstParag() ); 4472 c.place( pos, doc->firstParagraph() );
4394 if ( c.parag() ) { 4473 if ( c.paragraph() ) {
4395 if ( para ) 4474 if ( para )
4396 *para = c.parag()->paragId(); 4475 *para = c.paragraph()->paragId();
4397 return c.index(); 4476 return c.index();
4398 } 4477 }
4399 return -1; 4478 return -1;
4400} 4479}
4401 4480
4402/*! Sets the background color of the paragraph \a para to \a bg */ 4481/*! Sets the background color of the paragraph \a para to \a bg */
4403 4482
4404void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) 4483void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg )
4405{ 4484{
4406 QTextParag *p = doc->paragAt( para ); 4485 QTextParagraph *p = doc->paragAt( para );
4407 if ( !p ) 4486 if ( !p )
4408 return; 4487 return;
4409 p->setBackgroundColor( bg ); 4488 p->setBackgroundColor( bg );
4410 repaintChanged(); 4489 repaintChanged();
4411} 4490}
4412 4491
4413/*! Clears the background color of the paragraph \a para, so that the 4492/*! Clears the background color of the paragraph \a para, so that the
4414 default color is used again. 4493 default color is used again.
4415*/ 4494*/
4416 4495
4417void QTextEdit::clearParagraphBackground( int para ) 4496void QTextEdit::clearParagraphBackground( int para )
4418{ 4497{
4419 QTextParag *p = doc->paragAt( para ); 4498 QTextParagraph *p = doc->paragAt( para );
4420 if ( !p ) 4499 if ( !p )
4421 return; 4500 return;
4422 p->clearBackgroundColor(); 4501 p->clearBackgroundColor();
4423 repaintChanged(); 4502 repaintChanged();
4424} 4503}
4425 4504
4426/*! Returns the background color of the paragraph \a para or an 4505/*! Returns the background color of the paragraph \a para or an
4427 invalid color if \a para is out of range or the paragraph has no 4506 invalid color if \a para is out of range or the paragraph has no
4428 background set 4507 background set
4429*/ 4508*/
4430 4509
4431QColor QTextEdit::paragraphBackgroundColor( int para ) const 4510QColor QTextEdit::paragraphBackgroundColor( int para ) const
4432{ 4511{
4433 QTextParag *p = doc->paragAt( para ); 4512 QTextParagraph *p = doc->paragAt( para );
4434 if ( !p ) 4513 if ( !p )
4435 return QColor(); 4514 return QColor();
4436 QColor *c = p->backgroundColor(); 4515 QColor *c = p->backgroundColor();
4437 if ( c ) 4516 if ( c )
4438 return *c; 4517 return *c;
4439 return QColor(); 4518 return QColor();
4440} 4519}
4441 4520
4442/*! \property QTextEdit::undoRedoEnabled 4521/*! \property QTextEdit::undoRedoEnabled
4443 \brief whether undo/redo is enabled 4522 \brief whether undo/redo is enabled
4444 4523
4445 The default is TRUE. 4524 The default is TRUE.
4446*/ 4525*/
4447 4526
4448void QTextEdit::setUndoRedoEnabled( bool b ) 4527void QTextEdit::setUndoRedoEnabled( bool b )
4449{ 4528{
4450 undoEnabled = b; 4529 undoEnabled = b;
4451} 4530}
4452 4531
4453bool QTextEdit::isUndoRedoEnabled() const 4532bool QTextEdit::isUndoRedoEnabled() const
4454{ 4533{
4455 return undoEnabled; 4534 return undoEnabled;
4456} 4535}
4457 4536
4458/*! Returns whether undo is available */ 4537/*! Returns whether undo is available */
4459 4538
4460bool QTextEdit::isUndoAvailable() const 4539bool QTextEdit::isUndoAvailable() const
4461{ 4540{
4462 return doc->commands()->isUndoAvailable() || undoRedoInfo.valid(); 4541 return doc->commands()->isUndoAvailable() || undoRedoInfo.valid();
4463} 4542}
4464 4543
4465/*! Returns whether redo is available */ 4544/*! Returns whether redo is available */
4466 4545
4467bool QTextEdit::isRedoAvailable() const 4546bool QTextEdit::isRedoAvailable() const
4468{ 4547{
4469 return doc->commands()->isRedoAvailable(); 4548 return doc->commands()->isRedoAvailable();
4470} 4549}
4471 4550
4472void QTextEdit::ensureFormatted( QTextParag *p ) 4551void QTextEdit::ensureFormatted( QTextParagraph *p )
4473{ 4552{
4474 while ( !p->isValid() ) { 4553 while ( !p->isValid() ) {
4475 if ( !lastFormatted ) 4554 if ( !lastFormatted )
4476 return; 4555 return;
4477 formatMore(); 4556 formatMore();
4478 } 4557 }
4479} 4558}
4480 4559
4481/*! \internal */ 4560/*! \internal */
4482void QTextEdit::updateCursor( const QPoint & pos ) 4561void QTextEdit::updateCursor( const QPoint & pos )
4483{ 4562{
4484 if ( isReadOnly() && linksEnabled() ) { 4563 if ( isReadOnly() && linksEnabled() ) {
4485 QTextCursor c = *cursor; 4564 QTextCursor c = *cursor;
4486 placeCursor( pos, &c, TRUE ); 4565 placeCursor( pos, &c, TRUE );
4487 4566
4488#ifndef QT_NO_NETWORKPROTOCOL 4567#ifndef QT_NO_NETWORKPROTOCOL
4489 if ( c.parag() && c.parag()->at( c.index() ) && 4568 if ( c.paragraph() && c.paragraph()->at( c.index() ) &&
4490 c.parag()->at( c.index() )->isAnchor() && 4569 c.paragraph()->at( c.index() )->isAnchor() &&
4491 !c.parag()->at( c.index() )->anchorHref().isEmpty() ) { 4570 !c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) {
4492 if ( c.index() < c.parag()->length() - 1 ) 4571 if ( c.index() < c.paragraph()->length() - 1 )
4493 onLink = c.parag()->at( c.index() )->anchorHref(); 4572 onLink = c.paragraph()->at( c.index() )->anchorHref();
4494 else 4573 else
4495 onLink = QString::null; 4574 onLink = QString::null;
4496 4575
4497#ifndef QT_NO_CURSOR 4576#ifndef QT_NO_CURSOR
4498 viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor ); 4577 viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor );
4499#endif 4578#endif
4500 QUrl u( doc->context(), onLink, TRUE ); 4579 QUrl u( doc->context(), onLink, TRUE );
4501 emitHighlighted( u.toString( FALSE, FALSE ) ); 4580 emitHighlighted( u.toString( FALSE, FALSE ) );
4502 } else { 4581 } else {
4503#ifndef QT_NO_CURSOR 4582#ifndef QT_NO_CURSOR
4504 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); 4583 viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor );
4505#endif 4584#endif
4506 onLink = QString::null; 4585 onLink = QString::null;
4507 emitHighlighted( QString::null ); 4586 emitHighlighted( QString::null );
4508 } 4587 }
4509#endif 4588#endif
4510 } 4589 }
4511} 4590}
4512 4591
4513void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) 4592void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c )
4514{ 4593{
4515 placeCursor( pos, c, FALSE ); 4594 placeCursor( pos, c, FALSE );
4516} 4595}
diff --git a/noncore/apps/opie-write/qtextedit.h b/noncore/apps/opie-write/qtextedit.h
index b4e5701..64e8f45 100644
--- a/noncore/apps/opie-write/qtextedit.h
+++ b/noncore/apps/opie-write/qtextedit.h
@@ -32,67 +32,69 @@
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#ifndef QTEXTEDIT_H 38#ifndef QTEXTEDIT_H
39#define QTEXTEDIT_H 39#define QTEXTEDIT_H
40 40
41#ifndef QT_H 41#ifndef QT_H
42#include "qscrollview.h" 42#include "qscrollview.h"
43#include "qstylesheet.h" 43#include "qstylesheet.h"
44#include "qvector.h" 44#include "qvector.h"
45#include "qvaluelist.h" 45#include "qvaluelist.h"
46#endif // QT_H 46#endif // QT_H
47 47
48class QPainter; 48class QPainter;
49class QKeyEvent; 49class QKeyEvent;
50class QResizeEvent; 50class QResizeEvent;
51class QMouseEvent; 51class QMouseEvent;
52class QTimer; 52class QTimer;
53class QFont; 53class QFont;
54class QColor; 54class QColor;
55struct QUndoRedoInfoPrivate; 55struct QUndoRedoInfoPrivate;
56class QPopupMenu; 56class QPopupMenu;
57 57
58namespace Qt3 { 58namespace Qt3 {
59 59
60class QTextString; 60class QTextString;
61class QTextDocument; 61class QTextDocument;
62class QTextCursor; 62class QTextCursor;
63class QTextCommand; 63class QTextCommand;
64class QTextParag; 64class QTextParagraph;
65class QTextFormat; 65class QTextFormat;
66class QTextEdit;
66class QTextBrowser; 67class QTextBrowser;
68class QTextString;
67class QTextEditPrivate; 69class QTextEditPrivate;
68 70
69class Q_EXPORT QTextEdit : public QScrollView 71class Q_EXPORT QTextEdit : public QScrollView
70{ 72{
71 friend class QTextBrowser; 73 friend class QTextBrowser;
72 74
73 Q_OBJECT 75 Q_OBJECT
74 Q_ENUMS( WordWrap WrapPolicy ) 76 Q_ENUMS( WordWrap WrapPolicy )
75 Q_PROPERTY( TextFormat textFormat READ textFormat WRITE setTextFormat ) 77 Q_PROPERTY( TextFormat textFormat READ textFormat WRITE setTextFormat )
76 Q_PROPERTY( QString text READ text WRITE setText ) 78 Q_PROPERTY( QString text READ text WRITE setText )
77 Q_PROPERTY( QBrush paper READ paper WRITE setPaper ) 79 Q_PROPERTY( QBrush paper READ paper WRITE setPaper )
78 Q_PROPERTY( bool linkUnderline READ linkUnderline WRITE setLinkUnderline ) 80 Q_PROPERTY( bool linkUnderline READ linkUnderline WRITE setLinkUnderline )
79 Q_PROPERTY( QString documentTitle READ documentTitle ) 81 Q_PROPERTY( QString documentTitle READ documentTitle )
80 Q_PROPERTY( int length READ length ) 82 Q_PROPERTY( int length READ length )
81 Q_PROPERTY( WordWrap wordWrap READ wordWrap WRITE setWordWrap ) 83 Q_PROPERTY( WordWrap wordWrap READ wordWrap WRITE setWordWrap )
82 Q_PROPERTY( int wrapColumnOrWidth READ wrapColumnOrWidth WRITE setWrapColumnOrWidth ) 84 Q_PROPERTY( int wrapColumnOrWidth READ wrapColumnOrWidth WRITE setWrapColumnOrWidth )
83 Q_PROPERTY( WrapPolicy wrapPolicy READ wrapPolicy WRITE setWrapPolicy ) 85 Q_PROPERTY( WrapPolicy wrapPolicy READ wrapPolicy WRITE setWrapPolicy )
84 Q_PROPERTY( bool hasSelectedText READ hasSelectedText ) 86 Q_PROPERTY( bool hasSelectedText READ hasSelectedText )
85 Q_PROPERTY( QString selectedText READ selectedText ) 87 Q_PROPERTY( QString selectedText READ selectedText )
86 Q_PROPERTY( int undoDepth READ undoDepth WRITE setUndoDepth ) 88 Q_PROPERTY( int undoDepth READ undoDepth WRITE setUndoDepth )
87 Q_PROPERTY( bool overwriteMode READ isOverwriteMode WRITE setOverwriteMode ) 89 Q_PROPERTY( bool overwriteMode READ isOverwriteMode WRITE setOverwriteMode )
88 Q_PROPERTY( bool modified READ isModified WRITE setModified DESIGNABLE false ) 90 Q_PROPERTY( bool modified READ isModified WRITE setModified DESIGNABLE false )
89 Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly ) 91 Q_PROPERTY( bool readOnly READ isReadOnly WRITE setReadOnly )
90 Q_PROPERTY( bool undoRedoEnabled READ isUndoRedoEnabled WRITE setUndoRedoEnabled ) 92 Q_PROPERTY( bool undoRedoEnabled READ isUndoRedoEnabled WRITE setUndoRedoEnabled )
91 Q_PROPERTY( int tabStopWidth READ tabStopWidth WRITE setTabStopWidth ) 93 Q_PROPERTY( int tabStopWidth READ tabStopWidth WRITE setTabStopWidth )
92 94
93public: 95public:
94 enum WordWrap { 96 enum WordWrap {
95 NoWrap, 97 NoWrap,
96 WidgetWidth, 98 WidgetWidth,
97 FixedPixelWidth, 99 FixedPixelWidth,
98 FixedColumnWidth 100 FixedColumnWidth
@@ -167,126 +169,134 @@ public:
167 169
168 int heightForWidth( int w ) const; 170 int heightForWidth( int w ) const;
169 171
170 bool hasSelectedText() const; 172 bool hasSelectedText() const;
171 QString selectedText() const; 173 QString selectedText() const;
172 bool isUndoAvailable() const; 174 bool isUndoAvailable() const;
173 bool isRedoAvailable() const; 175 bool isRedoAvailable() const;
174 176
175 WordWrap wordWrap() const; 177 WordWrap wordWrap() const;
176 int wrapColumnOrWidth() const; 178 int wrapColumnOrWidth() const;
177 WrapPolicy wrapPolicy() const; 179 WrapPolicy wrapPolicy() const;
178 180
179 int tabStopWidth() const; 181 int tabStopWidth() const;
180 182
181 QString anchorAt( const QPoint& pos ); 183 QString anchorAt( const QPoint& pos );
182 184
183 QSize sizeHint() const; 185 QSize sizeHint() const;
184 186
185 bool isReadOnly() const { return readonly; } 187 bool isReadOnly() const { return readonly; }
186 188
187 void getCursorPosition( int *parag, int *index ) const; 189 void getCursorPosition( int *parag, int *index ) const;
188 190
189 bool isModified() const; 191 bool isModified() const;
190 bool italic() const; 192 bool italic() const;
191 bool bold() const; 193 bool bold() const;
192 bool underline() const; 194 bool underline() const;
193 QString family() const; 195 QString family() const;
194 int pointSize() const; 196 int pointSize() const;
195 QColor color() const; 197 QColor color() const;
196 QFont font() const; 198 QFont font() const;
197 int alignment() const; 199 int alignment() const;
198 int undoDepth() const; 200 int undoDepth() const;
201
202 // do not use, will go away
199 virtual bool getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment ); 203 virtual bool getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment );
204 // do not use, will go away
200 virtual bool getParagraphFormat( int para, QFont *font, QColor *color, 205 virtual bool getParagraphFormat( int para, QFont *font, QColor *color,
201 VerticalAlignment *verticalAlignment, int *alignment, 206 VerticalAlignment *verticalAlignment, int *alignment,
202 QStyleSheetItem::DisplayMode *displayMode, 207 QStyleSheetItem::DisplayMode *displayMode,
203 QStyleSheetItem::ListStyle *listStyle, 208 QStyleSheetItem::ListStyle *listStyle,
204 int *listDepth ); 209 int *listDepth );
210
211
205 bool isOverwriteMode() const { return overWrite; } 212 bool isOverwriteMode() const { return overWrite; }
206 QColor paragraphBackgroundColor( int para ) const; 213 QColor paragraphBackgroundColor( int para ) const;
207 214
208 bool isUndoRedoEnabled() const; 215 bool isUndoRedoEnabled() const;
209 bool eventFilter( QObject *o, QEvent *e ); 216 bool eventFilter( QObject *o, QEvent *e );
210 217
211public slots: 218public slots:
212 void setEnabled( bool ); 219 void setEnabled( bool );
213 virtual void setMimeSourceFactory( QMimeSourceFactory* factory ); 220 virtual void setMimeSourceFactory( QMimeSourceFactory* factory );
214 virtual void setStyleSheet( QStyleSheet* styleSheet ); 221 virtual void setStyleSheet( QStyleSheet* styleSheet );
215 virtual void scrollToAnchor( const QString& name ); 222 virtual void scrollToAnchor( const QString& name );
216 virtual void setPaper( const QBrush& pap ); 223 virtual void setPaper( const QBrush& pap );
217 virtual void setLinkUnderline( bool ); 224 virtual void setLinkUnderline( bool );
218 225
219 virtual void setWordWrap( WordWrap mode ); 226 virtual void setWordWrap( WordWrap mode );
220 virtual void setWrapColumnOrWidth( int ); 227 virtual void setWrapColumnOrWidth( int );
221 virtual void setWrapPolicy( WrapPolicy policy ); 228 virtual void setWrapPolicy( WrapPolicy policy );
222 229
223 virtual void copy(); 230 virtual void copy();
224 virtual void append( const QString& text ); 231 virtual void append( const QString& text );
225 232
226 void setText( const QString &txt ) { setText( txt, QString::null ); } 233 void setText( const QString &txt ) { setText( txt, QString::null ); }
227 virtual void setText( const QString &txt, const QString &context ); 234 virtual void setText( const QString &txt, const QString &context );
228 virtual void setTextFormat( TextFormat f ); 235 virtual void setTextFormat( TextFormat f );
229 236
230 virtual void selectAll( bool select = TRUE ); 237 virtual void selectAll( bool select = TRUE );
231 virtual void setTabStopWidth( int ts ); 238 virtual void setTabStopWidth( int ts );
232 virtual void zoomIn( int range ); 239 virtual void zoomIn( int range );
233 virtual void zoomIn() { zoomIn( 1 ); } 240 virtual void zoomIn() { zoomIn( 1 ); }
234 virtual void zoomOut( int range ); 241 virtual void zoomOut( int range );
235 virtual void zoomOut() { zoomOut( 1 ); } 242 virtual void zoomOut() { zoomOut( 1 ); }
236 virtual void zoomTo( int size ); 243 virtual void zoomTo( int size );
237 244
238 virtual void sync(); 245 virtual void sync();
239 virtual void setReadOnly( bool b ); 246 virtual void setReadOnly( bool b );
240 247
241 virtual void undo(); 248 virtual void undo();
242 virtual void redo(); 249 virtual void redo();
243 virtual void cut(); 250 virtual void cut();
244 virtual void paste(); 251 virtual void paste();
245#ifndef QT_NO_CLIPBOARD 252#ifndef QT_NO_CLIPBOARD
246 virtual void pasteSubType( const QCString &subtype ); 253 virtual void pasteSubType( const QCString &subtype );
247#endif 254#endif
248 virtual void clear(); 255 virtual void clear();
249 virtual void del(); 256 virtual void del();
250 virtual void indent(); 257 virtual void indent();
251 virtual void setItalic( bool b ); 258 virtual void setItalic( bool b );
252 virtual void setBold( bool b ); 259 virtual void setBold( bool b );
253 virtual void setUnderline( bool b ); 260 virtual void setUnderline( bool b );
254 virtual void setFamily( const QString &f ); 261 virtual void setFamily( const QString &f );
255 virtual void setPointSize( int s ); 262 virtual void setPointSize( int s );
256 virtual void setColor( const QColor &c ); 263 virtual void setColor( const QColor &c );
257 virtual void setFont( const QFont &f ); 264 virtual void setFont( const QFont &f );
258 virtual void setVerticalAlignment( VerticalAlignment a ); 265 virtual void setVerticalAlignment( VerticalAlignment a );
259 virtual void setAlignment( int a ); 266 virtual void setAlignment( int a );
267
268 // do not use, will go away
260 virtual void setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle ); 269 virtual void setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle );
270
261 virtual void setCursorPosition( int parag, int index ); 271 virtual void setCursorPosition( int parag, int index );
262 virtual void setSelection( int parag_from, int index_from, int parag_to, int index_to, int selNum = 0 ); 272 virtual void setSelection( int parag_from, int index_from, int parag_to, int index_to, int selNum = 0 );
263 virtual void setSelectionAttributes( int selNum, const QColor &back, bool invertText ); 273 virtual void setSelectionAttributes( int selNum, const QColor &back, bool invertText );
264 virtual void setModified( bool m ); 274 virtual void setModified( bool m );
265 virtual void resetFormat(); 275 virtual void resetFormat();
266 virtual void setUndoDepth( int d ); 276 virtual void setUndoDepth( int d );
267 virtual void setFormat( QTextFormat *f, int flags ); 277 virtual void setFormat( QTextFormat *f, int flags );
268 virtual void ensureCursorVisible(); 278 virtual void ensureCursorVisible();
269 virtual void placeCursor( const QPoint &pos, QTextCursor *c = 0 ); 279 virtual void placeCursor( const QPoint &pos, QTextCursor *c = 0 );
270 virtual void moveCursor( CursorAction action, bool select ); 280 virtual void moveCursor( CursorAction action, bool select );
271 virtual void doKeyboardAction( KeyboardAction action ); 281 virtual void doKeyboardAction( KeyboardAction action );
272 virtual void removeSelectedText( int selNum = 0 ); 282 virtual void removeSelectedText( int selNum = 0 );
273 virtual void removeSelection( int selNum = 0 ); 283 virtual void removeSelection( int selNum = 0 );
274 virtual void setCurrentFont( const QFont &f ); 284 virtual void setCurrentFont( const QFont &f );
275 virtual void setOverwriteMode( bool b ) { overWrite = b; } 285 virtual void setOverwriteMode( bool b ) { overWrite = b; }
276 286
277 virtual void scrollToBottom(); 287 virtual void scrollToBottom();
278 288
279 virtual void insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected ); 289 virtual void insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected );
280 virtual void insertAt( const QString &text, int para, int index ); 290 virtual void insertAt( const QString &text, int para, int index );
281 virtual void removeParagraph( int para ); 291 virtual void removeParagraph( int para );
282 virtual void insertParagraph( const QString &text, int para ); 292 virtual void insertParagraph( const QString &text, int para );
283 293
284 virtual void setParagraphBackgroundColor( int para, const QColor &bg ); 294 virtual void setParagraphBackgroundColor( int para, const QColor &bg );
285 virtual void clearParagraphBackground( int para ); 295 virtual void clearParagraphBackground( int para );
286 296
287 virtual void setUndoRedoEnabled( bool b ); 297 virtual void setUndoRedoEnabled( bool b );
288 298
289signals: 299signals:
290 void textChanged(); 300 void textChanged();
291 void selectionChanged(); 301 void selectionChanged();
292 void copyAvailable( bool ); 302 void copyAvailable( bool );
@@ -317,121 +327,117 @@ protected:
317 void contentsWheelEvent( QWheelEvent *e ); 327 void contentsWheelEvent( QWheelEvent *e );
318#endif 328#endif
319#ifndef QT_NO_DRAGANDDROP 329#ifndef QT_NO_DRAGANDDROP
320 void contentsDragEnterEvent( QDragEnterEvent *e ); 330 void contentsDragEnterEvent( QDragEnterEvent *e );
321 void contentsDragMoveEvent( QDragMoveEvent *e ); 331 void contentsDragMoveEvent( QDragMoveEvent *e );
322 void contentsDragLeaveEvent( QDragLeaveEvent *e ); 332 void contentsDragLeaveEvent( QDragLeaveEvent *e );
323 void contentsDropEvent( QDropEvent *e ); 333 void contentsDropEvent( QDropEvent *e );
324#endif 334#endif
325 bool focusNextPrevChild( bool next ); 335 bool focusNextPrevChild( bool next );
326 QTextDocument *document() const; 336 QTextDocument *document() const;
327 QTextCursor *textCursor() const; 337 QTextCursor *textCursor() const;
328 void setDocument( QTextDocument *doc ); 338 void setDocument( QTextDocument *doc );
329 virtual QPopupMenu *createPopupMenu( const QPoint& pos ); 339 virtual QPopupMenu *createPopupMenu( const QPoint& pos );
330 virtual QPopupMenu *createPopupMenu(); 340 virtual QPopupMenu *createPopupMenu();
331 void drawCursor( bool visible ); 341 void drawCursor( bool visible );
332 342
333 void windowActivationChange( bool ); 343 void windowActivationChange( bool );
334 344
335protected slots: 345protected slots:
336 virtual void doChangeInterval(); 346 virtual void doChangeInterval();
337 347
338private slots: 348private slots:
339 void formatMore(); 349 void formatMore();
340 void doResize(); 350 void doResize();
341 void autoScrollTimerDone(); 351 void autoScrollTimerDone();
342 void blinkCursor(); 352 void blinkCursor();
343 void setModified(); 353 void setModified();
344 void startDrag(); 354 void startDrag();
345 void documentWidthChanged( int w ); 355 void documentWidthChanged( int w );
346 356
347private: 357private:
348 struct Q_EXPORT UndoRedoInfo { 358 struct Q_EXPORT UndoRedoInfo {
349 enum Type { Invalid, Insert, Delete, Backspace, Return, RemoveSelected, Format, Alignment, ParagType }; 359 enum Type { Invalid, Insert, Delete, Backspace, Return, RemoveSelected, Format, Style };
350 360
351 UndoRedoInfo( QTextDocument *dc ); 361 UndoRedoInfo( QTextDocument *dc );
352 ~UndoRedoInfo(); 362 ~UndoRedoInfo();
353 void clear(); 363 void clear();
354 bool valid() const; 364 bool valid() const;
355 365
356 QUndoRedoInfoPrivate *d; 366 QUndoRedoInfoPrivate *d;
357 int id; 367 int id;
358 int index; 368 int index;
359 int eid; 369 int eid;
360 int eindex; 370 int eindex;
361 QTextFormat *format; 371 QTextFormat *format;
362 int flags; 372 int flags;
363 Type type; 373 Type type;
364 QTextDocument *doc; 374 QTextDocument *doc;
365 QMemArray<int> oldAligns; 375 QByteArray styleInformation;
366 int newAlign;
367 bool list;
368 QStyleSheetItem::ListStyle listStyle;
369 QValueList< QPtrVector<QStyleSheetItem> > oldStyles;
370 QValueList<QStyleSheetItem::ListStyle> oldListStyles;
371 }; 376 };
372 377
373private: 378private:
374 void updateCursor( const QPoint & pos ); 379 void updateCursor( const QPoint & pos );
375 void handleMouseMove( const QPoint& pos ); 380 void handleMouseMove( const QPoint& pos );
376 void drawContents( QPainter * ); 381 void drawContents( QPainter * );
377 virtual bool linksEnabled() const { return FALSE; } 382 virtual bool linksEnabled() const { return FALSE; }
378 void init(); 383 void init();
379 void checkUndoRedoInfo( UndoRedoInfo::Type t ); 384 void checkUndoRedoInfo( UndoRedoInfo::Type t );
380 void updateCurrentFormat(); 385 void updateCurrentFormat();
381 bool handleReadOnlyKeyEvent( QKeyEvent *e ); 386 bool handleReadOnlyKeyEvent( QKeyEvent *e );
382 void makeParagVisible( QTextParag *p ); 387 void makeParagVisible( QTextParagraph *p );
383#ifndef QT_NO_MIME 388#ifndef QT_NO_MIME
384 QCString pickSpecial(QMimeSource* ms, bool always_ask, const QPoint&); 389 QCString pickSpecial(QMimeSource* ms, bool always_ask, const QPoint&);
385#endif 390#endif
386#ifndef QT_NO_MIMECLIPBOARD 391#ifndef QT_NO_MIMECLIPBOARD
387 void pasteSpecial(const QPoint&); 392 void pasteSpecial(const QPoint&);
388#endif 393#endif
389 void setFontInternal( const QFont &f ); 394 void setFontInternal( const QFont &f );
390 395
391 virtual void emitHighlighted( const QString & ) {} 396 virtual void emitHighlighted( const QString & ) {}
392 virtual void emitLinkClicked( const QString & ) {} 397 virtual void emitLinkClicked( const QString & ) {}
393 398
394 void readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles = FALSE ); 399 void readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles = FALSE );
395 void clearUndoRedo(); 400 void clearUndoRedo();
396 void paintDocument( bool drawAll, QPainter *p, int cx = -1, int cy = -1, int cw = -1, int ch = -1 ); 401 void paintDocument( bool drawAll, QPainter *p, int cx = -1, int cy = -1, int cw = -1, int ch = -1 );
397 void moveCursor( CursorAction action ); 402 void moveCursor( CursorAction action );
398 void ensureFormatted( QTextParag *p ); 403 void ensureFormatted( QTextParagraph *p );
399 void placeCursor( const QPoint &pos, QTextCursor *c, bool link ); 404 void placeCursor( const QPoint &pos, QTextCursor *c, bool link );
405 void updateMicroFocusHint();
400 406
401private: 407private:
402 QTextDocument *doc; 408 QTextDocument *doc;
403 QTextCursor *cursor; 409 QTextCursor *cursor;
404 QTimer *formatTimer, *scrollTimer, *changeIntervalTimer, *blinkTimer, *dragStartTimer; 410 QTimer *formatTimer, *scrollTimer, *changeIntervalTimer, *blinkTimer, *dragStartTimer;
405 QTextParag *lastFormatted; 411 QTextParagraph *lastFormatted;
406 int interval; 412 int interval;
407 UndoRedoInfo undoRedoInfo; 413 UndoRedoInfo undoRedoInfo;
408 QTextFormat *currentFormat; 414 QTextFormat *currentFormat;
409 int currentAlignment; 415 int currentAlignment;
410 QPoint oldMousePos, mousePos; 416 QPoint oldMousePos, mousePos;
411 QPoint dragStartPos; 417 QPoint dragStartPos;
412 QString onLink; 418 QString onLink;
413 WordWrap wrapMode; 419 WordWrap wrapMode;
414 WrapPolicy wPolicy; 420 WrapPolicy wPolicy;
415 int wrapWidth; 421 int wrapWidth;
416 QString pressedLink; 422 QString pressedLink;
417 QTextEditPrivate *d; 423 QTextEditPrivate *d;
418 bool inDoubleClick : 1; 424 bool inDoubleClick : 1;
419 bool mousePressed : 1; 425 bool mousePressed : 1;
420 bool cursorVisible : 1; 426 bool cursorVisible : 1;
421 bool blinkCursorVisible : 1; 427 bool blinkCursorVisible : 1;
422 bool readOnly : 1; 428 bool readOnly : 1;
423 bool modified : 1; 429 bool modified : 1;
424 bool mightStartDrag : 1; 430 bool mightStartDrag : 1;
425 bool inDnD : 1; 431 bool inDnD : 1;
426 bool readonly : 1; 432 bool readonly : 1;
427 bool undoEnabled : 1; 433 bool undoEnabled : 1;
428 bool overWrite : 1; 434 bool overWrite : 1;
429}; 435};
430 436
431inline QTextDocument *QTextEdit::document() const 437inline QTextDocument *QTextEdit::document() const
432{ 438{
433 return doc; 439 return doc;
434} 440}
435 441
436inline QTextCursor *QTextEdit::textCursor() const 442inline QTextCursor *QTextEdit::textCursor() const
437{ 443{