- Klammerpaare werden farblich hervorgehoben - Beim einrücken oder ausrücken eines markierten Blocks wird die Zeile, in der der Coursor steht, nicht mehr mitgerückt - Beim eintippen von Variablen wird eine Liste mit bereits deklarierten Variablen angezeigt
590 lines
22 KiB
C++
590 lines
22 KiB
C++
#include "SyntaxHighlighter.h"
|
||
#include <QTextDocument>
|
||
|
||
// ===========================================================================
|
||
// SyntaxHighlighter – Basis
|
||
// ===========================================================================
|
||
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
|
||
: QSyntaxHighlighter(parent)
|
||
{
|
||
}
|
||
|
||
void SyntaxHighlighter::highlightBlock(const QString &text)
|
||
{
|
||
// Einzel-Zeilen-Regeln anwenden
|
||
for (const HighlightRule &rule : m_rules)
|
||
{
|
||
QRegularExpressionMatchIterator it = rule.pattern.globalMatch(text);
|
||
while (it.hasNext())
|
||
{
|
||
QRegularExpressionMatch match = it.next();
|
||
setFormat(
|
||
static_cast<int>(match.capturedStart()),
|
||
static_cast<int>(match.capturedLength()),
|
||
rule.format
|
||
);
|
||
}
|
||
}
|
||
|
||
if (!m_hasMultiLineComment)
|
||
{
|
||
setCurrentBlockState(0);
|
||
return;
|
||
}
|
||
|
||
// Mehrzeilige Kommentare
|
||
// Zustand 0 = normal, 1 = mitten in /* ... */
|
||
setCurrentBlockState(0);
|
||
|
||
// Leere Zeile mitten im Kommentar — Zustand weitertragen
|
||
if (text.isEmpty())
|
||
{
|
||
if (previousBlockState() == 1)
|
||
{
|
||
setCurrentBlockState(1);
|
||
}
|
||
return;
|
||
}
|
||
|
||
int startIndex = 0;
|
||
|
||
if (previousBlockState() == 1)
|
||
{
|
||
// Vorherige Zeile war mitten im Kommentar — ab Zeilenanfang nach Ende suchen
|
||
QRegularExpressionMatch endMatch = m_commentEndExpression.match(text, 0);
|
||
|
||
if (endMatch.hasMatch())
|
||
{
|
||
// Ende des Kommentars gefunden
|
||
const int commentLength = static_cast<int>(endMatch.capturedStart())
|
||
+ static_cast<int>(endMatch.capturedLength());
|
||
setFormat(0, commentLength, m_multiLineCommentFormat);
|
||
|
||
// Nach weiteren Kommentaren in der gleichen Zeile suchen
|
||
QRegularExpressionMatch nextStart =
|
||
m_commentStartExpression.match(text, commentLength);
|
||
startIndex = nextStart.hasMatch()
|
||
? static_cast<int>(nextStart.capturedStart())
|
||
: -1;
|
||
}
|
||
else
|
||
{
|
||
// Noch kein Ende — gesamte Zeile ist Kommentar
|
||
setFormat(0, text.length(), m_multiLineCommentFormat);
|
||
setCurrentBlockState(1);
|
||
return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Neuen Kommentaranfang suchen
|
||
QRegularExpressionMatch m = m_commentStartExpression.match(text);
|
||
startIndex = m.hasMatch() ? static_cast<int>(m.capturedStart()) : -1;
|
||
}
|
||
|
||
while (startIndex >= 0)
|
||
{
|
||
QRegularExpressionMatch endMatch =
|
||
m_commentEndExpression.match(text, startIndex);
|
||
|
||
int commentLength = 0;
|
||
|
||
if (endMatch.hasMatch())
|
||
{
|
||
commentLength = static_cast<int>(endMatch.capturedStart())
|
||
- startIndex
|
||
+ static_cast<int>(endMatch.capturedLength());
|
||
}
|
||
else
|
||
{
|
||
// Kommentar geht über Zeilenende
|
||
setCurrentBlockState(1);
|
||
commentLength = text.length() - startIndex;
|
||
}
|
||
|
||
setFormat(startIndex, commentLength, m_multiLineCommentFormat);
|
||
|
||
if (!endMatch.hasMatch())
|
||
{
|
||
break;
|
||
}
|
||
|
||
// Nach weiteren Kommentaren in dieser Zeile suchen
|
||
QRegularExpressionMatch nextStart =
|
||
m_commentStartExpression.match(text, startIndex + commentLength);
|
||
startIndex = nextStart.hasMatch()
|
||
? static_cast<int>(nextStart.capturedStart())
|
||
: -1;
|
||
}
|
||
}
|
||
|
||
// ===========================================================================
|
||
// CppHighlighter
|
||
// ===========================================================================
|
||
CppHighlighter::CppHighlighter(QTextDocument *parent)
|
||
: SyntaxHighlighter(parent)
|
||
{
|
||
m_hasMultiLineComment = true;
|
||
|
||
QTextCharFormat keywordFormat;
|
||
keywordFormat.setForeground(QColor("#569CD6"));
|
||
keywordFormat.setFontWeight(QFont::Bold);
|
||
|
||
const QStringList keywords = {
|
||
"alignas","alignof","and","and_eq","asm","auto","bitand","bitor",
|
||
"bool","break","case","catch","char","char8_t","char16_t","char32_t",
|
||
"class","compl","concept","const","consteval","constexpr","constinit",
|
||
"const_cast","continue","co_await","co_return","co_yield","decltype",
|
||
"default","delete","do","double","dynamic_cast","else","enum",
|
||
"explicit","export","extern","false","float","for","friend","goto",
|
||
"if","inline","int","long","mutable","namespace","new","noexcept",
|
||
"not","not_eq","nullptr","operator","or","or_eq","private","protected",
|
||
"public","register","reinterpret_cast","requires","return","short",
|
||
"signed","sizeof","static","static_assert","static_cast","struct",
|
||
"switch","template","this","thread_local","throw","true","try",
|
||
"typedef","typeid","typename","union","unsigned","using","virtual",
|
||
"void","volatile","wchar_t","while","xor","xor_eq","override","final"
|
||
};
|
||
|
||
for (const QString &kw : keywords)
|
||
{
|
||
HighlightRule rule;
|
||
rule.pattern = QRegularExpression(QString("\\b%1\\b").arg(kw));
|
||
rule.format = keywordFormat;
|
||
m_rules.append(rule);
|
||
}
|
||
|
||
QTextCharFormat preprocFormat;
|
||
preprocFormat.setForeground(QColor("#C586C0"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression("^\\s*#\\s*\\w+"); r.format = preprocFormat; m_rules.append(r); }
|
||
|
||
QTextCharFormat stringFormat;
|
||
stringFormat.setForeground(QColor("#CE9178"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*")"); r.format = stringFormat; m_rules.append(r); }
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"('(?:[^'\\]|\\.)*')"); r.format = stringFormat; m_rules.append(r); }
|
||
|
||
QTextCharFormat numberFormat;
|
||
numberFormat.setForeground(QColor("#B5CEA8"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(\b(0[xX][0-9A-Fa-f]+[uUlL]*|[0-9]+\.?[0-9]*([eE][+-]?[0-9]+)?[fFlLuU]*)\b)"); r.format = numberFormat; m_rules.append(r); }
|
||
|
||
QTextCharFormat commentFormat;
|
||
commentFormat.setForeground(QColor("#6A9955"));
|
||
commentFormat.setFontItalic(true);
|
||
{ HighlightRule r; r.pattern = QRegularExpression("//[^\n]*"); r.format = commentFormat; m_rules.append(r); }
|
||
|
||
m_multiLineCommentFormat = commentFormat;
|
||
m_commentStartExpression = QRegularExpression(R"(/\*)");
|
||
m_commentEndExpression = QRegularExpression(R"(\*/)");
|
||
}
|
||
|
||
void CppHighlighter::highlightBlock(const QString &text)
|
||
{
|
||
SyntaxHighlighter::highlightBlock(text);
|
||
}
|
||
|
||
// ===========================================================================
|
||
// CssHighlighter
|
||
// ===========================================================================
|
||
CssHighlighter::CssHighlighter(QTextDocument *parent)
|
||
: SyntaxHighlighter(parent)
|
||
{
|
||
m_hasMultiLineComment = true;
|
||
|
||
// Selektoren: .klasse #id element ::pseudo :pseudo
|
||
QTextCharFormat selectorFormat;
|
||
selectorFormat.setForeground(QColor("#D7BA7D"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"([.#]?[\w-]+\s*(?=\s*[,{]))"); r.format = selectorFormat; m_rules.append(r); }
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(:{1,2}[\w-]+)"); r.format = selectorFormat; m_rules.append(r); }
|
||
|
||
// Eigenschaften (property:)
|
||
QTextCharFormat propFormat;
|
||
propFormat.setForeground(QColor("#9CDCFE"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"([\w-]+\s*(?=:))"); r.format = propFormat; m_rules.append(r); }
|
||
|
||
// Werte – Farben #hex
|
||
QTextCharFormat colorFormat;
|
||
colorFormat.setForeground(QColor("#CE9178"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(#[0-9A-Fa-f]{3,8}\b)"); r.format = colorFormat; m_rules.append(r); }
|
||
|
||
// Zahlen + Einheiten
|
||
QTextCharFormat numberFormat;
|
||
numberFormat.setForeground(QColor("#B5CEA8"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(\b\d+\.?\d*(px|em|rem|%|vh|vw|pt|cm|mm|s|ms)?\b)"); r.format = numberFormat; m_rules.append(r); }
|
||
|
||
// Strings
|
||
QTextCharFormat stringFormat;
|
||
stringFormat.setForeground(QColor("#CE9178"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = stringFormat; m_rules.append(r); }
|
||
|
||
// !important
|
||
QTextCharFormat importantFormat;
|
||
importantFormat.setForeground(QColor("#F44747"));
|
||
importantFormat.setFontWeight(QFont::Bold);
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(!important)"); r.format = importantFormat; m_rules.append(r); }
|
||
|
||
// @-Regeln
|
||
QTextCharFormat atFormat;
|
||
atFormat.setForeground(QColor("#C586C0"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(@[\w-]+)"); r.format = atFormat; m_rules.append(r); }
|
||
|
||
QTextCharFormat commentFormat;
|
||
commentFormat.setForeground(QColor("#6A9955"));
|
||
commentFormat.setFontItalic(true);
|
||
m_multiLineCommentFormat = commentFormat;
|
||
m_commentStartExpression = QRegularExpression(R"(/\*)");
|
||
m_commentEndExpression = QRegularExpression(R"(\*/)");
|
||
}
|
||
|
||
void CssHighlighter::highlightBlock(const QString &text)
|
||
{
|
||
SyntaxHighlighter::highlightBlock(text);
|
||
}
|
||
|
||
// ===========================================================================
|
||
// HtmlHighlighter
|
||
// ===========================================================================
|
||
HtmlHighlighter::HtmlHighlighter(QTextDocument *parent)
|
||
: SyntaxHighlighter(parent)
|
||
{
|
||
// Tag-Namen <div </div />
|
||
QTextCharFormat tagFormat;
|
||
tagFormat.setForeground(QColor("#569CD6"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(</?[\w:-]+)"); r.format = tagFormat; m_rules.append(r); }
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(/?>)"); r.format = tagFormat; m_rules.append(r); }
|
||
|
||
// Attribute name=
|
||
QTextCharFormat attrFormat;
|
||
attrFormat.setForeground(QColor("#9CDCFE"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(\b[\w:-]+=)"); r.format = attrFormat; m_rules.append(r); }
|
||
|
||
// Attributwerte "wert" 'wert'
|
||
QTextCharFormat valueFormat;
|
||
valueFormat.setForeground(QColor("#CE9178"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = valueFormat; m_rules.append(r); }
|
||
|
||
// DOCTYPE
|
||
QTextCharFormat doctypeFormat;
|
||
doctypeFormat.setForeground(QColor("#808080"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(<!DOCTYPE[^>]*>)", QRegularExpression::CaseInsensitiveOption); r.format = doctypeFormat; m_rules.append(r); }
|
||
|
||
// Entities & {
|
||
QTextCharFormat entityFormat;
|
||
entityFormat.setForeground(QColor("#D7BA7D"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(&(?:#\d+|#x[0-9A-Fa-f]+|[\w]+);)"); r.format = entityFormat; m_rules.append(r); }
|
||
|
||
// Kommentare <!-- ... --> (mehrzeilig)
|
||
QTextCharFormat commentFormat;
|
||
commentFormat.setForeground(QColor("#6A9955"));
|
||
commentFormat.setFontItalic(true);
|
||
m_multiLineCommentFormat = commentFormat;
|
||
m_commentStartExpression = QRegularExpression("<!--");
|
||
m_commentEndExpression = QRegularExpression("-->");
|
||
m_hasMultiLineComment = true;
|
||
}
|
||
|
||
void HtmlHighlighter::highlightBlock(const QString &text)
|
||
{
|
||
SyntaxHighlighter::highlightBlock(text);
|
||
}
|
||
|
||
// ===========================================================================
|
||
// PhpHighlighter
|
||
// ===========================================================================
|
||
PhpHighlighter::PhpHighlighter(QTextDocument *parent)
|
||
: SyntaxHighlighter(parent)
|
||
{
|
||
// ---- HTML-Regeln (Basis, für den Teil außerhalb von <?php ?>) ----
|
||
|
||
QTextCharFormat tagFormat;
|
||
tagFormat.setForeground(QColor("#569CD6"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(</?[\w:-]+)"); r.format = tagFormat; m_rules.append(r); }
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(/?>)"); r.format = tagFormat; m_rules.append(r); }
|
||
|
||
QTextCharFormat attrFormat;
|
||
attrFormat.setForeground(QColor("#9CDCFE"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(\b[\w:-]+=)"); r.format = attrFormat; m_rules.append(r); }
|
||
|
||
QTextCharFormat valueFormat;
|
||
valueFormat.setForeground(QColor("#CE9178"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = valueFormat; m_rules.append(r); }
|
||
|
||
QTextCharFormat entityFormat;
|
||
entityFormat.setForeground(QColor("#D7BA7D"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(&(?:#\d+|#x[0-9A-Fa-f]+|[\w]+);)"); r.format = entityFormat; m_rules.append(r); }
|
||
|
||
// HTML-Kommentare
|
||
QTextCharFormat htmlCommentFormat;
|
||
htmlCommentFormat.setForeground(QColor("#6A9955"));
|
||
htmlCommentFormat.setFontItalic(true);
|
||
m_multiLineCommentFormat = htmlCommentFormat;
|
||
m_commentStartExpression = QRegularExpression("<!--");
|
||
m_commentEndExpression = QRegularExpression("-->");
|
||
m_hasMultiLineComment = true;
|
||
|
||
// ---- PHP-Tags hervorheben ----
|
||
m_phpTagFormat.setForeground(QColor("#C586C0"));
|
||
m_phpTagFormat.setFontWeight(QFont::Bold);
|
||
|
||
// ---- PHP-spezifische Regeln ----
|
||
m_phpStringFormat.setForeground(QColor("#CE9178"));
|
||
m_phpCommentFormat.setForeground(QColor("#6A9955"));
|
||
m_phpCommentFormat.setFontItalic(true);
|
||
|
||
// Keywords
|
||
QTextCharFormat kwFormat;
|
||
kwFormat.setForeground(QColor("#569CD6"));
|
||
kwFormat.setFontWeight(QFont::Bold);
|
||
|
||
const QStringList phpKeywords = {
|
||
"abstract","and","array","as","break","callable","case","catch",
|
||
"class","clone","const","continue","declare","default","die","do",
|
||
"echo","else","elseif","empty","enddeclare","endfor","endforeach",
|
||
"endif","endswitch","endwhile","enum","extends","final","finally",
|
||
"fn","for","foreach","function","global","goto","if","implements",
|
||
"include","include_once","instanceof","insteadof","interface",
|
||
"isset","list","match","namespace","new","or","print","private",
|
||
"protected","public","readonly","require","require_once","return",
|
||
"static","switch","throw","trait","try","unset","use","var",
|
||
"while","xor","yield","null","true","false","NULL","TRUE","FALSE"
|
||
};
|
||
|
||
for (const QString &kw : phpKeywords)
|
||
{
|
||
HighlightRule r;
|
||
r.pattern = QRegularExpression(QString("\\b%1\\b").arg(kw));
|
||
r.format = kwFormat;
|
||
m_phpRules.append(r);
|
||
}
|
||
|
||
// Variablen $var
|
||
QTextCharFormat varFormat;
|
||
varFormat.setForeground(QColor("#9CDCFE"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(\$[\w]+)"); r.format = varFormat; m_phpRules.append(r); }
|
||
|
||
// Strings
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')"); r.format = m_phpStringFormat; m_phpRules.append(r); }
|
||
|
||
// Zahlen
|
||
QTextCharFormat numFormat;
|
||
numFormat.setForeground(QColor("#B5CEA8"));
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"(\b\d+\.?\d*\b)"); r.format = numFormat; m_phpRules.append(r); }
|
||
|
||
// Einzeilige Kommentare
|
||
{ HighlightRule r; r.pattern = QRegularExpression(R"((//|#)[^\n]*)"); r.format = m_phpCommentFormat; m_phpRules.append(r); }
|
||
|
||
// Eingebaute Funktionen (Auswahl der häufigsten)
|
||
QTextCharFormat builtinFormat;
|
||
builtinFormat.setForeground(QColor("#DCDCAA"));
|
||
const QStringList builtins = {
|
||
"array_map","array_filter","array_keys","array_values","array_merge",
|
||
"array_push","array_pop","array_shift","array_slice","array_splice",
|
||
"count","strlen","substr","strpos","strtolower","strtoupper","trim",
|
||
"ltrim","rtrim","explode","implode","str_replace","preg_match",
|
||
"preg_replace","sprintf","printf","print_r","var_dump","isset",
|
||
"empty","unset","intval","floatval","strval","is_array","is_string",
|
||
"is_int","is_float","is_null","is_bool","is_numeric","date","time",
|
||
"mktime","json_encode","json_decode","header","session_start",
|
||
"htmlspecialchars","htmlentities","strip_tags","nl2br","round",
|
||
"floor","ceil","abs","min","max","rand","in_array","array_key_exists",
|
||
"sort","rsort","usort","ksort","krsort","ob_start","ob_get_clean"
|
||
};
|
||
|
||
for (const QString &fn : builtins)
|
||
{
|
||
HighlightRule r;
|
||
r.pattern = QRegularExpression(QString("\\b%1\\b").arg(fn));
|
||
r.format = builtinFormat;
|
||
m_phpRules.append(r);
|
||
}
|
||
}
|
||
|
||
void PhpHighlighter::highlightPhpRange(const QString &text, int start, int length)
|
||
{
|
||
if (length <= 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
const QString phpText = text.mid(start, length);
|
||
|
||
for (const HighlightRule &rule : m_phpRules)
|
||
{
|
||
QRegularExpressionMatchIterator it = rule.pattern.globalMatch(phpText);
|
||
while (it.hasNext())
|
||
{
|
||
QRegularExpressionMatch match = it.next();
|
||
setFormat(
|
||
start + static_cast<int>(match.capturedStart()),
|
||
static_cast<int>(match.capturedLength()),
|
||
rule.format
|
||
);
|
||
}
|
||
}
|
||
|
||
static const QRegularExpression blockOpen(R"(/\*)");
|
||
static const QRegularExpression blockClose(R"(\*/)");
|
||
|
||
int searchFrom = 0;
|
||
|
||
// Leere Zeile mitten im PHP-Blockkommentar — Zustand weitertragen
|
||
if (phpText.trimmed().isEmpty())
|
||
{
|
||
if (previousBlockState() == 3)
|
||
{
|
||
setFormat(start, length, m_phpCommentFormat);
|
||
setCurrentBlockState(3);
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (previousBlockState() == 3)
|
||
{
|
||
QRegularExpressionMatch closeMatch = blockClose.match(phpText, 0);
|
||
if (closeMatch.hasMatch())
|
||
{
|
||
const int end = static_cast<int>(closeMatch.capturedStart())
|
||
+ static_cast<int>(closeMatch.capturedLength());
|
||
setFormat(start, end, m_phpCommentFormat);
|
||
searchFrom = end;
|
||
}
|
||
else
|
||
{
|
||
setFormat(start, length, m_phpCommentFormat);
|
||
setCurrentBlockState(3);
|
||
return;
|
||
}
|
||
}
|
||
|
||
while (searchFrom < phpText.length())
|
||
{
|
||
QRegularExpressionMatch openMatch = blockOpen.match(phpText, searchFrom);
|
||
if (!openMatch.hasMatch())
|
||
{
|
||
break;
|
||
}
|
||
|
||
const int openPos = static_cast<int>(openMatch.capturedStart());
|
||
QRegularExpressionMatch closeMatch = blockClose.match(phpText, openPos + 2);
|
||
|
||
if (closeMatch.hasMatch())
|
||
{
|
||
const int closeEnd = static_cast<int>(closeMatch.capturedStart())
|
||
+ static_cast<int>(closeMatch.capturedLength());
|
||
setFormat(start + openPos, closeEnd - openPos, m_phpCommentFormat);
|
||
searchFrom = closeEnd;
|
||
}
|
||
else
|
||
{
|
||
setFormat(start + openPos, length - openPos, m_phpCommentFormat);
|
||
setCurrentBlockState(3);
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
void PhpHighlighter::highlightBlock(const QString &text)
|
||
{
|
||
// Zuerst HTML-Basis-Regeln auf den gesamten Text anwenden
|
||
// (setzt auch den State für HTML <!-- --> Kommentare)
|
||
SyntaxHighlighter::highlightBlock(text);
|
||
|
||
// Block-Zustände:
|
||
// 0 = HTML-Modus
|
||
// 1 = HTML <!-- --> Kommentar (von Basisklasse verwaltet)
|
||
// 2 = innerhalb PHP-Block (kein /* */ Kommentar)
|
||
// 3 = innerhalb PHP /* */ Block-Kommentar
|
||
|
||
// State 1 (HTML-Kommentar) wurde von der Basisklasse gesetzt — nicht überschreiben
|
||
if (currentBlockState() == 1)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// Wenn der vorherige Block ein HTML-Kommentar war und dieser noch nicht
|
||
// abgeschlossen wurde, hat die Basisklasse das bereits korrekt behandelt.
|
||
// Wir setzen nur dann auf 0 zurück wenn wir sicher nicht in HTML-Kommentar sind.
|
||
if (previousBlockState() != 1)
|
||
{
|
||
setCurrentBlockState(0);
|
||
}
|
||
|
||
// Leere Zeile — Zustand weitertragen
|
||
if (text.isEmpty())
|
||
{
|
||
const int prev = previousBlockState();
|
||
if (prev == 2 || prev == 3)
|
||
{
|
||
setCurrentBlockState(prev);
|
||
}
|
||
return;
|
||
}
|
||
|
||
static const QRegularExpression phpOpen(R"(<\?(?:php|=)?\s?)",
|
||
QRegularExpression::CaseInsensitiveOption);
|
||
static const QRegularExpression phpClose(R"(\?>)");
|
||
|
||
int pos = 0;
|
||
|
||
if (previousBlockState() == 2 || previousBlockState() == 3)
|
||
{
|
||
// Wir befinden uns bereits in einem PHP-Block (ggf. in einem Kommentar)
|
||
QRegularExpressionMatch closeMatch = phpClose.match(text, 0);
|
||
if (closeMatch.hasMatch())
|
||
{
|
||
const int end = static_cast<int>(closeMatch.capturedStart())
|
||
+ static_cast<int>(closeMatch.capturedLength());
|
||
highlightPhpRange(text, 0, end);
|
||
setFormat(static_cast<int>(closeMatch.capturedStart()),
|
||
static_cast<int>(closeMatch.capturedLength()),
|
||
m_phpTagFormat);
|
||
pos = end;
|
||
setCurrentBlockState(0);
|
||
}
|
||
else
|
||
{
|
||
highlightPhpRange(text, 0, text.length());
|
||
if (currentBlockState() != 3)
|
||
{
|
||
setCurrentBlockState(2);
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
|
||
while (pos < text.length())
|
||
{
|
||
QRegularExpressionMatch openMatch = phpOpen.match(text, pos);
|
||
if (!openMatch.hasMatch())
|
||
{
|
||
break;
|
||
}
|
||
|
||
const int openStart = static_cast<int>(openMatch.capturedStart());
|
||
const int openEnd = openStart + static_cast<int>(openMatch.capturedLength());
|
||
|
||
setFormat(openStart, static_cast<int>(openMatch.capturedLength()), m_phpTagFormat);
|
||
|
||
QRegularExpressionMatch closeMatch = phpClose.match(text, openEnd);
|
||
if (closeMatch.hasMatch())
|
||
{
|
||
const int closeStart = static_cast<int>(closeMatch.capturedStart());
|
||
const int closeEnd = closeStart + static_cast<int>(closeMatch.capturedLength());
|
||
|
||
highlightPhpRange(text, openEnd, closeStart - openEnd);
|
||
setFormat(closeStart, static_cast<int>(closeMatch.capturedLength()), m_phpTagFormat);
|
||
|
||
pos = closeEnd;
|
||
setCurrentBlockState(0);
|
||
}
|
||
else
|
||
{
|
||
highlightPhpRange(text, openEnd, text.length() - openEnd);
|
||
if (currentBlockState() != 3)
|
||
{
|
||
setCurrentBlockState(2);
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
}
|