#include "stdafx.h" #include "IniHighlighter.h" CIniHighlighter::CIniHighlighter(bool bDarkMode, QTextDocument *parent) : QSyntaxHighlighter(parent) { // Define colors for light and dark mode QColor blue = bDarkMode ? QColor("#87CEFA") : QColor("#0000FF"); // Lighter blue for dark mode QColor green = bDarkMode ? QColor("#90EE90") : QColor("#008000"); // Lighter green for dark mode QColor darkRed = bDarkMode ? QColor("#FF6347") : QColor("#800000"); // Lighter red for dark mode QColor red = bDarkMode ? QColor("#FF4500") : QColor("#FF0000"); // Brighter red for dark mode QColor black = bDarkMode ? QColor("#DCDCDC") : QColor("#000000"); // Light gray for dark mode QColor brown = bDarkMode ? QColor("#F4A460") : QColor("#A52A2A"); // Light brown for dark mode QColor purple = bDarkMode ? QColor("#DA70D6") : QColor("#800080"); // Brighter purple for dark mode QColor gray = bDarkMode ? QColor("#A9A9A9") : QColor("#808080"); // Lighter gray for dark mode HighlightRule rule; // Section headers: [Section] sectionFormat.setForeground(blue); sectionFormat.setFontWeight(QFont::Bold); rule.pattern = QRegularExpression("^\\s*\\[.*\\]\\s*$"); rule.format = sectionFormat; highlightRules.append(rule); // Comments: ; comment or # comment commentFormat.setForeground(green); rule.pattern = QRegularExpression("^\\s*[;#].*"); rule.format = commentFormat; highlightRules.append(rule); // Keys: key= keyFormat.setForeground(darkRed); rule.pattern = QRegularExpression("^[\\w\\.]+(?=\\s*=)"); rule.format = keyFormat; highlightRules.append(rule); // Equals sign: = equalsFormat.setForeground(red); rule.pattern = QRegularExpression("="); rule.format = equalsFormat; highlightRules.append(rule); // Values: =value valueFormat.setForeground(black); rule.pattern = QRegularExpression("(?<=\\=).*"); rule.format = valueFormat; highlightRules.append(rule); // Initialize formats for value prefix and first comma valuePrefixFormat.setForeground(blue); firstCommaFormat.setForeground(red); #ifdef INI_WITH_JSON // Initialize JSON formats jsonKeyFormat.setForeground(brown); jsonStringFormat.setForeground(black); jsonNumberFormat.setForeground(blue); jsonBoolNullFormat.setForeground(purple); jsonBracesFormat.setForeground(gray); jsonColonFormat.setForeground(red); jsonCommaFormat.setForeground(red); // 1. JSON Colon: Match colons not preceded by backslash HighlightRule jsonRule; jsonRule.pattern = QRegularExpression(R"((? 0) braceLevel--; } else if (currentChar == ',' && braceLevel == 0) { firstRelevantCommaIndex = i; break; } } if (firstRelevantCommaIndex != -1) { // Position of the first comma relative to the entire line int commaPos = valueStart + firstRelevantCommaIndex; // Highlight text before the first comma in blue if (firstRelevantCommaIndex > 0) { setFormat(valueStart, firstRelevantCommaIndex, valuePrefixFormat); } // Highlight the first comma in red setFormat(commaPos, 1, firstCommaFormat); } #ifdef INI_WITH_JSON bool inString = false; int stringStart = -1; for (int i = firstRelevantCommaIndex != -1 ? firstRelevantCommaIndex + 1 : 0; i < valueText.length(); ++i) { QChar currentChar = valueText[i]; if (currentChar == '\"') { // Check if the quote is escaped bool escaped = false; int backslashCount = 0; int j = i - 1; while (j >= 0 && valueText[j] == '\\') { backslashCount++; j--; } if (backslashCount % 2 == 1) escaped = true; if (!escaped) { if (!inString) { inString = true; stringStart = valueStart + i; } else { inString = false; // Apply string formatting from stringStart to current position int length = (valueStart + i + 1) - stringStart; setFormat(stringStart, length, jsonStringFormat); } } } // Apply colon and comma formatting only if not inside a string if (!inString) { if (currentChar == ':') { setFormat(valueStart + i, 1, jsonColonFormat); } else if (currentChar == ',') { setFormat(valueStart + i, 1, jsonCommaFormat); } } } // If still inside a string (unclosed), format till end if (inString && stringStart != -1) { int length = text.length() - stringStart; setFormat(stringStart, length, jsonStringFormat); } // 4. Apply JSON Key Formatting within JSON Substrings // Find all JSON substrings and apply key formatting int current = 0; while (current < valueText.length()) { int startBrace = valueText.indexOf('{', current); if (startBrace == -1) break; int braceCounter = 1; int endBrace = startBrace + 1; while (endBrace < valueText.length() && braceCounter > 0) { if (valueText[endBrace] == '{') braceCounter++; else if (valueText[endBrace] == '}') braceCounter--; endBrace++; } if (braceCounter == 0) { // Found a JSON substring from startBrace to endBrace-1 QString jsonString = valueText.mid(startBrace, endBrace - startBrace); QRegularExpression keyRegex(R"("(?:(?:\\.)|[^"\\])*"(?=\s*:))"); QRegularExpressionMatchIterator keyMatches = keyRegex.globalMatch(jsonString); while (keyMatches.hasNext()) { QRegularExpressionMatch keyMatch = keyMatches.next(); int keyStart = valueStart + startBrace + keyMatch.capturedStart(); int keyLength = keyMatch.capturedLength(); setFormat(keyStart, keyLength, jsonKeyFormat); } current = endBrace; } else { break; } } #endif } }