source: trunk/src/kernel/qrichtext_p.cpp@ 8

Last change on this file since 8 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 16.3 KB
Line 
1/****************************************************************************
2** $Id: qrichtext_p.cpp 2 2005-11-16 15:49:26Z dmik $
3**
4** Implementation of the internal Qt classes dealing with rich text
5**
6** Created : 990101
7**
8** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
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
14** LICENSE.QPL included in the packaging of this file.
15**
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
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
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.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qrichtext_p.h"
39
40#ifndef QT_NO_RICHTEXT
41
42QTextCommand::~QTextCommand() {}
43QTextCommand::Commands QTextCommand::type() const { return Invalid; }
44
45
46#ifndef QT_NO_TEXTCUSTOMITEM
47QTextCustomItem::~QTextCustomItem() {}
48void QTextCustomItem::adjustToPainter( QPainter* p){ if ( p ) width = 0; }
49QTextCustomItem::Placement QTextCustomItem::placement() const { return PlaceInline; }
50
51bool QTextCustomItem::ownLine() const { return FALSE; }
52void QTextCustomItem::resize( int nwidth ){ width = nwidth; }
53void QTextCustomItem::invalidate() {}
54
55bool QTextCustomItem::isNested() const { return FALSE; }
56int QTextCustomItem::minimumWidth() const { return 0; }
57
58QString QTextCustomItem::richText() const { return QString::null; }
59
60bool QTextCustomItem::enter( QTextCursor *, QTextDocument*&, QTextParagraph *&, int &, int &, int &, bool )
61{
62 return TRUE;
63}
64bool QTextCustomItem::enterAt( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int &, const QPoint & )
65{
66 return TRUE;
67}
68bool QTextCustomItem::next( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
69{
70 return TRUE;
71}
72bool QTextCustomItem::prev( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
73{
74 return TRUE;
75}
76bool QTextCustomItem::down( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
77{
78 return TRUE;
79}
80bool QTextCustomItem::up( QTextCursor *, QTextDocument *&, QTextParagraph *&, int &, int &, int & )
81{
82 return TRUE;
83}
84#endif // QT_NO_TEXTCUSTOMITEM
85
86void QTextFlow::setPageSize( int ps ) { pagesize = ps; }
87#ifndef QT_NO_TEXTCUSTOMITEM
88bool QTextFlow::isEmpty() { return leftItems.isEmpty() && rightItems.isEmpty(); }
89#else
90bool QTextFlow::isEmpty() { return TRUE; }
91#endif
92
93#ifndef QT_NO_TEXTCUSTOMITEM
94void QTextTableCell::invalidate() { cached_width = -1; cached_sizehint = -1; }
95
96void QTextTable::invalidate() { cachewidth = -1; }
97#endif
98
99QTextParagraphData::~QTextParagraphData() {}
100void QTextParagraphData::join( QTextParagraphData * ) {}
101
102QTextFormatter::~QTextFormatter() {}
103void QTextFormatter::setWrapEnabled( bool b ) { wrapEnabled = b; }
104void QTextFormatter::setWrapAtColumn( int c ) { wrapColumn = c; }
105
106
107
108int QTextCursor::x() const
109{
110 if ( idx >= para->length() )
111 return 0;
112 QTextStringChar *c = para->at( idx );
113 int curx = c->x;
114 if ( !c->rightToLeft &&
115 c->c.isSpace() &&
116 idx > 0 &&
117 para->at( idx - 1 )->c != '\t' &&
118 !c->lineStart &&
119 ( para->alignment() & Qt::AlignJustify ) == Qt::AlignJustify )
120 curx = para->at( idx - 1 )->x + para->string()->width( idx - 1 );
121 if ( c->rightToLeft )
122 curx += para->string()->width( idx );
123 return curx;
124}
125
126int QTextCursor::y() const
127{
128 int dummy, line;
129 para->lineStartOfChar( idx, &dummy, &line );
130 return para->lineY( line );
131}
132
133int QTextCursor::globalX() const { return totalOffsetX() + para->rect().x() + x(); }
134int QTextCursor::globalY() const { return totalOffsetY() + para->rect().y() + y(); }
135
136QTextDocument *QTextCursor::document() const
137{
138 return para ? para->document() : 0;
139}
140
141void QTextCursor::gotoPosition( QTextParagraph* p, int index )
142{
143 if ( para && p != para ) {
144 while ( para->document() != p->document() && !indices.isEmpty() )
145 pop();
146 Q_ASSERT( indices.isEmpty() || para->document() == p->document() );
147 }
148 para = p;
149 if ( index < 0 || index >= para->length() ) {
150#if defined(QT_CHECK_RANGE)
151 qWarning( "QTextCursor::gotoParagraph Index: %d out of range", index );
152#endif
153 if ( index < 0 || para->length() == 0 )
154 index = 0;
155 else
156 index = para->length() - 1;
157 }
158
159 tmpX = -1;
160 idx = index;
161 fixCursorPosition();
162}
163
164bool QTextDocument::hasSelection( int id, bool visible ) const
165{
166 return ( selections.find( id ) != selections.end() &&
167 ( !visible ||
168 ( (QTextDocument*)this )->selectionStartCursor( id ) !=
169 ( (QTextDocument*)this )->selectionEndCursor( id ) ) );
170}
171
172void QTextDocument::setSelectionStart( int id, const QTextCursor &cursor )
173{
174 QTextDocumentSelection sel;
175 sel.startCursor = cursor;
176 sel.endCursor = cursor;
177 sel.swapped = FALSE;
178 selections[ id ] = sel;
179}
180
181QTextParagraph *QTextDocument::paragAt( int i ) const
182{
183 QTextParagraph* p = curParag;
184 if ( !p || p->paragId() > i )
185 p = fParag;
186 while ( p && p->paragId() != i )
187 p = p->next();
188 ((QTextDocument*)this)->curParag = p;
189 return p;
190}
191
192
193QTextFormat::~QTextFormat()
194{
195}
196
197QTextFormat::QTextFormat()
198 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() )
199{
200 ref = 0;
201
202 usePixelSizes = FALSE;
203 if ( stdSize == -1 ) {
204 stdSize = qApp->font().pixelSize();
205 usePixelSizes = TRUE;
206 }
207
208 missp = FALSE;
209 ha = AlignNormal;
210 collection = 0;
211}
212
213QTextFormat::QTextFormat( const QStyleSheetItem *style )
214 : fm( QFontMetrics( fn ) ), linkColor( TRUE ), logicalFontSize( 3 ), stdSize( qApp->font().pointSize() )
215{
216 ref = 0;
217
218 usePixelSizes = FALSE;
219 if ( stdSize == -1 ) {
220 stdSize = qApp->font().pixelSize();
221 usePixelSizes = TRUE;
222 }
223
224 missp = FALSE;
225 ha = AlignNormal;
226 collection = 0;
227 fn = QFont( style->fontFamily(),
228 style->fontSize(),
229 style->fontWeight(),
230 style->fontItalic() );
231 fn.setUnderline( style->fontUnderline() );
232 fn.setStrikeOut( style->fontStrikeOut() );
233 col = style->color();
234 fm = QFontMetrics( fn );
235 leftBearing = fm.minLeftBearing();
236 rightBearing = fm.minRightBearing();
237 hei = fm.lineSpacing();
238 asc = fm.ascent() + (fm.leading()+1)/2;
239 dsc = fm.descent();
240 missp = FALSE;
241 ha = AlignNormal;
242 memset( widths, 0, 256 );
243 generateKey();
244 addRef();
245}
246
247QTextFormat::QTextFormat( const QFont &f, const QColor &c, QTextFormatCollection *parent )
248 : fn( f ), col( c ), fm( QFontMetrics( f ) ), linkColor( TRUE ),
249 logicalFontSize( 3 ), stdSize( f.pointSize() )
250{
251 ref = 0;
252 usePixelSizes = FALSE;
253 if ( stdSize == -1 ) {
254 stdSize = f.pixelSize();
255 usePixelSizes = TRUE;
256 }
257 collection = parent;
258 leftBearing = fm.minLeftBearing();
259 rightBearing = fm.minRightBearing();
260 hei = fm.lineSpacing();
261 asc = fm.ascent() + (fm.leading()+1)/2;
262 dsc = fm.descent();
263 missp = FALSE;
264 ha = AlignNormal;
265 memset( widths, 0, 256 );
266 generateKey();
267 addRef();
268}
269
270QTextFormat::QTextFormat( const QTextFormat &f )
271 : fm( f.fm )
272{
273 ref = 0;
274 collection = 0;
275 fn = f.fn;
276 col = f.col;
277 leftBearing = f.leftBearing;
278 rightBearing = f.rightBearing;
279 memset( widths, 0, 256 );
280 hei = f.hei;
281 asc = f.asc;
282 dsc = f.dsc;
283 stdSize = f.stdSize;
284 usePixelSizes = f.usePixelSizes;
285 logicalFontSize = f.logicalFontSize;
286 missp = f.missp;
287 ha = f.ha;
288 k = f.k;
289 linkColor = f.linkColor;
290 addRef();
291}
292
293QTextFormat& QTextFormat::operator=( const QTextFormat &f )
294{
295 ref = 0;
296 collection = f.collection;
297 fn = f.fn;
298 col = f.col;
299 fm = f.fm;
300 leftBearing = f.leftBearing;
301 rightBearing = f.rightBearing;
302 memset( widths, 0, 256 );
303 hei = f.hei;
304 asc = f.asc;
305 dsc = f.dsc;
306 stdSize = f.stdSize;
307 usePixelSizes = f.usePixelSizes;
308 logicalFontSize = f.logicalFontSize;
309 missp = f.missp;
310 ha = f.ha;
311 k = f.k;
312 linkColor = f.linkColor;
313 addRef();
314 return *this;
315}
316
317void QTextFormat::update()
318{
319 fm = QFontMetrics( fn );
320 leftBearing = fm.minLeftBearing();
321 rightBearing = fm.minRightBearing();
322 hei = fm.lineSpacing();
323 asc = fm.ascent() + (fm.leading()+1)/2;
324 dsc = fm.descent();
325 memset( widths, 0, 256 );
326 generateKey();
327}
328
329
330QPainter* QTextFormat::pntr = 0;
331QFontMetrics* QTextFormat::pntr_fm = 0;
332int QTextFormat::pntr_ldg=-1;
333int QTextFormat::pntr_asc=-1;
334int QTextFormat::pntr_hei=-1;
335int QTextFormat::pntr_dsc=-1;
336
337void QTextFormat::setPainter( QPainter *p )
338{
339 pntr = p;
340}
341
342QPainter* QTextFormat::painter()
343{
344 return pntr;
345}
346
347void QTextFormat::applyFont( const QFont &f )
348{
349 QFontMetrics fm( pntr->fontMetrics() );
350 if ( !pntr_fm
351 || pntr_fm->painter != pntr
352 || pntr_fm->d != fm.d
353 || !pntr->font().isCopyOf( f ) ) {
354 pntr->setFont( f );
355 delete pntr_fm;
356 pntr_fm = new QFontMetrics( pntr->fontMetrics() );
357 pntr_ldg = pntr_fm->leading();
358 pntr_asc = pntr_fm->ascent()+(pntr_ldg+1)/2;
359 pntr_hei = pntr_fm->lineSpacing();
360 pntr_dsc = -1;
361 }
362}
363
364int QTextFormat::minLeftBearing() const
365{
366 if ( !pntr || !pntr->isActive() )
367 return leftBearing;
368 applyFont( fn );
369 return pntr_fm->minLeftBearing();
370}
371
372int QTextFormat::minRightBearing() const
373{
374 if ( !pntr || !pntr->isActive() )
375 return rightBearing;
376 applyFont( fn );
377 return pntr_fm->minRightBearing();
378}
379
380int QTextFormat::height() const
381{
382 if ( !pntr || !pntr->isActive() )
383 return hei;
384 applyFont( fn );
385 return pntr_hei;
386}
387
388int QTextFormat::ascent() const
389{
390 if ( !pntr || !pntr->isActive() )
391 return asc;
392 applyFont( fn );
393 return pntr_asc;
394}
395
396int QTextFormat::descent() const
397{
398 if ( !pntr || !pntr->isActive() )
399 return dsc;
400 applyFont( fn );
401 if ( pntr_dsc < 0 )
402 pntr_dsc = pntr_fm->descent();
403 return pntr_dsc;
404}
405
406int QTextFormat::leading() const
407{
408 if ( !pntr || !pntr->isActive() )
409 return fm.leading();
410 applyFont( fn );
411 return pntr_ldg;
412}
413
414void QTextFormat::generateKey()
415{
416 k = getKey( fn, col, isMisspelled(), vAlign() );
417}
418
419QString QTextFormat::getKey( const QFont &fn, const QColor &col, bool misspelled, VerticalAlignment a )
420{
421 QString k = fn.key();
422 k += '/';
423 k += QString::number( (uint)col.rgb() );
424 k += '/';
425 k += QString::number( (int)misspelled );
426 k += '/';
427 k += QString::number( (int)a );
428 return k;
429}
430
431QString QTextString::toString( const QMemArray<QTextStringChar> &data )
432{
433 QString s;
434 int l = data.size();
435 s.setUnicode( 0, l );
436 QTextStringChar *c = data.data();
437 QChar *uc = (QChar *)s.unicode();
438 while ( l-- )
439 *(uc++) = (c++)->c;
440
441 return s;
442}
443
444void QTextParagraph::setSelection( int id, int start, int end )
445{
446 QMap<int, QTextParagraphSelection>::ConstIterator it = selections().find( id );
447 if ( it != mSelections->end() ) {
448 if ( start == ( *it ).start && end == ( *it ).end )
449 return;
450 }
451
452 QTextParagraphSelection sel;
453 sel.start = start;
454 sel.end = end;
455 (*mSelections)[ id ] = sel;
456 setChanged( TRUE, TRUE );
457}
458
459void QTextParagraph::removeSelection( int id )
460{
461 if ( !hasSelection( id ) )
462 return;
463 if ( mSelections )
464 mSelections->remove( id );
465 setChanged( TRUE, TRUE );
466}
467
468int QTextParagraph::selectionStart( int id ) const
469{
470 if ( !mSelections )
471 return -1;
472 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
473 if ( it == mSelections->end() )
474 return -1;
475 return ( *it ).start;
476}
477
478int QTextParagraph::selectionEnd( int id ) const
479{
480 if ( !mSelections )
481 return -1;
482 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
483 if ( it == mSelections->end() )
484 return -1;
485 return ( *it ).end;
486}
487
488bool QTextParagraph::hasSelection( int id ) const
489{
490 return mSelections ? mSelections->contains( id ) : FALSE;
491}
492
493bool QTextParagraph::fullSelected( int id ) const
494{
495 if ( !mSelections )
496 return FALSE;
497 QMap<int, QTextParagraphSelection>::ConstIterator it = mSelections->find( id );
498 if ( it == mSelections->end() )
499 return FALSE;
500 return ( *it ).start == 0 && ( *it ).end == str->length() - 1;
501}
502
503int QTextParagraph::lineY( int l ) const
504{
505 if ( l > (int)lineStarts.count() - 1 ) {
506 qWarning( "QTextParagraph::lineY: line %d out of range!", l );
507 return 0;
508 }
509
510 if ( !isValid() )
511 ( (QTextParagraph*)this )->format();
512
513 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
514 while ( l-- > 0 )
515 ++it;
516 return ( *it )->y;
517}
518
519int QTextParagraph::lineBaseLine( int l ) const
520{
521 if ( l > (int)lineStarts.count() - 1 ) {
522 qWarning( "QTextParagraph::lineBaseLine: line %d out of range!", l );
523 return 10;
524 }
525
526 if ( !isValid() )
527 ( (QTextParagraph*)this )->format();
528
529 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
530 while ( l-- > 0 )
531 ++it;
532 return ( *it )->baseLine;
533}
534
535int QTextParagraph::lineHeight( int l ) const
536{
537 if ( l > (int)lineStarts.count() - 1 ) {
538 qWarning( "QTextParagraph::lineHeight: line %d out of range!", l );
539 return 15;
540 }
541
542 if ( !isValid() )
543 ( (QTextParagraph*)this )->format();
544
545 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
546 while ( l-- > 0 )
547 ++it;
548 return ( *it )->h;
549}
550
551void QTextParagraph::lineInfo( int l, int &y, int &h, int &bl ) const
552{
553 if ( l > (int)lineStarts.count() - 1 ) {
554 qWarning( "QTextParagraph::lineInfo: line %d out of range!", l );
555 qDebug( "%d %d", (int)lineStarts.count() - 1, l );
556 y = 0;
557 h = 15;
558 bl = 10;
559 return;
560 }
561
562 if ( !isValid() )
563 ( (QTextParagraph*)this )->format();
564
565 QMap<int, QTextLineStart*>::ConstIterator it = lineStarts.begin();
566 while ( l-- > 0 )
567 ++it;
568 y = ( *it )->y;
569 h = ( *it )->h;
570 bl = ( *it )->baseLine;
571}
572
573
574void QTextParagraph::setAlignment( int a )
575{
576 if ( a == (int)align )
577 return;
578 align = a;
579 invalidate( 0 );
580}
581
582QTextFormatter *QTextParagraph::formatter() const
583{
584 if ( hasdoc )
585 return document()->formatter();
586 if ( pseudoDocument()->pFormatter )
587 return pseudoDocument()->pFormatter;
588 return ( ( (QTextParagraph*)this )->pseudoDocument()->pFormatter = new QTextFormatterBreakWords );
589}
590
591void QTextParagraph::setTabArray( int *a )
592{
593 delete [] tArray;
594 tArray = a;
595}
596
597void QTextParagraph::setTabStops( int tw )
598{
599 if ( hasdoc )
600 document()->setTabStops( tw );
601 else
602 tabStopWidth = tw;
603}
604
605QMap<int, QTextParagraphSelection> &QTextParagraph::selections() const
606{
607 if ( !mSelections )
608 ((QTextParagraph *)this)->mSelections = new QMap<int, QTextParagraphSelection>;
609 return *mSelections;
610}
611
612#ifndef QT_NO_TEXTCUSTOMITEM
613QPtrList<QTextCustomItem> &QTextParagraph::floatingItems() const
614{
615 if ( !mFloatingItems )
616 ((QTextParagraph *)this)->mFloatingItems = new QPtrList<QTextCustomItem>;
617 return *mFloatingItems;
618}
619#endif
620
621QTextStringChar::~QTextStringChar()
622{
623 if ( format() )
624 format()->removeRef();
625 if ( type ) // not Regular
626 delete d.custom;
627}
628
629QTextParagraphPseudoDocument::QTextParagraphPseudoDocument():pFormatter(0),commandHistory(0), minw(0),wused(0),collection(){}
630QTextParagraphPseudoDocument::~QTextParagraphPseudoDocument(){ delete pFormatter; delete commandHistory; }
631
632
633#endif //QT_NO_RICHTEXT
Note: See TracBrowser for help on using the repository browser.