qtextdocument_p.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/text/qtextdocument_p.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include <private/qtools_p.h>-
41#include <qdebug.h>-
42-
43#include "qtextdocument_p.h"-
44#include "qtextdocument.h"-
45#include <qtextformat.h>-
46#include "qtextformat_p.h"-
47#include "qtextobject_p.h"-
48#include "qtextcursor.h"-
49#include "qtextimagehandler_p.h"-
50#include "qtextcursor_p.h"-
51#include "qtextdocumentlayout_p.h"-
52#include "qtexttable.h"-
53#include "qtextengine_p.h"-
54-
55#include <stdlib.h>-
56-
57QT_BEGIN_NAMESPACE-
58-
59#define PMDEBUG if(0) qDebug-
60-
61// The VxWorks DIAB compiler crashes when initializing the anonymouse union with { a7 }-
62#if !defined(Q_CC_DIAB)-
63# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \-
64 QTextUndoCommand c = { a1, a2, 0, 0, quint8(a3), a4, quint32(a5), quint32(a6), { int(a7) }, quint32(a8) }-
65#else-
66# define QT_INIT_TEXTUNDOCOMMAND(c, a1, a2, a3, a4, a5, a6, a7, a8) \-
67 QTextUndoCommand c = { a1, a2, 0, 0, a3, a4, a5, a6 }; c.blockFormat = a7; c.revision = a8-
68#endif-
69-
70/*-
71 Structure of a document:-
72-
73 DOCUMENT :== FRAME_CONTENTS-
74 FRAME :== START_OF_FRAME FRAME_CONTENTS END_OF_FRAME-
75 FRAME_CONTENTS = LIST_OF_BLOCKS ((FRAME | TABLE) LIST_OF_BLOCKS)*-
76 TABLE :== (START_OF_FRAME TABLE_CELL)+ END_OF_FRAME-
77 TABLE_CELL = FRAME_CONTENTS-
78 LIST_OF_BLOCKS :== (BLOCK END_OF_PARA)* BLOCK-
79 BLOCK :== (FRAGMENT)*-
80 FRAGMENT :== String of characters-
81-
82 END_OF_PARA :== 0x2029 # Paragraph separator in Unicode-
83 START_OF_FRAME :== 0xfdd0-
84 END_OF_FRAME := 0xfdd1-
85-
86 Note also that LIST_OF_BLOCKS can be empty. Nevertheless, there is-
87 at least one valid cursor position there where you could start-
88 typing. The block format is in this case determined by the last-
89 END_OF_PARA/START_OF_FRAME/END_OF_FRAME (see below).-
90-
91 Lists are not in here, as they are treated specially. A list is just-
92 a collection of (not necessarily connected) blocks, that share the-
93 same objectIndex() in the format that refers to the list format and-
94 object.-
95-
96 The above does not clearly note where formats are. Here's-
97 how it looks currently:-
98-
99 FRAGMENT: one charFormat associated-
100-
101 END_OF_PARA: one charFormat, and a blockFormat for the _next_ block.-
102-
103 START_OF_FRAME: one char format, and a blockFormat (for the next-
104 block). The format associated with the objectIndex() of the-
105 charFormat decides whether this is a frame or table and its-
106 properties-
107-
108 END_OF_FRAME: one charFormat and a blockFormat (for the next-
109 block). The object() of the charFormat is the same as for the-
110 corresponding START_OF_BLOCK.-
111-
112-
113 The document is independent of the layout with certain restrictions:-
114-
115 * Cursor movement (esp. up and down) depend on the layout.-
116 * You cannot have more than one layout, as the layout data of QTextObjects-
117 is stored in the text object itself.-
118-
119*/-
120-
121void QTextBlockData::invalidate() const-
122{-
123 if (layout)-
124 layout->engine()->invalidate();-
125}-
126-
127static bool isValidBlockSeparator(QChar ch)-
128{-
129 return ch == QChar::ParagraphSeparator-
130 || ch == QTextBeginningOfFrame-
131 || ch == QTextEndOfFrame;-
132}-
133-
134static bool noBlockInString(const QString &str)-
135{-
136 return !str.contains(QChar::ParagraphSeparator)-
137 && !str.contains(QTextBeginningOfFrame)-
138 && !str.contains(QTextEndOfFrame);-
139}-
140-
141bool QTextUndoCommand::tryMerge(const QTextUndoCommand &other)-
142{-
143 if (command != other.command)-
144 return false;-
145-
146 if (command == Inserted-
147 && (pos + length == other.pos)-
148 && (strPos + length == other.strPos)-
149 && format == other.format) {-
150-
151 length += other.length;-
152 return true;-
153 }-
154-
155 // removal to the 'right' using 'Delete' key-
156 if (command == Removed-
157 && pos == other.pos-
158 && (strPos + length == other.strPos)-
159 && format == other.format) {-
160-
161 length += other.length;-
162 return true;-
163 }-
164-
165 // removal to the 'left' using 'Backspace'-
166 if (command == Removed-
167 && (other.pos + other.length == pos)-
168 && (other.strPos + other.length == strPos)-
169 && (format == other.format)) {-
170-
171 int l = length;-
172 (*this) = other;-
173-
174 length += l;-
175 return true;-
176 }-
177-
178 return false;-
179}-
180-
181QTextDocumentPrivate::QTextDocumentPrivate()-
182 : wasUndoAvailable(false),-
183 wasRedoAvailable(false),-
184 docChangeOldLength(0),-
185 docChangeLength(0),-
186 framesDirty(true),-
187 rtFrame(0),-
188 initialBlockCharFormatIndex(-1) // set correctly later in init()-
189{-
190 editBlock = 0;-
191 editBlockCursorPosition = -1;-
192 docChangeFrom = -1;-
193-
194 undoState = 0;-
195 revision = -1; // init() inserts a block, bringing it to 0-
196-
197 lout = 0;-
198-
199 modified = false;-
200 modifiedState = 0;-
201-
202 undoEnabled = true;-
203 inContentsChange = false;-
204 blockCursorAdjustment = false;-
205-
206 defaultTextOption.setTabStop(80); // same as in qtextengine.cpp-
207 defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);-
208 defaultCursorMoveStyle = Qt::LogicalMoveStyle;-
209-
210 indentWidth = 40;-
211 documentMargin = 4;-
212-
213 maximumBlockCount = 0;-
214 needsEnsureMaximumBlockCount = false;-
215 unreachableCharacterCount = 0;-
216 lastBlockCount = 0;-
217}-
218-
219void QTextDocumentPrivate::init()-
220{-
221 framesDirty = false;-
222-
223 bool undoState = undoEnabled;-
224 undoEnabled = false;-
225 initialBlockCharFormatIndex = formats.indexForFormat(QTextCharFormat());-
226 insertBlock(0, formats.indexForFormat(QTextBlockFormat()), formats.indexForFormat(QTextCharFormat()));-
227 undoEnabled = undoState;-
228 modified = false;-
229 modifiedState = 0;-
230-
231 qRegisterMetaType<QTextDocument *>();-
232}-
233-
234void QTextDocumentPrivate::clear()-
235{-
236 Q_Q(QTextDocument);-
237-
238 foreachfor (QTextCursorPrivate *curs ,: qAsConst(cursors))) {-
239 curs->setPosition(0);-
240 curs->currentCharFormat = -1;-
241 curs->anchor = 0;-
242 curs->adjusted_anchor = 0;-
243 }
never executed: end of block
0
244-
245 QList<QTextCursorPrivate *>oldCursors = cursors;-
246 QT_TRY{-
247 cursors.clear();-
248-
249 QMap<int, QTextObject *>::Iterator objectIt = objects.begin();-
250 while (objectIt != objects.end()) {
objectIt != objects.end()Description
TRUEnever evaluated
FALSEnever evaluated
0
251 if (*objectIt != rtFrame) {
*objectIt != rtFrameDescription
TRUEnever evaluated
FALSEnever evaluated
0
252 delete *objectIt;-
253 objectIt = objects.erase(objectIt);-
254 } else {
never executed: end of block
0
255 ++objectIt;-
256 }
never executed: end of block
0
257 }-
258 // also clear out the remaining root frame pointer-
259 // (we're going to delete the object further down)-
260 objects.clear();-
261-
262 title.clear();-
263 clearUndoRedoStacks(QTextDocument::UndoAndRedoStacks);-
264 text = QString();-
265 unreachableCharacterCount = 0;-
266 modifiedState = 0;-
267 modified = false;-
268 formats = QTextFormatCollection();-
269 int len = fragments.length();-
270 fragments.clear();-
271 blocks.clear();-
272 cachedResources.clear();-
273 delete rtFrame;-
274 rtFrame = 0;-
275 init();-
276 cursors = oldCursors;-
277 inContentsChange = true;-
278 q->contentsChange(0, len, 0);-
279 inContentsChange = false;-
280 if (lout)
loutDescription
TRUEnever evaluated
FALSEnever evaluated
0
281 lout->documentChanged(0, len, 0);
never executed: lout->documentChanged(0, len, 0);
0
282 } QT_CATCH(...) {
never executed: end of block
dead code: { cursors = oldCursors; qt_noop(); }
-
283 cursors = oldCursors; // at least recover the cursors
dead code: { cursors = oldCursors; qt_noop(); }
-
284 QT_RETHROW;
dead code: { cursors = oldCursors; qt_noop(); }
-
285 }
dead code: { cursors = oldCursors; qt_noop(); }
-
286}-
287-
288QTextDocumentPrivate::~QTextDocumentPrivate()-
289{-
290 foreachfor (QTextCursorPrivate *curs ,: qAsConst(cursors)))-
291 curs->priv = 0;
never executed: curs->priv = 0;
0
292 cursors.clear();-
293 undoState = 0;-
294 undoEnabled = true;-
295 clearUndoRedoStacks(QTextDocument::RedoStack);-
296}
never executed: end of block
0
297-
298void QTextDocumentPrivate::setLayout(QAbstractTextDocumentLayout *layout)-
299{-
300 Q_Q(QTextDocument);-
301 if (lout == layout)-
302 return;-
303 const bool firstLayout = !lout;-
304 delete lout;-
305 lout = layout;-
306-
307 if (!firstLayout)-
308 for (BlockMap::Iterator it = blocks.begin(); !it.atEnd(); ++it)-
309 it->free();-
310-
311 emit q->documentLayoutChanged();-
312 inContentsChange = true;-
313 emit q->contentsChange(0, 0, length());-
314 inContentsChange = false;-
315 if (lout)-
316 lout->documentChanged(0, 0, length());-
317}-
318-
319-
320void QTextDocumentPrivate::insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op)-
321{-
322 // ##### optimize when only appending to the fragment!-
323 Q_ASSERT(noBlockInString(text.mid(strPos, length)));-
324-
325 split(pos);-
326 uint x = fragments.insert_single(pos, length);-
327 QTextFragmentData *X = fragments.fragment(x);-
328 X->format = format;-
329 X->stringPosition = strPos;-
330 uint w = fragments.previous(x);-
331 if (w)-
332 unite(w);-
333-
334 int b = blocks.findNode(pos);-
335 blocks.setSize(b, blocks.size(b)+length);-
336-
337 Q_ASSERT(blocks.length() == fragments.length());-
338-
339 QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(format));-
340 if (frame) {-
341 frame->d_func()->fragmentAdded(text.at(strPos), x);-
342 framesDirty = true;-
343 }-
344-
345 adjustDocumentChangesAndCursors(pos, length, op);-
346}-
347-
348int QTextDocumentPrivate::insert_block(int pos, uint strPos, int format, int blockFormat, QTextUndoCommand::Operation op, int command)-
349{-
350 split(pos);-
351 uint x = fragments.insert_single(pos, 1);-
352 QTextFragmentData *X = fragments.fragment(x);-
353 X->format = format;-
354 X->stringPosition = strPos;-
355 // no need trying to unite, since paragraph separators are always in a fragment of their own-
356-
357 Q_ASSERT(isValidBlockSeparator(text.at(strPos)));-
358 Q_ASSERT(blocks.length()+1 == fragments.length());-
359-
360 int block_pos = pos;-
361 if (blocks.length() && command == QTextUndoCommand::BlockRemoved)-
362 ++block_pos;-
363 int size = 1;-
364 int n = blocks.findNode(block_pos);-
365 int key = n ? blocks.position(n) : blocks.length();-
366-
367 Q_ASSERT(n || (!n && block_pos == blocks.length()));-
368 if (key != block_pos) {-
369 Q_ASSERT(key < block_pos);-
370 int oldSize = blocks.size(n);-
371 blocks.setSize(n, block_pos-key);-
372 size += oldSize - (block_pos-key);-
373 }-
374 int b = blocks.insert_single(block_pos, size);-
375 QTextBlockData *B = blocks.fragment(b);-
376 B->format = blockFormat;-
377-
378 Q_ASSERT(blocks.length() == fragments.length());-
379-
380 QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(blockFormat));-
381 if (group)-
382 group->blockInserted(QTextBlock(this, b));-
383-
384 QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(formats.format(format)));-
385 if (frame) {-
386 frame->d_func()->fragmentAdded(text.at(strPos), x);-
387 framesDirty = true;-
388 }-
389-
390 adjustDocumentChangesAndCursors(pos, 1, op);-
391 return x;-
392}-
393-
394int QTextDocumentPrivate::insertBlock(QChar blockSeparator,-
395 int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op)-
396{-
397 Q_ASSERT(formats.format(blockFormat).isBlockFormat());-
398 Q_ASSERT(formats.format(charFormat).isCharFormat());-
399 Q_ASSERT(pos >= 0 && (pos < fragments.length() || (pos == 0 && fragments.length() == 0)));-
400 Q_ASSERT(isValidBlockSeparator(blockSeparator));-
401-
402 beginEditBlock();-
403-
404 int strPos = text.length();-
405 text.append(blockSeparator);-
406-
407 int ob = blocks.findNode(pos);-
408 bool atBlockEnd = true;-
409 bool atBlockStart = true;-
410 int oldRevision = 0;-
411 if (ob) {-
412 atBlockEnd = (pos - blocks.position(ob) == blocks.size(ob)-1);-
413 atBlockStart = ((int)blocks.position(ob) == pos);-
414 oldRevision = blocks.fragment(ob)->revision;-
415 }-
416-
417 const int fragment = insert_block(pos, strPos, charFormat, blockFormat, op, QTextUndoCommand::BlockRemoved);-
418-
419 Q_ASSERT(blocks.length() == fragments.length());-
420-
421 int b = blocks.findNode(pos);-
422 QTextBlockData *B = blocks.fragment(b);-
423-
424 QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockInserted, (editBlock != 0),-
425 op, charFormat, strPos, pos, blockFormat,-
426 B->revision);-
427-
428 appendUndoItem(c);-
429 Q_ASSERT(undoState == undoStack.size());-
430-
431 // update revision numbers of the modified blocks.-
432 B->revision = (atBlockEnd && !atBlockStart)? oldRevision : revision;-
433 b = blocks.next(b);-
434 if (b) {-
435 B = blocks.fragment(b);-
436 B->revision = atBlockStart ? oldRevision : revision;-
437 }-
438-
439 if (formats.charFormat(charFormat).objectIndex() == -1)-
440 needsEnsureMaximumBlockCount = true;-
441-
442 endEditBlock();-
443 return fragment;-
444}-
445-
446int QTextDocumentPrivate::insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation op)-
447{-
448 return insertBlock(QChar::ParagraphSeparator, pos, blockFormat, charFormat, op);-
449}-
450-
451void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format)-
452{-
453 if (strLength <= 0)-
454 return;-
455-
456 Q_ASSERT(pos >= 0 && pos < fragments.length());-
457 Q_ASSERT(formats.format(format).isCharFormat());-
458-
459 insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor);-
460 if (undoEnabled) {-
461 int b = blocks.findNode(pos);-
462 QTextBlockData *B = blocks.fragment(b);-
463-
464 QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Inserted, (editBlock != 0),-
465 QTextUndoCommand::MoveCursor, format, strPos, pos, strLength,-
466 B->revision);-
467 appendUndoItem(c);-
468 B->revision = revision;-
469 Q_ASSERT(undoState == undoStack.size());-
470 }-
471 finishEdit();-
472}-
473-
474void QTextDocumentPrivate::insert(int pos, const QString &str, int format)-
475{-
476 if (str.size() == 0)-
477 return;-
478-
479 Q_ASSERT(noBlockInString(str));-
480-
481 int strPos = text.length();-
482 text.append(str);-
483 insert(pos, strPos, str.length(), format);-
484}-
485-
486int QTextDocumentPrivate::remove_string(int pos, uint length, QTextUndoCommand::Operation op)-
487{-
488 Q_ASSERT(pos >= 0);-
489 Q_ASSERT(blocks.length() == fragments.length());-
490 Q_ASSERT(blocks.length() >= pos+(int)length);-
491-
492 int b = blocks.findNode(pos);-
493 uint x = fragments.findNode(pos);-
494-
495 Q_ASSERT(blocks.size(b) > length);-
496 Q_ASSERT(x && fragments.position(x) == (uint)pos && fragments.size(x) == length);-
497 Q_ASSERT(noBlockInString(text.mid(fragments.fragment(x)->stringPosition, length)));-
498-
499 blocks.setSize(b, blocks.size(b)-length);-
500-
501 QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(fragments.fragment(x)->format));-
502 if (frame) {-
503 frame->d_func()->fragmentRemoved(text.at(fragments.fragment(x)->stringPosition), x);-
504 framesDirty = true;-
505 }-
506-
507 const int w = fragments.erase_single(x);-
508-
509 if (!undoEnabled)-
510 unreachableCharacterCount += length;-
511-
512 adjustDocumentChangesAndCursors(pos, -int(length), op);-
513-
514 return w;-
515}-
516-
517int QTextDocumentPrivate::remove_block(int pos, int *blockFormat, int command, QTextUndoCommand::Operation op)-
518{-
519 Q_ASSERT(pos >= 0);-
520 Q_ASSERT(blocks.length() == fragments.length());-
521 Q_ASSERT(blocks.length() > pos);-
522-
523 int b = blocks.findNode(pos);-
524 uint x = fragments.findNode(pos);-
525-
526 Q_ASSERT(x && (int)fragments.position(x) == pos);-
527 Q_ASSERT(fragments.size(x) == 1);-
528 Q_ASSERT(isValidBlockSeparator(text.at(fragments.fragment(x)->stringPosition)));-
529 Q_ASSERT(b);-
530-
531 if (blocks.size(b) == 1 && command == QTextUndoCommand::BlockAdded) {-
532 Q_ASSERT((int)blocks.position(b) == pos);-
533 // qDebug("removing empty block");-
534 // empty block remove the block itself-
535 } else {-
536 // non empty block, merge with next one into this block-
537 // qDebug("merging block with next");-
538 int n = blocks.next(b);-
539 Q_ASSERT((int)blocks.position(n) == pos + 1);-
540 blocks.setSize(b, blocks.size(b) + blocks.size(n) - 1);-
541 blocks.fragment(b)->userState = blocks.fragment(n)->userState;-
542 b = n;-
543 }-
544 *blockFormat = blocks.fragment(b)->format;-
545-
546 QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(blocks.fragment(b)->format));-
547 if (group)-
548 group->blockRemoved(QTextBlock(this, b));-
549-
550 QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(fragments.fragment(x)->format));-
551 if (frame) {-
552 frame->d_func()->fragmentRemoved(text.at(fragments.fragment(x)->stringPosition), x);-
553 framesDirty = true;-
554 }-
555-
556 blocks.erase_single(b);-
557 const int w = fragments.erase_single(x);-
558-
559 adjustDocumentChangesAndCursors(pos, -1, op);-
560-
561 return w;-
562}-
563-
564#if !defined(QT_NO_DEBUG)-
565static bool isAncestorFrame(QTextFrame *possibleAncestor, QTextFrame *child)-
566{-
567 while (child) {-
568 if (child == possibleAncestor)-
569 return true;-
570 child = child->parentFrame();-
571 }-
572 return false;-
573}-
574#endif-
575-
576void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::Operation op)-
577{-
578 Q_ASSERT(to <= fragments.length() && to <= pos);-
579 Q_ASSERT(pos >= 0 && pos+length <= fragments.length());-
580 Q_ASSERT(blocks.length() == fragments.length());-
581-
582 if (pos == to)-
583 return;-
584-
585 const bool needsInsert = to != -1;-
586-
587#if !defined(QT_NO_DEBUG)-
588 const bool startAndEndInSameFrame = (frameAt(pos) == frameAt(pos + length - 1));-
589-
590 const bool endIsEndOfChildFrame = (isAncestorFrame(frameAt(pos), frameAt(pos + length - 1))-
591 && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame);-
592-
593 const bool startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent-
594 = (text.at(find(pos)->stringPosition) == QTextBeginningOfFrame-
595 && text.at(find(pos + length - 1)->stringPosition) == QTextEndOfFrame-
596 && frameAt(pos)->parentFrame() == frameAt(pos + length - 1)->parentFrame());-
597-
598 const bool isFirstTableCell = (qobject_cast<QTextTable *>(frameAt(pos + length - 1))-
599 && frameAt(pos + length - 1)->parentFrame() == frameAt(pos));-
600-
601 Q_ASSERT(startAndEndInSameFrame || endIsEndOfChildFrame || startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent || isFirstTableCell);-
602#endif-
603-
604 split(pos);-
605 split(pos+length);-
606-
607 uint dst = needsInsert ? fragments.findNode(to) : 0;-
608 uint dstKey = needsInsert ? fragments.position(dst) : 0;-
609-
610 uint x = fragments.findNode(pos);-
611 uint end = fragments.findNode(pos+length);-
612-
613 uint w = 0;-
614 while (x != end) {-
615 uint n = fragments.next(x);-
616-
617 uint key = fragments.position(x);-
618 uint b = blocks.findNode(key+1);-
619 QTextBlockData *B = blocks.fragment(b);-
620 int blockRevision = B->revision;-
621-
622 QTextFragmentData *X = fragments.fragment(x);-
623 QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::Removed, (editBlock != 0),-
624 op, X->format, X->stringPosition, key, X->size_array[0],-
625 blockRevision);-
626 QT_INIT_TEXTUNDOCOMMAND(cInsert, QTextUndoCommand::Inserted, (editBlock != 0),-
627 op, X->format, X->stringPosition, dstKey, X->size_array[0],-
628 blockRevision);-
629-
630 if (key+1 != blocks.position(b)) {-
631// qDebug("remove_string from %d length %d", key, X->size_array[0]);-
632 Q_ASSERT(noBlockInString(text.mid(X->stringPosition, X->size_array[0])));-
633 w = remove_string(key, X->size_array[0], op);-
634-
635 if (needsInsert) {-
636 insert_string(dstKey, X->stringPosition, X->size_array[0], X->format, op);-
637 dstKey += X->size_array[0];-
638 }-
639 } else {-
640// qDebug("remove_block at %d", key);-
641 Q_ASSERT(X->size_array[0] == 1 && isValidBlockSeparator(text.at(X->stringPosition)));-
642 b = blocks.previous(b);-
643 B = 0;-
644 c.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockDeleted : QTextUndoCommand::BlockRemoved;-
645 w = remove_block(key, &c.blockFormat, QTextUndoCommand::BlockAdded, op);-
646-
647 if (needsInsert) {-
648 insert_block(dstKey++, X->stringPosition, X->format, c.blockFormat, op, QTextUndoCommand::BlockRemoved);-
649 cInsert.command = blocks.size(b) == 1 ? QTextUndoCommand::BlockAdded : QTextUndoCommand::BlockInserted;-
650 cInsert.blockFormat = c.blockFormat;-
651 }-
652 }-
653 appendUndoItem(c);-
654 if (B)-
655 B->revision = revision;-
656 x = n;-
657-
658 if (needsInsert)-
659 appendUndoItem(cInsert);-
660 }-
661 if (w)-
662 unite(w);-
663-
664 Q_ASSERT(blocks.length() == fragments.length());-
665-
666 if (!blockCursorAdjustment)-
667 finishEdit();-
668}-
669-
670void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op)-
671{-
672 if (length == 0)
length == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
673 return;
never executed: return;
0
674 blockCursorAdjustment = true;-
675 move(pos, -1, length, op);-
676 blockCursorAdjustment = false;-
677 foreachfor (QTextCursorPrivate *curs ,: qAsConst(cursors))) {-
678 if (curs->adjustPosition(pos, -length, op) == QTextCursorPrivate::CursorMoved) {
curs->adjustPo...e::CursorMovedDescription
TRUEnever evaluated
FALSEnever evaluated
0
679 curs->changed = true;-
680 }
never executed: end of block
0
681 }
never executed: end of block
0
682 finishEdit();-
683}
never executed: end of block
0
684-
685void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode)-
686{-
687 beginEditBlock();-
688-
689 Q_ASSERT(newFormat.isValid());-
690-
691 int newFormatIdx = -1;-
692 if (mode == SetFormatAndPreserveObjectIndices) {-
693 QTextCharFormat cleanFormat = newFormat;-
694 cleanFormat.clearProperty(QTextFormat::ObjectIndex);-
695 newFormatIdx = formats.indexForFormat(cleanFormat);-
696 } else if (mode == SetFormat) {-
697 newFormatIdx = formats.indexForFormat(newFormat);-
698 }-
699-
700 if (pos == -1) {-
701 if (mode == MergeFormat) {-
702 QTextFormat format = formats.format(initialBlockCharFormatIndex);-
703 format.merge(newFormat);-
704 initialBlockCharFormatIndex = formats.indexForFormat(format);-
705 } else if (mode == SetFormatAndPreserveObjectIndices-
706 && formats.format(initialBlockCharFormatIndex).objectIndex() != -1) {-
707 QTextCharFormat f = newFormat;-
708 f.setObjectIndex(formats.format(initialBlockCharFormatIndex).objectIndex());-
709 initialBlockCharFormatIndex = formats.indexForFormat(f);-
710 } else {-
711 initialBlockCharFormatIndex = newFormatIdx;-
712 }-
713-
714 ++pos;-
715 --length;-
716 }-
717-
718 const int startPos = pos;-
719 const int endPos = pos + length;-
720-
721 split(startPos);-
722 split(endPos);-
723-
724 while (pos < endPos) {-
725 FragmentMap::Iterator it = fragments.find(pos);-
726 Q_ASSERT(!it.atEnd());-
727-
728 QTextFragmentData *fragment = it.value();-
729-
730 Q_ASSERT(formats.format(fragment->format).type() == QTextFormat::CharFormat);-
731-
732 int offset = pos - it.position();-
733 int length = qMin(endPos - pos, int(fragment->size_array[0] - offset));-
734 int oldFormat = fragment->format;-
735-
736 if (mode == MergeFormat) {-
737 QTextFormat format = formats.format(fragment->format);-
738 format.merge(newFormat);-
739 fragment->format = formats.indexForFormat(format);-
740 } else if (mode == SetFormatAndPreserveObjectIndices-
741 && formats.format(oldFormat).objectIndex() != -1) {-
742 QTextCharFormat f = newFormat;-
743 f.setObjectIndex(formats.format(oldFormat).objectIndex());-
744 fragment->format = formats.indexForFormat(f);-
745 } else {-
746 fragment->format = newFormatIdx;-
747 }-
748-
749 QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::CharFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,-
750 0, pos, length, 0);-
751 appendUndoItem(c);-
752-
753 pos += length;-
754 Q_ASSERT(pos == (int)(it.position() + fragment->size_array[0]) || pos >= endPos);-
755 }-
756-
757 int n = fragments.findNode(startPos - 1);-
758 if (n)-
759 unite(n);-
760-
761 n = fragments.findNode(endPos);-
762 if (n)-
763 unite(n);-
764-
765 QTextBlock blockIt = blocksFind(startPos);-
766 QTextBlock endIt = blocksFind(endPos);-
767 if (endIt.isValid())-
768 endIt = endIt.next();-
769 for (; blockIt.isValid() && blockIt != endIt; blockIt = blockIt.next())-
770 QTextDocumentPrivate::block(blockIt)->invalidate();-
771-
772 documentChange(startPos, length);-
773-
774 endEditBlock();-
775}-
776-
777void QTextDocumentPrivate::setBlockFormat(const QTextBlock &from, const QTextBlock &to,-
778 const QTextBlockFormat &newFormat, FormatChangeMode mode)-
779{-
780 beginEditBlock();-
781-
782 Q_ASSERT(mode != SetFormatAndPreserveObjectIndices); // only implemented for setCharFormat-
783-
784 Q_ASSERT(newFormat.isValid());-
785-
786 int newFormatIdx = -1;-
787 if (mode == SetFormat)-
788 newFormatIdx = formats.indexForFormat(newFormat);-
789 QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(newFormat));-
790-
791 QTextBlock it = from;-
792 QTextBlock end = to;-
793 if (end.isValid())-
794 end = end.next();-
795-
796 for (; it != end; it = it.next()) {-
797 int oldFormat = block(it)->format;-
798 QTextBlockFormat format = formats.blockFormat(oldFormat);-
799 QTextBlockGroup *oldGroup = qobject_cast<QTextBlockGroup *>(objectForFormat(format));-
800 if (mode == MergeFormat) {-
801 format.merge(newFormat);-
802 newFormatIdx = formats.indexForFormat(format);-
803 group = qobject_cast<QTextBlockGroup *>(objectForFormat(format));-
804 }-
805 block(it)->format = newFormatIdx;-
806-
807 block(it)->invalidate();-
808-
809 QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::BlockFormatChanged, true, QTextUndoCommand::MoveCursor, oldFormat,-
810 0, it.position(), 1, 0);-
811 appendUndoItem(c);-
812-
813 if (group != oldGroup) {-
814 if (oldGroup)-
815 oldGroup->blockRemoved(it);-
816 if (group)-
817 group->blockInserted(it);-
818 } else if (group) {-
819 group->blockFormatChanged(it);-
820 }-
821 }-
822-
823 documentChange(from.position(), to.position() + to.length() - from.position());-
824-
825 endEditBlock();-
826}-
827-
828-
829bool QTextDocumentPrivate::split(int pos)-
830{-
831 uint x = fragments.findNode(pos);-
832 if (x) {-
833 int k = fragments.position(x);-
834// qDebug("found fragment with key %d, size_left=%d, size=%d to split at %d",-
835// k, (*it)->size_left[0], (*it)->size_array[0], pos);-
836 if (k != pos) {-
837 Q_ASSERT(k <= pos);-
838 // need to resize the first fragment and add a new one-
839 QTextFragmentData *X = fragments.fragment(x);-
840 int oldsize = X->size_array[0];-
841 fragments.setSize(x, pos-k);-
842 uint n = fragments.insert_single(pos, oldsize-(pos-k));-
843 X = fragments.fragment(x);-
844 QTextFragmentData *N = fragments.fragment(n);-
845 N->stringPosition = X->stringPosition + pos-k;-
846 N->format = X->format;-
847 return true;-
848 }-
849 }-
850 return false;-
851}-
852-
853bool QTextDocumentPrivate::unite(uint f)-
854{-
855 uint n = fragments.next(f);-
856 if (!n)-
857 return false;-
858-
859 QTextFragmentData *ff = fragments.fragment(f);-
860 QTextFragmentData *nf = fragments.fragment(n);-
861-
862 if (nf->format == ff->format && (ff->stringPosition + (int)ff->size_array[0] == nf->stringPosition)) {-
863 if (isValidBlockSeparator(text.at(ff->stringPosition))-
864 || isValidBlockSeparator(text.at(nf->stringPosition)))-
865 return false;-
866-
867 fragments.setSize(f, ff->size_array[0] + nf->size_array[0]);-
868 fragments.erase_single(n);-
869 return true;-
870 }-
871 return false;-
872}-
873-
874-
875int QTextDocumentPrivate::undoRedo(bool undo)-
876{-
877 PMDEBUG("%s, undoState=%d, undoStack size=%d", undo ? "undo:" : "redo:", undoState, undoStack.size());
dead code: QMessageLogger(__FILE__, 877, __PRETTY_FUNCTION__).debug("%s, undoState=%d, undoStack size=%d", undo ? "undo:" : "redo:", undoState, undoStack.size());
-
878 if (!undoEnabled || (undo && undoState == 0) || (!undo && undoState == undoStack.size()))
!undoEnabledDescription
TRUEnever evaluated
FALSEnever evaluated
undoDescription
TRUEnever evaluated
FALSEnever evaluated
undoState == 0Description
TRUEnever evaluated
FALSEnever evaluated
!undoDescription
TRUEnever evaluated
FALSEnever evaluated
undoState == undoStack.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
879 return -1;
never executed: return -1;
0
880-
881 undoEnabled = false;-
882 beginEditBlock();-
883 int editPos = -1;-
884 int editLength = -1;-
885 while (1) {-
886 if (undo)
undoDescription
TRUEnever evaluated
FALSEnever evaluated
0
887 --undoState;
never executed: --undoState;
0
888 QTextUndoCommand &c = undoStack[undoState];-
889 int resetBlockRevision = c.pos;-
890-
891 switch (c.command) {-
892 case QTextUndoCommand::Inserted:
never executed: case QTextUndoCommand::Inserted:
0
893 remove(c.pos, c.length, (QTextUndoCommand::Operation)c.operation);-
894 PMDEBUG(" erase: from %d, length %d", c.pos, c.length);
dead code: QMessageLogger(__FILE__, 894, __PRETTY_FUNCTION__).debug(" erase: from %d, length %d", c.pos, c.length);
-
895 c.command = QTextUndoCommand::Removed;-
896 editPos = c.pos;-
897 editLength = 0;-
898 break;
never executed: break;
0
899 case QTextUndoCommand::Removed:
never executed: case QTextUndoCommand::Removed:
0
900 PMDEBUG(" insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos);
dead code: QMessageLogger(__FILE__, 900, __PRETTY_FUNCTION__).debug(" insert: format %d (from %d, length %d, strpos=%d)", c.format, c.pos, c.length, c.strPos);
-
901 insert_string(c.pos, c.strPos, c.length, c.format, (QTextUndoCommand::Operation)c.operation);-
902 c.command = QTextUndoCommand::Inserted;-
903 if (editPos != (int)c.pos)
editPos != (int)c.posDescription
TRUEnever evaluated
FALSEnever evaluated
0
904 editLength = 0;
never executed: editLength = 0;
0
905 editPos = c.pos;-
906 editLength += c.length;-
907 break;
never executed: break;
0
908 case QTextUndoCommand::BlockInserted:
never executed: case QTextUndoCommand::BlockInserted:
0
909 case QTextUndoCommand::BlockAdded:
never executed: case QTextUndoCommand::BlockAdded:
0
910 remove_block(c.pos, &c.blockFormat, c.command, (QTextUndoCommand::Operation)c.operation);-
911 PMDEBUG(" blockremove: from %d", c.pos);
dead code: QMessageLogger(__FILE__, 911, __PRETTY_FUNCTION__).debug(" blockremove: from %d", c.pos);
-
912 if (c.command == QTextUndoCommand::BlockInserted)
c.command == Q...:BlockInsertedDescription
TRUEnever evaluated
FALSEnever evaluated
0
913 c.command = QTextUndoCommand::BlockRemoved;
never executed: c.command = QTextUndoCommand::BlockRemoved;
0
914 else-
915 c.command = QTextUndoCommand::BlockDeleted;
never executed: c.command = QTextUndoCommand::BlockDeleted;
0
916 editPos = c.pos;-
917 editLength = 0;-
918 break;
never executed: break;
0
919 case QTextUndoCommand::BlockRemoved:
never executed: case QTextUndoCommand::BlockRemoved:
0
920 case QTextUndoCommand::BlockDeleted:
never executed: case QTextUndoCommand::BlockDeleted:
0
921 PMDEBUG(" blockinsert: charformat %d blockformat %d (pos %d, strpos=%d)", c.format, c.blockFormat, c.pos, c.strPos);
dead code: QMessageLogger(__FILE__, 921, __PRETTY_FUNCTION__).debug(" blockinsert: charformat %d blockformat %d (pos %d, strpos=%d)", c.format, c.blockFormat, c.pos, c.strPos);
-
922 insert_block(c.pos, c.strPos, c.format, c.blockFormat, (QTextUndoCommand::Operation)c.operation, c.command);-
923 resetBlockRevision += 1;-
924 if (c.command == QTextUndoCommand::BlockRemoved)
c.command == Q...::BlockRemovedDescription
TRUEnever evaluated
FALSEnever evaluated
0
925 c.command = QTextUndoCommand::BlockInserted;
never executed: c.command = QTextUndoCommand::BlockInserted;
0
926 else-
927 c.command = QTextUndoCommand::BlockAdded;
never executed: c.command = QTextUndoCommand::BlockAdded;
0
928 if (editPos != (int)c.pos)
editPos != (int)c.posDescription
TRUEnever evaluated
FALSEnever evaluated
0
929 editLength = 0;
never executed: editLength = 0;
0
930 editPos = c.pos;-
931 editLength += 1;-
932 break;
never executed: break;
0
933 case QTextUndoCommand::CharFormatChanged: {
never executed: case QTextUndoCommand::CharFormatChanged:
0
934 resetBlockRevision = -1; // ## TODO-
935 PMDEBUG(" charFormat: format %d (from %d, length %d)", c.format, c.pos, c.length);
dead code: QMessageLogger(__FILE__, 935, __PRETTY_FUNCTION__).debug(" charFormat: format %d (from %d, length %d)", c.format, c.pos, c.length);
-
936 FragmentIterator it = find(c.pos);-
937 Q_ASSERT(!it.atEnd());-
938-
939 int oldFormat = it.value()->format;-
940 setCharFormat(c.pos, c.length, formats.charFormat(c.format));-
941 c.format = oldFormat;-
942 if (editPos != (int)c.pos)
editPos != (int)c.posDescription
TRUEnever evaluated
FALSEnever evaluated
0
943 editLength = 0;
never executed: editLength = 0;
0
944 editPos = c.pos;-
945 editLength += c.length;-
946 break;
never executed: break;
0
947 }-
948 case QTextUndoCommand::BlockFormatChanged: {
never executed: case QTextUndoCommand::BlockFormatChanged:
0
949 resetBlockRevision = -1; // ## TODO-
950 PMDEBUG(" blockformat: format %d pos %d", c.format, c.pos);
dead code: QMessageLogger(__FILE__, 950, __PRETTY_FUNCTION__).debug(" blockformat: format %d pos %d", c.format, c.pos);
-
951 QTextBlock it = blocksFind(c.pos);-
952 Q_ASSERT(it.isValid());-
953-
954 int oldFormat = block(it)->format;-
955 block(it)->format = c.format;-
956 QTextBlockGroup *oldGroup = qobject_cast<QTextBlockGroup *>(objectForFormat(formats.blockFormat(oldFormat)));-
957 QTextBlockGroup *group = qobject_cast<QTextBlockGroup *>(objectForFormat(formats.blockFormat(c.format)));-
958 c.format = oldFormat;-
959 if (group != oldGroup) {
group != oldGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
960 if (oldGroup)
oldGroupDescription
TRUEnever evaluated
FALSEnever evaluated
0
961 oldGroup->blockRemoved(it);
never executed: oldGroup->blockRemoved(it);
0
962 if (group)
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
963 group->blockInserted(it);
never executed: group->blockInserted(it);
0
964 } else if (group) {
never executed: end of block
groupDescription
TRUEnever evaluated
FALSEnever evaluated
0
965 group->blockFormatChanged(it);-
966 }
never executed: end of block
0
967 documentChange(it.position(), it.length());-
968 editPos = -1;-
969 break;
never executed: break;
0
970 }-
971 case QTextUndoCommand::GroupFormatChange: {
never executed: case QTextUndoCommand::GroupFormatChange:
0
972 resetBlockRevision = -1; // ## TODO-
973 PMDEBUG(" group format change");
dead code: QMessageLogger(__FILE__, 973, __PRETTY_FUNCTION__).debug(" group format change");
-
974 QTextObject *object = objectForIndex(c.objectIndex);-
975 int oldFormat = formats.objectFormatIndex(c.objectIndex);-
976 changeObjectFormat(object, c.format);-
977 c.format = oldFormat;-
978 editPos = -1;-
979 break;
never executed: break;
0
980 }-
981 case QTextUndoCommand::CursorMoved:
never executed: case QTextUndoCommand::CursorMoved:
0
982 editPos = c.pos;-
983 editLength = 0;-
984 break;
never executed: break;
0
985 case QTextUndoCommand::Custom:
never executed: case QTextUndoCommand::Custom:
0
986 resetBlockRevision = -1; // ## TODO-
987 if (undo)
undoDescription
TRUEnever evaluated
FALSEnever evaluated
0
988 c.custom->undo();
never executed: c.custom->undo();
0
989 else-
990 c.custom->redo();
never executed: c.custom->redo();
0
991 editPos = -1;-
992 break;
never executed: break;
0
993 default:
never executed: default:
0
994 Q_ASSERT(false);-
995 }
never executed: end of block
0
996-
997 if (resetBlockRevision >= 0) {
resetBlockRevision >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
998 int b = blocks.findNode(resetBlockRevision);-
999 QTextBlockData *B = blocks.fragment(b);-
1000 B->revision = c.revision;-
1001 }
never executed: end of block
0
1002-
1003 if (!undo)
!undoDescription
TRUEnever evaluated
FALSEnever evaluated
0
1004 ++undoState;
never executed: ++undoState;
0
1005-
1006 bool inBlock = (-
1007 undoState > 0
undoState > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1008 && undoState < undoStack.size()
undoState < undoStack.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1009 && undoStack[.at(undoState].).block_part
undoStack.at(u...te).block_partDescription
TRUEnever evaluated
FALSEnever evaluated
0
1010 && undoStack[.at(undoState - 1].).block_part
undoStack.at(u... 1).block_partDescription
TRUEnever evaluated
FALSEnever evaluated
0
1011 && !undoStack[.at(undoState - 1].).block_end
!undoStack.at(...- 1).block_endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1012 );-
1013 if (!inBlock)
!inBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1014 break;
never executed: break;
0
1015 }
never executed: end of block
0
1016 undoEnabled = true;-
1017-
1018 int newCursorPos = -1;-
1019-
1020 if (editPos >=0)
editPos >=0Description
TRUEnever evaluated
FALSEnever evaluated
0
1021 newCursorPos = editPos + editLength;
never executed: newCursorPos = editPos + editLength;
0
1022 else if (docChangeFrom >= 0)
docChangeFrom >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1023 newCursorPos= qMin(docChangeFrom + docChangeLength, length() - 1);
never executed: newCursorPos= qMin(docChangeFrom + docChangeLength, length() - 1);
0
1024-
1025 endEditBlock();-
1026 emitUndoAvailable(isUndoAvailable());-
1027 emitRedoAvailable(isRedoAvailable());-
1028-
1029 return newCursorPos;
never executed: return newCursorPos;
0
1030}-
1031-
1032/*!-
1033 Appends a custom undo \a item to the undo stack.-
1034*/-
1035void QTextDocumentPrivate::appendUndoItem(QAbstractUndoItem *item)-
1036{-
1037 if (!undoEnabled) {-
1038 delete item;-
1039 return;-
1040 }-
1041-
1042 QTextUndoCommand c;-
1043 c.command = QTextUndoCommand::Custom;-
1044 c.block_part = editBlock != 0;-
1045 c.block_end = 0;-
1046 c.operation = QTextUndoCommand::MoveCursor;-
1047 c.format = 0;-
1048 c.strPos = 0;-
1049 c.pos = 0;-
1050 c.blockFormat = 0;-
1051-
1052 c.custom = item;-
1053 appendUndoItem(c);-
1054}-
1055-
1056void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)-
1057{-
1058 PMDEBUG("appendUndoItem, command=%d enabled=%d", c.command, undoEnabled);
dead code: QMessageLogger(__FILE__, 1058, __PRETTY_FUNCTION__).debug("appendUndoItem, command=%d enabled=%d", c.command, undoEnabled);
-
1059 if (!undoEnabled)
!undoEnabledDescription
TRUEnever evaluated
FALSEnever evaluated
0
1060 return;
never executed: return;
0
1061 if (undoState < undoStack.size())
undoState < undoStack.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1062 clearUndoRedoStacks(QTextDocument::RedoStack);
never executed: clearUndoRedoStacks(QTextDocument::RedoStack);
0
1063-
1064 if (editBlock != 0 && editBlockCursorPosition >= 0) { // we had a beginEditBlock() with a cursor position
editBlock != 0Description
TRUEnever evaluated
FALSEnever evaluated
editBlockCursorPosition >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1065 if (c.pos != (quint32) editBlockCursorPosition) { // and that cursor position is different from the command
c.pos != (quin...CursorPositionDescription
TRUEnever evaluated
FALSEnever evaluated
0
1066 // generate a CursorMoved undo item-
1067 QT_INIT_TEXTUNDOCOMMAND(cc, QTextUndoCommand::CursorMoved, true, QTextUndoCommand::MoveCursor,-
1068 0, 0, editBlockCursorPosition, 0, 0);-
1069 undoStack.append(cc);-
1070 undoState++;-
1071 editBlockCursorPosition = -1;-
1072 }
never executed: end of block
0
1073 }
never executed: end of block
0
1074-
1075-
1076 if (!undoStack.isEmpty() && modified) {
!undoStack.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
modifiedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1077 QTextUndoCommand &lastconst int lastIdx = undoStack[undoState - 1];;-
1078 const QTextUndoCommand &last = undoStack.at(lastIdx);-
1079-
1080 if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge
last.block_partDescription
TRUEnever evaluated
FALSEnever evaluated
c.block_partDescription
TRUEnever evaluated
FALSEnever evaluated
!last.block_endDescription
TRUEnever evaluated
FALSEnever evaluated
0
1081 || (!c.block_part && !last.block_part)) { // two single undo items => can merge
!c.block_partDescription
TRUEnever evaluated
FALSEnever evaluated
!last.block_partDescription
TRUEnever evaluated
FALSEnever evaluated
0
1082-
1083 if (last.undoStack[lastIdx].tryMerge(c))
undoStack[lastIdx].tryMerge(c)Description
TRUEnever evaluated
FALSEnever evaluated
0
1084 return;
never executed: return;
0
1085 }
never executed: end of block
0
1086 }
never executed: end of block
0
1087 if (modifiedState > undoState)
modifiedState > undoStateDescription
TRUEnever evaluated
FALSEnever evaluated
0
1088 modifiedState = -1;
never executed: modifiedState = -1;
0
1089 undoStack.append(c);-
1090 undoState++;-
1091 emitUndoAvailable(true);-
1092 emitRedoAvailable(false);-
1093-
1094 if (!c.block_part)
!c.block_partDescription
TRUEnever evaluated
FALSEnever evaluated
0
1095 emit document()->undoCommandAdded();
never executed: document()->undoCommandAdded();
0
1096}
never executed: end of block
0
1097-
1098void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToClear,-
1099 bool emitSignals)-
1100{-
1101 bool undoCommandsAvailable = undoState != 0;-
1102 bool redoCommandsAvailable = undoState != undoStack.size();-
1103 if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
stacksToClear ...ent::UndoStackDescription
TRUEnever evaluated
FALSEnever evaluated
undoCommandsAvailableDescription
TRUEnever evaluated
FALSEnever evaluated
0
1104 for (int i = 0; i < undoState; ++i) {
i < undoStateDescription
TRUEnever evaluated
FALSEnever evaluated
0
1105 QTextUndoCommand c = undoStack[.at(undoState];);-
1106 if (c.command & QTextUndoCommand::Custom)
c.command & QT...ommand::CustomDescription
TRUEnever evaluated
FALSEnever evaluated
0
1107 delete c.custom;
never executed: delete c.custom;
0
1108 }
never executed: end of block
0
1109 undoStack.remove(0, undoState);-
1110 undoStack.resize(undoStack.size() - undoState);-
1111 undoState = 0;-
1112 if (emitSignals)
emitSignalsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1113 emitUndoAvailable(false);
never executed: emitUndoAvailable(false);
0
1114 } else if (stacksToClear == QTextDocument::RedoStack
never executed: end of block
stacksToClear ...ent::RedoStackDescription
TRUEnever evaluated
FALSEnever evaluated
0
1115 && redoCommandsAvailable) {
redoCommandsAvailableDescription
TRUEnever evaluated
FALSEnever evaluated
0
1116 for (int i = undoState; i < undoStack.size(); ++i) {
i < undoStack.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1117 QTextUndoCommand c = undoStack[.at(i];);-
1118 if (c.command & QTextUndoCommand::Custom)
c.command & QT...ommand::CustomDescription
TRUEnever evaluated
FALSEnever evaluated
0
1119 delete c.custom;
never executed: delete c.custom;
0
1120 }
never executed: end of block
0
1121 undoStack.resize(undoState);-
1122 if (emitSignals)
emitSignalsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1123 emitRedoAvailable(false);
never executed: emitRedoAvailable(false);
0
1124 } else if (stacksToClear == QTextDocument::UndoAndRedoStacks
never executed: end of block
stacksToClear ...oAndRedoStacksDescription
TRUEnever evaluated
FALSEnever evaluated
0
1125 && !undoStack.isEmpty()) {
!undoStack.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1126 for (int i = 0; i < undoStack.size(); ++i) {
i < undoStack.size()Description
TRUEnever evaluated
FALSEnever evaluated
0
1127 QTextUndoCommand c = undoStack[.at(i];);-
1128 if (c.command & QTextUndoCommand::Custom)
c.command & QT...ommand::CustomDescription
TRUEnever evaluated
FALSEnever evaluated
0
1129 delete c.custom;
never executed: delete c.custom;
0
1130 }
never executed: end of block
0
1131 undoState = 0;-
1132 undoStack.resize(0);clear();-
1133 if (emitSignals && undoCommandsAvailable)
emitSignalsDescription
TRUEnever evaluated
FALSEnever evaluated
undoCommandsAvailableDescription
TRUEnever evaluated
FALSEnever evaluated
0
1134 emitUndoAvailable(false);
never executed: emitUndoAvailable(false);
0
1135 if (emitSignals && redoCommandsAvailable)
emitSignalsDescription
TRUEnever evaluated
FALSEnever evaluated
redoCommandsAvailableDescription
TRUEnever evaluated
FALSEnever evaluated
0
1136 emitRedoAvailable(false);
never executed: emitRedoAvailable(false);
0
1137 }
never executed: end of block
0
1138}
never executed: end of block
0
1139-
1140void QTextDocumentPrivate::emitUndoAvailable(bool available)-
1141{-
1142 if (available != wasUndoAvailable) {-
1143 Q_Q(QTextDocument);-
1144 emit q->undoAvailable(available);-
1145 wasUndoAvailable = available;-
1146 }-
1147}-
1148-
1149void QTextDocumentPrivate::emitRedoAvailable(bool available)-
1150{-
1151 if (available != wasRedoAvailable) {-
1152 Q_Q(QTextDocument);-
1153 emit q->redoAvailable(available);-
1154 wasRedoAvailable = available;-
1155 }-
1156}-
1157-
1158void QTextDocumentPrivate::enableUndoRedo(bool enable)-
1159{-
1160 if (enable && maximumBlockCount > 0)-
1161 return;-
1162-
1163 if (!enable) {-
1164 undoState = 0;-
1165 clearUndoRedoStacks(QTextDocument::RedoStack);-
1166 emitUndoAvailable(false);-
1167 emitRedoAvailable(false);-
1168 }-
1169 modifiedState = modified ? -1 : undoState;-
1170 undoEnabled = enable;-
1171 if (!undoEnabled)-
1172 compressPieceTable();-
1173}-
1174-
1175void QTextDocumentPrivate::joinPreviousEditBlock()-
1176{-
1177 beginEditBlock();-
1178-
1179 if (undoEnabled && undoState)-
1180 undoStack[undoState - 1].block_end = false;-
1181}-
1182-
1183void QTextDocumentPrivate::endEditBlock()-
1184{-
1185 Q_ASSERT(editBlock > 0);-
1186 if (--editBlock)
--editBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1187 return;
never executed: return;
0
1188-
1189 if (undoEnabled && undoState > 0) {
undoEnabledDescription
TRUEnever evaluated
FALSEnever evaluated
undoState > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1190 const bool wasBlocking = !undoStack[.at(undoState - 1].).block_end;-
1191 if (undoStack[.at(undoState - 1].).block_part) {
undoStack.at(u... 1).block_partDescription
TRUEnever evaluated
FALSEnever evaluated
0
1192 undoStack[undoState - 1].block_end = true;-
1193 if (wasBlocking)
wasBlockingDescription
TRUEnever evaluated
FALSEnever evaluated
0
1194 emit document()->undoCommandAdded();
never executed: document()->undoCommandAdded();
0
1195 }
never executed: end of block
0
1196 }
never executed: end of block
0
1197-
1198 editBlockCursorPosition = -1;-
1199-
1200 finishEdit();-
1201}
never executed: end of block
0
1202-
1203void QTextDocumentPrivate::finishEdit()-
1204{-
1205 Q_Q(QTextDocument);-
1206-
1207 if (editBlock)
editBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1208 return;
never executed: return;
0
1209-
1210 if (framesDirty)
framesDirtyDescription
TRUEnever evaluated
FALSEnever evaluated
0
1211 scan_frames(docChangeFrom, docChangeOldLength, docChangeLength);
never executed: scan_frames(docChangeFrom, docChangeOldLength, docChangeLength);
0
1212-
1213 if (lout && docChangeFrom >= 0) {
loutDescription
TRUEnever evaluated
FALSEnever evaluated
docChangeFrom >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1214 if (!inContentsChange) {
!inContentsChangeDescription
TRUEnever evaluated
FALSEnever evaluated
0
1215 inContentsChange = true;-
1216 emit q->contentsChange(docChangeFrom, docChangeOldLength, docChangeLength);-
1217 inContentsChange = false;-
1218 }
never executed: end of block
0
1219 lout->documentChanged(docChangeFrom, docChangeOldLength, docChangeLength);-
1220 }
never executed: end of block
0
1221-
1222 docChangeFrom = -1;-
1223-
1224 if (needsEnsureMaximumBlockCount) {
needsEnsureMaximumBlockCountDescription
TRUEnever evaluated
FALSEnever evaluated
0
1225 needsEnsureMaximumBlockCount = false;-
1226 if (ensureMaximumBlockCount()) {
ensureMaximumBlockCount()Description
TRUEnever evaluated
FALSEnever evaluated
0
1227 // if ensureMaximumBlockCount() returns true-
1228 // it will have called endEditBlock() and-
1229 // compressPieceTable() itself, so we return here-
1230 // to prevent getting two contentsChanged emits-
1231 return;
never executed: return;
0
1232 }-
1233 }
never executed: end of block
0
1234-
1235 QList<QTextCursor> changedCursors;-
1236 foreachfor (QTextCursorPrivate *curs ,: qAsConst(cursors))) {-
1237 if (curs->changed) {
curs->changedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1238 curs->changed = false;-
1239 changedCursors.append(QTextCursor(curs));-
1240 }
never executed: end of block
0
1241 }
never executed: end of block
0
1242 foreachfor (const QTextCursor &cursor ,: qAsConst(changedCursors)))-
1243 emit q->cursorPositionChanged(cursor);
never executed: q->cursorPositionChanged(cursor);
0
1244-
1245 contentsChanged();-
1246-
1247 if (blocks.numNodes() != lastBlockCount) {
blocks.numNode...lastBlockCountDescription
TRUEnever evaluated
FALSEnever evaluated
0
1248 lastBlockCount = blocks.numNodes();-
1249 emit q->blockCountChanged(lastBlockCount);-
1250 }
never executed: end of block
0
1251-
1252 if (!undoEnabled && unreachableCharacterCount)
!undoEnabledDescription
TRUEnever evaluated
FALSEnever evaluated
unreachableCharacterCountDescription
TRUEnever evaluated
FALSEnever evaluated
0
1253 compressPieceTable();
never executed: compressPieceTable();
0
1254}
never executed: end of block
0
1255-
1256void QTextDocumentPrivate::documentChange(int from, int length)-
1257{-
1258// qDebug("QTextDocumentPrivate::documentChange: from=%d,length=%d", from, length);-
1259 if (docChangeFrom < 0) {-
1260 docChangeFrom = from;-
1261 docChangeOldLength = length;-
1262 docChangeLength = length;-
1263 return;-
1264 }-
1265 int start = qMin(from, docChangeFrom);-
1266 int end = qMax(from + length, docChangeFrom + docChangeLength);-
1267 int diff = qMax(0, end - start - docChangeLength);-
1268 docChangeFrom = start;-
1269 docChangeOldLength += diff;-
1270 docChangeLength += diff;-
1271}-
1272-
1273/*-
1274 adjustDocumentChangesAndCursors is called whenever there is an insert or remove of characters.-
1275 param from is the cursor position in the document-
1276 param addedOrRemoved is the amount of characters added or removed. A negative number means characters are removed.-
1277-
1278 The function stores information to be emitted when finishEdit() is called.-
1279*/-
1280void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op)-
1281{-
1282 if (!editBlock)
!editBlockDescription
TRUEnever evaluated
FALSEnever evaluated
0
1283 ++revision;
never executed: ++revision;
0
1284-
1285 if (blockCursorAdjustment) {
blockCursorAdjustmentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1286 ; // postpone, will be called again from QTextDocumentPrivate::remove()-
1287 } else {
never executed: end of block
0
1288 foreachfor (QTextCursorPrivate *curs ,: qAsConst(cursors))) {-
1289 if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) {
curs->adjustPo...e::CursorMovedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1290 curs->changed = true;-
1291 }
never executed: end of block
0
1292 }
never executed: end of block
0
1293 }
never executed: end of block
0
1294-
1295// qDebug("QTextDocumentPrivate::adjustDocumentChanges: from=%d,addedOrRemoved=%d", from, addedOrRemoved);-
1296 if (docChangeFrom < 0) {
docChangeFrom < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1297 docChangeFrom = from;-
1298 if (addedOrRemoved > 0) {
addedOrRemoved > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1299 docChangeOldLength = 0;-
1300 docChangeLength = addedOrRemoved;-
1301 } else {
never executed: end of block
0
1302 docChangeOldLength = -addedOrRemoved;-
1303 docChangeLength = 0;-
1304 }
never executed: end of block
0
1305// qDebug("adjustDocumentChanges:");-
1306// qDebug(" -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength);-
1307 return;
never executed: return;
0
1308 }-
1309-
1310 // have to merge the new change with the already existing one.-
1311 int added = qMax(0, addedOrRemoved);-
1312 int removed = qMax(0, -addedOrRemoved);-
1313-
1314 int diff = 0;-
1315 if (from + removed < docChangeFrom)
from + removed < docChangeFromDescription
TRUEnever evaluated
FALSEnever evaluated
0
1316 diff = docChangeFrom - from - removed;
never executed: diff = docChangeFrom - from - removed;
0
1317 else if (from > docChangeFrom + docChangeLength)
from > docChan...ocChangeLengthDescription
TRUEnever evaluated
FALSEnever evaluated
0
1318 diff = from - (docChangeFrom + docChangeLength);
never executed: diff = from - (docChangeFrom + docChangeLength);
0
1319-
1320 int overlap_start = qMax(from, docChangeFrom);-
1321 int overlap_end = qMin(from + removed, docChangeFrom + docChangeLength);-
1322 int removedInside = qMax(0, overlap_end - overlap_start);-
1323 removed -= removedInside;-
1324-
1325// qDebug("adjustDocumentChanges: from=%d, addedOrRemoved=%d, diff=%d, removedInside=%d", from, addedOrRemoved, diff, removedInside);-
1326 docChangeFrom = qMin(docChangeFrom, from);-
1327 docChangeOldLength += removed + diff;-
1328 docChangeLength += added - removedInside + diff;-
1329// qDebug(" -> %d %d %d", docChangeFrom, docChangeOldLength, docChangeLength);-
1330-
1331}
never executed: end of block
0
1332-
1333-
1334QString QTextDocumentPrivate::plainText() const-
1335{-
1336 QString result;-
1337 result.resize(length());-
1338 const QChar *text_unicode = text.unicode();-
1339 QChar *data = result.data();-
1340 for (QTextDocumentPrivate::FragmentIterator it = begin(); it != end(); ++it) {-
1341 const QTextFragmentData *f = *it;-
1342 ::memcpy(data, text_unicode + f->stringPosition, f->size_array[0] * sizeof(QChar));-
1343 data += f->size_array[0];-
1344 }-
1345 // remove trailing block separator-
1346 result.chop(1);-
1347 return result;-
1348}-
1349-
1350int QTextDocumentPrivate::blockCharFormatIndex(int node) const-
1351{-
1352 int pos = blocks.position(node);-
1353 if (pos == 0)-
1354 return initialBlockCharFormatIndex;-
1355-
1356 return fragments.find(pos - 1)->format;-
1357}-
1358-
1359int QTextDocumentPrivate::nextCursorPosition(int position, QTextLayout::CursorMode mode) const-
1360{-
1361 if (position == length()-1)-
1362 return position;-
1363-
1364 QTextBlock it = blocksFind(position);-
1365 int start = it.position();-
1366 int end = start + it.length() - 1;-
1367 if (position == end)-
1368 return end + 1;-
1369-
1370 return it.layout()->nextCursorPosition(position-start, mode) + start;-
1371}-
1372-
1373int QTextDocumentPrivate::previousCursorPosition(int position, QTextLayout::CursorMode mode) const-
1374{-
1375 if (position == 0)-
1376 return position;-
1377-
1378 QTextBlock it = blocksFind(position);-
1379 int start = it.position();-
1380 if (position == start)-
1381 return start - 1;-
1382-
1383 return it.layout()->previousCursorPosition(position-start, mode) + start;-
1384}-
1385-
1386int QTextDocumentPrivate::leftCursorPosition(int position) const-
1387{-
1388 QTextBlock it = blocksFind(position);-
1389 int start = it.position();-
1390 return it.layout()->leftCursorPosition(position-start) + start;-
1391}-
1392-
1393int QTextDocumentPrivate::rightCursorPosition(int position) const-
1394{-
1395 QTextBlock it = blocksFind(position);-
1396 int start = it.position();-
1397 return it.layout()->rightCursorPosition(position-start) + start;-
1398}-
1399-
1400void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)-
1401{-
1402 beginEditBlock();-
1403 int objectIndex = obj->objectIndex();-
1404 int oldFormatIndex = formats.objectFormatIndex(objectIndex);-
1405 formats.setObjectFormatIndex(objectIndex, format);-
1406-
1407 QTextBlockGroup *b = qobject_cast<QTextBlockGroup *>(obj);-
1408 if (b) {-
1409 b->d_func()->markBlocksDirty();-
1410 }-
1411 QTextFrame *f = qobject_cast<QTextFrame *>(obj);-
1412 if (f)-
1413 documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition());-
1414-
1415 QT_INIT_TEXTUNDOCOMMAND(c, QTextUndoCommand::GroupFormatChange, (editBlock != 0), QTextUndoCommand::MoveCursor, oldFormatIndex,-
1416 0, 0, obj->d_func()->objectIndex, 0);-
1417 appendUndoItem(c);-
1418-
1419 endEditBlock();-
1420}-
1421-
1422static QTextFrame *findChildFrame(QTextFrame *f, int pos)-
1423{-
1424 /* Binary search for frame at pos */-
1425 const QList<QTextFrame *> children = f->childFrames();-
1426 int first = 0;-
1427 int last = children.size() - 1;-
1428 while (first <= last) {-
1429 int mid = (first + last) / 2;-
1430 QTextFrame *c = children.at(mid);-
1431 if (pos > c->lastPosition())-
1432 first = mid + 1;-
1433 else if (pos < c->firstPosition())-
1434 last = mid - 1;-
1435 else-
1436 return c;-
1437 }-
1438 return 0;-
1439}-
1440-
1441QTextFrame *QTextDocumentPrivate::rootFrame() const-
1442{-
1443 if (!rtFrame) {-
1444 QTextFrameFormat defaultRootFrameFormat;-
1445 defaultRootFrameFormat.setMargin(documentMargin);-
1446 rtFrame = qobject_cast<QTextFrame *>(const_cast<QTextDocumentPrivate *>(this)->createObject(defaultRootFrameFormat));-
1447 }-
1448 return rtFrame;-
1449}-
1450-
1451QTextFrame *QTextDocumentPrivate::frameAt(int pos) const-
1452{-
1453 QTextFrame *f = rootFrame();-
1454-
1455 while (1) {-
1456 QTextFrame *c = findChildFrame(f, pos);-
1457 if (!c)-
1458 return f;-
1459 f = c;-
1460 }-
1461}-
1462-
1463void QTextDocumentPrivate::clearFrame(QTextFrame *f)-
1464{-
1465 for (int i = 0; i < f->d_func()->childFrames.count(); ++i)-
1466 clearFrame(f->d_func()->childFrames.at(i));-
1467 f->d_func()->childFrames.clear();-
1468 f->d_func()->parentFrame = 0;-
1469}-
1470-
1471void QTextDocumentPrivate::scan_frames(int pos, int charsRemoved, int charsAdded)-
1472{-
1473 // ###### optimize-
1474 Q_UNUSED(pos);-
1475 Q_UNUSED(charsRemoved);-
1476 Q_UNUSED(charsAdded);-
1477-
1478 QTextFrame *f = rootFrame();-
1479 clearFrame(f);-
1480-
1481 for (FragmentIterator it = begin(); it != end(); ++it) {-
1482 // QTextFormat fmt = formats.format(it->format);-
1483 QTextFrame *frame = qobject_cast<QTextFrame *>(objectForFormat(it->format));-
1484 if (!frame)-
1485 continue;-
1486-
1487 Q_ASSERT(it.size() == 1);-
1488 QChar ch = text.at(it->stringPosition);-
1489-
1490 if (ch == QTextBeginningOfFrame) {-
1491 if (f != frame) {-
1492 // f == frame happens for tables-
1493 Q_ASSERT(frame->d_func()->fragment_start == it.n || frame->d_func()->fragment_start == 0);-
1494 frame->d_func()->parentFrame = f;-
1495 f->d_func()->childFrames.append(frame);-
1496 f = frame;-
1497 }-
1498 } else if (ch == QTextEndOfFrame) {-
1499 Q_ASSERT(f == frame);-
1500 Q_ASSERT(frame->d_func()->fragment_end == it.n || frame->d_func()->fragment_end == 0);-
1501 f = frame->d_func()->parentFrame;-
1502 } else if (ch == QChar::ObjectReplacementCharacter) {-
1503 Q_ASSERT(f != frame);-
1504 Q_ASSERT(frame->d_func()->fragment_start == it.n || frame->d_func()->fragment_start == 0);-
1505 Q_ASSERT(frame->d_func()->fragment_end == it.n || frame->d_func()->fragment_end == 0);-
1506 frame->d_func()->parentFrame = f;-
1507 f->d_func()->childFrames.append(frame);-
1508 } else {-
1509 Q_ASSERT(false);-
1510 }-
1511 }-
1512 Q_ASSERT(f == rtFrame);-
1513 framesDirty = false;-
1514}-
1515-
1516void QTextDocumentPrivate::insert_frame(QTextFrame *f)-
1517{-
1518 int start = f->firstPosition();-
1519 int end = f->lastPosition();-
1520 QTextFrame *parent = frameAt(start-1);-
1521 Q_ASSERT(parent == frameAt(end+1));-
1522-
1523 if (start != end) {-
1524 // iterator over the parent and move all children contained in my frame to myself-
1525 for (int i = 0; i < parent->d_func()->childFrames.size(); ++i) {-
1526 QTextFrame *c = parent->d_func()->childFrames.at(i);-
1527 if (start < c->firstPosition() && end > c->lastPosition()) {-
1528 parent->d_func()->childFrames.removeAt(i);-
1529 f->d_func()->childFrames.append(c);-
1530 c->d_func()->parentFrame = f;-
1531 }-
1532 }-
1533 }-
1534 // insert at the correct position-
1535 int i = 0;-
1536 for (; i < parent->d_func()->childFrames.size(); ++i) {-
1537 QTextFrame *c = parent->d_func()->childFrames.at(i);-
1538 if (c->firstPosition() > end)-
1539 break;-
1540 }-
1541 parent->d_func()->childFrames.insert(i, f);-
1542 f->d_func()->parentFrame = parent;-
1543}-
1544-
1545QTextFrame *QTextDocumentPrivate::insertFrame(int start, int end, const QTextFrameFormat &format)-
1546{-
1547 Q_ASSERT(start >= 0 && start < length());-
1548 Q_ASSERT(end >= 0 && end < length());-
1549 Q_ASSERT(start <= end || end == -1);-
1550-
1551 if (start != end && frameAt(start) != frameAt(end))-
1552 return 0;-
1553-
1554 beginEditBlock();-
1555-
1556 QTextFrame *frame = qobject_cast<QTextFrame *>(createObject(format));-
1557 Q_ASSERT(frame);-
1558-
1559 // #### using the default block and char format below might be wrong-
1560 int idx = formats.indexForFormat(QTextBlockFormat());-
1561 QTextCharFormat cfmt;-
1562 cfmt.setObjectIndex(frame->objectIndex());-
1563 int charIdx = formats.indexForFormat(cfmt);-
1564-
1565 insertBlock(QTextBeginningOfFrame, start, idx, charIdx, QTextUndoCommand::MoveCursor);-
1566 insertBlock(QTextEndOfFrame, ++end, idx, charIdx, QTextUndoCommand::KeepCursor);-
1567-
1568 frame->d_func()->fragment_start = find(start).n;-
1569 frame->d_func()->fragment_end = find(end).n;-
1570-
1571 insert_frame(frame);-
1572-
1573 endEditBlock();-
1574-
1575 return frame;-
1576}-
1577-
1578void QTextDocumentPrivate::removeFrame(QTextFrame *frame)-
1579{-
1580 QTextFrame *parent = frame->d_func()->parentFrame;-
1581 if (!parent)-
1582 return;-
1583-
1584 int start = frame->firstPosition();-
1585 int end = frame->lastPosition();-
1586 Q_ASSERT(end >= start);-
1587-
1588 beginEditBlock();-
1589-
1590 // remove already removes the frames from the tree-
1591 remove(end, 1);-
1592 remove(start-1, 1);-
1593-
1594 endEditBlock();-
1595}-
1596-
1597QTextObject *QTextDocumentPrivate::objectForIndex(int objectIndex) const-
1598{-
1599 if (objectIndex < 0)-
1600 return 0;-
1601-
1602 QTextObject *object = objects.value(objectIndex, 0);-
1603 if (!object) {-
1604 QTextDocumentPrivate *that = const_cast<QTextDocumentPrivate *>(this);-
1605 QTextFormat fmt = formats.objectFormat(objectIndex);-
1606 object = that->createObject(fmt, objectIndex);-
1607 }-
1608 return object;-
1609}-
1610-
1611QTextObject *QTextDocumentPrivate::objectForFormat(int formatIndex) const-
1612{-
1613 int objectIndex = formats.format(formatIndex).objectIndex();-
1614 return objectForIndex(objectIndex);-
1615}-
1616-
1617QTextObject *QTextDocumentPrivate::objectForFormat(const QTextFormat &f) const-
1618{-
1619 return objectForIndex(f.objectIndex());-
1620}-
1621-
1622QTextObject *QTextDocumentPrivate::createObject(const QTextFormat &f, int objectIndex)-
1623{-
1624 QTextObject *obj = document()->createObject(f);-
1625-
1626 if (obj) {-
1627 obj->d_func()->objectIndex = objectIndex == -1 ? formats.createObjectIndex(f) : objectIndex;-
1628 objects[obj->d_func()->objectIndex] = obj;-
1629 }-
1630-
1631 return obj;-
1632}-
1633-
1634void QTextDocumentPrivate::deleteObject(QTextObject *object)-
1635{-
1636 const int objIdx = object->d_func()->objectIndex;-
1637 objects.remove(objIdx);-
1638 delete object;-
1639}-
1640-
1641void QTextDocumentPrivate::contentsChanged()-
1642{-
1643 Q_Q(QTextDocument);-
1644 if (editBlock)-
1645 return;-
1646-
1647 bool m = undoEnabled ? (modifiedState != undoState) : true;-
1648 if (modified != m) {-
1649 modified = m;-
1650 emit q->modificationChanged(modified);-
1651 }-
1652-
1653 emit q->contentsChanged();-
1654}-
1655-
1656void QTextDocumentPrivate::compressPieceTable()-
1657{-
1658 if (undoEnabled)-
1659 return;-
1660-
1661 const uint garbageCollectionThreshold = 96 * 1024; // bytes-
1662-
1663 //qDebug() << "unreachable bytes:" << unreachableCharacterCount * sizeof(QChar) << " -- limit" << garbageCollectionThreshold << "text size =" << text.size() << "capacity:" << text.capacity();-
1664-
1665 bool compressTable = unreachableCharacterCount * sizeof(QChar) > garbageCollectionThreshold-
1666 && text.size() >= text.capacity() * 0.9;-
1667 if (!compressTable)-
1668 return;-
1669-
1670 QString newText;-
1671 newText.resize(text.size());-
1672 QChar *newTextPtr = newText.data();-
1673 int newLen = 0;-
1674-
1675 for (FragmentMap::Iterator it = fragments.begin(); !it.atEnd(); ++it) {-
1676 memcpy(newTextPtr, text.constData() + it->stringPosition, it->size_array[0] * sizeof(QChar));-
1677 it->stringPosition = newLen;-
1678 newTextPtr += it->size_array[0];-
1679 newLen += it->size_array[0];-
1680 }-
1681-
1682 newText.resize(newLen);-
1683 newText.squeeze();-
1684 //qDebug() << "removed" << text.size() - newText.size() << "characters";-
1685 text = newText;-
1686 unreachableCharacterCount = 0;-
1687}-
1688-
1689void QTextDocumentPrivate::setModified(bool m)-
1690{-
1691 Q_Q(QTextDocument);-
1692 if (m == modified)-
1693 return;-
1694-
1695 modified = m;-
1696 if (!modified)-
1697 modifiedState = undoState;-
1698 else-
1699 modifiedState = -1;-
1700-
1701 emit q->modificationChanged(modified);-
1702}-
1703-
1704bool QTextDocumentPrivate::ensureMaximumBlockCount()-
1705{-
1706 if (maximumBlockCount <= 0)-
1707 return false;-
1708 if (blocks.numNodes() <= maximumBlockCount)-
1709 return false;-
1710-
1711 beginEditBlock();-
1712-
1713 const int blocksToRemove = blocks.numNodes() - maximumBlockCount;-
1714 QTextCursor cursor(this, 0);-
1715 cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, blocksToRemove);-
1716-
1717 unreachableCharacterCount += cursor.selectionEnd() - cursor.selectionStart();-
1718-
1719 // preserve the char format of the paragraph that is to become the new first one-
1720 QTextCharFormat charFmt = cursor.blockCharFormat();-
1721 cursor.removeSelectedText();-
1722 cursor.setBlockCharFormat(charFmt);-
1723-
1724 endEditBlock();-
1725-
1726 compressPieceTable();-
1727-
1728 return true;-
1729}-
1730-
1731/// This method is called from QTextTable when it is about to remove a table-cell to allow cursors to update their selection.-
1732void QTextDocumentPrivate::aboutToRemoveCell(int from, int to)-
1733{-
1734 Q_ASSERT(from <= to);-
1735 foreachfor (QTextCursorPrivate *curs ,: qAsConst(cursors)))-
1736 curs->aboutToRemoveCell(from, to);
never executed: curs->aboutToRemoveCell(from, to);
0
1737}
never executed: end of block
0
1738-
1739QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9