0
0
mirror of https://github.com/fralx/LimeReport.git synced 2024-12-27 18:08:10 +03:00
LimeReport/limereport/scripteditor/lrscripthighlighter.cpp
2017-09-19 19:05:38 +03:00

227 lines
8.6 KiB
C++

#include "lrscripthighlighter.h"
#include <QDebug>
#include <QPalette>
namespace LimeReport{
#define KEYWORDS_COUNT 59
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"
};
enum LiteralsType{SpaceFound, AlpahabetFound, NumberFound, HashFound, SlashFound, AsterixFound,
BracketFound, QuotationFound, ApostropheFound, SeparatorFound, BackSlashFound, LiteralsCount};
enum States {Start, MayBeKeyWord, Code, MayBeComment, Comment, Comment2, MayBeComment2End, String, String2, MayBeNumber, Separator, StatesCount};
void ScriptHighlighter::createParentheisisInfo(const char& literal, TextBlockData *data, const QString& text)
{
int pos = text.indexOf(literal);
while (pos != -1) {
ParenthesisInfo *info = new ParenthesisInfo;
info->character = literal;
info->position = pos;
data->insert(info);
pos = text.indexOf(literal, pos + 1);
}
}
void ScriptHighlighter::highlightBlock(const QString& text)
{
int literal = -1;
bool lastWasBackSlash = false;
int state = previousBlockState() != -1 ? previousBlockState() : Start ;
int oldState = -1;
int stateMaschine[StatesCount][LiteralsCount] = {
{Separator, MayBeKeyWord, MayBeNumber, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Separator},
{Separator, MayBeKeyWord, Code, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Separator},
{Separator, Code, Code, Separator, Separator, Separator, Separator, String, String2, Separator, Separator},
{Separator, Code, MayBeNumber, Code, Comment, Comment2, Code, String, String2, Separator, Code},
{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, Separator, Comment2, Comment2, Comment2, Comment2, Comment2, Comment2},
{String, String, String, String, String, String, String, Separator, String, String, String},
{String2, String2, String2, String2, String2, String2, String2, String2, Separator, String2, String2},
{Separator, Code, MayBeNumber, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Code},
{Separator, MayBeKeyWord, MayBeNumber, Separator, MayBeComment, Separator, Separator, String, String2, Separator, Separator }
};
QString buffer;
if (text.isEmpty()) return;
int i = 0;
for (;;){
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 '{': 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;
};
lastWasBackSlash = !lastWasBackSlash && currentChar == QLatin1Char('\\');
oldState = state;
state = stateMaschine[state][literal];
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 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(-1);
buffer.clear();
break;
case MayBeKeyWord:
if (isKeyWord(buffer.left(buffer.length()-1))){
setFormat(i-(buffer.length()-1), buffer.length()-1, m_formats[KeywordFormat]);
}
buffer.clear();
break;
case MayBeNumber:
setFormat(i-(buffer.length()-1), buffer.length()-1, m_formats[NumberFormat]);
buffer.clear();
case String:
case String2:
setFormat(i-(buffer.length()-1), buffer.length(), m_formats[StringFormat]);
buffer.clear();
break;
}
default:
break;
}
}
if ( state == Comment || state == Comment2 ){
setFormat(i-(buffer.length()-1), buffer.length(), m_formats[CommentFormat]);
}
if ( state == String || state == String2 ){
setFormat(i-(buffer.length()-1), buffer.length(), m_formats[StringFormat]);
}
i++;
if ( i>= text.length()) break;
}
TextBlockData *data = new TextBlockData;
for (int i = 0; i < PARENHEIS_COUNT; ++i){
createParentheisisInfo(parenthesisCharacters[LeftParenthesis][i].toLatin1(), data, text);
createParentheisisInfo(parenthesisCharacters[RightParenthesis][i].toLatin1(), data, text);
}
// createParentheisisInfo('(', data, text);
// createParentheisisInfo(')', data, text);
// createParentheisisInfo('{', data, text);
// createParentheisisInfo('}', data, text);
// createParentheisisInfo('[', data, text);
// createParentheisisInfo(']', data, text);
setCurrentBlockUserData(data);
}
bool ScriptHighlighter::isKeyWord(const QString& word)
{
for (int i = 0; i < KEYWORDS_COUNT-1; ++i){
if (QLatin1String(keywords[i]) == word) return true;
}
return false;
}
bool ScriptHighlighter::isDark(QColor color)
{
double a = 1 - ( 0.299 * color.red() + 0.587 * color.green() + 0.114 * color.blue()) / 255;
return (a < 0.5);
}
ScriptHighlighter::ScriptHighlighter(QTextDocument* parent):
QSyntaxHighlighter(parent)
{
if ( isDark(QPalette().background().color())){
m_formats[NumberFormat].setForeground(Qt::darkBlue);
m_formats[StringFormat].setForeground(Qt::darkGreen);
m_formats[KeywordFormat].setForeground(Qt::darkYellow);
m_formats[CommentFormat].setForeground(Qt::darkGreen);
m_formats[CommentFormat].setFontItalic(true);
} else {
m_formats[NumberFormat].setForeground(QColor("#ff6aad"));
m_formats[StringFormat].setForeground(QColor("#b27f40"));
m_formats[KeywordFormat].setForeground(QColor("#45c5d5"));
m_formats[CommentFormat].setForeground(QColor("#a1a4a9"));
m_formats[CommentFormat].setFontItalic(true);
}
}
QVector<ParenthesisInfo*> TextBlockData::parentheses()
{
return m_parentheses;
}
void TextBlockData::insert(ParenthesisInfo* info)
{
int i = 0;
while (i < m_parentheses.size() &&
info->position > m_parentheses.at(i)->position)
++i;
m_parentheses.insert(i, info);
}
} // namespace LimeReport