0
0
mirror of https://github.com/fralx/LimeReport.git synced 2024-12-24 16:44:39 +03:00
LimeReport/limereport/scripteditor/lrscripthighlighter.cpp

307 lines
10 KiB
C++
Raw Normal View History

2017-09-16 16:04:29 +03:00
#include "lrscripthighlighter.h"
2018-04-04 00:22:44 +03:00
#include "lrglobal.h"
2017-09-16 16:04:29 +03:00
#include <QDebug>
2017-09-19 19:05:38 +03:00
#include <QPalette>
2017-09-16 16:04:29 +03:00
namespace LimeReport {
2017-09-16 16:04:29 +03:00
#define KEYWORDS_COUNT 60
2017-09-16 16:04:29 +03:00
static const char* const keywords[KEYWORDS_COUNT]
= { "do", "if", "in", "for", "int", "new",
"try", "var", "byte", "case", "char", "else",
"enum", "goto", "long", "null", "this", "true",
"void", "with", "break", "catch", "class", "const",
"false", "final", "float", "short", "super", "throw",
"while", "delete", "double", "export", "import", "native",
"public", "return", "static", "switch", "throws", "typeof",
"boolean", "default", "extends", "finally", "package", "private",
"abstract", "continue", "debugger", "function", "volatile", "interface",
"protected", "transient", "implements", "instanceof", "synchronized", "let" };
2017-09-16 16:04:29 +03:00
enum LiteralsType {
SpaceFound,
AlpahabetFound,
NumberFound,
HashFound,
SlashFound,
AsterixFound,
BracketFound,
QuotationFound,
ApostropheFound,
Apostrophe2Found,
SeparatorFound,
BackSlashFound,
LiteralsCount
};
enum States {
Undefined = -1,
Start,
MayBeKeyWord,
Code,
MayBeComment,
Comment,
Comment2,
MayBeComment2End,
String,
String2,
String3,
MayBeNumber,
Separator,
StatesCount
};
2017-09-19 19:05:38 +03:00
void ScriptHighlighter::createParentheisisInfo(const char& literal, TextBlockData* data,
const QString& text)
2017-09-19 19:05:38 +03:00
{
int pos = text.indexOf(literal);
while (pos != -1) {
ParenthesisInfo* info = new ParenthesisInfo;
2017-09-19 19:05:38 +03:00
info->character = literal;
info->position = pos;
data->insert(info);
pos = text.indexOf(literal, pos + 1);
}
}
2017-09-16 16:04:29 +03:00
void ScriptHighlighter::highlightBlock(const QString& text)
{
int literal = -1;
bool lastWasBackSlash = false;
States prevState = (States)previousBlockState();
States state = prevState != Undefined ? (States)prevState : Start;
States oldState = Undefined;
const States stateMaschine[StatesCount][LiteralsCount] = {
// Space Alpahabet Number Hash Slash Asterix,
// Bracket, Quotation, Apostrophe, Apostrophe2 Separator, Back Slash
{ Separator, MayBeKeyWord, MayBeNumber, Separator, MayBeComment, Separator, Separator,
String, String2, String3, Separator, Separator },
{ Separator, MayBeKeyWord, Code, Separator, MayBeComment, Separator, Separator, String,
String2, String3, Separator, Separator },
{ Separator, Code, Code, Separator, Separator, Separator, Separator, String, String2,
String3, Separator, Separator },
{ Separator, Code, MayBeNumber, Code, Comment, Comment2, Code, String, String2, String3,
Separator, Code },
{ Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment, Comment,
Comment, Comment },
{ Comment2, Comment2, Comment2, Comment2, Comment2, MayBeComment2End, Comment2, Comment2,
Comment2, Comment2, Comment2, Comment2 },
{ Comment2, Comment2, Comment2, Comment2, Separator, Comment2, Comment2, Comment2, Comment2,
Comment2, Comment2, Comment2 },
{ String, String, String, String, String, String, String, Separator, String, String, String,
String },
{ String2, String2, String2, String2, String2, String2, String2, String2, Separator,
String2, String2, String2 },
{ String3, String3, String3, String3, String3, String3, String3, String3, String3,
Separator, String3, String3 },
{ Separator, Code, MayBeNumber, Separator, MayBeComment, Separator, Separator, String,
String2, String3, Separator, Code },
{ Separator, MayBeKeyWord, MayBeNumber, Separator, MayBeComment, Separator, Separator,
String, String2, String3, Separator, Separator },
2017-09-16 16:04:29 +03:00
};
QString buffer;
setCurrentBlockState(Undefined);
if (text.isEmpty()) {
if (prevState == Comment2)
setCurrentBlockState(Comment2);
return;
}
2017-09-16 16:04:29 +03:00
int i = 0;
for (;;) {
2017-09-16 16:04:29 +03:00
QChar currentChar = text.at(i);
switch (currentChar.toLatin1()) {
case ' ':
literal = SpaceFound;
break;
case '/':
literal = SlashFound;
break;
case '*':
literal = AsterixFound;
break;
case '#':
literal = HashFound;
break;
case '\'':
literal = ApostropheFound;
break;
case '\\':
literal = BackSlashFound;
break;
case '"':
literal = QuotationFound;
break;
case '`':
literal = Apostrophe2Found;
break;
case '{':
case '[':
case '(':
case '}':
case ']':
case ')':
literal = BracketFound;
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
literal = NumberFound;
break;
default:
if (currentChar.isLetter())
literal = AlpahabetFound;
else
literal = SeparatorFound;
2017-09-16 16:04:29 +03:00
};
lastWasBackSlash = !lastWasBackSlash && currentChar == QLatin1Char('\\');
oldState = state;
state = stateMaschine[state][literal];
2017-09-19 19:05:38 +03:00
buffer += currentChar;
if (oldState != state) {
switch (state) {
case MayBeComment:
if (oldState == MayBeNumber) {
setFormat(i - (buffer.length() - 1), buffer.length() - 1,
m_formats[NumberFormat]);
}
buffer.clear();
buffer += currentChar;
break;
case String:
case String2:
case String3:
buffer.clear();
buffer += currentChar;
break;
case MayBeKeyWord:
case MayBeNumber:
buffer.clear();
buffer += currentChar;
break;
case Comment2:
setCurrentBlockState(Comment2);
case Separator:
switch (oldState) {
case MayBeComment2End:
setFormat(i - (buffer.length() - 1), buffer.length(), m_formats[CommentFormat]);
setCurrentBlockState(Undefined);
buffer.clear();
break;
case MayBeKeyWord:
if (isKeyWord(buffer.left(buffer.length() - 1))) {
setFormat(i - (buffer.length() - 1), buffer.length() - 1,
m_formats[KeywordFormat]);
2017-09-19 19:05:38 +03:00
}
2017-09-16 16:04:29 +03:00
buffer.clear();
2017-12-16 18:02:13 +03:00
break;
case MayBeNumber:
setFormat(i - (buffer.length() - 1), buffer.length() - 1,
m_formats[NumberFormat]);
buffer.clear();
2017-12-16 18:02:13 +03:00
case String:
case String2:
case String3:
setFormat(i - (buffer.length() - 1), buffer.length(), m_formats[StringFormat]);
2017-12-16 18:02:13 +03:00
buffer.clear();
2017-09-16 16:04:29 +03:00
break;
}
default:
break;
2017-09-16 16:04:29 +03:00
}
} else if (state == Comment2) {
setCurrentBlockState(Comment2);
}
2017-09-19 19:05:38 +03:00
if (state == Comment || state == Comment2) {
setFormat(i - (buffer.length() - 1), buffer.length(), m_formats[CommentFormat]);
2017-09-19 19:05:38 +03:00
}
if (state == String || state == String2 || state == String3) {
setFormat(i - (buffer.length() - 1), buffer.length(), m_formats[StringFormat]);
2017-09-16 16:04:29 +03:00
}
i++;
if (i >= text.length())
break;
2017-09-16 16:04:29 +03:00
}
2017-09-19 19:05:38 +03:00
if (buffer.length()) {
if (state == MayBeKeyWord) {
if (isKeyWord(buffer))
setFormat(i - buffer.length(), buffer.length(), m_formats[KeywordFormat]);
} else if (state == MayBeNumber) {
setFormat(i - buffer.length(), buffer.length(), m_formats[NumberFormat]);
}
}
TextBlockData* data = new TextBlockData;
2017-09-19 19:05:38 +03:00
for (int i = 0; i < PARENHEIS_COUNT; ++i) {
2017-09-19 19:05:38 +03:00
createParentheisisInfo(parenthesisCharacters[LeftParenthesis][i].toLatin1(), data, text);
createParentheisisInfo(parenthesisCharacters[RightParenthesis][i].toLatin1(), data, text);
}
setCurrentBlockUserData(data);
}
bool ScriptHighlighter::isKeyWord(const QString& word) { return m_keywords.contains(word); }
2017-09-19 19:05:38 +03:00
ScriptHighlighter::ScriptHighlighter(QTextDocument* parent): QSyntaxHighlighter(parent)
2017-09-19 19:05:38 +03:00
{
for (int i = 0; i < KEYWORDS_COUNT; ++i) {
2020-09-17 10:35:48 +03:00
m_keywords.insert(keywords[i]);
}
2017-09-19 19:05:38 +03:00
if (isColorDark(QPalette().window().color())) {
2024-07-31 20:04:07 +03:00
m_formats[NumberFormat].setForeground(QColor("#45c6d1"));
2017-09-19 19:05:38 +03:00
m_formats[StringFormat].setForeground(Qt::darkGreen);
2024-07-31 20:04:07 +03:00
m_formats[KeywordFormat].setForeground(QColor("#cd5125"));
m_formats[CommentFormat].setForeground(QColor("#80807e"));
2017-09-19 19:05:38 +03:00
m_formats[CommentFormat].setFontItalic(true);
} else {
m_formats[NumberFormat].setForeground(QColor("#ff6aad"));
m_formats[StringFormat].setForeground(QColor("#b27f40"));
m_formats[KeywordFormat].setForeground(QColor("#45c5d5"));
2024-07-31 20:04:07 +03:00
m_formats[CommentFormat].setForeground(QColor("#a8aaab"));
2017-09-19 19:05:38 +03:00
m_formats[CommentFormat].setFontItalic(true);
}
}
2018-03-07 19:46:23 +03:00
TextBlockData::~TextBlockData()
{
foreach (ParenthesisInfo* info, m_parentheses) {
2018-03-07 19:46:23 +03:00
delete info;
}
}
QVector<ParenthesisInfo*> TextBlockData::parentheses() { return m_parentheses; }
2017-09-19 19:05:38 +03:00
void TextBlockData::insert(ParenthesisInfo* info)
{
int i = 0;
while (i < m_parentheses.size() && info->position > m_parentheses.at(i)->position)
2017-09-19 19:05:38 +03:00
++i;
m_parentheses.insert(i, info);
2017-09-16 16:04:29 +03:00
}
} // namespace LimeReport