60void QSyntaxHighlighterPrivate::applyFormatChanges()
62 bool formatsChanged =
false;
64 QTextLayout *layout = currentBlock.layout();
66 QList<QTextLayout::FormatRange> ranges = layout->formats();
68 const int preeditAreaStart = layout->preeditAreaPosition();
69 const int preeditAreaLength = layout->preeditAreaText().size();
71 if (preeditAreaLength != 0) {
72 auto isOutsidePreeditArea = [=](
const QTextLayout::FormatRange &range) {
73 return range.start < preeditAreaStart
74 || range.start + range.length > preeditAreaStart + preeditAreaLength;
76 if (ranges.removeIf(isOutsidePreeditArea) > 0)
77 formatsChanged =
true;
78 }
else if (!ranges.isEmpty()) {
80 formatsChanged =
true;
84 while (i < formatChanges.size()) {
85 QTextLayout::FormatRange r;
87 while (i < formatChanges.size() && formatChanges.at(i) == r.format)
90 if (i == formatChanges.size())
94 r.format = formatChanges.at(i);
96 while (i < formatChanges.size() && formatChanges.at(i) == r.format)
99 Q_ASSERT(i <= formatChanges.size());
100 r.length = i - r.start;
102 if (preeditAreaLength != 0) {
103 if (r.start >= preeditAreaStart)
104 r.start += preeditAreaLength;
105 else if (r.start + r.length >= preeditAreaStart)
106 r.length += preeditAreaLength;
110 formatsChanged =
true;
113 if (formatsChanged) {
114 layout->setFormats(ranges);
115 doc->markContentsDirty(currentBlock.position(), currentBlock.length());
125void QSyntaxHighlighterPrivate::reformatBlocks(
int from,
int charsRemoved,
int charsAdded)
127 QTextBlock block = doc->findBlock(from);
128 if (!block.isValid())
132 QTextBlock lastBlock = doc->findBlock(from + charsAdded + (charsRemoved > 0 ? 1 : 0));
133 if (lastBlock.isValid())
134 endPosition = lastBlock.position() + lastBlock.length();
136 endPosition = QTextDocumentPrivate::get(doc)->length();
138 bool forceHighlightOfNextBlock =
false;
140 while (block.isValid() && (block.position() < endPosition || forceHighlightOfNextBlock)) {
141 const int stateBeforeHighlight = block.userState();
143 reformatBlock(block);
145 forceHighlightOfNextBlock = (block.userState() != stateBeforeHighlight);
147 block = block.next();
150 formatChanges.clear();
153void QSyntaxHighlighterPrivate::reformatBlock(
const QTextBlock &block)
155 Q_Q(QSyntaxHighlighter);
157 Q_ASSERT_X(!currentBlock.isValid(),
"QSyntaxHighlighter::reformatBlock()",
"reFormatBlock() called recursively");
159 currentBlock = block;
161 formatChanges.fill(QTextCharFormat(), block.length() - 1);
162 q->highlightBlock(block.text());
163 applyFormatChanges();
165 currentBlock = QTextBlock();
258QSyntaxHighlighter::QSyntaxHighlighter(QObject *parent)
259 : QObject(*
new QSyntaxHighlighterPrivate, parent)
261 if (parent && parent->inherits(
"QTextEdit")) {
262 QTextDocument *doc = qvariant_cast<QTextDocument *>(parent->property(
"document"));
291void QSyntaxHighlighter::setDocument(QTextDocument *doc)
293 Q_D(QSyntaxHighlighter);
295 disconnect(d->doc, SIGNAL(contentsChange(
int,
int,
int)),
296 this, SLOT(_q_reformatBlocks(
int,
int,
int)));
298 QTextCursor cursor(d->doc);
299 cursor.beginEditBlock();
300 for (QTextBlock blk = d->doc->begin(); blk.isValid(); blk = blk.next())
301 blk.layout()->clearFormats();
302 cursor.endEditBlock();
306 connect(d->doc, SIGNAL(contentsChange(
int,
int,
int)),
307 this, SLOT(_q_reformatBlocks(
int,
int,
int)));
308 if (!d->doc->isEmpty()) {
309 d->rehighlightPending =
true;
310 QTimer::singleShot(0,
this, SLOT(_q_delayedRehighlight()));
350void QSyntaxHighlighter::rehighlightBlock(
const QTextBlock &block)
352 Q_D(QSyntaxHighlighter);
353 if (!d->doc || !block.isValid() || block.document() != d->doc)
356 const bool rehighlightPending = d->rehighlightPending;
358 QTextCursor cursor(block);
359 d->rehighlight(cursor, QTextCursor::EndOfBlock);
361 if (rehighlightPending)
362 d->rehighlightPending = rehighlightPending;
403void QSyntaxHighlighter::setFormat(
int start,
int count,
const QTextCharFormat &format)
405 Q_D(QSyntaxHighlighter);
406 if (start < 0 || start >= d->formatChanges.size())
409 const int end = qMin(start + count, d->formatChanges.size());
410 for (
int i = start; i < end; ++i)
411 d->formatChanges[i] = format;