Warning, file /sdk/lokalize/src/syntaxhighlighter.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of Lokalize 0003 0004 SPDX-FileCopyrightText: 2007-2009 Nick Shaforostoff <shafff@ukr.net> 0005 SPDX-FileCopyrightText: 2018-2019 Simon Depiets <sdepiets@gmail.com> 0006 0007 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0008 */ 0009 0010 #include "syntaxhighlighter.h" 0011 0012 #include "lokalize_debug.h" 0013 0014 #include "project.h" 0015 #include "prefs_lokalize.h" 0016 #include "prefs.h" 0017 0018 #include <kcolorscheme.h> 0019 0020 #include <QTextEdit> 0021 #include <QApplication> 0022 #include <QStringBuilder> 0023 0024 #define STATE_NORMAL 0 0025 #define STATE_TAG 1 0026 0027 0028 0029 #define NUM_OF_RULES 5 0030 0031 SyntaxHighlighter::SyntaxHighlighter(QTextEdit *parent) 0032 : Sonnet::Highlighter(parent) 0033 , tagBrush(KColorScheme::View, KColorScheme::VisitedText) 0034 , m_approved(true) 0035 // , fromDocbook(docbook) 0036 { 0037 highlightingRules.reserve(NUM_OF_RULES); 0038 HighlightingRule rule; 0039 //rule.format.setFontItalic(true); 0040 // tagFormat.setForeground(tagBrush.brush(QApplication::palette())); 0041 setAutomatic(false); 0042 0043 tagFormat.setForeground(tagBrush.brush(QApplication::palette())); 0044 0045 //QTextCharFormat format; 0046 //tagFormat.setForeground(Qt::darkBlue); 0047 // if (!docbook) //support multiline tags 0048 // { 0049 // rule.format = tagFormat; 0050 // rule.pattern = QRegExp("<.+>"); 0051 // rule.pattern.setMinimal(true); 0052 // highlightingRules.append(rule); 0053 // } 0054 0055 //entity 0056 rule.format.setForeground(Qt::darkMagenta); 0057 rule.pattern = QRegExp(QStringLiteral("(&[A-Za-z_:][A-Za-z0-9_\\.:-]*;)")); 0058 highlightingRules.append(rule); 0059 0060 QString accel = Project::instance()->accel(); 0061 if (!accel.isEmpty()) { 0062 rule.format.setForeground(Qt::darkMagenta); 0063 rule.pattern = QRegExp(accel); 0064 highlightingRules.append(rule); 0065 } 0066 0067 //\n \t \" 0068 rule.format.setForeground(Qt::darkGreen); 0069 rule.pattern = QRegExp(QStringLiteral("(\\\\[abfnrtv'\?\\\\])|(\\\\\\d+)|(\\\\x[\\dabcdef]+)")); 0070 highlightingRules.append(rule); 0071 0072 //spaces 0073 settingsChanged(); 0074 connect(SettingsController::instance(), &SettingsController::generalSettingsChanged, this, &SyntaxHighlighter::settingsChanged); 0075 0076 } 0077 0078 void SyntaxHighlighter::settingsChanged() 0079 { 0080 QRegExp re(" +$|^ +|.?" + QChar(0x0000AD) + ".?"); //soft hyphen 0081 if (Settings::highlightSpaces() && highlightingRules.last().pattern != re) { 0082 HighlightingRule rule; 0083 rule.format.clearForeground(); 0084 0085 KColorScheme colorScheme(QPalette::Normal); 0086 //nbsp 0087 //rule.format.setBackground(colorScheme.background(KColorScheme::NegativeBackground)); 0088 rule.format.setBackground(colorScheme.foreground(KColorScheme::InactiveText)); 0089 rule.format.setFontLetterSpacing(200); 0090 0091 rule.pattern = QRegExp(QChar(0x00a0U), Qt::CaseSensitive, QRegExp::FixedString); 0092 highlightingRules.append(rule); 0093 0094 //usual spaces at the end 0095 rule.format.setFontLetterSpacing(100); 0096 rule.format.setBackground(colorScheme.background(KColorScheme::ActiveBackground)); 0097 rule.pattern = re; 0098 highlightingRules.append(rule); 0099 rehighlight(); 0100 } else if (!Settings::highlightSpaces() && highlightingRules.last().pattern == re) { 0101 highlightingRules.resize(highlightingRules.size() - 2); 0102 rehighlight(); 0103 } 0104 } 0105 0106 /* 0107 void SyntaxHighlighter::setFuzzyState(bool fuzzy) 0108 { 0109 return; 0110 int i=NUM_OF_RULES; 0111 while(--i>=0) 0112 highlightingRules[i].format.setFontItalic(fuzzy); 0113 0114 tagFormat.setFontItalic(fuzzy); 0115 }*/ 0116 0117 void SyntaxHighlighter::highlightBlock(const QString &text) 0118 { 0119 int currentBlockState = STATE_NORMAL; 0120 QTextCharFormat f; 0121 f.setFontItalic(!m_approved); 0122 setFormat(0, text.length(), f); 0123 0124 tagFormat.setFontItalic(!m_approved); 0125 //if (fromDocbook) 0126 { 0127 int startIndex = STATE_NORMAL; 0128 if (previousBlockState() != STATE_TAG) 0129 startIndex = text.indexOf('<'); 0130 0131 while (startIndex >= 0) { 0132 int endIndex = text.indexOf('>', startIndex); 0133 int commentLength; 0134 if (endIndex == -1) { 0135 currentBlockState = STATE_TAG; 0136 commentLength = text.length() - startIndex; 0137 } else { 0138 commentLength = endIndex - startIndex 0139 + 1/*+ commentEndExpression.matchedLength()*/; 0140 } 0141 setFormat(startIndex, commentLength, tagFormat); 0142 startIndex = text.indexOf('<', startIndex + commentLength); 0143 } 0144 } 0145 0146 for (const HighlightingRule &rule : qAsConst(highlightingRules)) { 0147 QRegExp expression(rule.pattern); 0148 int index = expression.indexIn(text); 0149 while (index >= 0) { 0150 int length = expression.matchedLength(); 0151 QTextCharFormat f = rule.format; 0152 f.setFontItalic(!m_approved); 0153 setFormat(index, length, f); 0154 index = expression.indexIn(text, index + length); 0155 } 0156 } 0157 0158 if (spellCheckerFound()) 0159 Sonnet::Highlighter::highlightBlock(text); // Resets current block state 0160 setCurrentBlockState(currentBlockState); 0161 } 0162 0163 #if 0 0164 void SyntaxHighlighter::setFormatRetainingUnderlines(int start, int count, QTextCharFormat f) 0165 { 0166 QVector<bool> underLines(count); 0167 for (int i = 0; i < count; ++i) 0168 underLines[i] = format(start + i).fontUnderline(); 0169 0170 setFormat(start, count, f); 0171 0172 f.setFontUnderline(true); 0173 int prevStart = -1; 0174 bool isPrevUnderLined = false; 0175 for (int i = 0; i < count; ++i) { 0176 if (!underLines.at(i) && prevStart != -1) 0177 setFormat(start + isPrevUnderLined, i - prevStart, f); 0178 else if (underLines.at(i) && !isPrevUnderLined) 0179 prevStart = i; 0180 0181 isPrevUnderLined = underLines.at(i); 0182 } 0183 } 0184 #endif 0185 0186 void SyntaxHighlighter::setMisspelled(int start, int count) 0187 { 0188 const Project& project = *Project::instance(); 0189 0190 const QString text = currentBlock().text(); 0191 QString word = text.mid(start, count); 0192 if (m_sourceString.contains(word) 0193 && project.targetLangCode().leftRef(2) != project.sourceLangCode().leftRef(2)) 0194 return; 0195 0196 const QString accel = project.accel(); 0197 0198 if (!isWordMisspelled(word.remove(accel))) 0199 return; 0200 count = word.length(); //safety 0201 0202 bool smthPreceeding = (start > 0) && 0203 (accel.endsWith(text.at(start - 1)) 0204 || text.at(start - 1) == QChar(0x0000AD) //soft hyphen 0205 ); 0206 0207 //HACK. Needs Sonnet API redesign (KDE 5) 0208 if (smthPreceeding) { 0209 qCWarning(LOKALIZE_LOG) << "ampersand is in the way. word len:" << count; 0210 int realStart = text.lastIndexOf(QRegExp("\\b"), start - 2); 0211 if (realStart == -1) 0212 realStart = 0; 0213 QString t = text.mid(realStart, count + start - realStart); 0214 t.remove(accel); 0215 t.remove(QChar(0x0000AD)); 0216 if (!isWordMisspelled(t)) 0217 return; 0218 } 0219 0220 bool smthAfter = (start + count + 1 < text.size()) && 0221 (accel.startsWith(text.at(start + count)) 0222 || text.at(start + count) == QChar(0x0000AD) //soft hyphen 0223 ); 0224 if (smthAfter) { 0225 qCWarning(LOKALIZE_LOG) << "smthAfter. ampersand is in the way. word len:" << count; 0226 int realEnd = text.indexOf(QRegExp(QStringLiteral("\\b")), start + count + 2); 0227 if (realEnd == -1) 0228 realEnd = text.size(); 0229 QString t = text.mid(start, realEnd - start); 0230 t.remove(accel); 0231 t.remove(QChar(0x0000AD)); 0232 if (!isWordMisspelled(t)) 0233 return; 0234 } 0235 0236 if (count && format(start) == tagFormat) 0237 return; 0238 0239 for (int i = 0; i < count; ++i) { 0240 QTextCharFormat f(format(start + i)); 0241 f.setFontUnderline(true); 0242 f.setUnderlineStyle(QTextCharFormat::SpellCheckUnderline); 0243 f.setUnderlineColor(Qt::red); 0244 setFormat(start + i, 1, f); 0245 } 0246 } 0247 0248 void SyntaxHighlighter::unsetMisspelled(int start, int count) 0249 { 0250 for (int i = 0; i < count; ++i) { 0251 QTextCharFormat f(format(start + i)); 0252 f.setFontUnderline(false); 0253 setFormat(start + i, 1, f); 0254 } 0255 } 0256 0257 0258 0259