From 9e51cf2f066cd52f144f3b1ee56e3a5840e74b8a Mon Sep 17 00:00:00 2001 From: "royqh1979@gmail.com" Date: Thu, 29 Apr 2021 20:54:44 +0800 Subject: [PATCH] * add QSynEdit --- RedPandaIDE/RedPandaIDE.pro | 16 +- RedPandaIDE/compiler/compiler.cpp | 2 +- RedPandaIDE/editor.cpp | 46 +- RedPandaIDE/editor.h | 13 +- RedPandaIDE/editorlist.cpp | 15 +- RedPandaIDE/editorlist.h | 4 +- RedPandaIDE/mainwindow.cpp | 16 +- RedPandaIDE/mainwindow.h | 2 + RedPandaIDE/mainwindow.ui | 3 + RedPandaIDE/qsynedit/CodeFolding.cpp | 96 + RedPandaIDE/qsynedit/CodeFolding.h | 75 + RedPandaIDE/qsynedit/Constants.cpp | 5 + RedPandaIDE/qsynedit/Constants.h | 160 ++ RedPandaIDE/qsynedit/MiscClasses.cpp | 306 ++++ RedPandaIDE/qsynedit/MiscClasses.h | 105 ++ RedPandaIDE/qsynedit/highlighter/base.cpp | 261 +++ RedPandaIDE/qsynedit/highlighter/base.h | 142 ++ RedPandaIDE/qsynedit/highlighter/cpp.cpp | 1562 +++++++++++++++++ RedPandaIDE/qsynedit/highlighter/cpp.h | 204 +++ .../compilersetdirectorieswidget.cpp | 2 +- RedPandaIDE/widgets/issuestable.cpp | 24 +- RedPandaIDE/widgets/issuestable.h | 4 + Red_Panda_CPP.pro | 1 - 23 files changed, 3023 insertions(+), 41 deletions(-) create mode 100644 RedPandaIDE/qsynedit/CodeFolding.cpp create mode 100644 RedPandaIDE/qsynedit/CodeFolding.h create mode 100644 RedPandaIDE/qsynedit/Constants.cpp create mode 100644 RedPandaIDE/qsynedit/Constants.h create mode 100644 RedPandaIDE/qsynedit/MiscClasses.cpp create mode 100644 RedPandaIDE/qsynedit/MiscClasses.h create mode 100644 RedPandaIDE/qsynedit/highlighter/base.cpp create mode 100644 RedPandaIDE/qsynedit/highlighter/base.h create mode 100644 RedPandaIDE/qsynedit/highlighter/cpp.cpp create mode 100644 RedPandaIDE/qsynedit/highlighter/cpp.h diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index 69518282..0d9bb18e 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -17,6 +17,11 @@ SOURCES += \ editorlist.cpp \ main.cpp \ mainwindow.cpp \ + qsynedit/CodeFolding.cpp \ + qsynedit/Constants.cpp \ + qsynedit/MiscClasses.cpp \ + qsynedit/highlighter/base.cpp \ + qsynedit/highlighter/cpp.cpp \ settingsdialog/compilersetdirectorieswidget.cpp \ settingsdialog/compilersetoptionwidget.cpp \ settings.cpp \ @@ -34,6 +39,11 @@ HEADERS += \ editor.h \ editorlist.h \ mainwindow.h \ + qsynedit/CodeFolding.h \ + qsynedit/Constants.h \ + qsynedit/MiscClasses.h \ + qsynedit/highlighter/base.h \ + qsynedit/highlighter/cpp.h \ settingsdialog/compilersetdirectorieswidget.h \ settingsdialog/compilersetoptionwidget.h \ settings.h \ @@ -61,9 +71,3 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin RESOURCES += \ icons.qrc -win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../QScintilla/src/release/ -lqscintilla2_qt5d -else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../QScintilla/src/debug/ -lqscintilla2_qt5d -else:unix: LIBS += -L$$OUT_PWD/../../QScintilla/src/ -lqscintilla2_qt5d - -INCLUDEPATH += $$PWD/../../QScintilla/src -DEPENDPATH += $$PWD/../../QScintilla/src diff --git a/RedPandaIDE/compiler/compiler.cpp b/RedPandaIDE/compiler/compiler.cpp index 85406de8..b3d0b022 100644 --- a/RedPandaIDE/compiler/compiler.cpp +++ b/RedPandaIDE/compiler/compiler.cpp @@ -60,7 +60,7 @@ QString Compiler::getFileNameFromOutputLine(QString &line) { continue; } - if (QFile(temp).fileName() == "ld.exe") { // skip ld.exe + if (QFile(temp).fileName() == QLatin1String("ld.exe")) { // skip ld.exe continue; } else { break; diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 1bfd3990..003592be 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -65,7 +65,7 @@ Editor::Editor(QWidget *parent, const QString& filename, lexer->setDefaultFont(QFont("Consolas",12)); this->setLexer(lexer); this->setAutoIndent(pSettings->editor().autoIndent()); - this->setFolding(FoldStyle::BoxedTreeFoldStyle,3); + this->setFolding(FoldStyle::BoxedTreeFoldStyle,FoldMargin); this->setTabWidth(4); this->setCaretLineVisible(true); @@ -75,34 +75,24 @@ Editor::Editor(QWidget *parent, const QString& filename, this->setBraceMatching(BraceMatch::SloppyBraceMatch); //行号显示区域 - setMarginType(0, QsciScintilla::NumberMargin); - setMarginLineNumbers(0, true); - setMarginWidth(0,"10"); + setMarginType(LineNumberMargin, QsciScintilla::NumberMargin); + setMarginLineNumbers(LineNumberMargin, true); + setMarginWidth(LineNumberMargin,10); this->onLinesChanged(0,0); //断点设置区域 - setMarginType(1, QsciScintilla::SymbolMargin); - setMarginLineNumbers(1, false); - setMarginWidth(1,20); - setMarginSensitivity(1, true); //设置是否可以显示断点 - setMarginsBackgroundColor(QColor("#bbfaae")); - setMarginMarkerMask(1, 0x02); + setMarginType(MarkerMargin, QsciScintilla::SymbolMargin); + setMarginLineNumbers(MarkerMargin, false); + setMarginWidth(MarkerMargin,20); + setMarginSensitivity(MarkerMargin, true); //set the margin as a selection margin, which is clickable + // connect(textEdit, SIGNAL(marginClicked(int, int, Qt::KeyboardModifiers)),this, // SLOT(on_margin_clicked(int, int, Qt::KeyboardModifiers))); - markerDefine(QsciScintilla::Circle, 1); - setMarkerBackgroundColor(QColor("#ee1111"), 1); - //单步执行显示区域 - setMarginType(2, QsciScintilla::SymbolMargin); - setMarginLineNumbers(2, false); - setMarginWidth(2, 20); - setMarginSensitivity(2, false); - setMarginMarkerMask(2, 0x04); - markerDefine(QsciScintilla::RightArrow, 2); - setMarkerBackgroundColor(QColor("#eaf593"), 2); - //自动折叠区域 - setMarginType(3, QsciScintilla::SymbolMargin); - setMarginLineNumbers(3, false); - setMarginWidth(3, 15); - setMarginSensitivity(3, true); + + //markers + markerDefine(QsciScintilla::CircledPlus, ErrorMarker); + setMarkerForegroundColor(QColor("BLACK"),ErrorMarker); + setMarkerBackgroundColor(QColor("RED"),ErrorMarker); + markerAdd(1,ErrorMarker); // connect will fail if use new function pointer syntax // connect(this, &QsciScintilla::modificationChanged, @@ -254,6 +244,7 @@ bool Editor::saveAs(){ void Editor::activate() { this->mParentPageControl->setCurrentWidget(this); + this->setFocus(); } const QByteArray& Editor::encodingOption() const noexcept{ @@ -296,6 +287,11 @@ void Editor::onModificationChanged(bool) { void Editor::onCursorPositionChanged(int line, int index) { pMainWindow->updateStatusBarForEditingInfo(line,index+1,lines(),text().length()); + long pos = getCursorPosition(); + long start = SendScintilla(SCI_WORDSTARTPOSITION,pos,false); + long end = SendScintilla(SCI_WORDENDPOSITION,pos,false); + + qDebug()< #include #include -#include class SaveException: public std::exception { @@ -23,6 +22,18 @@ class Editor : public QsciScintilla { Q_OBJECT public: + enum MarginNumber { + LineNumberMargin = 0, + MarkerMargin = 1, + FoldMargin = 2, + }; + + enum MarkerNumber { + BreakpointMarker, + ErrorMarker, + WarningMarker + }; + explicit Editor(QWidget *parent, const QString& filename, const QByteArray& encoding, bool inProject, bool isNew,QTabWidget* parentPageControl); diff --git a/RedPandaIDE/editorlist.cpp b/RedPandaIDE/editorlist.cpp index f0e88539..e282386c 100644 --- a/RedPandaIDE/editorlist.cpp +++ b/RedPandaIDE/editorlist.cpp @@ -4,6 +4,7 @@ #include #include #include +#include EditorList::EditorList(QTabWidget* leftPageWidget, QTabWidget* rightPageWidget, @@ -122,7 +123,7 @@ bool EditorList::closeAll(bool force) { return true; } -Editor* EditorList::findOpenedEditor(const QString &filename) +Editor* EditorList::getOpenedEditorByFilename(const QString &filename) { for (int i=0;icount();i++) { Editor* e = static_cast(mLeftPageWidget->widget(i)); @@ -138,3 +139,15 @@ Editor* EditorList::findOpenedEditor(const QString &filename) } return nullptr; } + +Editor *EditorList::getEditorByFilename(const QString &filename) +{ + //check if an editor is already openned + Editor* e=getOpenedEditorByFilename(filename); + if (e!=nullptr) + return e; + //Todo: check if is in the project + + //Create a new editor + return newEditor(filename,ENCODING_AUTO_DETECT,false,false); +} diff --git a/RedPandaIDE/editorlist.h b/RedPandaIDE/editorlist.h index 62576ef4..bf034a59 100644 --- a/RedPandaIDE/editorlist.h +++ b/RedPandaIDE/editorlist.h @@ -32,7 +32,9 @@ public: bool closeAll(bool force = false); - Editor* findOpenedEditor(const QString& filename); + Editor* getOpenedEditorByFilename(const QString& filename); + + Editor* getEditorByFilename(const QString& filename); void beginUpdate(); void endUpdate(); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index c57cd071..7aabd363 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -86,7 +86,7 @@ void MainWindow::openFiles(const QStringList &files) void MainWindow::openFile(const QString &filename) { - Editor* editor = mEditorList->findOpenedEditor(filename); + Editor* editor = mEditorList->getOpenedEditorByFilename(filename); if (editor!=nullptr) { editor->activate(); return; @@ -294,3 +294,17 @@ void MainWindow::on_actionFoldAll_triggered() editor->foldAll(); } } + +void MainWindow::on_tableIssues_doubleClicked(const QModelIndex &index) +{ + PCompileIssue issue = ui->tableIssues->issue(index); + if (!issue) + return; + + Editor * editor = mEditorList->getEditorByFilename(issue->filename); + if (editor == nullptr) + return; + + editor->setCursorPosition(issue->line-1,issue->column-1); + editor->activate(); +} diff --git a/RedPandaIDE/mainwindow.h b/RedPandaIDE/mainwindow.h index 77ab851c..2fae9992 100644 --- a/RedPandaIDE/mainwindow.h +++ b/RedPandaIDE/mainwindow.h @@ -70,6 +70,8 @@ private slots: void on_actionFoldAll_triggered(); + void on_tableIssues_doubleClicked(const QModelIndex &index); + public slots: void onCompileLog(const QString& msg); void onCompileIssue(PCompileIssue issue); diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui index b2f31b7c..d9e417f1 100644 --- a/RedPandaIDE/mainwindow.ui +++ b/RedPandaIDE/mainwindow.ui @@ -191,6 +191,9 @@ QAbstractItemView::SingleSelection + + QAbstractItemView::SelectRows + diff --git a/RedPandaIDE/qsynedit/CodeFolding.cpp b/RedPandaIDE/qsynedit/CodeFolding.cpp new file mode 100644 index 00000000..eb40bb59 --- /dev/null +++ b/RedPandaIDE/qsynedit/CodeFolding.cpp @@ -0,0 +1,96 @@ +#include "CodeFolding.h" + +int QSynFoldRegions::count() +{ + return fRegions.size(); +} + +int QSynFoldRegions::add(bool addEnding, const QChar &openSymbol, const QChar &closeSymbol, const QString &highlight) +{ + PSynFoldRegion region = std::make_shared(); + region->addEnding = addEnding; + region->openSymbol = openSymbol; + region->closeSymbol = closeSymbol; + region->highlight = highlight; + fRegions.push_back(region); +} + +PSynFoldRegion QSynFoldRegions::get(int index) +{ + return fRegions.at(index); +} + +QSynCodeFolding::QSynCodeFolding(): + indentGuides(true), + showCollapsedLine(true), + collapsedLineColor(QColor("black")), + folderBarLinesColor(QColor("black")), + indentGuidesColor("gray") +{ + foldRegions.add(true,'{','}',"Symbol"); +} + + +bool QSynEditFoldRange::parentCollapsed() +{ + PSynEditFoldRange parentFold = parent; + // Find first parent that is collapsed + while (parentFold) { + if (parentFold->collapsed) { + return true; + } + parentFold = parentFold->parent; + } + return false; +} + +void QSynEditFoldRange::move(int count) +{ + fromLine += count; + toLine += count; +} + +QSynEditFoldRange::QSynEditFoldRange(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynFoldRegion aFoldRegion, int aToLine): + fromLine(aFromLine), + toLine(aToLine), + linesCollapsed(0), + collapsed(false), + allFoldRanges(aAllFold), + foldRegion(aFoldRegion), + hintMarkLeft(0), + parent(aParent) +{ + +} + + +PSynEditFoldRange QSynEditFoldRanges::foldRange(int index) +{ + return ranges[index]; +} + +int QSynEditFoldRanges::count() +{ + return ranges.size(); +} + +QSynEditFoldRanges::QSynEditFoldRanges() +{ + +} + +PSynEditFoldRange QSynEditFoldRanges::addByParts(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynFoldRegion aFoldRegion, int aToLine) +{ + PSynEditFoldRange range=std::make_shared(aParent,aAllFold, aFromLine,aFoldRegion,aToLine); + return range; +} + +int QSynEditFoldRanges::remove(int index) +{ + ranges.erase(ranges.begin()+index); +} + +void QSynEditFoldRanges::addObject(PSynEditFoldRange foldRange) +{ + ranges.push_back(foldRange); +} diff --git a/RedPandaIDE/qsynedit/CodeFolding.h b/RedPandaIDE/qsynedit/CodeFolding.h new file mode 100644 index 00000000..2e4f69a3 --- /dev/null +++ b/RedPandaIDE/qsynedit/CodeFolding.h @@ -0,0 +1,75 @@ +#ifndef CODEFOLDING_H +#define CODEFOLDING_H +#include +#include +#include + +struct QSynFoldRegion; +typedef std::shared_ptr PSynFoldRegion; + +class QSynFoldRegions { +private: + std::vector fRegions; +public: + int count(); + int add(bool addEnding, const QChar& openSymbol, const QChar& closeSymbol, const QString& highlight); + PSynFoldRegion get(int index); +}; +typedef std::shared_ptr PSynFoldRegions; + + +struct QSynFoldRegion { + bool addEnding; + QSynFoldRegions subFoldRegions; + QChar openSymbol; + QChar closeSymbol; + QString highlight; +}; + +struct QSynCodeFolding { + bool indentGuides; + bool showCollapsedLine; + QColor collapsedLineColor; + QColor folderBarLinesColor; + QColor indentGuidesColor; + QSynFoldRegions foldRegions; + QSynCodeFolding(); +}; + +class QSynEditFoldRange; +typedef std::shared_ptr PSynEditFoldRange; +class QSynEditFoldRanges; +typedef std::shared_ptr PSynEditFoldRanges; + +class QSynEditFoldRanges{ +public: + std::vector ranges; + PSynEditFoldRange foldRange(int index); + int count(); + QSynEditFoldRanges(); + PSynEditFoldRange addByParts(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, + int aFromLine, PSynFoldRegion aFoldRegion, int aToLine); + + int remove(int index); + void addObject(PSynEditFoldRange foldRange); +}; + +// A single fold +class QSynEditFoldRange { +public: + int fromLine; // Beginning line + int toLine; // End line + int linesCollapsed; // Number of collapsed lines + QSynEditFoldRanges subFoldRanges; // Sub fold ranges + bool collapsed; // Is collapsed? + PSynEditFoldRanges allFoldRanges;// TAllFoldRanges pointer + PSynFoldRegion foldRegion; // FoldRegion + int hintMarkLeft; + PSynEditFoldRange parent; + bool parentCollapsed(); + void move(int count); + explicit QSynEditFoldRange(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, + int aFromLine, PSynFoldRegion aFoldRegion, int aToLine); +}; + +#endif // CODEFOLDING_H diff --git a/RedPandaIDE/qsynedit/Constants.cpp b/RedPandaIDE/qsynedit/Constants.cpp new file mode 100644 index 00000000..61f0260f --- /dev/null +++ b/RedPandaIDE/qsynedit/Constants.cpp @@ -0,0 +1,5 @@ +#include "Constants.h" +const std::set SynWordBreakChars{'.', ',', ';', ':', + '"', '\'', '!', '?', '[', ']', '(', ')', '{', '}', '^', '-', '=', '+', + '-', '*', '/', '\\', '|'}; +const QChar SynTabChar('\t'); diff --git a/RedPandaIDE/qsynedit/Constants.h b/RedPandaIDE/qsynedit/Constants.h new file mode 100644 index 00000000..1fb1cc75 --- /dev/null +++ b/RedPandaIDE/qsynedit/Constants.h @@ -0,0 +1,160 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H +#include +#include + +extern const std::set SynWordBreakChars; +extern const QChar SynTabChar; + +#define SYN_ATTR_COMMENT 0 +#define SYN_ATTR_IDENTIFIER 1 +#define SYN_ATTR_KEYWORD 2 +#define SYN_ATTR_STRING 3 +#define SYN_ATTR_WHITESPACE 4 +#define SYN_ATTR_SYMBOL 5 + +// names for highlighter attributes +#define SYNS_AttrAreaAIdentifier "Area A Identifier" +#define SYNS_AttrArrowHead "ArrowHead" +#define SYNS_AttrAsm "Asm" +#define SYNS_AttrAsmComment "Asm Comment" +#define SYNS_AttrAsmKey "Asm Key" +#define SYNS_AttrAssembler "Assembler" +#define SYNS_AttrAttribute "Attribute" +#define SYNS_AttrAttributeName "Attribute Name" +#define SYNS_AttrAttributeValue "Attribute Value" +#define SYNS_AttrBasicTypes "Basic Types" +#define SYNS_AttrBlock "Block" +#define SYNS_AttrBoolean "Boolean value" +#define SYNS_AttrBrackets "Brackets" +#define SYNS_AttrCDATASection "CDATA Section" +#define SYNS_AttrCharacter "Character" +#define SYNS_AttrClass "Class" +#define SYNS_AttrColor "Color Value" +#define SYNS_AttrComment "Comment" +#define SYNS_AttrCondition "Condition" +#define SYNS_AttrConditionalComment "Conditional Comment" +#define SYNS_AttrDataType "Data Type" +#define SYNS_AttrDebugLines "Debugging Lines" +#define SYNS_AttrDefaultPackage "Default Packages" +#define SYNS_AttrDelimitedIdentifier "Delimited Identifier" +#define SYNS_AttrDir "Direction" +#define SYNS_AttrDirections "Directions" +#define SYNS_AttrDirective "Directive" +#define SYNS_AttrDOCTYPESection "DOCTYPE Section" +#define SYNS_AttrDocumentation "Documentation" +#define SYNS_AttrElementName "Element Name" +#define SYNS_AttrEmbedSQL "Embedded SQL" +#define SYNS_AttrEmbedText "Embedded Text" +#define SYNS_AttrEntityReference "Entity Reference" +#define SYNS_AttrEscapeAmpersand "Escape Ampersand" +#define SYNS_AttrEvent "Event" +#define SYNS_AttrException "Exception" +#define SYNS_AttrFirstTri "FirstTri" +#define SYNS_AttrFloat "Float" +#define SYNS_AttrForm "Form" +#define SYNS_AttrFourthTri "FourthTri" +#define SYNS_AttrFunction "Function" +#define SYNS_AttrFunctionParameter "Function Parameter" +#define SYNS_AttrGlobalVariable "Global variable" +#define SYNS_AttrHexadecimal "Hexadecimal" +#define SYNS_AttrIcon "Icon Reference" +#define SYNS_AttrIdentifier "Identifier" +#define SYNS_AttrIllegalChar "Illegal Char" +#define SYNS_AttrInclude "Include" +#define SYNS_AttrIndicator "Indicator Area" +#define SYNS_AttrIndirect "Indirect" +#define SYNS_AttrInvalidSymbol "Invalid Symbol" +#define SYNS_AttrInternalFunction "Internal Function" +#define SYNS_AttrKey "Key" +#define SYNS_AttrLabel "Label" +#define SYNS_AttrLace "Lace" +#define SYNS_AttrLocalVariable "Local Variable" +#define SYNS_AttrLine "Line" +#define SYNS_AttrMacro "Macro" +#define SYNS_AttrMarker "Marker" +#define SYNS_AttrMathMode "Math Mode" +#define SYNS_AttrMessage "Message" +#define SYNS_AttrMiscellaneous "Miscellaneous" +#define SYNS_AttrNamespaceAttrName "Namespace Attribute Name" +#define SYNS_AttrNamespaceAttrValue "Namespace Attribute Value" +#define SYNS_AttrNonReservedKeyword "Non-reserved Keyword" +#define SYNS_AttrNull "Null" +#define SYNS_AttrNumber "Number" +#define SYNS_AttrOctal "Octal" +#define SYNS_AttrOperator "Operator" +#define SYNS_AttrOperatorAndSymbols "Operator And Symbols" +#define SYNS_AttrOpLine "OpLine" +#define SYNS_AttrPLSQL "PL/SQL Reserved Word" +#define SYNS_AttrPragma "Pragma" +#define SYNS_AttrPredefined "Predefined" +#define SYNS_AttrPreprocessor "Preprocessor" +#define SYNS_AttrProcessingInstr "Processing Instruction" +#define SYNS_AttrQuad "Quad" +#define SYNS_AttrQualifier "Qualifier" +#define SYNS_AttrRegister "Register" +#define SYNS_AttrReservedWord "Reserved Word" +#define SYNS_AttrResultValue "Result Value" +#define SYNS_AttrRoundBracket "Round Bracket" +#define SYNS_AttrRpl "Rpl" +#define SYNS_AttrRplKey "Rpl Key" +#define SYNS_AttrRplComment "Rpl Comment" +#define SYNS_AttrSASM "SASM" +#define SYNS_AttrSASMComment "SASM Comment" +#define SYNS_AttrSASMKey "SASM Key" +#define SYNS_AttrSecondReservedWord "Second Reserved Word" +#define SYNS_AttrSecondTri "SecondTri" +#define SYNS_AttrSection "Section" +#define SYNS_AttrSequence "Sequence Number Area" +#define SYNS_AttrShape "Shape" +#define SYNS_AttrSingleString "Single Quoted String" +#define SYNS_AttrSpace "Space" +#define SYNS_AttrSpecialVariable "Special Variable" +#define SYNS_AttrSQLKey "SQL Keyword" +#define SYNS_AttrSQLPlus "SQL*Plus Command" +#define SYNS_AttrSquareBracket "Square Bracket" +#define SYNS_AttrString "String" +#define SYNS_AttrStringEscapeSequences "Escape sequences" +#define SYNS_AttrSymbol "Symbol" +#define SYNS_AttrSyntaxError "Syntax Error" +#define SYNS_AttrSystem "System Functions and Variables" +#define SYNS_AttrSystemValue "System Value" +#define SYNS_AttrTagArea "Tag Area" +#define SYNS_AttrTableName "Table Name" +#define SYNS_AttrTerminator "Terminator" +#define SYNS_AttrTeXCommand "TeX Command" +#define SYNS_AttrText "Text" +#define SYNS_AttrTextMathMode "Text in Math Mode" +#define SYNS_AttrThirdTri "ThirdTri" +#define SYNS_AttrTriangle "Triangle" +#define SYNS_AttrUnknownWord "Unknown Word" +#define SYNS_AttrURI "URI" +#define SYNS_AttrUser "User Functions and Variables" +#define SYNS_AttrUserFunction "User Functions" +#define SYNS_AttrValue "Value" +#define SYNS_AttrVariable "Variable" +#define SYNS_AttrVisitedURI "Visited URI" +#define SYNS_AttrVrmlAppearance "Vrml_Appearance" +#define SYNS_AttrVrmlAttribute "Vrml_Attribute" +#define SYNS_AttrVrmlDefinition "Vrml_Definition" +#define SYNS_AttrVrmlEvent "Vrml_Event" +#define SYNS_AttrVrmlGrouping "Vrml_Grouping" +#define SYNS_AttrVrmlInterpolator "Vrml_Interpolator" +#define SYNS_AttrVrmlLight "Vrml_Light" +#define SYNS_AttrVrmlNode "Vrml_Node" +#define SYNS_AttrVrmlParameter "Vrml_Parameter" +#define SYNS_AttrVrmlProto "Vrml_Proto" +#define SYNS_AttrVrmlSensor "Vrml_Sensor" +#define SYNS_AttrVrmlShape "Vrml_Shape" +#define SYNS_AttrVrmlShape_Hint "Vrml_Shape_Hint" +#define SYNS_AttrVrmlTime_dependent "Vrml_Time_dependent" +#define SYNS_AttrVrmlViewpoint "Vrml_Viewpoint" +#define SYNS_AttrVrmlWorldInfo "Vrml_WorldInfo" +#define SYNS_AttrWhitespace "Whitespace" +#define SYNS_AttrX3DDocType "X3DDocType" +#define SYNS_AttrX3DHeader "X3DHeader" +// names of exporter output formats +#define SYNS_ExporterFormatHTML "HTML" +#define SYNS_ExporterFormatRTF "RTF" +#define SYNS_ExporterFormatTeX "TeX" +#endif // CONSTANTS_H diff --git a/RedPandaIDE/qsynedit/MiscClasses.cpp b/RedPandaIDE/qsynedit/MiscClasses.cpp new file mode 100644 index 00000000..31467a60 --- /dev/null +++ b/RedPandaIDE/qsynedit/MiscClasses.cpp @@ -0,0 +1,306 @@ +#include "MiscClasses.h" +#include "algorithm" + +SynGutter::SynGutter(QObject *parent): + QObject(parent) +{ + mFont = QFont("Courier New",9); + mColor= QColorConstants::Svg::lightgray; + mBorderColor = QColorConstants::Transparent; + mWidth = 30; + mShowLineNumbers = true; + mDigitCount = 4; + mLeadingZeros = false; + mLeftOffset = 16; + mRightOffset = 2; + mVisible = true; + mUseFontStyle = false; + mAutoSize = true; + mAutoSizeDigitCount = mDigitCount; + mBorderStyle = SynGutterBorderStyle::Middle; + mLineNumberStart = 1; + mGradient = false; + mGradientStartColor = QColorConstants::Transparent; + mGradientEndColor = QColorConstants::Transparent; + mGradientSteps = 48; +} + +QFont SynGutter::font() const +{ + return mFont; +} + +void SynGutter::setFont(const QFont &font) +{ + if (mFont != font) { + mFont = font; + setChanged(); + } +} + +bool SynGutter::autoSize() const +{ + return mAutoSize; +} + +void SynGutter::setAutoSize(bool value) +{ + if (mAutoSize != value) { + mAutoSize = value; + setChanged(); + } +} + +void SynGutter::setChanged() +{ + emit changed(); +} + +int SynGutter::width() const +{ + return mWidth; +} + +void SynGutter::setWidth(int width) +{ + if (mWidth != width ) { + mWidth = width; + setChanged(); + } +} + +void SynGutter::autoSizeDigitCount(int linesCount) +{ + if (mVisible && mAutoSize && mShowLineNumbers) { + linesCount += (mLineNumberStart - 1); + } + int nDigits = std::max(QString::number(linesCount).length(), mDigitCount); + if (mAutoSizeDigitCount!=nDigits) { + mAutoSizeDigitCount = nDigits; + setChanged(); + } +} + +QString SynGutter::formatLineNumber(int line) +{ + line += (mLineNumberStart - 1); + QString result = QString::number(line); + return QString(mAutoSizeDigitCount - result.length(),'0') + result; +} + +int SynGutter::realGutterWidth(int charWidth) +{ + if (!mVisible) { + return 0; + } + if (mShowLineNumbers) { + return mLeftOffset + mRightOffset + mAutoSizeDigitCount * charWidth + 2; + } + return mWidth; +} + +bool SynGutter::visible() const +{ + return mVisible; +} + +void SynGutter::setVisible(bool visible) +{ + if (mVisible!=visible) { + mVisible = visible; + setChanged(); + } +} + +bool SynGutter::useFontStyle() const +{ + return mUseFontStyle; +} + +void SynGutter::setUseFontStyle(bool useFontStyle) +{ + if (mUseFontStyle!=useFontStyle) { + mUseFontStyle = useFontStyle; + setChanged(); + } +} + +bool SynGutter::showLineNumbers() const +{ + return mShowLineNumbers; +} + +void SynGutter::setShowLineNumbers(bool showLineNumbers) +{ + if (mShowLineNumbers!=showLineNumbers) { + mShowLineNumbers = showLineNumbers; + setChanged(); + } +} + +int SynGutter::rightOffset() const +{ + return mRightOffset; +} + +void SynGutter::setRightOffset(int rightOffset) +{ + int value = std::max(0, rightOffset); + if (mRightOffset != value) { + mRightOffset = value; + setChanged(); + } +} + +int SynGutter::lineNumberStart() const +{ + return mLineNumberStart; +} + +void SynGutter::setLineNumberStart(int lineNumberStart) +{ + int value = std::max(0,lineNumberStart); + if (mLineNumberStart!=value) { + mLineNumberStart = value; + setChanged(); + } +} + +bool SynGutter::zeroStart() +{ + return mLineNumberStart == 0; +} + +int SynGutter::leftOffset() const +{ + return mLeftOffset; +} + +void SynGutter::setLeftOffset(int leftOffset) +{ + int value = std::max(0,leftOffset); + if (mLeftOffset != value) { + mLeftOffset = value; + setChanged(); + } +} + +bool SynGutter::leadingZeros() const +{ + return mLeadingZeros; +} + +void SynGutter::setLeadingZeros(bool value) +{ + if (mLeadingZeros!=value) { + mLeadingZeros = value; + setChanged(); + } +} + +int SynGutter::gradientSteps() const +{ + return mGradientSteps; +} + +void SynGutter::setGradientSteps(int value) +{ + if (mGradientSteps!=value) { + mGradientSteps = value; + if (mGradientSteps<2) + mGradientSteps = 2; + setChanged(); + } +} + +QColor SynGutter::gradientEndColor() const +{ + return mGradientEndColor; +} + +void SynGutter::setGradientEndColor(const QColor &value) +{ + if (mGradientEndColor!=value) { + mGradientEndColor = value; + setChanged(); + } +} + +QColor SynGutter::gradientStartColor() const +{ + return mGradientStartColor; +} + +void SynGutter::setGradientStartColor(const QColor &value) +{ + if (mGradientStartColor!=value) { + mGradientStartColor = value; + setChanged(); + } +} + +bool SynGutter::gradient() const +{ + return mGradient; +} + +void SynGutter::setGradient(bool value) +{ + if (mGradient!=value){ + mGradient = value; + setChanged(); + } +} + +SynGutterBorderStyle SynGutter::borderStyle() const +{ + return mBorderStyle; +} + +void SynGutter::setBorderStyle(const SynGutterBorderStyle &value) +{ + if (mBorderStyle!=value) { + mBorderStyle = value; + setChanged(); + } +} + +int SynGutter::digitCount() const +{ + return mDigitCount; +} + +void SynGutter::setDigitCount(int value) +{ + if (mDigitCount != value ) { + mDigitCount = value; + setChanged(); + } +} + +QColor SynGutter::color() const +{ + return mColor; +} + +void SynGutter::setColor(const QColor &value) +{ + if (mColor!=value) { + mColor = value; + setChanged(); + } +} + +QColor SynGutter::borderColor() const +{ + return mBorderColor; +} + +void SynGutter::setBorderColor(const QColor &value) +{ + if (mBorderColor!=value) { + mBorderColor = value; + setChanged(); + } +} + diff --git a/RedPandaIDE/qsynedit/MiscClasses.h b/RedPandaIDE/qsynedit/MiscClasses.h new file mode 100644 index 00000000..ea29aa14 --- /dev/null +++ b/RedPandaIDE/qsynedit/MiscClasses.h @@ -0,0 +1,105 @@ +#ifndef MISCCLASSES_H +#define MISCCLASSES_H + +#include +#include +#include + +enum class SynGutterBorderStyle { + None, + Middle, + Right +}; + +class SynGutter : public QObject { + Q_OBJECT +public: + explicit SynGutter(QObject* parent = nullptr); + QFont font() const; + void setFont(const QFont &value); + + bool autoSize() const; + void setAutoSize(bool value); + + QColor borderColor() const; + void setBorderColor(const QColor &value); + + QColor color() const; + void setColor(const QColor &value); + + int digitCount() const; + void setDigitCount(int value); + + SynGutterBorderStyle borderStyle() const; + void setBorderStyle(const SynGutterBorderStyle &value); + + bool gradient() const; + void setGradient(bool value); + + QColor gradientStartColor() const; + void setGradientStartColor(const QColor &value); + + QColor gradientEndColor() const; + void setGradientEndColor(const QColor &value); + + int gradientSteps() const; + void setGradientSteps(int value); + + bool leadingZeros() const; + void setLeadingZeros(bool value); + + + int leftOffset() const; + void setLeftOffset(int leftOffset); + + int lineNumberStart() const; + void setLineNumberStart(int lineNumberStart); + + bool zeroStart(); + int rightOffset() const; + void setRightOffset(int rightOffset); + + bool showLineNumbers() const; + void setShowLineNumbers(bool showLineNumbers); + + bool useFontStyle() const; + void setUseFontStyle(bool useFontStyle); + + bool visible() const; + void setVisible(bool visible); + + int width() const; + void setWidth(int width); + + void autoSizeDigitCount(int linesCount); + QString formatLineNumber(int line); + int realGutterWidth(int charWidth); + +signals: + void changed(); +private: + void setChanged(); +private: + bool mAutoSize; + QColor mBorderColor; + QColor mColor; + int mDigitCount; + QFont mFont; + bool mGradient; + QColor mGradientStartColor; + QColor mGradientEndColor; + int mGradientSteps; + bool mLeadingZeros; + int mLeftOffset; + int mLineNumberStart; + int mRightOffset; + bool mShowLineNumbers; + SynGutterBorderStyle mBorderStyle; + bool mUseFontStyle; + bool mVisible; + int mWidth; + int mAutoSizeDigitCount; + +}; + +#endif // MISCCLASSES_H diff --git a/RedPandaIDE/qsynedit/highlighter/base.cpp b/RedPandaIDE/qsynedit/highlighter/base.cpp new file mode 100644 index 00000000..5209b7ed --- /dev/null +++ b/RedPandaIDE/qsynedit/highlighter/base.cpp @@ -0,0 +1,261 @@ +#include "base.h" +#include "../Constants.h" + +SynHighligterBase::SynHighligterBase(QObject *parent) : QObject(parent), + mWordBreakChars{ SynWordBreakChars}, + mEnabled(true), + mUpdateCount(0) +{ + +} + +std::map SynHighligterBase::attributes() const +{ + return mAttributes; +} + +std::set SynHighligterBase::wordBreakChars() const +{ + return mWordBreakChars; +} + +PSynHighlighterAttribute SynHighligterBase::commentAttribute() const +{ + return mCommentAttribute; +} + +PSynHighlighterAttribute SynHighligterBase::identifierAttribute() const +{ + return mIdentifierAttribute; +} + +PSynHighlighterAttribute SynHighligterBase::keywordAttribute() const +{ + return mKeywordAttribute; +} + +PSynHighlighterAttribute SynHighligterBase::stringAttribute() const +{ + return mStringAttribute; +} + +PSynHighlighterAttribute SynHighligterBase::whitespaceAttribute() const +{ + return mWhitespaceAttribute; +} + +PSynHighlighterAttribute SynHighligterBase::symbolAttribute() const +{ + return mSymbolAttribute; +} + +void SynHighligterBase::onAttributeChanged() +{ + setAttributesChanged(); +} + +void SynHighligterBase::setAttributesChanged() +{ + if (mUpdateCount == 0) { + emit attributesChanged(); + } +} + +void SynHighligterBase::beginUpdate() +{ + mUpdateCount++; +} + +void SynHighligterBase::endUpdate() +{ + mUpdateCount--; + if (mUpdateCount == 0) { + setAttributesChanged(); + } + if (mUpdateCount<0) { + throw new std::out_of_range("mUpdateCount in SynHighlighterBase < 0"); + } +} + +SynRangeState SynHighligterBase::getRangeState() const +{ + return 0; +} + +SynRangeState SynHighligterBase::getSpaceRangeState() const +{ + +} + +int SynHighligterBase::getBraceLevel() const +{ + return 0; +} + +int SynHighligterBase::getBracketLevel() const +{ + return 0; +} + +int SynHighligterBase::getParenthesisLevel() const +{ + return 0; +} + +SynHighlighterTokenType SynHighligterBase::getTokenType() +{ + return SynHighlighterTokenType::httDefault; +} + +bool SynHighligterBase::isKeyword(const QString &) +{ + return false; +} + +bool SynHighligterBase::isSpaceChar(const QChar &ch) +{ + return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'; +} + +bool SynHighligterBase::isIdentChar(const QChar &ch) const +{ + if (ch == '_') { + return true; + } + if (ch>='0' && ch <= '9') { + return true; + } + if (ch>='a' && ch <= 'z') { + return true; + } + if (ch>='A' && ch <= 'A') { + return true; + } + +} + +void SynHighligterBase::addAttribute(PSynHighlighterAttribute attribute) +{ + mAttributes[attribute->name()]=attribute; +} + +void SynHighligterBase::clearAttributes() +{ + mAttributes.clear(); +} + +int SynHighligterBase::attributesCount() const +{ + return mAttributes.size(); +} + +PSynHighlighterAttribute SynHighligterBase::getAttribute(const QString &name) const +{ + auto search = mAttributes.find(name); + if (search!=mAttributes.end()) { + return search->second; + } + return PSynHighlighterAttribute(); +} + +void SynHighlighterAttribute::setChanged() +{ + emit changed(); +} + +bool SynHighlighterAttribute::strikeOut() const +{ + return mStrikeOut; +} + +void SynHighlighterAttribute::setStrikeOut(bool strikeOut) +{ + if (mStrikeOut!=strikeOut) { + mStrikeOut = strikeOut; + setChanged(); + } +} + +bool SynHighlighterAttribute::underline() const +{ + return mUnderline; +} + +void SynHighlighterAttribute::setUnderline(bool underline) +{ + mUnderline = underline; +} + +bool SynHighlighterAttribute::italic() const +{ + return mItalic; +} + +void SynHighlighterAttribute::setItalic(bool italic) +{ + if (mItalic!=italic) { + mItalic = italic; + setChanged(); + } +} + +bool SynHighlighterAttribute::bold() const +{ + return mBold; +} + +void SynHighlighterAttribute::setBold(bool bold) +{ + if (mBold!=bold) { + mBold = bold; + setChanged(); + } +} + +QString SynHighlighterAttribute::name() const +{ + return mName; +} + +void SynHighlighterAttribute::setName(const QString &name) +{ + if (mName!=name) { + mName = name; + setChanged(); + } +} + +QColor SynHighlighterAttribute::foreground() const +{ + return mForeground; +} + +void SynHighlighterAttribute::setForeground(const QColor &foreground) +{ + if (mForeground!=foreground) { + mForeground = foreground; + setChanged(); + } +} + +SynHighlighterAttribute::SynHighlighterAttribute(const QString &name, QObject *parent): + QObject(parent), + mName(name), + mForeground(QColorConstants::Black), + mBackground(QColorConstants::White) +{ + +} + +QColor SynHighlighterAttribute::background() const +{ + return mBackground; +} + +void SynHighlighterAttribute::setBackground(const QColor &background) +{ + if (mBackground!=background) { + mBackground = background; + setChanged(); + } +} diff --git a/RedPandaIDE/qsynedit/highlighter/base.h b/RedPandaIDE/qsynedit/highlighter/base.h new file mode 100644 index 00000000..cf54bc91 --- /dev/null +++ b/RedPandaIDE/qsynedit/highlighter/base.h @@ -0,0 +1,142 @@ +#ifndef SYNHIGHLIGTERBASE_H +#define SYNHIGHLIGTERBASE_H + +#include +#include +#include +#include +#include + +typedef struct { + int state; + int spaceState; +} SynRangeState; +typedef int SynTokenKind; + +enum class SynHighlighterTokenType { + Default, Space, Comment, + PreprocessDirective, String, StringEscapeSequence, + Identifier, Symbol, + Character, Keyword, Number}; + +class SynHighlighterAttribute : public QObject{ + Q_OBJECT +public: + explicit SynHighlighterAttribute(const QString& name, QObject* parent = nullptr); + QColor background() const; + void setBackground(const QColor &background); + + QColor foreground() const; + void setForeground(const QColor &foreground); + + QString name() const; + void setName(const QString &name); + + bool bold() const; + void setBold(bool bold); + + bool italic() const; + void setItalic(bool italic); + + bool underline() const; + void setUnderline(bool underline); + + bool strikeOut() const; + void setStrikeOut(bool strikeOut); + +signals: + void changed(); +private: + void setChanged(); +private: + QColor mBackground; + QColor mForeground; + QString mName; + bool mBold; + bool mItalic; + bool mUnderline; + bool mStrikeOut; +}; + +typedef std::shared_ptr PSynHighlighterAttribute; + +class SynHighligterBase : public QObject +{ + Q_OBJECT +public: + explicit SynHighligterBase(QObject *parent = nullptr); + + const std::map attributes() const; + + std::set wordBreakChars() const; + + + + PSynHighlighterAttribute commentAttribute() const; + + PSynHighlighterAttribute identifierAttribute() const; + + PSynHighlighterAttribute keywordAttribute() const; + + PSynHighlighterAttribute stringAttribute() const; + + PSynHighlighterAttribute whitespaceAttribute() const; + + PSynHighlighterAttribute symbolAttribute() const; + + virtual bool isIdentChar(const QChar& ch) const; + + void beginUpdate(); + void endUpdate(); + virtual bool getTokenFinished() const = 0; + virtual bool isLastLineCommentNotFinished(int state) const = 0; + virtual bool isLastLineStringNotFinished(int state) const = 0; + virtual bool eol() const = 0; + virtual SynRangeState getRangeState() const; + virtual int getBraceLevel() const; + virtual int getBracketLevel() const; + virtual int getParenthesisLevel() const; + virtual QString getToken() const=0; + virtual PSynHighlighterAttribute getTokenAttribute() const=0; + virtual SynHighlighterTokenType getTokenType(); + virtual SynTokenKind getTokenKind() = 0; + virtual int getTokenPos() = 0; + virtual bool isKeyword(const QString& word); + virtual void next() = 0; + virtual void nextToEol(); + virtual void setState(SynRangeState rangeState, int braceLevel, int bracketLevel, int parenthesisLevel) = 0; + virtual void setLine(const QString& newLine, int lineNumber) = 0; + virtual void resetState() = 0; + + virtual QString languageName(); + + static bool isSpaceChar(const QChar& ch); +signals: + void attributesChanged(); + +protected: + void onAttributeChanged(); + void setAttributesChanged(); + +protected: + PSynHighlighterAttribute mCommentAttribute; + PSynHighlighterAttribute mIdentifierAttribute; + PSynHighlighterAttribute mKeywordAttribute; + PSynHighlighterAttribute mStringAttribute; + PSynHighlighterAttribute mWhitespaceAttribute; + PSynHighlighterAttribute mSymbolAttribute; + + void addAttribute(PSynHighlighterAttribute attribute); + void clearAttributes(); + virtual int attributesCount() const; + + virtual PSynHighlighterAttribute getAttribute(const QString& name) const; + +private: + std::map mAttributes; + int mUpdateCount; + bool mEnabled; + std::set mWordBreakChars; +}; + +#endif // SYNHIGHLIGTERBASE_H diff --git a/RedPandaIDE/qsynedit/highlighter/cpp.cpp b/RedPandaIDE/qsynedit/highlighter/cpp.cpp new file mode 100644 index 00000000..6f972717 --- /dev/null +++ b/RedPandaIDE/qsynedit/highlighter/cpp.cpp @@ -0,0 +1,1562 @@ +#include "cpp.h" +#include "../Constants.h" + +#include + +const QSet SynEditCppHighlighter::Keywords { + "and", + "and_eq", + "bitand", + "bitor", + "break", + "compl", + "constexpr", + "const_cast", + "continue", + "dynamic_cast", + "else", + "explicit", + "export", + "extern", + "false", + "for", + "mutable", + "noexcept", + "not", + "not_eq", + "nullptr", + "or", + "or_eq", + "register", + "reinterpret_cast", + "static_assert", + "static_cast", + "template", + "this", + "thread_local", + "true", + "typename", + "virtual", + "volatile", + "xor", + "xor_eq", + "delete", + "delete[]", + "goto", + "new", + "return", + "throw", + "using", + "case", + "default", + + "alignas", + "alignof", + "decltype", + "if", + "sizeof", + "switch", + "typeid", + "while", + + "asm", + "catch", + "do", + "namespace", + "try", + + "atomic_cancel", + "atomic_commit", + "atomic_noexcept", + "concept", + "consteval", + "constinit", + "co_wait", + "co_return", + "co_yield", + "reflexpr", + "requires", + + "auto", + "bool", + "char", + "char8_t", + "char16_t", + "char32_t", + "double", + "float", + "int", + "long", + "short", + "signed", + "unsigned", + "void", + "wchar_t", + + "const", + "inline", + + "class", + "enum", + "friend", + "operator", + "private", + "protected", + "public", + "static", + "struct", + "typedef", + "union", + + "nullptr", +}; +SynEditCppHighlighter::SynEditCppHighlighter(QObject *parent): SynHighligterBase(parent) +{ + mAsmAttribute = std::make_shared(SYNS_AttrAssembler); + addAttribute(mAsmAttribute); + mCharAttribute = std::make_shared(SYNS_AttrCharacter); + addAttribute(mCharAttribute); + mCommentAttribute = std::make_shared(SYNS_AttrComment); + mCommentAttribute->setItalic(true); + 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); + mDirecAttribute = std::make_shared(SYNS_AttrPreprocessor); + addAttribute(mDirecAttribute); + mKeyAttribute = std::make_shared(SYNS_AttrReservedWord); + mKeyAttribute->setBold(true); + addAttribute(mKeyAttribute); + 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); + + mRange.state = RangeState::rsUnknown; + mRange.spaceState = RangeState::rsUnknown; + mParenthesisLevel = 0; + mBracketLevel = 0; + mBraceLevel = 0; + mAsmStart = false; +} + +PSynHighlighterAttribute SynEditCppHighlighter::asmAttribute() const +{ + return mAsmAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::direcAttribute() const +{ + return mDirecAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::invalidAttribute() const +{ + return mInvalidAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::keyAttribute() const +{ + return mKeyAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::numberAttribute() const +{ + return mNumberAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::floatAttribute() const +{ + return mFloatAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::hexAttribute() const +{ + return mHexAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::octAttribute() const +{ + return mOctAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::stringEscapeSequenceAttribute() const +{ + return mStringEscapeSequenceAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::charAttribute() const +{ + return mCharAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::variableAttribute() const +{ + return mVariableAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::functionAttribute() const +{ + return mFunctionAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::classAttribute() const +{ + return mClassAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::globalVarAttribute() const +{ + return mGlobalVarAttribute; +} + +PSynHighlighterAttribute SynEditCppHighlighter::localVarAttribute() const +{ + return mLocalVarAttribute; +} + +SynEditCppHighlighter::ExtTokenKind SynEditCppHighlighter::getExtTokenId() +{ + return mExtTokenId; +} + +SynTokenKind SynEditCppHighlighter::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 SynEditCppHighlighter::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 SynEditCppHighlighter::ansiCppProc() +{ + mTokenId = TokenKind::Comment; + if (mLine[mRun]==0) { + nullProc(); + if ( (mRun<1) || (mLine[mRun-1]!='\\')) { + mRange.state = RangeState::rsUnknown; + return; + } + } + while (mLine[mRun]!=0) { + if ( isSpaceChar(mLine[mRun]) ) { + mRange.spaceState = mRange.state; + mRange.state = RangeState::rsSpace; + break; + } + mRun+=1; + } + mRange.state = RangeState::rsUnknown; + if (mLine[mRun-1] == '\\' && mLine[mRun]==0) { // continues on next line + mRange.state = RangeState::rsCppComment; + } +} + +void SynEditCppHighlighter::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]!=13 && mLine[mRun]!=10) { + mRange.state = RangeState::rsMultiLineDirective; + } else { + mRange.state = RangeState::rsUnknown; + } + } else + mRun+=1; + case 9: + case 32: + mRange.spaceState = mRange.state; + mRange.state = RangeState::rsSpace; + finishProcess = true; + break; + default: + mRun+=1; + } + if (finishProcess) + break; + } +} + +void SynEditCppHighlighter::asciiCharProc() +{ + mTokenId = TokenKind::Char; + do { + if (isSpaceChar(mLine[mRun])) { + mRange.spaceState = RangeState::rsChar; + mRange.state = RangeState::rsSpace; + return; + } + 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 SynEditCppHighlighter::atSymbolProc() +{ + mTokenId = TokenKind::Unknown; + mRun+=1; +} + +void SynEditCppHighlighter::braceCloseProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::BraceClose; + if (mRange.state == RangeState::rsAsmBlock) { + mRange.state = rsUnknown; + } + mBraceLevel -= 1; +} + +void SynEditCppHighlighter::braceOpenProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::BraceOpen; + if (mRange.state == RangeState::rsAsm) { + mRange.state = RangeState::rsAsmBlock; + mAsmStart = true; + } + mBraceLevel += 1; +} + +void SynEditCppHighlighter::colonProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1]==':') { + mRun+=2; + mExtTokenId = ExtTokenKind::ScopeResolution; + } else { + mRun+=1; + mExtTokenId = ExtTokenKind::Colon; + } +} + +void SynEditCppHighlighter::commaProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::Comma; +} + +void SynEditCppHighlighter::directiveProc() +{ + if (mLine[0]!='#') { // '#' is not first char on the line, treat it as an invalid char + mTokenId = TokenKind::Unknown; + mRun+=1; + return; + } + mTokenId = TokenKind::Directive; + do { + if (isSpaceChar(mLine[mRun])) { + mRange.spaceState = RangeState::rsMultiLineDirective; + mRange.state = RangeState::rsSpace; + return; + } + 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 SynEditCppHighlighter::directiveEndProc() +{ + mTokenId = TokenKind::Directive; + if (mLine[mRun] == 0) { + nullProc(); + return; + } + mRange.state = RangeState::rsUnknown; + do { + if (isSpaceChar(mLine[mRun])) { + mRange.spaceState = RangeState::rsMultiLineDirective; + mRange.state = RangeState::rsSpace; + return; + } + 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 SynEditCppHighlighter::equalProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1] == '=') { + mRun += 2; + mExtTokenId = ExtTokenKind::LogEqual; + } else { + mRun += 1; + mExtTokenId = ExtTokenKind::Assign; + } +} + +void SynEditCppHighlighter::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 SynEditCppHighlighter::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; + } else { + mTokenId = TokenKind::Identifier; + } +} + +void SynEditCppHighlighter::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 SynEditCppHighlighter::minusProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun+1].unicode()) { + case '=': + mRun += 2; + mExtTokenId = ExtTokenKind::SubtractAssign; + break; + case '-': + mRun += 2; + mExtTokenId = ExtTokenKind::Decrement; + break; + case '>': + mRun += 2; + mExtTokenId = ExtTokenKind::Arrow; + break; + default: + mRun += 1; + mExtTokenId = ExtTokenKind::Subtract; + } +} + +void SynEditCppHighlighter::modSymbolProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun + 1].unicode()) { + case '=': + mRun += 2; + mExtTokenId = ExtTokenKind::ModAssign; + break; + default: + mRun += 1; + mExtTokenId = ExtTokenKind::Mod; + } +} + +void SynEditCppHighlighter::notSymbolProc() +{ + mTokenId = TokenKind::Symbol; + switch(mLine[mRun + 1].unicode()) { + case '=': + mRun+=2; + mExtTokenId = ExtTokenKind::NotEqual; + break; + default: + mRun+=1; + mExtTokenId = ExtTokenKind::LogComplement; + } +} + +void SynEditCppHighlighter::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 SynEditCppHighlighter::numberProc() +{ + int idx1; // token[1] + idx1 = mRun; + mRun+=1; + mTokenId = TokenKind::Number; + bool shouldExit = false; + double x=010.140; + 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; + } + mRun+=1; + } + if (mLine[mRun-1] == '\'') { + mTokenId = TokenKind::Unknown; + } +} + +void SynEditCppHighlighter::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 SynEditCppHighlighter::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 SynEditCppHighlighter::pointProc() +{ + mTokenId = TokenKind::Symbol; + 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 SynEditCppHighlighter::questionProc() +{ + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::Question; + mRun+=1; +} + +void SynEditCppHighlighter::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; + case ' ': + case '\t': + mRange.state = rsSpace; + if (noEscaping) { + mRange.spaceState = RangeState::rsRawStringNotEscaping; + } else { + mRange.spaceState = RangeState::rsRawStringEscaping; + } + return; + break; + } + mRun+=1; + } + mRange.state = RangeState::rsUnknown; +} + +void SynEditCppHighlighter::roundCloseProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::RoundClose; + mParenthesisLevel -= 1; +} + +void SynEditCppHighlighter::roundOpenProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::RoundOpen; + mParenthesisLevel += 1; +} + +void SynEditCppHighlighter::semiColonProc() +{ + mRun += 1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::SemiColon; + if (mRange.state == RangeState::rsAsm) + mRange.state = RangeState::rsUnknown; +} + +void SynEditCppHighlighter::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 SynEditCppHighlighter::spaceProc() +{ + mRun += 1; + mTokenId = TokenKind::Space; + while (mLine[mRun]>=1 && mLine[mRun]<=32) + mRun+=1; + mRange.state = mRange.spaceState; + mRange.spaceState = RangeState::rsUnknown; +} + +void SynEditCppHighlighter::squareCloseProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::SquareClose; + mBracketLevel+=1; +} + +void SynEditCppHighlighter::squareOpenProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::SquareOpen; + mBracketLevel +=1; +} + +void SynEditCppHighlighter::starProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1] == '=') { + mRun += 2; + mExtTokenId = ExtTokenKind::MultiplyAssign; + } else { + mRun += 1; + mExtTokenId = ExtTokenKind::Star; + } +} + +void SynEditCppHighlighter::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 (isSpaceChar(mLine[mRun])) { + mRange.spaceState = RangeState::rsMultiLineString; + mRange.state = RangeState::rsSpace; + return; + } + 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 SynEditCppHighlighter::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 SynEditCppHighlighter::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 (isSpaceChar(mLine[mRun])) { + mRange.spaceState = RangeState::rsString; + mRange.state = RangeState::rsSpace; + return; + } + 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; + } + } + } + mRange.state = RangeState::rsUnknown; +} + +void SynEditCppHighlighter::stringStartProc() +{ + mTokenId = TokenKind::String; + mRun += 1; + if (mLine[mRun]==0) { + mRange.state = RangeState::rsUnknown; + return; + } + stringProc(); +} + +void SynEditCppHighlighter::tildeProc() +{ + mRun+=1; + mTokenId = TokenKind::Symbol; + mExtTokenId = ExtTokenKind::BitComplement; +} + +void SynEditCppHighlighter::unknownProc() +{ + mRun+=1; + mTokenId = TokenKind::Unknown; +} + +void SynEditCppHighlighter::xorSymbolProc() +{ + mTokenId = TokenKind::Symbol; + if (mLine[mRun+1]=='=') { + mRun+=2; + mExtTokenId = ExtTokenKind::XorAssign; + } else { + mRun+=1; + mExtTokenId = ExtTokenKind::Xor; + } +} + +void SynEditCppHighlighter::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(); + } + } +} + +bool SynEditCppHighlighter::getTokenFinished() const +{ + if (mTokenId == TokenKind::Comment + || mTokenId == TokenKind::String + || mTokenId == TokenKind::RawString) { + return mRange.state == RangeState::rsUnknown; + } + return true; +} + +bool SynEditCppHighlighter::isLastLineCommentNotFinished(int state) const +{ + return (state == RangeState::rsAnsiC || + state == RangeState::rsAnsiCAsm || + state == RangeState::rsAnsiCAsmBlock || + state == RangeState::rsDirectiveComment|| + state == RangeState::rsCppComment); +} + +bool SynEditCppHighlighter::isLastLineStringNotFinished(int state) const +{ + return state == RangeState::rsMultiLineString; +} + +bool SynEditCppHighlighter::eol() const +{ + return mTokenId == TokenKind::Null; +} + +QString SynEditCppHighlighter::getToken() const +{ + return mLineString.mid(mTokenPos,mRun-mTokenPos); +} + +PSynHighlighterAttribute SynEditCppHighlighter::getTokenAttribute() const +{ + switch (mTokenId) { + case TokenKind::Asm: + return mAsmAttribute; + case TokenKind::Comment: + return mCommentAttribute; + case TokenKind::Directive: + return mDirecAttribute; + case TokenKind::Identifier: + return mIdentifierAttribute; + case TokenKind::Key: + return mKeyAttribute; + case TokenKind::Number: + return mNumberAttribute; + case TokenKind::Float: + case TokenKind::HexFloat: + return mFloatAttribute; + case TokenKind::Hex: + return mHexAttribute; + case TokenKind::Octal: + return mOctAttribute; + case TokenKind::Space: + return mWhitespaceAttribute; + case TokenKind::String: + return mStringAttribute; + case TokenKind::StringEscapeSeq: + return mStringEscapeSequenceAttribute; + case TokenKind::RawString: + return mStringAttribute; + case TokenKind::Char: + return mCharAttribute; + case TokenKind::Symbol: + return mSymbolAttribute; + case TokenKind::Unknown: + return mInvalidAttribute; + default: + return mInvalidAttribute; + } +} + +SynTokenKind SynEditCppHighlighter::getTokenKind() +{ + return mTokenId; +} + +int SynEditCppHighlighter::getTokenPos() +{ + return mTokenPos; +} + +void SynEditCppHighlighter::next() +{ + mAsmStart = false; + mTokenPos = mRun; + do { + switch (mRange.state) { + case RangeState::rsAnsiC: + case RangeState::rsAnsiCAsm: + case RangeState::rsAnsiCAsmBlock: + case RangeState::rsDirectiveComment: + ansiCProc(); + break; + case RangeState::rsString: + stringProc(); + break; + case RangeState::rsCppComment: + ansiCppProc(); + break; + case RangeState::rsMultiLineDirective: + directiveEndProc(); + break; + case RangeState::rsMultiLineString: + stringEndProc(); + break; + case RangeState::rsSpace: + spaceProc(); + break; + case RangeState::rsRawStringEscaping: + case RangeState::rsRawStringNotEscaping: + rawStringProc(); + break; + case RangeState::rsStringEscapeSeq: + case RangeState::rsMultiLineStringEscapeSeq: + stringEscapeSeqProc(); + break; + case RangeState::rsChar: + if (mLine[mRun]=='\'') { + mRange.state = rsUnknown; + mTokenId = TokenKind::Char; + mRun+=1; + } else { + asciiCharProc(); + } + break; + default: + mRange.state = RangeState::rsUnknown; + if (mLine[mRun] == 'R' && mLine[mRun+1] == '"') { + mRun+=2; + rawStringProc(); + } else if ((mLine[mRun] == 'L' || mLine[mRun] == 'u' || mLine[mRun]=='U') && mLine[mRun+1]=='\"') { + mRun+=1; + stringStartProc(); + } else if (mLine[mRun] == 'u' && mLine[mRun+1] == '8' && mLine[mRun+2]=='\"') { + mRun+=2; + stringStartProc(); + } else + processChar(); + } + } while (mTokenId!=TokenKind::Null && mRun<=mTokenPos); +} + +void SynEditCppHighlighter::setLine(const QString &newLine, int lineNumber) +{ + mLineString = newLine; + mLine = mLineString.data(); + mLineNumber = lineNumber; + mRun = 0; + next(); +} + +int SynEditCppHighlighter::getBraceLevel() const +{ + return mBraceLevel; +} + +int SynEditCppHighlighter::getBracketLevel() const +{ + return mBracketLevel; +} + +int SynEditCppHighlighter::getParenthesisLevel() const +{ + return mParenthesisLevel; +} + +bool SynEditCppHighlighter::isKeyword(const QString &word) +{ + return Keywords.contains(word); +} + +SynHighlighterTokenType SynEditCppHighlighter::getTokenType() +{ + switch(mTokenId) { + case TokenKind::Comment: + return SynHighlighterTokenType::Comment; + case TokenKind::Directive: + return SynHighlighterTokenType::PreprocessDirective; + case TokenKind::Identifier: + return SynHighlighterTokenType::Identifier; + case TokenKind::Key: + return SynHighlighterTokenType::Keyword; + case TokenKind::Space: + switch (mRange.state) { + case RangeState::rsAnsiC: + case RangeState::rsAnsiCAsm: + case RangeState::rsAnsiCAsmBlock: + case RangeState::rsAsm: + case RangeState::rsAsmBlock: + case RangeState::rsDirectiveComment: + case RangeState::rsCppComment: + return SynHighlighterTokenType::Comment; + case RangeState::rsDirective: + case RangeState::rsMultiLineDirective: + return SynHighlighterTokenType::PreprocessDirective; + case RangeState::rsString: + case RangeState::rsMultiLineString: + case RangeState::rsStringEscapeSeq: + case RangeState::rsMultiLineStringEscapeSeq: + case RangeState::rsRawString: + return SynHighlighterTokenType::String; + case RangeState::rsChar : + return SynHighlighterTokenType::Character; + default: + return SynHighlighterTokenType::Space; + } + case TokenKind::String: + return SynHighlighterTokenType::String; + case TokenKind::StringEscapeSeq: + return SynHighlighterTokenType::StringEscapeSequence; + case TokenKind::RawString: + return SynHighlighterTokenType::String; + case TokenKind::Char: + return SynHighlighterTokenType::Character; + case TokenKind::Symbol: + return SynHighlighterTokenType::Symbol; + default: + return SynHighlighterTokenType::Default; + } +} + +void SynEditCppHighlighter::setState(SynRangeState rangeState, int braceLevel, int bracketLevel, int parenthesisLevel) +{ + mRange = rangeState; + mBraceLevel = braceLevel; + mBracketLevel = bracketLevel; + mParenthesisLevel = parenthesisLevel; +} + +void SynEditCppHighlighter::resetState() +{ + mRange.state = RangeState::rsUnknown; + mRange.spaceState = RangeState::rsUnknown; + mBracketLevel = 0; + mBraceLevel = 0; + mParenthesisLevel = 0; +} diff --git a/RedPandaIDE/qsynedit/highlighter/cpp.h b/RedPandaIDE/qsynedit/highlighter/cpp.h new file mode 100644 index 00000000..ca0a008d --- /dev/null +++ b/RedPandaIDE/qsynedit/highlighter/cpp.h @@ -0,0 +1,204 @@ +#ifndef SYNEDITCPPHIGHLIGHTER_H +#define SYNEDITCPPHIGHLIGHTER_H +#include "base.h" +#include + +class SynEditCppHighlighter: public SynHighligterBase +{ + Q_OBJECT + + 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, 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 + }; + +public: + explicit SynEditCppHighlighter(QObject* parent = nullptr); + + PSynHighlighterAttribute asmAttribute() const; + + PSynHighlighterAttribute direcAttribute() const; + + PSynHighlighterAttribute invalidAttribute() const; + + PSynHighlighterAttribute keyAttribute() 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(); + +private: + bool mAsmStart; + SynRangeState mRange; +// SynRangeState mSpaceRange; + int mParenthesisLevel; + int mBracketLevel; + int mBraceLevel; + QString mLineString; + QChar* mLine; + int mLineSize; + int mRun; + int mStringLen; + int mToIdent; + int mTokenPos; + int mTokenId; + ExtTokenKind mExtTokenId; + int mLineNumber; + + PSynHighlighterAttribute mAsmAttribute; + PSynHighlighterAttribute mDirecAttribute; + PSynHighlighterAttribute mInvalidAttribute; + PSynHighlighterAttribute mKeyAttribute; + 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; + + // SynHighligterBase interface +public: + int getBraceLevel() const override; + int getBracketLevel() const override; + int getParenthesisLevel() const override; + + // SynHighligterBase interface +public: + bool isKeyword(const QString &word) override; + + // SynHighligterBase interface +public: + SynHighlighterTokenType getTokenType() override; + + // SynHighligterBase interface +public: + void setState(SynRangeState rangeState, int braceLevel, int bracketLevel, int parenthesisLevel) override; + + // SynHighligterBase interface +public: + void resetState() override; +}; + +#endif // SYNEDITCPPHIGHLIGHTER_H diff --git a/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp b/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp index c7b48cc1..bb9a7b76 100644 --- a/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp +++ b/RedPandaIDE/settingsdialog/compilersetdirectorieswidget.cpp @@ -40,7 +40,7 @@ Qt::ItemFlags CompilerSetDirectoriesWidget::ListModel::flags(const QModelIndex & Qt::ItemFlags flags = Qt::NoItemFlags; if (index.isValid()) { flags = Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable ; - } else if (index.row() ==-1) { + } else if (index.row() == -1) { // -1 means it's a drop target? flags = Qt::ItemIsDropEnabled; } diff --git a/RedPandaIDE/widgets/issuestable.cpp b/RedPandaIDE/widgets/issuestable.cpp index 1914acf8..47927230 100644 --- a/RedPandaIDE/widgets/issuestable.cpp +++ b/RedPandaIDE/widgets/issuestable.cpp @@ -7,11 +7,10 @@ IssuesTable::IssuesTable(QWidget *parent): { mModel = new IssuesModel(this); this->setModel(mModel); - this->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed); this->horizontalHeader()->setSectionResizeMode(3,QHeaderView::Stretch); this->setColumnWidth(0,200); - this->setColumnWidth(1,60); - this->setColumnWidth(2,60); + this->setColumnWidth(1,45); + this->setColumnWidth(2,45); } @@ -62,11 +61,30 @@ void IssuesModel::setWarningColor(QColor color) mWarningColor = color; } +PCompileIssue IssuesModel::issue(int row) +{ + if (row<0 || row>=static_cast(mIssues.size())) { + return PCompileIssue(); + } + + return mIssues[row]; +} + void IssuesTable::addIssue(PCompileIssue issue) { mModel->addIssue(issue); } +PCompileIssue IssuesTable::issue(const QModelIndex &index) +{ + return issue(index.row()); +} + +PCompileIssue IssuesTable::issue(const int row) +{ + return mModel->issue(row); +} + void IssuesTable::clearIssues() { mModel->clearIssues(); diff --git a/RedPandaIDE/widgets/issuestable.h b/RedPandaIDE/widgets/issuestable.h index b2e40b43..f8f1c8a8 100644 --- a/RedPandaIDE/widgets/issuestable.h +++ b/RedPandaIDE/widgets/issuestable.h @@ -18,6 +18,7 @@ public slots: void setErrorColor(QColor color); void setWarningColor(QColor color); + PCompileIssue issue(int row); private: std::vector mIssues; QColor mErrorColor; @@ -48,6 +49,9 @@ public: public slots: void addIssue(PCompileIssue issue); + PCompileIssue issue(const QModelIndex& index); + PCompileIssue issue(const int row); + void clearIssues(); private: diff --git a/Red_Panda_CPP.pro b/Red_Panda_CPP.pro index ce9748e1..d6cfd288 100644 --- a/Red_Panda_CPP.pro +++ b/Red_Panda_CPP.pro @@ -1,5 +1,4 @@ TEMPLATE = subdirs SUBDIRS += \ - ../QScintilla/src/qscintilla.pro \ RedPandaIDE