source: trunk/src/qt3support/text/q3richtext_p.cpp@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

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