#include "lrscripthighlighter.h" #include "lrglobal.h" #include #include namespace LimeReport{ #define KEYWORDS_COUNT 60 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" }; enum LiteralsType { SpaceFound, AlpahabetFound, NumberFound, HashFound, SlashFound, AsterixFound, BracketFound, QuotationFound, ApostropheFound, Apostrophe2Found, SeparatorFound, BackSlashFound, LiteralsCount }; enum States { Undefinded = -1, Start, MayBeKeyWord, Code, MayBeComment, Comment, Comment2, MayBeComment2End, String, String2, String3, 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; States prevState = (States)previousBlockState(); States state = prevState != Undefinded ? (States)prevState : Start; States oldState = Undefinded; 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}, }; QString buffer; setCurrentBlockState(Undefinded); if (text.isEmpty()) { if (prevState == Comment2) setCurrentBlockState(Comment2); 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 '`': 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; }; 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 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(Undefinded); 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: case String3: setFormat(i-(buffer.length()-1), buffer.length(), m_formats[StringFormat]); buffer.clear(); break; } default: break; } } else if (state == Comment2) { setCurrentBlockState(Comment2); } if ( state == Comment || state == Comment2 ){ setFormat(i-(buffer.length()-1), buffer.length(), m_formats[CommentFormat]); } if ( state == String || state == String2 || state == String3 ){ setFormat(i-(buffer.length()-1), buffer.length(), m_formats[StringFormat]); } i++; if ( i>= text.length()) break; } if (buffer.length()) { if (oldState == MayBeKeyWord) { if (isKeyWord(buffer)) setFormat(i - buffer.length(), buffer.length(), m_formats[KeywordFormat]); } } 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); } setCurrentBlockUserData(data); } bool ScriptHighlighter::isKeyWord(const QString& word) { return m_keywords.contains(word); } ScriptHighlighter::ScriptHighlighter(QTextDocument* parent): QSyntaxHighlighter(parent) { for(int i=0; i 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