From 609f611e8fdff424bc70c1e243e8bc469a5820be Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Sun, 23 Jan 2022 23:27:48 +0800 Subject: [PATCH] - enhancement: highlighter for GLSL (OpenGL Shading Language) --- NEWS.md | 1 + RedPandaIDE/HighlighterManager.cpp | 31 + RedPandaIDE/HighlighterManager.h | 1 + RedPandaIDE/RedPandaIDE.pro | 2 + RedPandaIDE/editor.cpp | 95 +- RedPandaIDE/parser/cppparser.cpp | 6 +- RedPandaIDE/qsynedit/highlighter/asm.cpp | 5 + RedPandaIDE/qsynedit/highlighter/asm.h | 4 + RedPandaIDE/qsynedit/highlighter/base.cpp | 5 + RedPandaIDE/qsynedit/highlighter/base.h | 6 +- RedPandaIDE/qsynedit/highlighter/cpp.cpp | 12 +- RedPandaIDE/qsynedit/highlighter/cpp.h | 4 + RedPandaIDE/qsynedit/highlighter/glsl.cpp | 1583 +++++++++++++++++ RedPandaIDE/qsynedit/highlighter/glsl.h | 215 +++ RedPandaIDE/widgets/codecompletionpopup.cpp | 33 +- RedPandaIDE/widgets/codecompletionpopup.h | 6 +- windows/templates/raylib.template | 2 +- windows/templates/raylib_3d.template | 2 +- windows/templates/raylib_3d_shader.template | 8 +- ..._shader_cpp.txt => raylib_3d_shader_c.txt} | 2 +- 20 files changed, 1969 insertions(+), 54 deletions(-) create mode 100644 RedPandaIDE/qsynedit/highlighter/glsl.cpp create mode 100644 RedPandaIDE/qsynedit/highlighter/glsl.h rename windows/templates/{raylib_3d_shader_cpp.txt => raylib_3d_shader_c.txt} (96%) diff --git a/NEWS.md b/NEWS.md index 354b1932..b0f2b3b0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -14,6 +14,7 @@ Red Panda C++ Version 0.13.3 - fix: editor crash when no highlighter is assigned (the editing file is a not c/cpp source file); - fix: ')' not correctly skip in the editor when no highlighter is assigned (the editing file is a not c/cpp source file); - fix: Undo in the editor will lose line indents when no highlighter is assigned (the editing file is a not c/cpp source file); + - enhancement: highlighter for GLSL (OpenGL Shading Language) Red Panda C++ Version 0.13.2 - fix: "delete and exit" button in the environtment / folder option page doesn't work correctly diff --git a/RedPandaIDE/HighlighterManager.cpp b/RedPandaIDE/HighlighterManager.cpp index 1be23a49..3a27b035 100644 --- a/RedPandaIDE/HighlighterManager.cpp +++ b/RedPandaIDE/HighlighterManager.cpp @@ -19,6 +19,7 @@ #include #include "qsynedit/highlighter/cpp.h" #include "qsynedit/highlighter/asm.h" +#include "qsynedit/highlighter/glsl.h" #include "qsynedit/Constants.h" #include "colorscheme.h" @@ -42,6 +43,8 @@ PSynHighlighter HighlighterManager::getHighlighter(const QString &filename) || suffix == "CPP" || suffix =="H" || suffix == "c++" || suffix == "h++") { return getCppHighlighter(); + } else if (suffix == "vs" || suffix == "fs") { + return getGLSLHighlighter(); } } return PSynHighlighter(); @@ -100,6 +103,34 @@ PSynHighlighter HighlighterManager::getAsmHighlighter() return pHighlighter; } +PSynHighlighter HighlighterManager::getGLSLHighlighter() +{ + SynEditGLSLHighlighter* highlighter = new SynEditGLSLHighlighter(); + PSynHighlighter pHighlighter(highlighter); + highlighter->asmAttribute()->setForeground(Qt::blue); + highlighter->charAttribute()->setForeground(Qt::black); + highlighter->commentAttribute()->setForeground(0x8C8C8C); + highlighter->commentAttribute()->setStyles(SynFontStyle::fsItalic); + highlighter->classAttribute()->setForeground(0x008080); + highlighter->floatAttribute()->setForeground(Qt::darkMagenta); + highlighter->functionAttribute()->setForeground(0x00627A); + highlighter->globalVarAttribute()->setForeground(0x660E7A); + highlighter->hexAttribute()->setForeground(Qt::darkMagenta); + highlighter->identifierAttribute()->setForeground(0x080808); + highlighter->invalidAttribute()->setForeground(Qt::red); + highlighter->localVarAttribute()->setForeground(Qt::black); + highlighter->numberAttribute()->setForeground(0x1750EB); + highlighter->octAttribute()->setForeground(Qt::darkMagenta); + highlighter->preprocessorAttribute()->setForeground(0x1f542e); + highlighter->keywordAttribute()->setForeground(0x0033b3); + highlighter->whitespaceAttribute()->setForeground(Qt::lightGray); + highlighter->stringAttribute()->setForeground(0x007d17); + highlighter->stringEscapeSequenceAttribute()->setForeground(Qt::red); + highlighter->symbolAttribute()->setForeground(0xc10000); + highlighter->variableAttribute()->setForeground(0x400080); + return pHighlighter; +} + void HighlighterManager::applyColorScheme(PSynHighlighter highlighter, const QString &schemeName) { if (!highlighter) diff --git a/RedPandaIDE/HighlighterManager.h b/RedPandaIDE/HighlighterManager.h index 0cb7986f..8048c543 100644 --- a/RedPandaIDE/HighlighterManager.h +++ b/RedPandaIDE/HighlighterManager.h @@ -27,6 +27,7 @@ public: PSynHighlighter copyHighlighter(PSynHighlighter highlighter); PSynHighlighter getCppHighlighter(); PSynHighlighter getAsmHighlighter(); + PSynHighlighter getGLSLHighlighter(); void applyColorScheme(PSynHighlighter highlighter, const QString& schemeName); }; diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 6dc625b9..ceaf84ed 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -116,6 +116,7 @@ SOURCES += \ qsynedit/highlighter/base.cpp \ qsynedit/highlighter/composition.cpp \ qsynedit/highlighter/cpp.cpp \ + qsynedit/highlighter/glsl.cpp \ settingsdialog/compilersetdirectorieswidget.cpp \ settingsdialog/compilersetoptionwidget.cpp \ settings.cpp \ @@ -238,6 +239,7 @@ HEADERS += \ qsynedit/highlighter/base.h \ qsynedit/highlighter/composition.h \ qsynedit/highlighter/cpp.h \ + qsynedit/highlighter/glsl.h \ settingsdialog/compilersetdirectorieswidget.h \ settingsdialog/compilersetoptionwidget.h \ settings.h \ diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index f5c18b73..739755f9 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -131,7 +131,7 @@ Editor::Editor(QWidget *parent, const QString& filename, } if (pSettings->editor().readOnlySytemHeader() - && (mParser->isSystemHeaderFile(mFilename) || mParser->isProjectHeaderFile(mFilename))) { + && mParser && (mParser->isSystemHeaderFile(mFilename) || mParser->isProjectHeaderFile(mFilename))) { this->setModified(false); setReadOnly(true); updateCaption(); @@ -710,7 +710,7 @@ void Editor::keyPressEvent(QKeyEvent *event) return; } else if (mLastIdCharPressed==pSettings->codeCompletion().minCharRequired()){ QString lastWord = getPreviousWordAtPositionForSuggestion(caretXY()); - if (!lastWord.isEmpty()) { + if (mParser && !lastWord.isEmpty()) { if (CppTypeKeywords.contains(lastWord)) { if (lastWord == "long" || lastWord == "short" || @@ -750,7 +750,7 @@ void Editor::keyPressEvent(QKeyEvent *event) } } else { //preprocessor ? - if ((mLastIdCharPressed=0) && (ch=='#') && lineText().isEmpty()) { + if (mParser && (mLastIdCharPressed=0) && (ch=='#') && lineText().isEmpty()) { if (pSettings->codeCompletion().enabled() && pSettings->codeCompletion().showCompletionWhileInput() ) { mLastIdCharPressed++; @@ -761,7 +761,7 @@ void Editor::keyPressEvent(QKeyEvent *event) } } //javadoc directive? - if ((mLastIdCharPressed=0) && (ch=='#') && + if (mParser && (mLastIdCharPressed=0) && (ch=='#') && lineText().trimmed().startsWith('*')) { if (pSettings->codeCompletion().enabled() && pSettings->codeCompletion().showCompletionWhileInput() ) { @@ -2223,34 +2223,37 @@ bool Editor::handleCodeCompletion(QChar key) { if (!mCompletionPopup->isEnabled()) return false; - switch(key.unicode()) { - case '.': - setSelText(key); - showCompletion("",false); - return true; - case '>': - setSelText(key); - if ((caretX() > 2) && (lineText().length() >= 2) && - (lineText()[caretX() - 3] == '-')) + if (mParser) { + switch(key.unicode()) { + case '.': + setSelText(key); showCompletion("",false); - return true; - case ':': - ExecuteCommand(SynEditorCommand::ecChar,':',nullptr); - //setSelText(key); - if ((caretX() > 2) && (lineText().length() >= 2) && - (lineText()[caretX() - 3] == ':')) - showCompletion("",false); - return true; - case '/': - case '\\': - setSelText(key); - if (mParser->isIncludeLine(lineText())) { - showHeaderCompletion(false); + return true; + case '>': + setSelText(key); + if ((caretX() > 2) && (lineText().length() >= 2) && + (lineText()[caretX() - 3] == '-')) + showCompletion("",false); + return true; + case ':': + ExecuteCommand(SynEditorCommand::ecChar,':',nullptr); + //setSelText(key); + if ((caretX() > 2) && (lineText().length() >= 2) && + (lineText()[caretX() - 3] == ':')) + showCompletion("",false); + return true; + case '/': + case '\\': + setSelText(key); + if (mParser->isIncludeLine(lineText())) { + showHeaderCompletion(false); + } + return true; + default: + return false; } - return true; - default: - return false; } + return false; } void Editor::initParser() @@ -2387,11 +2390,18 @@ Editor::QuoteStatus Editor::getQuoteStatus() void Editor::reparse() { + if (!highlighter()) + return; + if (highlighter()->language() != SynHighlighterLanguage::Cpp + && highlighter()->language() != SynHighlighterLanguage::GLSL) + return; parseFile(mParser,mFilename,mInProject); } void Editor::reparseTodo() { + if (!highlighter()) + return; pMainWindow->todoParser()->parseFile(mFilename); } @@ -2590,7 +2600,10 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete) } if (!pSettings->codeCompletion().enabled()) return; - if (!mParser->enabled()) + if (!mParser || !mParser->enabled()) + return; + + if (!highlighter()) return; if (mCompletionPopup->isVisible()) // already in search, don't do it again @@ -2662,6 +2675,19 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete) mParser->findAndScanBlockAt(mFilename, caretY()) ); + QSet keywords; + if (highlighter()) { + if (highlighter()->language() != SynHighlighterLanguage::Cpp ) { + keywords = highlighter()->keywords(); + } else if (mUseCppSyntax) { + foreach (const QString& keyword, CppKeywords.keys()) { + keywords.insert(keyword); + } + } else { + keywords = CKeywords; + } + } + if (word.isEmpty()) { //word=getWordAtPosition(this,caretXY(),pBeginPos,pEndPos, WordPurpose::wpCompletion); QString memberOperator; @@ -2680,14 +2706,15 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete) memberOperator, memberExpression, mFilename, - caretY()); + caretY(), + keywords); } else { QStringList memberExpression; memberExpression.append(word); mCompletionPopup->prepareSearch(preWord, QStringList(), "", - memberExpression, mFilename, caretY()); + memberExpression, mFilename, caretY(),keywords); } // Filter the whole statement list @@ -3901,6 +3928,10 @@ void Editor::checkSyntaxInBack() { if (readOnly()) return; + if (!highlighter()) + return; + if (highlighter()->language()!=SynHighlighterLanguage::Cpp) + return; if(pSettings->editor().syntaxCheck()) pMainWindow->checkSyntaxInBack(this); } diff --git a/RedPandaIDE/parser/cppparser.cpp b/RedPandaIDE/parser/cppparser.cpp index 8ef1308b..d8d7fa35 100644 --- a/RedPandaIDE/parser/cppparser.cpp +++ b/RedPandaIDE/parser/cppparser.cpp @@ -765,7 +765,7 @@ void CppParser::parseFile(const QString &fileName, bool inProject, bool onlyIfNo } //we only parse CFile in the second parse foreach (const QString& file,files) { - if (isCfile(file)) { + if (!isHfile(file)) { mFilesScannedCount++; emit onProgress(file,mFilesToScanCount,mFilesScannedCount); if (!mPreprocessor.scannedFiles().contains(file)) { @@ -3196,8 +3196,8 @@ void CppParser::internalParse(const QString &fileName) // Perform some validation before we start if (!mEnabled) return; - if (!isCfile(fileName) && !isHfile(fileName)) // support only known C/C++ files - return; +// if (!isCfile(fileName) && !isHfile(fileName)) // support only known C/C++ files +// return; QStringList buffer; if (mOnGetFileStream) { diff --git a/RedPandaIDE/qsynedit/highlighter/asm.cpp b/RedPandaIDE/qsynedit/highlighter/asm.cpp index 6e524354..8db3dd38 100644 --- a/RedPandaIDE/qsynedit/highlighter/asm.cpp +++ b/RedPandaIDE/qsynedit/highlighter/asm.cpp @@ -401,3 +401,8 @@ void SynEditASMHighlighter::resetState() { } + +QSet SynEditASMHighlighter::keywords() const +{ + return Keywords; +} diff --git a/RedPandaIDE/qsynedit/highlighter/asm.h b/RedPandaIDE/qsynedit/highlighter/asm.h index be0d0e8c..ad4879e4 100644 --- a/RedPandaIDE/qsynedit/highlighter/asm.h +++ b/RedPandaIDE/qsynedit/highlighter/asm.h @@ -93,6 +93,10 @@ public: SynRangeState getRangeState() const override; void setState(const SynRangeState& rangeState) override; void resetState() override; + + // SynHighlighter interface +public: + QSet keywords() const override; }; #endif // SYNEDITASMHIGHLIGHTER_H diff --git a/RedPandaIDE/qsynedit/highlighter/base.cpp b/RedPandaIDE/qsynedit/highlighter/base.cpp index 8792cbb6..355078e5 100644 --- a/RedPandaIDE/qsynedit/highlighter/base.cpp +++ b/RedPandaIDE/qsynedit/highlighter/base.cpp @@ -80,6 +80,11 @@ void SynHighlighter::nextToEol() next(); } +QSet SynHighlighter::keywords() const +{ + return QSet(); +} + bool SynHighlighter::isSpaceChar(const QChar &ch) { return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; diff --git a/RedPandaIDE/qsynedit/highlighter/base.h b/RedPandaIDE/qsynedit/highlighter/base.h index 34dda279..9af7f5e2 100644 --- a/RedPandaIDE/qsynedit/highlighter/base.h +++ b/RedPandaIDE/qsynedit/highlighter/base.h @@ -61,12 +61,14 @@ enum class SynHighlighterTokenType { enum class SynHighlighterClass { Composition, CppHighlighter, - AsmHighlighter + AsmHighlighter, + GLSLHighlighter }; enum class SynHighlighterLanguage { Asssembly, Cpp, + GLSL }; class SynHighlighterAttribute { @@ -104,7 +106,6 @@ public: const QSet& wordBreakChars() const; - PSynHighlighterAttribute commentAttribute() const; PSynHighlighterAttribute identifierAttribute() const; @@ -138,6 +139,7 @@ public: virtual void setState(const SynRangeState& rangeState) = 0; virtual void setLine(const QString& newLine, int lineNumber) = 0; virtual void resetState() = 0; + virtual QSet keywords() const; virtual QString languageName() = 0; virtual SynHighlighterLanguage language() = 0; diff --git a/RedPandaIDE/qsynedit/highlighter/cpp.cpp b/RedPandaIDE/qsynedit/highlighter/cpp.cpp index 0bac383a..77aa40e5 100644 --- a/RedPandaIDE/qsynedit/highlighter/cpp.cpp +++ b/RedPandaIDE/qsynedit/highlighter/cpp.cpp @@ -19,13 +19,14 @@ #include -static const QSet StatementKeyWords { +static const QSet CppStatementKeyWords { "if", "for", "try", "catch", "else", - "while" + "while", + "do" }; @@ -547,7 +548,7 @@ void SynEditCppHighlighter::identProc() mRun=wordEnd; if (isKeyword(word)) { mTokenId = TokenKind::Key; - if (StatementKeyWords.contains(word)) { + if (CppStatementKeyWords.contains(word)) { pushIndents(sitStatement); } } else { @@ -1633,3 +1634,8 @@ bool SynEditCppHighlighter::isIdentChar(const QChar &ch) const { return ch=='_' || ch.isDigit() || ch.isLetter(); } + +QSet SynEditCppHighlighter::keywords() const +{ + return Keywords; +} diff --git a/RedPandaIDE/qsynedit/highlighter/cpp.h b/RedPandaIDE/qsynedit/highlighter/cpp.h index f184545c..7cdba6dc 100644 --- a/RedPandaIDE/qsynedit/highlighter/cpp.h +++ b/RedPandaIDE/qsynedit/highlighter/cpp.h @@ -206,6 +206,10 @@ public: // SynHighlighter interface public: bool isIdentChar(const QChar &ch) const override; + + // SynHighlighter interface +public: + QSet keywords() const override; }; #endif // SYNEDITCPPHIGHLIGHTER_H diff --git a/RedPandaIDE/qsynedit/highlighter/glsl.cpp b/RedPandaIDE/qsynedit/highlighter/glsl.cpp new file mode 100644 index 00000000..dc688d96 --- /dev/null +++ b/RedPandaIDE/qsynedit/highlighter/glsl.cpp @@ -0,0 +1,1583 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "glsl.h" +#include "../Constants.h" + +#include + +static const QSet GLSLStatementKeyWords { + "if", + "for", + "try", + "catch", + "else", + "while" +}; + +const QSet SynEditGLSLHighlighter::Keywords { + "const", "uniform", "buffer", "shared", "attribute", "varying", + "coherent", "volatile", "restrict", "readonly", "writeonly", + "atomic_uint", + "layout", + "centroid", "flat", "smooth", "noperspective", + "patch", "sample", + "invariant", "precise", + "break", "continue", "do", "for", "while", "switch", "case", "default", + "if", "else", + "subroutine", + "in", "out", "inout", + "int", "void", "bool", "true", "false", "float", "double", + "discard", "return", + "vec2", "vec3", "vec4", "ivec2", "ivec3", "ivec4", "bvec2", "bvec3", "bvec4", + "uint", "uvec2", "uvec3", "uvec4", + "dvec2", "dvec3", "dvec4", + "mat2", "mat3", "mat4", + "mat2x2", "mat2x3", "mat2x4", + "mat3x2", "mat3x3", "mat3x4", + "mat4x2", "mat4x3", "mat4x4", + "dmat2", "dmat3", "dmat4", + "dmat2x2", "dmat2x3", "dmat2x4", + "dmat3x2", "dmat3x3", "dmat3x4", + "dmat4x2", "dmat4x3", "dmat4x4", + "lowp", "mediump", "highp", "precision", + "sampler1D", "sampler1DShadow", "sampler1DArray", "sampler1DArrayShadow", + "isampler1D", "isampler1DArray", "usampler1D", "usampler1DArray", + "sampler2D", "sampler2DShadow", "sampler2DArray", "sampler2DArrayShadow", + "isampler2D", "isampler2DArray", "usampler2D", "usampler2DArray", + "sampler2DRect", "sampler2DRectShadow", "isampler2DRect", "usampler2DRect", + "sampler2DMS", "isampler2DMS", "usampler2DMS", + "sampler2DMSArray", "isampler2DMSArray", "usampler2DMSArray", + "sampler3D", "isampler3D", "usampler3D", + "samplerCube", "samplerCubeShadow", "isamplerCube", "usamplerCube", + "samplerCubeArray", "samplerCubeArrayShadow", + "isamplerCubeArray", "usamplerCubeArray", + "samplerBuffer", "isamplerBuffer", "usamplerBuffer", + "image1D", "iimage1D", "uimage1D", + "image1DArray", "iimage1DArray", "uimage1DArray", + "image2D", "iimage2D", "uimage2D", + "image2DArray", "iimage2DArray", "uimage2DArray", + "image2DRect", "iimage2DRect", "uimage2DRect", + "image2DMS", "iimage2DMS", "uimage2DMS", + "image2DMSArray", "iimage2DMSArray", "uimage2DMSArray", + "image3D", "iimage3D", "uimage3D", + "imageCube", "iimageCube", "uimageCube", + "imageCubeArray", "iimageCubeArray", "uimageCubeArray", + "imageBuffer", "iimageBuffer", "uimageBuffer", + "struct" +}; + +SynEditGLSLHighlighter::SynEditGLSLHighlighter(): SynHighlighter() +{ + mAsmAttribute = std::make_shared(SYNS_AttrAssembler); + addAttribute(mAsmAttribute); + mCharAttribute = std::make_shared(SYNS_AttrCharacter); + addAttribute(mCharAttribute); + mCommentAttribute = std::make_shared(SYNS_AttrComment); + addAttribute(mCommentAttribute); + mClassAttribute = std::make_shared(SYNS_AttrClass); + addAttribute(mClassAttribute); + mFloatAttribute = std::make_shared(SYNS_AttrFloat); + addAttribute(mFloatAttribute); + mFunctionAttribute = std::make_shared(SYNS_AttrFunction); + addAttribute(mFunctionAttribute); + mGlobalVarAttribute = std::make_shared(SYNS_AttrGlobalVariable); + addAttribute(mGlobalVarAttribute); + mHexAttribute = std::make_shared(SYNS_AttrHexadecimal); + addAttribute(mHexAttribute); + mIdentifierAttribute = std::make_shared(SYNS_AttrIdentifier); + addAttribute(mIdentifierAttribute); + mInvalidAttribute = std::make_shared(SYNS_AttrIllegalChar); + addAttribute(mInvalidAttribute); + mLocalVarAttribute = std::make_shared(SYNS_AttrLocalVariable); + addAttribute(mLocalVarAttribute); + mNumberAttribute = std::make_shared(SYNS_AttrNumber); + addAttribute(mNumberAttribute); + mOctAttribute = std::make_shared(SYNS_AttrOctal); + addAttribute(mOctAttribute); + mPreprocessorAttribute = std::make_shared(SYNS_AttrPreprocessor); + addAttribute(mPreprocessorAttribute); + mKeywordAttribute = std::make_shared(SYNS_AttrReservedWord); + addAttribute(mKeywordAttribute); + mWhitespaceAttribute = std::make_shared(SYNS_AttrSpace); + addAttribute(mWhitespaceAttribute); + mStringAttribute = std::make_shared(SYNS_AttrString); + addAttribute(mStringAttribute); + mStringEscapeSequenceAttribute = std::make_shared(SYNS_AttrStringEscapeSequences); + addAttribute(mStringEscapeSequenceAttribute); + mSymbolAttribute = std::make_shared(SYNS_AttrSymbol); + addAttribute(mSymbolAttribute); + mVariableAttribute = std::make_shared(SYNS_AttrVariable); + addAttribute(mVariableAttribute); + + resetState(); +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::asmAttribute() const +{ + return mAsmAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::preprocessorAttribute() const +{ + return mPreprocessorAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::invalidAttribute() const +{ + return mInvalidAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::numberAttribute() const +{ + return mNumberAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::floatAttribute() const +{ + return mFloatAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::hexAttribute() const +{ + return mHexAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::octAttribute() const +{ + return mOctAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::stringEscapeSequenceAttribute() const +{ + return mStringEscapeSequenceAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::charAttribute() const +{ + return mCharAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::variableAttribute() const +{ + return mVariableAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::functionAttribute() const +{ + return mFunctionAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::classAttribute() const +{ + return mClassAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::globalVarAttribute() const +{ + return mGlobalVarAttribute; +} + +PSynHighlighterAttribute SynEditGLSLHighlighter::localVarAttribute() const +{ + return mLocalVarAttribute; +} + +SynEditGLSLHighlighter::ExtTokenKind SynEditGLSLHighlighter::getExtTokenId() +{ + return mExtTokenId; +} + +SynTokenKind SynEditGLSLHighlighter::getTokenId() +{ + if ((mRange.state == RangeState::rsAsm || mRange.state == RangeState::rsAsmBlock) + && !mAsmStart && !(mTokenId == TokenKind::Comment || mTokenId == TokenKind::Space + || mTokenId == TokenKind::Null)) { + return TokenKind::Asm; + } else { + return mTokenId; + } +} + +void SynEditGLSLHighlighter::andSymbolProc() +{ + mTokenId = TokenKind::Symbol; + switch (mLine[mRun+1].unicode()) { + case '=': + mRun+=2; + mExtTokenId = ExtTokenKind::AndAssign; + break; + case '&': + mRun+=2; + mExtTokenId = ExtTokenKind::LogAnd; + break; + default: + mRun+=1; + mExtTokenId = ExtTokenKind::And; + } +} + +void SynEditGLSLHighlighter::ansiCppProc() +{ + mTokenId = TokenKind::Comment; + if (mLine[mRun]==0) { + nullProc(); + if ( (mRun<1) || (mLine[mRun-1]!='\\')) { + mRange.state = RangeState::rsUnknown; + return; + } + } + while (mLine[mRun]!=0) { + mRun+=1; + } + mRange.state = RangeState::rsCppCommentEnded; + if (mLine[mRun-1] == '\\' && mLine[mRun]==0) { // continues on next line + mRange.state = RangeState::rsCppComment; + } +} + +void SynEditGLSLHighlighter::ansiCProc() +{ + bool finishProcess = false; + mTokenId = TokenKind::Comment; + if (mLine[mRun].unicode() == 0) { + nullProc(); + return; + } + while (mLine[mRun]!=0) { + switch(mLine[mRun].unicode()) { + case '*': + if (mLine[mRun+1] == '/') { + mRun += 2; + if (mRange.state == RangeState::rsAnsiCAsm) { + mRange.state = RangeState::rsAsm; + } else if (mRange.state == RangeState::rsAnsiCAsmBlock){ + mRange.state = RangeState::rsAsmBlock; + } else if (mRange.state == RangeState::rsDirectiveComment && + mLine[mRun] != 0 && mLine[mRun]!='\r' && mLine[mRun]!='\n') { + mRange.state = RangeState::rsMultiLineDirective; + } else { + mRange.state = RangeState::rsUnknown; + } + finishProcess = true; + } else + mRun+=1; + break; + default: + mRun+=1; + } + if (finishProcess) + break; + } +} + +void SynEditGLSLHighlighter::asciiCharProc() +{ + mTokenId = TokenKind::Char; + do { + if (mLine[mRun] == '\\') { + if (mLine[mRun+1] == '\'' || mLine[mRun+1] == '\\') { + mRun+=1; + } + } + mRun+=1; + } while (mLine[mRun]!=0 && mLine[mRun]!='\''); + if (mLine[mRun] == '\'') + mRun+=1; + mRange.state = RangeState::rsUnknown; +} + +void SynEditGLSLHighlighter::atSymbolProc() +{ + mTokenId = TokenKind::Unknown; + mRun+=1; +} + +void SynEditGLSLHighlighter::braceCloseProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::BraceClose; + if (mRange.state == RangeState::rsAsmBlock) { + mRange.state = rsUnknown; + } + + mRange.braceLevel -= 1; + if (mRange.leftBraces>0) { + mRange.leftBraces--; + } else { + mRange.rightBraces++ ; + } + popIndents(sitBrace); +} + +void SynEditGLSLHighlighter::braceOpenProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::BraceOpen; + if (mRange.state == RangeState::rsAsm) { + mRange.state = RangeState::rsAsmBlock; + mAsmStart = true; + } + mRange.braceLevel += 1; + mRange.leftBraces++; + if (mRange.getLastIndent() == sitStatement) { + // if last indent is started by 'if' 'for' etc + // just replace it + while (mRange.getLastIndent() == sitStatement) + popIndents(sitStatement); + pushIndents(sitBrace); +// int idx = mRange.indents.length()-1; +// if (idx < mRange.firstIndentThisLine) { +// mRange.firstIndentThisLine = idx; +// } +// mRange.indents.replace(idx,1,BraceIndentType); + } else { + pushIndents(sitBrace); + } +} + +void SynEditGLSLHighlighter::colonProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1]==':') { + mRun+=2; + mExtTokenId = ExtTokenKind::ScopeResolution; + } else { + mRun+=1; + mExtTokenId = ExtTokenKind::Colon; + } +} + +void SynEditGLSLHighlighter::commaProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::Comma; +} + +void SynEditGLSLHighlighter::directiveProc() +{ + QString preContents = mLineString.left(mRun).trimmed(); + if (!preContents.isEmpty()) { // '#' is not first non-space char on the line, treat it as an invalid char + mTokenId = TokenKind::Unknown; + mRun+=1; + return; + } + mTokenId = TokenKind::Directive; + mRun+=1; + //skip spaces + while (mLine[mRun]!=0 && isSpaceChar(mLine[mRun])) { + mRun+=1; + } + + while (mLine[mRun]!=0 && isIdentChar(mLine[mRun])) { + mRun+=1; + } + mRange.state = RangeState::rsUnknown; +// do { +// switch(mLine[mRun].unicode()) { +// case '/': //comment? +// switch (mLine[mRun+1].unicode()) { +// case '/': // is end of directive as well +// mRange.state = RangeState::rsUnknown; +// return; +// case '*': // might be embeded only +// mRange.state = RangeState::rsDirectiveComment; +// return; +// } +// break; +// case '\\': // yet another line? +// if (mLine[mRun+1] == 0) { +// mRun+=1; +// mRange.state = RangeState::rsMultiLineDirective; +// return; +// } +// break; +// } +// mRun+=1; +// } while (mLine[mRun]!=0); +} + +void SynEditGLSLHighlighter::directiveEndProc() +{ + mTokenId = TokenKind::Directive; + if (mLine[mRun] == 0) { + nullProc(); + return; + } + mRange.state = RangeState::rsUnknown; + do { + switch(mLine[mRun].unicode()) { + case '/': //comment? + switch (mLine[mRun+1].unicode()) { + case '/': // is end of directive as well + mRange.state = RangeState::rsUnknown; + return; + case '*': // might be embeded only + mRange.state = RangeState::rsDirectiveComment; + return; + } + break; + case '\\': // yet another line? + if (mLine[mRun+1] == 0) { + mRun+=1; + mRange.state = RangeState::rsMultiLineDirective; + return; + } + break; + } + mRun+=1; + } while (mLine[mRun]!=0); +} + +void SynEditGLSLHighlighter::equalProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1] == '=') { + mRun += 2; + mExtTokenId = ExtTokenKind::LogEqual; + } else { + mRun += 1; + mExtTokenId = ExtTokenKind::Assign; + } +} + +void SynEditGLSLHighlighter::greaterProc() +{ + mTokenId = TokenKind::Symbol; + switch (mLine[mRun + 1].unicode()) { + case '=': + mRun += 2; + mExtTokenId = ExtTokenKind::GreaterThanEqual; + break; + case '>': + if (mLine[mRun+2] == '=') { + mRun+=3; + mExtTokenId = ExtTokenKind::ShiftRightAssign; + } else { + mRun += 2; + mExtTokenId = ExtTokenKind::ShiftRight; + } + break; + default: + mRun+=1; + mExtTokenId = ExtTokenKind::GreaterThan; + } +} + +void SynEditGLSLHighlighter::identProc() +{ + int wordEnd = mRun; + while (isIdentChar(mLine[wordEnd])) { + wordEnd+=1; + } + QString word = mLineString.mid(mRun,wordEnd-mRun); + mRun=wordEnd; + if (isKeyword(word)) { + mTokenId = TokenKind::Key; + if (GLSLStatementKeyWords.contains(word)) { + pushIndents(sitStatement); + } + } else { + mTokenId = TokenKind::Identifier; + } +} + +void SynEditGLSLHighlighter::lowerProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun+1].unicode()) { + case '=': + mRun+=2; + mExtTokenId = ExtTokenKind::LessThanEqual; + break; + case '<': + if (mLine[mRun+2] == '=') { + mRun+=3; + mExtTokenId = ExtTokenKind::ShiftLeftAssign; + } else { + mRun+=2; + mExtTokenId = ExtTokenKind::ShiftLeft; + } + break; + default: + mRun+=1; + mExtTokenId = ExtTokenKind::LessThan; + } +} + +void SynEditGLSLHighlighter::minusProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun+1].unicode()) { + case '=': + mRun += 2; + mExtTokenId = ExtTokenKind::SubtractAssign; + break; + case '-': + mRun += 2; + mExtTokenId = ExtTokenKind::Decrement; + break; + case '>': + if (mLine[mRun+2]=='*') { + mRun += 3; + mExtTokenId = ExtTokenKind::PointerToMemberOfPointer; + } else { + mRun += 2; + mExtTokenId = ExtTokenKind::Arrow; + } + break; + default: + mRun += 1; + mExtTokenId = ExtTokenKind::Subtract; + } +} + +void SynEditGLSLHighlighter::modSymbolProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun + 1].unicode()) { + case '=': + mRun += 2; + mExtTokenId = ExtTokenKind::ModAssign; + break; + default: + mRun += 1; + mExtTokenId = ExtTokenKind::Mod; + } +} + +void SynEditGLSLHighlighter::notSymbolProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun + 1].unicode()) { + case '=': + mRun+=2; + mExtTokenId = ExtTokenKind::NotEqual; + break; + default: + mRun+=1; + mExtTokenId = ExtTokenKind::LogComplement; + } +} + +void SynEditGLSLHighlighter::nullProc() +{ + if ((mRun-1>=0) && isSpaceChar(mLine[mRun-1]) && + (mRange.state == RangeState::rsCppComment + || mRange.state == RangeState::rsDirective + || mRange.state == RangeState::rsString + || mRange.state == RangeState::rsMultiLineString + || mRange.state == RangeState::rsMultiLineDirective) ) { + mRange.state = RangeState::rsUnknown; + } else + mTokenId = TokenKind::Null; +} + +void SynEditGLSLHighlighter::numberProc() +{ + int idx1; // token[1] + idx1 = mRun; + mRun+=1; + mTokenId = TokenKind::Number; + bool shouldExit = false; + while (mLine[mRun]!=0) { + switch(mLine[mRun].unicode()) { + case '\'': + if (mTokenId != TokenKind::Number) { + mTokenId = TokenKind::Symbol; + return; + } + break; + case '.': + if (mLine[mRun+1] == '.') { + mRun+=2; + mTokenId = TokenKind::Unknown; + return; + } else if (mTokenId != TokenKind::Hex) { + mTokenId = TokenKind::Float; + } else { + mTokenId = TokenKind::Unknown; + return; + } + break; + case '-': + case '+': + if (mTokenId != TokenKind::Float) // number <> float. an arithmetic operator + return; + if (mLine[mRun-1]!= 'e' && mLine[mRun-1]!='E') // number = float, but no exponent. an arithmetic operator + return; + if (mLine[mRun+1]<'0' || mLine[mRun+1]>'9') {// invalid + mRun+=1; + mTokenId = TokenKind::Unknown; + return; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if ((mRun == idx1+1) && (mLine[idx1] == '0')) { // octal number + mTokenId = TokenKind::Octal; + } + break; + case '8': + case '9': + if ( (mLine[idx1]=='0') && (mTokenId != TokenKind::Hex) && (mTokenId != TokenKind::Float) ) // invalid octal char + mTokenId = TokenKind::Unknown; // we must continue parse, it may be an float number + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'A': + case 'B': + case 'C': + case 'D': + if (mTokenId!=TokenKind::Hex) { //invalid + mTokenId = TokenKind::Unknown; + return; + } + break; + case 'e': + case 'E': + if (mTokenId!=TokenKind::Hex) { + if (mLine[mRun-1]>='0' || mLine[mRun-1]<='9' ) {//exponent + for (int i=idx1;i='0' && mLine[mRun+1]<='9')) { + return; + } else { + mTokenId = TokenKind::Float; + } + } else { + mRun+=1; + mTokenId = TokenKind::Unknown; + return; + } + } + break; + case 'f': + case 'F': + if (mTokenId!=TokenKind::Hex) { + for (int i=idx1;i='0' && mLine[mRun+1]<='9') + || (mLine[mRun+1]>='a' && mLine[mRun+1]<='f') + || (mLine[mRun+1]>='A' && mLine[mRun+1]<='F')) ) { + mTokenId = TokenKind::Hex; + } else { + mRun+=1; + mTokenId = TokenKind::Unknown; + return; + } + break; + default: + shouldExit=true; + } + if (shouldExit) { + break; + } + mRun+=1; + } + if (mLine[mRun-1] == '\'') { + mTokenId = TokenKind::Unknown; + } +} + +void SynEditGLSLHighlighter::orSymbolProc() +{ + mTokenId = TokenKind::Symbol; + switch ( mLine[mRun+1].unicode()) { + case '=': + mRun+=2; + mExtTokenId = ExtTokenKind::IncOrAssign; + break; + case '|': + mRun+=2; + mExtTokenId = ExtTokenKind::LogOr; + break; + default: + mRun+=1; + mExtTokenId = ExtTokenKind::IncOr; + } +} + +void SynEditGLSLHighlighter::plusProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun+1].unicode()){ + case '=': + mRun+=2; + mExtTokenId = ExtTokenKind::AddAssign; + break; + case '+': + mRun+=2; + mExtTokenId = ExtTokenKind::Increment; + break; + default: + mRun+=1; + mExtTokenId = ExtTokenKind::Add; + } +} + +void SynEditGLSLHighlighter::pointProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1] == '*' ) { + mRun+=2; + mExtTokenId = ExtTokenKind::PointerToMemberOfObject; + } else if (mLine[mRun+1] == '.' && mLine[mRun+2] == '.') { + mRun+=3; + mExtTokenId = ExtTokenKind::Ellipse; + } else if (mLine[mRun+1]>='0' && mLine[mRun+1]<='9') { + numberProc(); + } else { + mRun+=1; + mExtTokenId = ExtTokenKind::Point; + } +} + +void SynEditGLSLHighlighter::questionProc() +{ + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::Question; + mRun+=1; +} + +void SynEditGLSLHighlighter::rawStringProc() +{ + bool noEscaping = false; + if (mRange.state == RangeState::rsRawStringNotEscaping) + noEscaping = true; + mTokenId = TokenKind::RawString; + mRange.state = RangeState::rsRawString; + + while (mLine[mRun]!=0) { + if ((!noEscaping) && (mLine[mRun]=='"')) { + mRun+=1; + break; + } + switch (mLine[mRun].unicode()) { + case '(': + noEscaping = true; + break; + case ')': + noEscaping = false; + break; + } + mRun+=1; + } + mRange.state = RangeState::rsUnknown; +} + +void SynEditGLSLHighlighter::roundCloseProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::RoundClose; + mRange.parenthesisLevel--; + popIndents(sitParenthesis); +} + +void SynEditGLSLHighlighter::roundOpenProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::RoundOpen; + mRange.parenthesisLevel++; + pushIndents(sitParenthesis); +} + +void SynEditGLSLHighlighter::semiColonProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::SemiColon; + if (mRange.state == RangeState::rsAsm) + mRange.state = RangeState::rsUnknown; + while (mRange.getLastIndent() == sitStatement) { + popIndents(sitStatement); + } +} + +void SynEditGLSLHighlighter::slashProc() +{ + switch(mLine[mRun+1].unicode()) { + case '/': // Cpp style comment + mTokenId = TokenKind::Comment; + mRun+=2; + mRange.state = RangeState::rsCppComment; + return; + case '*': // C style comment + mTokenId = TokenKind::Comment; + if (mRange.state == RangeState::rsAsm) { + mRange.state = RangeState::rsAnsiCAsm; + } else if (mRange.state == RangeState::rsAsmBlock) { + mRange.state = RangeState::rsAnsiCAsmBlock; + } else if (mRange.state == RangeState::rsDirective) { + mRange.state = RangeState::rsDirectiveComment; + } else { + mRange.state = RangeState::rsAnsiC; + } + mRun += 2; + if (mLine[mRun]!=0) + ansiCProc(); + break; + case '=': + mRun+=2; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::DivideAssign; + break; + default: + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::Divide; + } +} + +void SynEditGLSLHighlighter::spaceProc() +{ + mRun += 1; + mTokenId = TokenKind::Space; + while (mLine[mRun]>=1 && mLine[mRun]<=32) + mRun+=1; + mRange.state = RangeState::rsUnknown; +} + +void SynEditGLSLHighlighter::squareCloseProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::SquareClose; + mRange.bracketLevel--; + popIndents(sitBracket); +} + +void SynEditGLSLHighlighter::squareOpenProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::SquareOpen; + mRange.bracketLevel++; + pushIndents(sitBracket); +} + +void SynEditGLSLHighlighter::starProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1] == '=') { + mRun += 2; + mExtTokenId = ExtTokenKind::MultiplyAssign; + } else { + mRun += 1; + mExtTokenId = ExtTokenKind::Star; + } +} + +void SynEditGLSLHighlighter::stringEndProc() +{ + mTokenId = TokenKind::String; + if (mLine[mRun]==0) { + nullProc(); + return; + } + mRange.state = RangeState::rsUnknown; + + while (mLine[mRun]!=0) { + if (mLine[mRun]=='"') { + mRun += 1; + break; + } + if (mLine[mRun].unicode()=='\\') { + switch(mLine[mRun+1].unicode()) { + case '\'': + case '"': + case '\\': + case '?': + case 'a': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'x': + case 'u': + case 'U': + mRange.state = RangeState::rsMultiLineStringEscapeSeq; + return; + case 0: + mRun+=1; + mRange.state = RangeState::rsMultiLineString; + return; + } + } + mRun += 1; + } +} + +void SynEditGLSLHighlighter::stringEscapeSeqProc() +{ + mTokenId = TokenKind::StringEscapeSeq; + mRun+=1; + switch(mLine[mRun].unicode()) { + case '\'': + case '"': + case '?': + case 'a': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case '\\': + mRun+=1; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + for (int i=0;i<3;i++) { + if (mLine[mRun]<'0' || mLine[mRun]>'7') + break; + mRun+=1; + } + break; + case '8': + case '9': + mTokenId = TokenKind::Unknown; + mRun+=1; + break; + case 'x': + mRun+=1; + if ( !( + (mLine[mRun]>='0' && mLine[mRun]<='9') + || (mLine[mRun]>='a' && mLine[mRun]<='f') + || (mLine[mRun]>='A' && mLine[mRun]<='F') + )) { + mTokenId = TokenKind::Unknown; + } else { + while ( + (mLine[mRun]>='0' && mLine[mRun]<='9') + || (mLine[mRun]>='a' && mLine[mRun]<='f') + || (mLine[mRun]>='A' && mLine[mRun]<='F') + ) { + mRun+=1; + } + } + break; + case 'u': + mRun+=1; + for (int i=0;i<4;i++) { + if (mLine[mRun]<'0' || mLine[mRun]>'7') { + mTokenId = TokenKind::Unknown; + return; + } + mRun+=1; + } + break; + case 'U': + mRun+=1; + for (int i=0;i<8;i++) { + if (mLine[mRun]<'0' || mLine[mRun]>'7') { + mTokenId = TokenKind::Unknown; + return; + } + mRun+=1; + } + break; + } + if (mRange.state == RangeState::rsMultiLineStringEscapeSeq) + mRange.state = RangeState::rsMultiLineString; + else + mRange.state = RangeState::rsString; +} + +void SynEditGLSLHighlighter::stringProc() +{ + if (mLine[mRun] == 0) { + mRange.state = RangeState::rsUnknown; + return; + } + mTokenId = TokenKind::String; + mRange.state = RangeState::rsString; + while (mLine[mRun]!=0) { + if (mLine[mRun]=='"') { + mRun+=1; + break; + } + if (mLine[mRun].unicode()=='\\') { + switch(mLine[mRun+1].unicode()) { + case '\'': + case '"': + case '\\': + case '?': + case 'a': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + case 'v': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'x': + case 'u': + case 'U': + mRange.state = RangeState::rsStringEscapeSeq; + return; + case 0: + mRun+=1; + mRange.state = RangeState::rsMultiLineString; + return; + } + } + mRun+=1; + } + mRange.state = RangeState::rsUnknown; +} + +void SynEditGLSLHighlighter::stringStartProc() +{ + mTokenId = TokenKind::String; + mRun += 1; + if (mLine[mRun]==0) { + mRange.state = RangeState::rsUnknown; + return; + } + stringProc(); +} + +void SynEditGLSLHighlighter::tildeProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::BitComplement; +} + +void SynEditGLSLHighlighter::unknownProc() +{ + mRun+=1; + mTokenId = TokenKind::Unknown; +} + +void SynEditGLSLHighlighter::xorSymbolProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1]=='=') { + mRun+=2; + mExtTokenId = ExtTokenKind::XorAssign; + } else { + mRun+=1; + mExtTokenId = ExtTokenKind::Xor; + } +} + +void SynEditGLSLHighlighter::processChar() +{ + switch(mLine[mRun].unicode()) { + case '&': + andSymbolProc(); + break; + case '\'': + asciiCharProc(); + break; + case '@': + atSymbolProc(); + break; + case '}': + braceCloseProc(); + break; + case '{': + braceOpenProc(); + break; + case '\r': + case '\n': + spaceProc(); + break; + case ':': + colonProc(); + break; + case ',': + commaProc(); + break; + case '#': + directiveProc(); + break; + case '=': + equalProc(); + break; + case '>': + greaterProc(); + break; + case '?': + questionProc(); + break; + case '<': + lowerProc(); + break; + case '-': + minusProc(); + break; + case '%': + modSymbolProc(); + break; + case '!': + notSymbolProc(); + break; + case 0: + nullProc(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + numberProc(); + break; + case '|': + orSymbolProc(); + break; + case '+': + plusProc(); + break; + case '.': + pointProc(); + break; + case ')': + roundCloseProc(); + break; + case '(': + roundOpenProc(); + break; + case ';': + semiColonProc(); + break; + case '/': + slashProc(); + break; + case ']': + squareCloseProc(); + break; + case '[': + squareOpenProc(); + break; + case '*': + starProc(); + break; + case '"': + stringStartProc(); + break; + case '~': + tildeProc(); + break; + case '^': + xorSymbolProc(); + break; + default: + if (isIdentChar(mLine[mRun])) { + identProc(); + } else if (isSpaceChar(mLine[mRun])) { + spaceProc(); + } else { + unknownProc(); + } + } +} + +void SynEditGLSLHighlighter::popIndents(int indentType) +{ + while (!mRange.indents.isEmpty() && mRange.indents.back()!=indentType) { + mRange.indents.pop_back(); + } + if (!mRange.indents.isEmpty()) { + int idx = mRange.indents.length()-1; + if (idx < mRange.firstIndentThisLine) { + mRange.matchingIndents.append(mRange.indents[idx]); + } + mRange.indents.pop_back(); + } +} + +void SynEditGLSLHighlighter::pushIndents(int indentType) +{ + int idx = mRange.indents.length(); + if (idx='a' && ch<='z') || (ch>='A' && ch<='Z') || (ch>='0' && ch<='9'); +} + +QSet SynEditGLSLHighlighter::keywords() const +{ + return Keywords; +} diff --git a/RedPandaIDE/qsynedit/highlighter/glsl.h b/RedPandaIDE/qsynedit/highlighter/glsl.h new file mode 100644 index 00000000..772ad9fc --- /dev/null +++ b/RedPandaIDE/qsynedit/highlighter/glsl.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef SYNEDITGLSLHIGHLIGHTER_H +#define SYNEDITGLSLHIGHLIGHTER_H +#include "base.h" +#include + +class SynEditGLSLHighlighter: public SynHighlighter +{ + enum TokenKind { + Asm = 1, + Comment, + Directive, + Identifier, + Key, + Null, + Number, + Space, + String, + StringEscapeSeq, + Symbol, + Unknown, + Char, + Float, + Hex, + HexFloat, + Octal, + RawString + }; + + enum class ExtTokenKind { + Add, AddAssign, And, AndAssign, Arrow, Assign, + BitComplement, BraceClose, BraceOpen, Colon, Comma, + Decrement, Divide, DivideAssign, Ellipse, GreaterThan, + GreaterThanEqual, IncOr, IncOrAssign, Increment, LessThan, + LessThanEqual, LogAnd, LogComplement, LogEqual, LogOr, + Mod, ModAssign, MultiplyAssign, NotEqual, Point, PointerToMemberOfObject, + PointerToMemberOfPointer,Question, + RoundClose, RoundOpen, ScopeResolution, SemiColon, ShiftLeft, + ShiftLeftAssign, ShiftRight, ShiftRightAssign, SquareClose, + SquareOpen, Star, Subtract, SubtractAssign, Xor, + XorAssign + }; + + enum RangeState { + rsUnknown, rsAnsiC, rsAnsiCAsm, rsAnsiCAsmBlock, rsAsm, + rsAsmBlock, rsDirective, rsDirectiveComment, rsString, + rsMultiLineString, rsMultiLineDirective, rsCppComment, + rsStringEscapeSeq, rsMultiLineStringEscapeSeq, + rsRawString, rsSpace,rsRawStringEscaping,rsRawStringNotEscaping,rsChar, + rsCppCommentEnded + }; + +public: + explicit SynEditGLSLHighlighter(); + + PSynHighlighterAttribute asmAttribute() const; + + PSynHighlighterAttribute preprocessorAttribute() const; + + PSynHighlighterAttribute invalidAttribute() const; + + PSynHighlighterAttribute numberAttribute() const; + + PSynHighlighterAttribute floatAttribute() const; + + PSynHighlighterAttribute hexAttribute() const; + + PSynHighlighterAttribute octAttribute() const; + + PSynHighlighterAttribute stringEscapeSequenceAttribute() const; + + PSynHighlighterAttribute charAttribute() const; + + PSynHighlighterAttribute variableAttribute() const; + + PSynHighlighterAttribute functionAttribute() const; + + PSynHighlighterAttribute classAttribute() const; + + PSynHighlighterAttribute globalVarAttribute() const; + + PSynHighlighterAttribute localVarAttribute() const; + + static const QSet Keywords; + + ExtTokenKind getExtTokenId(); + SynTokenKind getTokenId(); +private: + void andSymbolProc(); + void ansiCppProc(); + void ansiCProc(); + void asciiCharProc(); + void atSymbolProc(); + void braceCloseProc(); + void braceOpenProc(); + void colonProc(); + void commaProc(); + void directiveProc(); + void directiveEndProc(); + void equalProc(); + void greaterProc(); + void identProc(); + void lowerProc(); + void minusProc(); + void modSymbolProc(); + void notSymbolProc(); + void nullProc(); + void numberProc(); + void orSymbolProc(); + void plusProc(); + void pointProc(); + void questionProc(); + void rawStringProc(); + void roundCloseProc(); + void roundOpenProc(); + void semiColonProc(); + void slashProc(); + void spaceProc(); + void squareCloseProc(); + void squareOpenProc(); + void starProc(); + void stringEndProc(); + void stringEscapeSeqProc(); + void stringProc(); + void stringStartProc(); + void tildeProc(); + void unknownProc(); + void xorSymbolProc(); + void processChar(); + void popIndents(int indentType); + void pushIndents(int indentType); + +private: + bool mAsmStart; + SynRangeState mRange; +// SynRangeState mSpaceRange; + QString mLineString; + QChar* mLine; + int mLineSize; + int mRun; + int mStringLen; + int mToIdent; + int mTokenPos; + int mTokenId; + ExtTokenKind mExtTokenId; + int mLineNumber; + int mLeftBraces; + int mRightBraces; + + PSynHighlighterAttribute mAsmAttribute; + PSynHighlighterAttribute mPreprocessorAttribute; + PSynHighlighterAttribute mInvalidAttribute; + PSynHighlighterAttribute mNumberAttribute; + PSynHighlighterAttribute mFloatAttribute; + PSynHighlighterAttribute mHexAttribute; + PSynHighlighterAttribute mOctAttribute; + PSynHighlighterAttribute mStringEscapeSequenceAttribute; + PSynHighlighterAttribute mCharAttribute; + PSynHighlighterAttribute mVariableAttribute; + PSynHighlighterAttribute mFunctionAttribute; + PSynHighlighterAttribute mClassAttribute; + PSynHighlighterAttribute mGlobalVarAttribute; + PSynHighlighterAttribute mLocalVarAttribute; + + // SynHighligterBase interface +public: + bool getTokenFinished() const override; + bool isLastLineCommentNotFinished(int state) const override; + bool isLastLineStringNotFinished(int state) const override; + bool eol() const override; + QString getToken() const override; + PSynHighlighterAttribute getTokenAttribute() const override; + SynTokenKind getTokenKind() override; + int getTokenPos() override; + void next() override; + void setLine(const QString &newLine, int lineNumber) override; + bool isKeyword(const QString &word) override; + SynHighlighterTokenType getTokenType() override; + void setState(const SynRangeState& rangeState) override; + void resetState() override; + SynHighlighterClass getClass() const override; + QString getName() const override; + + QString languageName() override; + SynHighlighterLanguage language() override; + + // SynHighlighter interface +public: + SynRangeState getRangeState() const override; + + // SynHighlighter interface +public: + bool isIdentChar(const QChar &ch) const override; + + // SynHighlighter interface +public: + QSet keywords() const override; +}; + +#endif // SYNEDITGLSLHIGHLIGHTER_H diff --git a/RedPandaIDE/widgets/codecompletionpopup.cpp b/RedPandaIDE/widgets/codecompletionpopup.cpp index 98a36a4c..b3a7560b 100644 --- a/RedPandaIDE/widgets/codecompletionpopup.cpp +++ b/RedPandaIDE/widgets/codecompletionpopup.cpp @@ -81,7 +81,8 @@ void CodeCompletionPopup::prepareSearch( const QString& memberOperator, const QStringList& memberExpression, const QString &filename, - int line) + int line, + const QSet& customKeywords) { QMutexLocker locker(&mMutex); if (!isEnabled()) @@ -94,7 +95,7 @@ void CodeCompletionPopup::prepareSearch( mMemberOperator = memberOperator; if (preWord.isEmpty()) { mIncludedFiles = mParser->getFileIncludes(filename); - getCompletionFor(ownerExpression,memberOperator,memberExpression, filename,line); + getCompletionFor(ownerExpression,memberOperator,memberExpression, filename,line, customKeywords); } else { getCompletionListForPreWord(preWord); } @@ -458,10 +459,28 @@ void CodeCompletionPopup::getCompletionFor( const QString& memberOperator, const QStringList& memberExpression, const QString &fileName, - int line) + int line, + const QSet& customKeywords) { - if(!mParser) + if(!mParser) { + if (mShowKeywords) { + //add keywords + if (!customKeywords.isEmpty()) { + foreach (const QString& keyword,customKeywords) { + addKeyword(keyword); + } + } else if (mUseCppKeyword) { + foreach (const QString& keyword,CppKeywords.keys()) { + addKeyword(keyword); + } + } else { + foreach (const QString& keyword,CKeywords) { + addKeyword(keyword); + } + } + } return; + } if (!mParser->enabled()) return; if (memberOperator.isEmpty() && ownerExpression.isEmpty() && memberExpression.isEmpty()) @@ -514,7 +533,11 @@ void CodeCompletionPopup::getCompletionFor( if (mShowKeywords) { //add keywords - if (mUseCppKeyword) { + if (!customKeywords.isEmpty()) { + foreach (const QString& keyword,customKeywords) { + addKeyword(keyword); + } + } else if (mUseCppKeyword) { foreach (const QString& keyword,CppKeywords.keys()) { addKeyword(keyword); } diff --git a/RedPandaIDE/widgets/codecompletionpopup.h b/RedPandaIDE/widgets/codecompletionpopup.h index b30dbb54..b3dadb71 100644 --- a/RedPandaIDE/widgets/codecompletionpopup.h +++ b/RedPandaIDE/widgets/codecompletionpopup.h @@ -52,7 +52,8 @@ public: const QString& memberOperator, const QStringList& memberExpression, const QString& filename, - int line); + int line, + const QSet& customKeywords); bool search(const QString& memberPhrase, bool autoHideOnSingleResult); PStatement selectedStatement(); @@ -101,7 +102,8 @@ private: const QString& memberOperator, const QStringList& memberExpression, const QString& fileName, - int line); + int line, + const QSet& customKeywords); void getCompletionListForPreWord(const QString& preWord); void addKeyword(const QString& keyword); bool isIncluded(const QString& fileName); diff --git a/windows/templates/raylib.template b/windows/templates/raylib.template index 00f118b8..999d68b7 100644 --- a/windows/templates/raylib.template +++ b/windows/templates/raylib.template @@ -22,7 +22,7 @@ Target=explosion.png [Project] UnitCount=3 -Type=0 +Type=1 IsCpp=0 linker=-lraylib -lopengl32 -lgdi32 -lwinmm_@@__@@_ diff --git a/windows/templates/raylib_3d.template b/windows/templates/raylib_3d.template index 176257e7..1a4e7134 100644 --- a/windows/templates/raylib_3d.template +++ b/windows/templates/raylib_3d.template @@ -14,7 +14,7 @@ C=raylib_3d_c.txt [Project] UnitCount=1 -Type=0 +Type=1 IsCpp=0 linker=-lraylib -lopengl32 -lgdi32 -lwinmm_@@__@@_ diff --git a/windows/templates/raylib_3d_shader.template b/windows/templates/raylib_3d_shader.template index 339b9c74..5fe22e98 100644 --- a/windows/templates/raylib_3d_shader.template +++ b/windows/templates/raylib_3d_shader.template @@ -9,8 +9,8 @@ Category=3D Category[zh_CN]=3D [Unit0] -CPPName=main.cpp -C=raylib_3d_shader_cpp.txt +CPPName=main.c +C=raylib_3d_shader_c.txt [Unit1] Source=raylib_base.vs @@ -22,7 +22,7 @@ Target=fragment_shader.fs [Project] UnitCount=3 -Type=0 -IsCpp=1 +Type=1 +IsCpp=0 linker=-lraylib -lopengl32 -lgdi32 -lwinmm_@@__@@_ diff --git a/windows/templates/raylib_3d_shader_cpp.txt b/windows/templates/raylib_3d_shader_c.txt similarity index 96% rename from windows/templates/raylib_3d_shader_cpp.txt rename to windows/templates/raylib_3d_shader_c.txt index e3e28d27..50a0250a 100644 --- a/windows/templates/raylib_3d_shader_cpp.txt +++ b/windows/templates/raylib_3d_shader_c.txt @@ -22,7 +22,7 @@ int main(void) // Load plane model from a generated mesh Model model = LoadModelFromMesh(GenMeshCube(10.0f, 10.0f, 3.3)); - Shader shader = LoadShader("vertices_shader.vs","raylib_base.fs"); + Shader shader = LoadShader("vertices_shader.vs","fragment_shader.fs"); // Assign out lighting shader to model model.materials[0].shader = shader;