work save

This commit is contained in:
royqh1979@gmail.com 2021-05-14 23:56:43 +08:00
parent 0049f4f1e1
commit fcd640b0e3
25 changed files with 7966 additions and 9 deletions

View File

@ -17,6 +17,17 @@ SOURCES += \
editorlist.cpp \
main.cpp \
mainwindow.cpp \
qsynedit/CodeFolding.cpp \
qsynedit/Constants.cpp \
qsynedit/KeyStrokes.cpp \
qsynedit/MiscClasses.cpp \
qsynedit/MiscProcs.cpp \
qsynedit/SynEdit.cpp \
qsynedit/TextBuffer.cpp \
qsynedit/TextPainter.cpp \
qsynedit/highlighter/base.cpp \
qsynedit/highlighter/composition.cpp \
qsynedit/highlighter/cpp.cpp \
settingsdialog/compilersetdirectorieswidget.cpp \
settingsdialog/compilersetoptionwidget.cpp \
settings.cpp \
@ -34,6 +45,18 @@ HEADERS += \
editor.h \
editorlist.h \
mainwindow.h \
qsynedit/CodeFolding.h \
qsynedit/Constants.h \
qsynedit/KeyStrokes.h \
qsynedit/MiscClasses.h \
qsynedit/MiscProcs.h \
qsynedit/SynEdit.h \
qsynedit/TextBuffer.h \
qsynedit/TextPainter.h \
qsynedit/Types.h \
qsynedit/highlighter/base.h \
qsynedit/highlighter/composition.h \
qsynedit/highlighter/cpp.h \
settingsdialog/compilersetdirectorieswidget.h \
settingsdialog/compilersetoptionwidget.h \
settings.h \
@ -61,9 +84,9 @@ 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
#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
#INCLUDEPATH += $$PWD/../../QScintilla/src
#DEPENDPATH += $$PWD/../../QScintilla/src

View File

@ -89,10 +89,10 @@ Editor::Editor(QWidget *parent, const QString& filename,
// SLOT(on_margin_clicked(int, int, Qt::KeyboardModifiers)));
//markers
markerDefine(QsciScintilla::CircledPlus, ErrorMarker);
setMarkerForegroundColor(QColor("BLACK"),ErrorMarker);
setMarkerBackgroundColor(QColor("RED"),ErrorMarker);
markerAdd(1,ErrorMarker);
// 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,

View File

@ -0,0 +1,112 @@
#include "CodeFolding.h"
#include "Constants.h"
int SynEditFoldRegions::count()
{
return fRegions.size();
}
int SynEditFoldRegions::add(bool addEnding, const QChar &openSymbol, const QChar &closeSymbol, const QString &highlight)
{
PSynEditFoldRegion region = std::make_shared<SynEditFoldRegion>();
region->addEnding = addEnding;
region->openSymbol = openSymbol;
region->closeSymbol = closeSymbol;
region->highlight = highlight;
fRegions.push_back(region);
}
PSynEditFoldRegion SynEditFoldRegions::get(int index)
{
return fRegions.at(index);
}
SynEditCodeFolding::SynEditCodeFolding():
indentGuides(true),
showCollapsedLine(true),
collapsedLineColor(QColor("black")),
folderBarLinesColor(QColor("black")),
indentGuidesColor("gray")
{
foldRegions.add(true,'{','}',SYNS_AttrSymbol);
}
bool SynEditFoldRange::parentCollapsed()
{
PSynEditFoldRange parentFold = parent;
// Find first parent that is collapsed
while (parentFold) {
if (parentFold->collapsed) {
return true;
}
parentFold = parentFold->parent;
}
return false;
}
void SynEditFoldRange::move(int count)
{
fromLine += count;
toLine += count;
}
SynEditFoldRange::SynEditFoldRange(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynEditFoldRegion aFoldRegion, int aToLine):
fromLine(aFromLine),
toLine(aToLine),
linesCollapsed(0),
collapsed(false),
allFoldRanges(aAllFold),
foldRegion(aFoldRegion),
hintMarkLeft(0),
parent(aParent)
{
subFoldRanges = std::make_shared<SynEditFoldRanges>();
}
PSynEditFoldRange SynEditFoldRanges::range(int index)
{
return mRanges[index];
}
void SynEditFoldRanges::clear()
{
mRanges.clear();
}
int SynEditFoldRanges::count()
{
return mRanges.size();
}
SynEditFoldRanges::SynEditFoldRanges()
{
}
PSynEditFoldRange SynEditFoldRanges::addByParts(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynEditFoldRegion aFoldRegion, int aToLine)
{
PSynEditFoldRange range=std::make_shared<SynEditFoldRange>(aParent,aAllFold, aFromLine,aFoldRegion,aToLine);
return range;
}
void SynEditFoldRanges::insert(int index, PSynEditFoldRange range)
{
mRanges.insert(index,range);
}
int SynEditFoldRanges::remove(int index)
{
mRanges.remove(index);
}
void SynEditFoldRanges::add(PSynEditFoldRange foldRange)
{
mRanges.push_back(foldRange);
}
PSynEditFoldRange SynEditFoldRanges::operator[](int index)
{
return mRanges[index];
}

View File

@ -0,0 +1,80 @@
#ifndef CODEFOLDING_H
#define CODEFOLDING_H
#include <QColor>
#include <vector>
#include <memory>
#include <QVector>
struct SynEditFoldRegion;
typedef std::shared_ptr<SynEditFoldRegion> PSynEditFoldRegion;
class SynEditFoldRegions {
private:
std::vector<PSynEditFoldRegion> fRegions;
public:
int count();
int add(bool addEnding, const QChar& openSymbol, const QChar& closeSymbol, const QString& highlight);
PSynEditFoldRegion get(int index);
};
typedef std::shared_ptr<SynEditFoldRegions> PSynFoldRegions;
struct SynEditFoldRegion {
bool addEnding;
SynEditFoldRegions subFoldRegions;
QChar openSymbol;
QChar closeSymbol;
QString highlight;
};
struct SynEditCodeFolding {
bool indentGuides;
bool showCollapsedLine;
QColor collapsedLineColor;
QColor folderBarLinesColor;
QColor indentGuidesColor;
SynEditFoldRegions foldRegions;
SynEditCodeFolding();
};
class SynEditFoldRange;
typedef std::shared_ptr<SynEditFoldRange> PSynEditFoldRange;
class SynEditFoldRanges;
typedef std::shared_ptr<SynEditFoldRanges> PSynEditFoldRanges;
class SynEditFoldRanges{
private:
QVector<PSynEditFoldRange> mRanges;
public:
PSynEditFoldRange range(int index);
void clear();
int count();
SynEditFoldRanges();
PSynEditFoldRange addByParts(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold,
int aFromLine, PSynEditFoldRegion aFoldRegion, int aToLine);
void insert(int index, PSynEditFoldRange range);
int remove(int index);
void add(PSynEditFoldRange foldRange);
PSynEditFoldRange operator[](int index);
};
// A single fold
class SynEditFoldRange {
public:
int fromLine; // Beginning line
int toLine; // End line
int linesCollapsed; // Number of collapsed lines
PSynEditFoldRanges subFoldRanges; // Sub fold ranges
bool collapsed; // Is collapsed?
PSynEditFoldRanges allFoldRanges;// TAllFoldRanges pointer
PSynEditFoldRegion foldRegion; // FoldRegion
int hintMarkLeft;
PSynEditFoldRange parent;
bool parentCollapsed();
void move(int count);
explicit SynEditFoldRange(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold,
int aFromLine, PSynEditFoldRegion aFoldRegion, int aToLine);
};
#endif // CODEFOLDING_H

View File

@ -0,0 +1,6 @@
#include "Constants.h"
const QSet<QChar> SynWordBreakChars{'.', ',', ';', ':',
'"', '\'', '!', '?', '[', ']', '(', ')', '{', '}', '^', '-', '=', '+',
'-', '*', '/', '\\', '|'};
const QChar SynTabChar('\t');
const QChar SynSpaceGlyph(' ');

View File

@ -0,0 +1,163 @@
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <QSet>
#include <QChar>
extern const QSet<QChar> SynWordBreakChars;
extern const QChar SynTabChar;
extern const QChar SynSpaceGlyph;
#define MAX_SCROLL 65535
#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

View File

@ -0,0 +1,243 @@
#include "KeyStrokes.h"
SynEditKeyStroke::SynEditKeyStroke()
{
mKey = 0;
mKeyModifiers = Qt::NoModifier;
mKey2 = 0;
mKeyModifiers2 = Qt::NoModifier;
mCommand = SynEditorCommand::ecNone;
}
QKeySequence SynEditKeyStroke::keySequence() const
{
if (mKey2 == 0) {
return QKeySequence(mKey + mKeyModifiers);
} else {
return QKeySequence(mKey + mKeyModifiers, mKey2+mKeyModifiers2);
}
}
void SynEditKeyStroke::setKeySequence(QKeySequence &keySequence)
{
if (keySequence.isEmpty()<=0)
return;
decodeKey(keySequence[0],mKey,mKeyModifiers);
if (keySequence.count()>1) {
decodeKey(keySequence[1],mKey2,mKeyModifiers2);
} else {
mKey2=0;
mKeyModifiers2=Qt::NoModifier;
}
}
int SynEditKeyStroke::key() const
{
return mKey;
}
void SynEditKeyStroke::setKey(int key)
{
mKey = key;
}
Qt::KeyboardModifiers SynEditKeyStroke::keyModifiers() const
{
return mKeyModifiers;
}
void SynEditKeyStroke::setKeyModifiers(const Qt::KeyboardModifiers &keyModifiers)
{
mKeyModifiers = keyModifiers;
}
int SynEditKeyStroke::key2() const
{
return mKey2;
}
void SynEditKeyStroke::setKey2(int key2)
{
mKey2 = key2;
}
Qt::KeyboardModifiers SynEditKeyStroke::keyModifiers2() const
{
return mKeyModifiers2;
}
void SynEditKeyStroke::setKeyModifiers2(const Qt::KeyboardModifiers &keyModifiers2)
{
mKeyModifiers2 = keyModifiers2;
}
SynEditorCommand SynEditKeyStroke::command() const
{
return mCommand;
}
void SynEditKeyStroke::setCommand(const SynEditorCommand &command)
{
mCommand = command;
}
SynKeyError::SynKeyError(const QString &reason):BaseError(reason)
{
}
PSynEditKeyStroke SynEditKeyStrokes::add(SynEditorCommand command, int key, Qt::KeyboardModifiers modifiers)
{
PSynEditKeyStroke keyStroke = std::make_shared<SynEditKeyStroke>();
keyStroke->setKey(key);
keyStroke->setKeyModifiers(modifiers);
keyStroke->setCommand(command);
}
PSynEditKeyStroke SynEditKeyStrokes::findCommand(SynEditorCommand command)
{
for (PSynEditKeyStroke& keyStroke:mList) {
if (keyStroke->command() == command)
return keyStroke;
}
return PSynEditKeyStroke();
}
PSynEditKeyStroke SynEditKeyStrokes::findKeycode(int key, Qt::KeyboardModifiers modifiers)
{
for (PSynEditKeyStroke& keyStroke:mList) {
if (keyStroke->key() == key && keyStroke->keyModifiers()==modifiers && keyStroke->key2()==0)
return keyStroke;
}
return PSynEditKeyStroke();
}
PSynEditKeyStroke SynEditKeyStrokes::findKeycode2(int key, Qt::KeyboardModifiers modifiers,
int key2, Qt::KeyboardModifiers modifiers2)
{
for (PSynEditKeyStroke& keyStroke:mList) {
if (keyStroke->key() == key && keyStroke->keyModifiers()==modifiers && keyStroke->key2()==key2
&& keyStroke->keyModifiers2() ==modifiers2)
return keyStroke;
}
return PSynEditKeyStroke();
}
PSynEditKeyStroke SynEditKeyStrokes::findKeySequence(const QKeySequence &keySeq)
{
switch (keySeq.count()) {
case 1: {
int key;
Qt::KeyboardModifiers modifiers;
decodeKey(keySeq[0],key,modifiers);
return findKeycode(key,modifiers);
}
case 2:
case 3:
case 4:
{
int key;
Qt::KeyboardModifiers modifiers;
int key2;
Qt::KeyboardModifiers modifiers2;
decodeKey(keySeq[0],key,modifiers);
decodeKey(keySeq[1],key2,modifiers2);
return findKeycode2(key,modifiers,key2,modifiers2);
}
default:
return PSynEditKeyStroke();
}
}
void SynEditKeyStrokes::clear()
{
return mList.clear();
}
void SynEditKeyStrokes::resetDefaults()
{
clear();
add(SynEditorCommand::ecUp, Qt::Key_Up, Qt::NoModifier);
add(SynEditorCommand::ecSelUp, Qt::Key_Up, Qt::ShiftModifier);
add(SynEditorCommand::ecScrollUp, Qt::Key_Up, Qt::ControlModifier);
add(SynEditorCommand::ecDown, Qt::Key_Down, Qt::NoModifier);
add(SynEditorCommand::ecSelDown, Qt::Key_Down, Qt::ShiftModifier);
add(SynEditorCommand::ecScrollDown, Qt::Key_Down, Qt::ControlModifier);
add(SynEditorCommand::ecLeft, Qt::Key_Left, Qt::NoModifier);
add(SynEditorCommand::ecSelLeft, Qt::Key_Left, Qt::ShiftModifier);
add(SynEditorCommand::ecWordLeft, Qt::Key_Left, Qt::ControlModifier);
add(SynEditorCommand::ecSelWordLeft, Qt::Key_Left, Qt::ShiftModifier|Qt::ControlModifier);
add(SynEditorCommand::ecRight, Qt::Key_Right, Qt::NoModifier);
add(SynEditorCommand::ecSelRight, Qt::Key_Right, Qt::ShiftModifier);
add(SynEditorCommand::ecWordRight, Qt::Key_Right, Qt::ControlModifier);
add(SynEditorCommand::ecSelWordRight, Qt::Key_Right, Qt::ShiftModifier|Qt::ControlModifier);
add(SynEditorCommand::ecPageDown, Qt::Key_PageDown, Qt::NoModifier);
add(SynEditorCommand::ecSelPageDown, Qt::Key_PageDown, Qt::ShiftModifier);
add(SynEditorCommand::ecPageBottom, Qt::Key_PageDown, Qt::ControlModifier);
add(SynEditorCommand::ecSelPageBottom, Qt::Key_PageDown, Qt::ShiftModifier|Qt::ControlModifier);
add(SynEditorCommand::ecPageUp, Qt::Key_PageUp, Qt::NoModifier);
add(SynEditorCommand::ecSelPageUp, Qt::Key_PageUp, Qt::ShiftModifier);
add(SynEditorCommand::ecPageTop, Qt::Key_PageUp, Qt::ControlModifier);
add(SynEditorCommand::ecSelPageTop, Qt::Key_PageUp, Qt::ShiftModifier|Qt::ControlModifier);
add(SynEditorCommand::ecLineStart, Qt::Key_Home, Qt::NoModifier);
add(SynEditorCommand::ecSelLineStart, Qt::Key_Home, Qt::ShiftModifier);
add(SynEditorCommand::ecEditorTop, Qt::Key_Home, Qt::ControlModifier);
add(SynEditorCommand::ecSelEditorTop, Qt::Key_Home, Qt::ShiftModifier|Qt::ControlModifier);
add(SynEditorCommand::ecLineEnd, Qt::Key_End, Qt::NoModifier);
add(SynEditorCommand::ecSelLineEnd, Qt::Key_End, Qt::ShiftModifier);
add(SynEditorCommand::ecEditorBottom, Qt::Key_End, Qt::ControlModifier);
add(SynEditorCommand::ecSelEditorBottom, Qt::Key_End, Qt::ShiftModifier|Qt::ControlModifier);
add(SynEditorCommand::ecToggleMode, Qt::Key_Insert, Qt::ShiftModifier);
add(SynEditorCommand::ecCopy, Qt::Key_Insert, Qt::ControlModifier);
add(SynEditorCommand::ecCut, Qt::Key_Delete, Qt::ShiftModifier);
add(SynEditorCommand::ecPaste, Qt::Key_Insert, Qt::ShiftModifier);
add(SynEditorCommand::ecDeleteChar, Qt::Key_Delete, Qt::NoModifier);
add(SynEditorCommand::ecDeleteLastChar, Qt::Key_Backspace, Qt::NoModifier);
add(SynEditorCommand::ecDeleteLastChar, Qt::Key_Backspace, Qt::ShiftModifier);
add(SynEditorCommand::ecDeleteLastWord, Qt::Key_Backspace, Qt::ControlModifier);
add(SynEditorCommand::ecUndo, Qt::Key_Backspace, Qt::AltModifier);
add(SynEditorCommand::ecRedo, Qt::Key_Backspace, Qt::AltModifier|Qt::ShiftModifier);
add(SynEditorCommand::ecLineBreak, Qt::Key_Return, Qt::NoModifier);
add(SynEditorCommand::ecLineBreak, Qt::Key_Return, Qt::ShiftModifier);
add(SynEditorCommand::ecTab, Qt::Key_Tab, Qt::NoModifier);
add(SynEditorCommand::ecShiftTab, Qt::Key_Tab, Qt::ShiftModifier);
add(SynEditorCommand::ecContextHelp, Qt::Key_F1, Qt::NoModifier);
add(SynEditorCommand::ecSelectAll, Qt::Key_A, Qt::ControlModifier);
add(SynEditorCommand::ecCopy, Qt::Key_C, Qt::ControlModifier);
add(SynEditorCommand::ecPaste, Qt::Key_V, Qt::ControlModifier);
add(SynEditorCommand::ecCut, Qt::Key_X, Qt::ControlModifier);
add(SynEditorCommand::ecBlockIndent, Qt::Key_I, Qt::ControlModifier|Qt::ShiftModifier);
add(SynEditorCommand::ecBlockUnindent, Qt::Key_U, Qt::ControlModifier|Qt::ShiftModifier);
add(SynEditorCommand::ecLineBreak, Qt::Key_M, Qt::ControlModifier);
add(SynEditorCommand::ecInsertLine, Qt::Key_N, Qt::ControlModifier);
add(SynEditorCommand::ecDeleteWord, Qt::Key_T, Qt::ControlModifier);
add(SynEditorCommand::ecDeleteLine, Qt::Key_Y, Qt::ControlModifier);
add(SynEditorCommand::ecDeleteEOL, Qt::Key_Y, Qt::ControlModifier|Qt::ShiftModifier);
add(SynEditorCommand::ecUndo, Qt::Key_Z, Qt::ControlModifier);
add(SynEditorCommand::ecRedo, Qt::Key_Z, Qt::ControlModifier|Qt::ShiftModifier);
add(SynEditorCommand::ecGotoMarker0, Qt::Key_0, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker1, Qt::Key_1, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker2, Qt::Key_2, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker3, Qt::Key_3, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker4, Qt::Key_4, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker5, Qt::Key_5, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker6, Qt::Key_6, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker7, Qt::Key_7, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker8, Qt::Key_8, Qt::ControlModifier);
add(SynEditorCommand::ecGotoMarker9, Qt::Key_9, Qt::ControlModifier);
add(SynEditorCommand::ecSetMarker0, Qt::Key_0, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker1, Qt::Key_1, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker2, Qt::Key_2, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker3, Qt::Key_3, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker4, Qt::Key_4, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker5, Qt::Key_5, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker6, Qt::Key_6, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker7, Qt::Key_7, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker8, Qt::Key_8, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecSetMarker9, Qt::Key_9, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecNormalSelect, Qt::Key_N, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecColumnSelect, Qt::Key_C, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecLineSelect, Qt::Key_L, Qt::ControlModifier | Qt::ShiftModifier);
add(SynEditorCommand::ecMatchBracket, Qt::Key_B, Qt::ControlModifier | Qt::ShiftModifier);
}

View File

@ -0,0 +1,225 @@
#ifndef SYNEDITKEYSTROKE_H
#define SYNEDITKEYSTROKE_H
#include "../utils.h"
#include <QKeySequence>
#include <QList>
#include <memory>
//****************************************************************************
// NOTE! If you add an editor command, you must also update the
// EditorCommandStrs constant array in implementation section below, or the
// command will not show up in the IDE.
//****************************************************************************
// "Editor Commands". Key strokes are translated from a table into these
// I used constants instead of a set so that additional commands could be
// added in descendants (you can't extend a set)
// There are two ranges of editor commands: the ecViewXXX commands are always
// valid, while the ecEditXXX commands are ignored when the editor is in
// read-only mode
enum class SynEditorCommand {
ecNone = 0, // Nothing. Useful for user event to handle command
ecViewCommandFirst = 0,
ecViewCommandLast = 500,
ecEditCommandFirst = 501,
ecEditCommandLast = 1000,
ecLeft = 1, // Move cursor left one char
ecRight = 2, // Move cursor right one char
ecUp = 3, // Move cursor up one line
ecDown = 4, // Move cursor down one line
ecWordLeft = 5, // Move cursor left one word
ecWordRight = 6, // Move cursor right one word
ecLineStart = 7, // Move cursor to beginning of line
ecLineEnd = 8, // Move cursor to end of line
ecPageUp = 9, // Move cursor up one page
ecPageDown = 10, // Move cursor down one page
ecPageLeft = 11, // Move cursor right one page
ecPageRight = 12, // Move cursor left one page
ecPageTop = 13, // Move cursor to top of page
ecPageBottom = 14, // Move cursor to bottom of page
ecEditorTop = 15, // Move cursor to absolute beginning
ecEditorBottom = 16, // Move cursor to absolute end
ecGotoXY = 17, // Move cursor to specific coordinates, Data = PPoint
//******************************************************************************
// Maybe the command processor should just take a boolean that signifies if
// selection is affected or not?
//******************************************************************************
ecSelection = 100, // Add this to ecXXX command to get equivalent
// command, but with selection enabled. This is not
// a command itself.
// Same as commands above, except they affect selection, too
ecSelLeft = ecLeft + ecSelection,
ecSelRight = ecRight + ecSelection,
ecSelUp = ecUp + ecSelection,
ecSelDown = ecDown + ecSelection,
ecSelWordLeft = ecWordLeft + ecSelection,
ecSelWordRight = ecWordRight + ecSelection,
ecSelLineStart = ecLineStart + ecSelection,
ecSelLineEnd = ecLineEnd + ecSelection,
ecSelPageUp = ecPageUp + ecSelection,
ecSelPageDown = ecPageDown + ecSelection,
ecSelPageLeft = ecPageLeft + ecSelection,
ecSelPageRight = ecPageRight + ecSelection,
ecSelPageTop = ecPageTop + ecSelection,
ecSelPageBottom = ecPageBottom + ecSelection,
ecSelEditorTop = ecEditorTop + ecSelection,
ecSelEditorBottom = ecEditorBottom + ecSelection,
ecSelGotoXY = ecGotoXY + ecSelection, // Data = PPoint
ecSelWord = 198,
ecSelectAll = 199, // Select entire contents of editor, cursor to end
ecCopy = 201, // Copy selection to clipboard
ecScrollUp = 211, // Scroll up one line leaving cursor position unchanged.
ecScrollDown = 212, // Scroll down one line leaving cursor position unchanged.
ecScrollLeft = 213, // Scroll left one char leaving cursor position unchanged.
ecScrollRight = 214, // Scroll right one char leaving cursor position unchanged.
ecInsertMode = 221, // Set insert mode
ecOverwriteMode = 222, // Set overwrite mode
ecToggleMode = 223, // Toggle ins/ovr mode
ecNormalSelect = 231, // Normal selection mode
ecColumnSelect = 232, // Column selection mode
ecLineSelect = 233, // Line selection mode
ecMatchBracket = 250, // Go to matching bracket
ecGotoMarker0 = 301, // Goto marker
ecGotoMarker1 = 302, // Goto marker
ecGotoMarker2 = 303, // Goto marker
ecGotoMarker3 = 304, // Goto marker
ecGotoMarker4 = 305, // Goto marker
ecGotoMarker5 = 306, // Goto marker
ecGotoMarker6 = 307, // Goto marker
ecGotoMarker7 = 308, // Goto marker
ecGotoMarker8 = 309, // Goto marker
ecGotoMarker9 = 310, // Goto marker
ecSetMarker0 = 351, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker1 = 352, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker2 = 353, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker3 = 354, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker4 = 355, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker5 = 356, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker6 = 357, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker7 = 358, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker8 = 359, // Set marker, Data = PPoint - X, Y Pos
ecSetMarker9 = 360, // Set marker, Data = PPoint - X, Y Pos
ecGotFocus = 480,
ecLostFocus = 481,
ecContextHelp = 490, // Help on Word, Data = Word
ecDeleteLastChar = 501, // Delete last char (i.e. backspace key)
ecDeleteChar = 502, // Delete char at cursor (i.e. delete key)
ecDeleteWord = 503, // Delete from cursor to end of word
ecDeleteLastWord = 504, // Delete from cursor to start of word
ecDeleteBOL = 505, // Delete from cursor to beginning of line
ecDeleteEOL = 506, // Delete from cursor to end of line
ecDeleteLine = 507, // Delete current line
ecClearAll = 508, // Delete everything
ecLineBreak = 509, // Break line at current position, move caret to new line
ecInsertLine = 510, // Break line at current position, leave caret
ecChar = 511, // Insert a character at current position
ecDuplicateLine = 512, // Duplicate current line
ecMoveSelUp = 513, // Move selection up
ecMoveSelDown = 514, // Move selection down
ecImeStr = 550, // Insert character(s) from IME
ecUndo = 601, // Perform undo if available
ecRedo = 602, // Perform redo if available
ecCut = 603, // Cut selection to clipboard
ecPaste = 604, // Paste clipboard to current position
ecBlockIndent = 610, // Indent selection
ecBlockUnindent = 611, // Unindent selection
ecTab = 612, // Tab key
ecShiftTab = 613, // Shift+Tab key
ecComment = 614,
ecUncomment = 615,
ecToggleComment = 616,
ecCommentInline = 617,
ecAutoCompletion = 650,
ecUpperCase = 620, // apply to the current or previous word
ecLowerCase = 621,
ecToggleCase = 622,
ecTitleCase = 623,
ecUpperCaseBlock = 625, // apply to current selection, or current char if no selection
ecLowerCaseBlock = 626,
ecToggleCaseBlock = 627,
ecString = 630, //Insert a whole string
ecUserFirst = 1001, // Start of user-defined commands
//### Code Folding ###
ecCollapse = ecUserFirst + 100,
ecUncollapse = ecUserFirst + 101,
ecCollapseLevel = ecUserFirst + 102,
ecUncollapseLevel = ecUserFirst + 103,
ecCollapseAll = ecUserFirst + 104,
ecUncollapseAll = ecUserFirst + 105,
//### End Code Folding ###
};
class SynKeyError: public BaseError {
public:
explicit SynKeyError(const QString& reason);
};
class SynEditKeyStroke
{
public:
explicit SynEditKeyStroke();
QKeySequence keySequence() const;
void setKeySequence(QKeySequence& keySequence);
int key() const;
void setKey(int key);
Qt::KeyboardModifiers keyModifiers() const;
void setKeyModifiers(const Qt::KeyboardModifiers &keyModifiers);
int key2() const;
void setKey2(int key2);
Qt::KeyboardModifiers keyModifiers2() const;
void setKeyModifiers2(const Qt::KeyboardModifiers &keyModifiers2);
SynEditorCommand command() const;
void setCommand(const SynEditorCommand &command);
private:
int mKey; // Virtual keycode, i.e. VK_xxx
Qt::KeyboardModifiers mKeyModifiers;
int mKey2;
Qt::KeyboardModifiers mKeyModifiers2;
SynEditorCommand mCommand;
};
using PSynEditKeyStroke = std::shared_ptr<SynEditKeyStroke>;
using SynEditKeyStrokeList = QList<PSynEditKeyStroke>;
class SynEditKeyStrokes {
public:
PSynEditKeyStroke add(SynEditorCommand command, int key, Qt::KeyboardModifiers modifiers);
PSynEditKeyStroke findCommand(SynEditorCommand command);
PSynEditKeyStroke findKeycode(int key, Qt::KeyboardModifiers modifiers);
PSynEditKeyStroke findKeycode2(int key, Qt::KeyboardModifiers modifiers,
int key2, Qt::KeyboardModifiers modifiers2);
PSynEditKeyStroke findKeySequence(const QKeySequence& keySeq);
void clear();
void resetDefaults();
SynEditKeyStrokeList mList;
};
#endif // SYNEDITKEYSTROKE_H

View File

@ -0,0 +1,480 @@
#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();
}
}
SynEditMark::SynEditMark(QObject *parent)
{
mBookmarkNum = -1;
}
int SynEditMark::Char() const
{
return mChar;
}
void SynEditMark::setChar(int value)
{
if (value != mChar) {
mChar = value;
}
}
int SynEditMark::image() const
{
return mImage;
}
void SynEditMark::setImage(int image)
{
if (mImage != image) {
mImage = image;
if (mVisible)
emit changed();
}
}
bool SynEditMark::visible() const
{
return mVisible;
}
void SynEditMark::setVisible(bool visible)
{
if (mVisible!=visible) {
mVisible = visible;
emit changed();
}
}
int SynEditMark::bookmarkNum() const
{
return mBookmarkNum;
}
void SynEditMark::setBookmarkNum(int bookmarkNum)
{
mBookmarkNum = bookmarkNum;
}
bool SynEditMark::internalImage() const
{
return mInternalImage;
}
void SynEditMark::setInternalImage(bool internalImage)
{
if (mInternalImage!=internalImage) {
mInternalImage = internalImage;
if (mVisible)
emit changed();
}
}
bool SynEditMark::isBookmark() const
{
return (mBookmarkNum>=0);
}
int SynEditMark::line() const
{
return mLine;
}
void SynEditMark::setLine(int line)
{
if (mLine!=line) {
if (mVisible && mLine>0)
emit changed();
mLine = line;
if (mVisible && mLine>0)
emit changed();
}
}
SynBookMarkOpt::SynBookMarkOpt(QObject *parent)
{
mDrawBookmarksFirst = true;
mEnableKeys = true;
mGlyphsVisible = true;
mLeftMargin = 2;
mXOffset = 12;
}
PSynIconList SynBookMarkOpt::bookmarkImages() const
{
return mBookmarkImages;
}
void SynBookMarkOpt::setBookmarkImages(const PSynIconList &images)
{
if (mBookmarkImages != images) {
mBookmarkImages = images;
emit changed();
}
}
bool SynBookMarkOpt::drawBookmarksFirst() const
{
return mDrawBookmarksFirst;
}
void SynBookMarkOpt::setDrawBookmarksFirst(bool drawBookmarksFirst)
{
if (mDrawBookmarksFirst != drawBookmarksFirst) {
mDrawBookmarksFirst = drawBookmarksFirst;
emit changed();
}
}
bool SynBookMarkOpt::enableKeys() const
{
return mEnableKeys;
}
void SynBookMarkOpt::setEnableKeys(bool enableKeys)
{
mEnableKeys = enableKeys;
}
bool SynBookMarkOpt::glyphsVisible() const
{
return mGlyphsVisible;
}
void SynBookMarkOpt::setGlyphsVisible(bool glyphsVisible)
{
if (mGlyphsVisible!=glyphsVisible) {
mGlyphsVisible = glyphsVisible;
emit changed();
}
}
int SynBookMarkOpt::leftMargin() const
{
return mLeftMargin;
}
void SynBookMarkOpt::setLeftMargin(int leftMargin)
{
if (leftMargin!=mLeftMargin) {
mLeftMargin = leftMargin;
emit changed();
}
}
int SynBookMarkOpt::xOffset() const
{
return mXOffset;
}
void SynBookMarkOpt::setXOffset(int xOffset)
{
if (mXOffset!=xOffset) {
mXOffset = xOffset;
emit changed();
}
}

View File

@ -0,0 +1,183 @@
#ifndef MISCCLASSES_H
#define MISCCLASSES_H
#include <QColor>
#include <QFont>
#include <QObject>
#include "Types.h"
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;
};
using PSynGutter = std::shared_ptr<SynGutter>;
class SynEditMark : public QObject {
Q_OBJECT
public:
explicit SynEditMark(QObject* parent = nullptr);
int Char() const;
void setChar(int value);
int image() const;
void setImage(int image);
bool visible() const;
void setVisible(bool visible);
int bookmarkNum() const;
void setBookmarkNum(int bookmarkNum);
bool internalImage() const;
void setInternalImage(bool internalImage);
bool isBookmark() const ;
int line() const;
void setLine(int line);
signals:
void changed();
protected:
int mLine;
int mChar;
int mImage;
bool mVisible;
bool mInternalImage;
int mBookmarkNum;
};
using PSynEditMark = std::shared_ptr<SynEditMark>;
using SynEditMarkList = QList<SynEditMark>;
using PSynEditMarkList = std::shared_ptr<SynEditMarkList>;
class SynBookMarkOpt: public QObject {
Q_OBJECT
public:
explicit SynBookMarkOpt(QObject* parent=nullptr);
PSynIconList bookmarkImages() const;
void setBookmarkImages(const PSynIconList &images);
bool drawBookmarksFirst() const;
void setDrawBookmarksFirst(bool drawBookmarksFirst);
bool enableKeys() const;
void setEnableKeys(bool enableKeys);
bool glyphsVisible() const;
void setGlyphsVisible(bool glyphsVisible);
int leftMargin() const;
void setLeftMargin(int leftMargin);
int xOffset() const;
void setXOffset(int xOffset);
signals:
void changed();
private:
PSynIconList mBookmarkImages;
bool mDrawBookmarksFirst;
bool mEnableKeys;
bool mGlyphsVisible;
int mLeftMargin;
int mXOffset;
};
using PSynBookMarkOpt = std::shared_ptr<SynBookMarkOpt>;
#endif // MISCCLASSES_H

View File

@ -0,0 +1,533 @@
#include "MiscProcs.h"
#include <QFile>
#include <QPainter>
#include <QTextStream>
#include <algorithm>
int MinMax(int x, int mi, int ma)
{
x = std::min(x, ma );
return std::max( x, mi );
}
void SwapInt(int &l, int &r)
{
int tmp = r;
r = l;
l = tmp;
}
QPoint MaxPoint(const QPoint &P1, const QPoint &P2)
{
if ( (P2.y() > P1.y()) || ( (P2.y() == P1.y()) && (P2.x() > P1.x())) ) {
return P2;
} else {
return P1;
}
}
QPoint MinPoint(const QPoint &P1, const QPoint &P2)
{
if ( (P2.y() < P1.y()) || ( (P2.y() == P1.y()) && (P2.x() < P1.x())) ) {
return P2;
} else {
return P1;
}
}
PIntArray GetIntArray(size_t Count, int InitialValue)
{
return std::make_shared<IntArray>(Count,InitialValue);
}
void InternalFillRect(QPainter *painter, const QRect &rcPaint, const QColor& color)
{
painter->fillRect(rcPaint,color);
}
bool IsPowerOfTwo(int TabWidth) {
if (TabWidth<2)
return false;
int nW = 2;
do {
if (nW >= TabWidth)
break;
nW <<= 1;
} while (nW<0x10000);
return (nW == TabWidth);
}
QString ConvertTabs1Ex(const QString &Line, int TabWidth, bool &HasTabs) {
QString Result = Line; // increment reference count only
int nBeforeTab;
if (GetHasTabs(Line, nBeforeTab)) {
QChar* pDest;
HasTabs = true;
pDest = Result.data()+nBeforeTab+1;
// this will make a copy of Line
// We have at least one tab in the string, and the tab width is 1.
// pDest points to the first tab char. We overwrite all tabs with spaces.
while (*pDest!=0) {
if (*pDest == '\t') {
*pDest = ' ';
};
pDest++;
}
} else
HasTabs = false;
return Result;
}
QString ConvertTabs1(const QString &Line, int TabWidth) {
bool HasTabs;
return ConvertTabs1Ex(Line, TabWidth, HasTabs);
}
QString ConvertTabs2nEx(const QString &Line, int TabWidth, bool &HasTabs) {
QString Result = Line; // increment reference count only
int DestLen;
if (GetHasTabs(Line, DestLen)) {
HasTabs = true;
int pSrc = 1 + DestLen;
// We have at least one tab in the string, and the tab width equals 2^n.
// pSrc points to the first tab char in Line. We get the number of tabs
// and the length of the expanded string now.
int TabCount = 0;
int TabMask = (TabWidth - 1) ^ 0x7FFFFFFF;
do {
if (Line[pSrc] == '\t') {
DestLen = (DestLen + TabWidth) & TabMask;
TabCount++;
} else
DestLen ++ ;
} while (pSrc < Line.length());
// Set the length of the expanded string.
Result.resize(DestLen);
DestLen = 0;
pSrc = 0;
QChar * pDest = Result.data();
// We use another TabMask here to get the difference to 2^n.
TabMask = TabWidth - 1;
do {
if (Line[pSrc] == '\t') {
int i = TabWidth - (DestLen & TabMask);
DestLen += i;
//This is used for both drawing and other stuff and is meant to be #9 and not #32
do {
*pDest = '\t';
pDest ++ ;
i--;
} while (i > 0);
TabCount -- ;
if (TabCount == 0) {
do {
pSrc++ ;
*pDest = Line[pSrc];
pDest++;
} while (pSrc < Line.length());
return Result;
}
} else {
*pDest = Line[pSrc];
pDest ++ ;
DestLen ++;
}
pSrc++;
} while (pSrc < Line.length());
} else
HasTabs = false;
return Result;
}
QString ConvertTabs2n(const QString &Line, int TabWidth) {
bool HasTabs;
return ConvertTabs2nEx(Line, TabWidth, HasTabs);
}
ConvertTabsProc GetBestConvertTabsProc(int TabWidth)
{
if (TabWidth < 2)
return &ConvertTabs1;
else if (IsPowerOfTwo(TabWidth))
return &ConvertTabs2n;
else
return &ConvertTabs;
}
QString ConvertTabs(const QString &Line, int TabWidth)
{
bool HasTabs;
return ConvertTabsEx(Line, TabWidth, HasTabs);
}
ConvertTabsProcEx GetBestConvertTabsProcEx(int TabWidth)
{
if (TabWidth < 2)
return &ConvertTabs1Ex;
else if (IsPowerOfTwo(TabWidth))
return &ConvertTabs2nEx;
else
return &ConvertTabsEx;
}
QString ConvertTabsEx(const QString &Line, int TabWidth, bool &HasTabs)
{
QString Result = Line; // increment reference count only
int DestLen;
int pSrc;
QChar* pDest;
if (GetHasTabs(Line, DestLen)) {
HasTabs = true;
pSrc = (DestLen+1);
// We have at least one tab in the string, and the tab width is greater
// than 1. pSrc points to the first tab char in Line. We get the number
// of tabs and the length of the expanded string now.
int TabCount = 0;
do {
if (Line[pSrc] == '\t') {
DestLen = DestLen + TabWidth - DestLen % TabWidth;
TabCount++;
} else {
DestLen ++;
}
pSrc++;
} while (pSrc<Line.length());
// Set the length of the expanded string.
Result.resize(DestLen);
DestLen = 0;
pSrc = 0;
pDest = Result.data();
do {
if (Line[pSrc] == '\t') {
int i = TabWidth - (DestLen % TabWidth);
DestLen+=i;
do {
*pDest = '\t';
pDest++;
i--;
} while (i != 0);
TabCount--;
if (TabCount == 0) {
do {
pSrc++;
*pDest = Line[pSrc];
pDest++;
} while (pSrc<Line.length());
return Result;
}
} else {
*pDest = Line[pSrc];
pDest++;
DestLen++;
}
pSrc++;
} while (pSrc<Line.length());
} else
HasTabs = false;
return Result;
}
bool GetHasTabs(const QString &line, int &CharsBefore)
{
bool result = false;
CharsBefore = 0;
if (!line.isEmpty()) {
for (const QChar& ch:line) {
if (ch == '\t') {
result = true;
break;
}
CharsBefore ++;
}
}
return result;
}
int GetExpandedLength(const QString &aStr, int aTabWidth)
{
int Result = 0;
for (const QChar& ch : aStr) {
if (ch == '\t') {
Result += aTabWidth - (Result % aTabWidth);
} else {
Result ++;
}
}
return Result;
}
int CharIndex2CaretPos(int Index, int TabWidth, const QString &Line)
{
int Result;
int iChar;
if (Index > 1) {
if ((TabWidth <= 1) || !GetHasTabs(Line, iChar) ) {
Result = Index;
} else {
if (iChar + 1 >= Index) {
Result = Index;
} else {
// iChar is number of chars before first Tab
Result = iChar;
// Index is *not* zero-based
iChar++;
Index -= iChar;
int pNext = iChar;
while (Index > 0) {
if (pNext>=Line.length()) {
Result += Index;
break;
}
if (Line[pNext] == '\t') {
Result += TabWidth;
Result -= Result % TabWidth;
} else
Result++;
Index--;
pNext++;
}
// done with zero-based computation
Result++;
}
}
} else
Result = 1;
return Result;
}
int CaretPos2CharIndex(int Position, int TabWidth, const QString &Line, bool &InsideTabChar)
{
int Result;
int iPos;
InsideTabChar = false;
if (Position > 1) {
if ( (TabWidth <= 1) || !GetHasTabs(Line, iPos) ) {
Result = Position;
} else {
if (iPos + 1 >= Position) {
Result = Position;
} else {
// iPos is number of chars before first #9
Result = iPos + 1;
int pNext = Result;
// for easier computation go zero-based (mod-operation)
Position -=1;
while (iPos < Position) {
if (pNext>=Line.length())
break;
if (Line[pNext] == '\t') {
iPos+=TabWidth;
iPos-=iPos % TabWidth;
if (iPos > Position) {
InsideTabChar = true;
break;
}
} else
iPos++;
Result++;
pNext++;
}
}
}
} else
Result = Position;
return Result;
}
int StrScanForCharInSet(const QString &Line, int Start, const QSet<QChar>& AChars)
{
for (int i=Start;i<Line.length();i++) {
if (AChars.contains(Line[i])) {
return i;
}
}
return -1;
}
int StrRScanForCharInSet(const QString &Line, int Start, const QSet<QChar> &AChars)
{
for (int i=Line.size()-1;i>=Start;i--) {
if (AChars.contains(Line[i])) {
return i;
}
}
return -1;
}
int GetEOL(const QString &Line, int start)
{
if (start<0 || start>=Line.size()) {
return start;
}
for (int i=start;i<Line.size();i++) {
if (Line[i] == '\n' || Line[i] == '\r') {
return i;
}
}
return Line.size();
}
QString EncodeString(const QString &s)
{
QString Result;
Result.resize(s.length()*2); // worst case
int j=0;
for (const QChar& ch: s) {
if (ch == '\\' ) {
Result[j] = '\\';
Result[j+1] = '\\';
j+=2;
} else if (ch == '/') {
Result[j] = '\\';
Result[j+1] = '.';
j+=2;
} else {
Result[j]=ch;
j+=1;
}
}
Result.resize(j);
return Result;
}
QString DecodeString(const QString &s)
{
QString Result;
Result.resize(s.length()); // worst case
int j = 0;
int i = 0;
while (i < s.length()) {
if (i<s.length()-1 && s[i] == '\\' ) {
if (s[i+1] == '\\') {
Result[j]= '\\';
i+=2;
j+=1;
continue;
} else if (s[i+1] == '.') {
Result[j]= '/';
i+=2;
j+=1;
continue;
}
}
Result[j] = Result[i];
i+=1;
j+=1;
}
Result.resize(j);
return Result;
}
bool InternalEnumHighlighterAttris(PSynHighlighter Highlighter,
bool SkipDuplicates,
HighlighterAttriProc highlighterAttriProc,
std::initializer_list<void *>& Params,
SynHighlighterList& HighlighterList) {
bool Result = true;
if (HighlighterList.indexOf(Highlighter)>0) {
if (SkipDuplicates)
return Result;
} else {
HighlighterList.append(Highlighter);
}
if (Highlighter->getClass() == SynHighlighterClass::Composition) {
//todo: handle composition highlighter
} else if (Highlighter) {
for (PSynHighlighterAttribute pAttr: Highlighter->attributes()){
QString UniqueAttriName = Highlighter->getName()
+ HighlighterList.indexOf(Highlighter) + '.'
+ pAttr->name();
Result = highlighterAttriProc(Highlighter, pAttr,
UniqueAttriName, Params);
if (!Result)
break;
}
}
return Result;
}
bool EnumHighlighterAttris(PSynHighlighter Highlighter, bool SkipDuplicates,
HighlighterAttriProc highlighterAttriProc,
std::initializer_list<void *> Params)
{
if (!Highlighter || !highlighterAttriProc) {
return false;
}
SynHighlighterList HighlighterList;
return InternalEnumHighlighterAttris(Highlighter, SkipDuplicates,
highlighterAttriProc, Params, HighlighterList);
}
uint16_t fcstab[] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
uint16_t CalcFCS(unsigned char *ABuf, int ABufSize)
{
uint16_t CurFCS = 0xffff;
unsigned char* P = ABuf;
while (ABufSize>0) {
CurFCS = (CurFCS >> 8) ^ fcstab[(CurFCS ^ *P) & 0xff];
ABufSize -- ;
P ++ ;
}
return CurFCS;
}
void SynDrawGradient(QPaintDevice *ACanvas, const QColor &AStartColor, const QColor &AEndColor, int , const QRect &ARect, bool AHorizontal)
{
QPainter painter(ACanvas);
if (AHorizontal) {
int Size = ARect.right() - ARect.left();
QLinearGradient gradient(0,0,Size,0);
gradient.setColorAt(0,AStartColor);
gradient.setColorAt(1,AEndColor);
painter.fillRect(ARect,gradient);
} else {
int Size = ARect.bottom() - ARect.top();
QLinearGradient gradient(0,0,0,Size);
gradient.setColorAt(0,AStartColor);
gradient.setColorAt(1,AEndColor);
painter.fillRect(ARect,gradient);
}
}
int MulDiv(int a, int b, int c)
{
//todo: handle overflow?
return a*b/c;
}

View File

@ -0,0 +1,90 @@
#ifndef MISCPROCS_H
#define MISCPROCS_H
#include <QPoint>
#include <vector>
#include <memory>
#include <QString>
#include <QSet>
#include "highlighter/base.h"
#include <QPaintDevice>
#include <QTextStream>
#include <QVector>
#include <initializer_list>
//#include <QRect>
//#include <QColor>
class QPainter;
class QRect;
class QColor;
using IntArray = QVector<int>;
using PIntArray = std::shared_ptr<IntArray>;
int MinMax(int x, int mi, int ma);
int MulDiv(int a, int b, int c);
void SwapInt(int& l, int &r);
QPoint MaxPoint(const QPoint& P1, const QPoint& P2);
QPoint MinPoint(const QPoint& P1, const QPoint& P2);
PIntArray GetIntArray(size_t Count, int InitialValue);
void InternalFillRect(QPainter* painter, const QRect& rcPaint, const QColor& color);
// Converting tabs to spaces: To use the function several times it's better
// to use a function pointer that is set to the fastest conversion function.
using ConvertTabsProc = std::function<QString(const QString&, int)>;
ConvertTabsProc GetBestConvertTabsProc(int TabWidth);
// This is the slowest conversion function which can handle TabWidth <> 2^n.
QString ConvertTabs(const QString& Line, int TabWidth);
using ConvertTabsProcEx = std::function<QString(const QString&, int, bool& )>;
ConvertTabsProcEx GetBestConvertTabsProcEx(int TabWidth);
// This is the slowest conversion function which can handle TabWidth <> 2^n.
QString ConvertTabsEx(const QString& Line, int TabWidth, bool& HasTabs);
bool GetHasTabs(const QString& line, int& CharsBefore);
int GetExpandedLength(const QString& aStr, int aTabWidth);
int CharIndex2CaretPos(int Index, int TabWidth,
const QString& Line);
int CaretPos2CharIndex(int Position, int TabWidth, const QString& Line,
bool& InsideTabChar);
// search for the first char of set AChars in Line, starting at index Start
int StrScanForCharInSet(const QString& Line, int Start, const QSet<QChar>& AChars);
// the same, but searching backwards
int StrRScanForCharInSet(const QString& Line, int Start, const QSet<QChar>& AChars);
int GetEOL(const QString& Line, int start);
// Remove all '/' characters from string by changing them into '\.'.
// Change all '\' characters into '\\' to allow for unique decoding.
QString EncodeString(const QString & s);
// Decodes string, encoded with EncodeString.
QString DecodeString(const QString& s);
using HighlighterAttriProc = std::function<bool(PSynHighlighter Highlighter,
PSynHighlighterAttribute Attri, const QString& UniqueAttriName,
std::initializer_list<void *> Params)>;
// Enums all child highlighters and their attributes of a TSynMultiSyn through a
// callback function.
// This function also handles nested TSynMultiSyns including their MarkerAttri.
bool EnumHighlighterAttris(PSynHighlighter Highlighter,
bool SkipDuplicates, HighlighterAttriProc highlighterAttriProc,
std::initializer_list<void *> Params);
// Calculates Frame Check Sequence (FCS) 16-bit Checksum (as defined in RFC 1171)
uint16_t CalcFCS(unsigned char* ABuf, int ABufSize);
void SynDrawGradient(QPaintDevice* ACanvas, const QColor& AStartColor, const QColor& AEndColor,
int ASteps, const QRect& ARect, bool AHorizontal);
#endif // MISCPROCS_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,426 @@
#ifndef SYNEDIT_H
#define SYNEDIT_H
#include <QAbstractScrollArea>
#include <QCursor>
#include <QDateTime>
#include <QFrame>
#include <QStringList>
#include <QTimer>
#include <QWidget>
#include "MiscClasses.h"
#include "CodeFolding.h"
#include "Types.h"
#include "TextBuffer.h"
#include "KeyStrokes.h"
enum class SynFontSmoothMethod {
None, AntiAlias, ClearType
};
enum class SynScrollHintFormat {
shfTopLineOnly, shfTopToBottom
};
enum class SynScrollStyle {
ssNone, ssHorizontal, ssVertical, ssBoth
};
enum class SynEditCaretType {
ctVerticalLine, ctHorizontalLine, ctHalfBlock, ctBlock
};
enum class SynStatusChange {
scNone = 0,
scAll = 0x0001,
scCaretX = 0x0002,
scCaretY = 0x0004,
scLeftChar = 0x0008,
scTopLine = 0x0010,
scInsertMode = 0x0020,
scModified = 0x0040,
scSelection = 0x0080,
scReadOnly = 0x0100,
scOpenFile = 0x0200
};
Q_DECLARE_FLAGS(SynStatusChanges, SynStatusChange)
Q_DECLARE_OPERATORS_FOR_FLAGS(SynStatusChanges)
enum class SynStateFlag {
sfCaretChanged = 0x0001,
sfScrollbarChanged = 0x0002,
sfLinesChanging = 0x0004,
sfIgnoreNextChar = 0x0008,
sfCaretVisible = 0x0010,
sfDblClicked = 0x0020,
sfWaitForDragging = 0x0040
};
Q_DECLARE_FLAGS(SynStateFlags,SynStateFlag)
Q_DECLARE_OPERATORS_FOR_FLAGS(SynStateFlags)
enum SynEditorOption {
eoAltSetsColumnMode = 0x00000001, //Holding down the Alt Key will put the selection mode into columnar format
eoAutoIndent = 0x00000002, //Will indent the caret on new lines with the same amount of leading white space as the preceding line
eoAddIndent = 0x00000004, //Will add one tab width of indent when typing { and :, and remove the same amount when typing }
eoAutoSizeMaxScrollWidth = 0x00000008, //Automatically resizes the MaxScrollWidth property when inserting text
//eoDisableScrollArrows = 0x00000010 , //Disables the scroll bar arrow buttons when you can't scroll in that direction any more
eoDragDropEditing = 0x00000020, //Allows you to select a block of text and drag it within the document to another location
eoDropFiles = 0x00000040, //Allows the editor accept OLE file drops
eoEnhanceHomeKey = 0x00000080, //enhances home key positioning, similar to visual studio
eoEnhanceEndKey = 0x00000100, //enhances End key positioning, similar to JDeveloper
eoGroupUndo = 0x00000200, //When undoing/redoing actions, handle all continous changes of the same kind in one call instead undoing/redoing each command separately
eoHalfPageScroll = 0x00000400, //When scrolling with page-up and page-down commands, only scroll a half page at a time
eoHideShowScrollbars = 0x00000800, //if enabled, then the scrollbars will only show when necessary. If you have ScrollPastEOL, then it the horizontal bar will always be there (it uses MaxLength instead)
eoKeepCaretX = 0x00001000 , //When moving through lines w/o Cursor Past EOL, keeps the X position of the cursor
eoNoCaret = 0x00002000, //Makes it so the caret is never visible
eoNoSelection = 0x00004000, //Disables selecting text
eoRightMouseMovesCursor = 0x00008000, //When clicking with the right mouse for a popup menu, move the cursor to that location
eoScrollByOneLess = 0x00010000, //Forces scrolling to be one less
eoScrollHintFollows = 0x00020000, //The scroll hint follows the mouse when scrolling vertically
eoScrollPastEof = 0x00040000, //Allows the cursor to go past the end of file marker
eoScrollPastEol = 0x00080000, //Allows the cursor to go past the last character into the white space at the end of a line
eoShowScrollHint = 0x00100000, //Shows a hint of the visible line numbers when scrolling vertically
eoShowSpecialChars = 0x00200000, //Shows the special Characters
eoSmartTabDelete = 0x00400000, //similar to Smart Tabs, but when you delete characters
eoSmartTabs = 0x00800000, //When tabbing, the cursor will go to the next non-white space character of the previous line
eoSpecialLineDefaultFg = 0x01000000, //disables the foreground text color override when using the OnSpecialLineColor event
eoTabIndent = 0x02000000, //When active <Tab> and <Shift><Tab> act as block indent, unindent when text is selected
eoTabsToSpaces = 0x04000000, //Converts a tab character to a specified number of space characters
eoShowRainbowColor = 0x08000000,
eoTrimTrailingSpaces = 0x10000000 //Spaces at the end of lines will be trimmed and not saved
};
Q_DECLARE_FLAGS(SynEditorOptions, SynEditorOption)
Q_DECLARE_OPERATORS_FOR_FLAGS(SynEditorOptions)
enum class SynReplaceAction {
raCancel, raSkip, raReplace, raReplaceAll
};
struct SynEditingArea {
int beginX;
int endX;
QColor color;
};
using PSynEditingArea = std::shared_ptr<SynEditingArea>;
using SynEditingAreaList = QList<PSynEditingArea>;
enum class SynEditingAreaType {
eatRectangleBorder,
eatWaveUnderLine,
eatUnderLine
};
enum class SynTransientType {
ttBefore, ttAfter
};
enum class SynScrollBarKind {
sbHorizontal, sbVertical
};
/*
using SynPaintTransientProc = std::function<void(const QPaintDevice& paintDevice,
SynTransientType transientType)>;
*/
using SynPlaceMarkProc = std::function<void(PSynEditMark& Mark)>;
using SynProcessCommandProc = std::function<void(SynEditorCommand& command, QChar& AChar, void* data)>;
using SynMouseCursorProc = std::function<void(const BufferCoord& aLineCharPos, QCursor & aCursor)>;
using SynPaintProc = std::function<void(const QPaintDevice& paintDevice )>;
using SynPreparePaintHighlightTokenProc = std::function<void(int row,
int column, const QString& token, PSynHighlighterAttribute attr,
SynFontStyles& style, QColor& foreground, QColor& background)>;
using SynReplaceTextProc = std::function<void(const QString& ASearch, const QString& AReplace,
int Line, int Column, int wordLen, SynReplaceAction& action)>;
using SynSpecialLineColorsProc = std::function<void(int Line,
bool& Special, QColor& foreground, QColor& backgroundColor)>;
using SynEditingAreasProc = std::function<void(int Line, SynEditingAreaList& areaList,
QColor& borderColor,SynEditingAreaType& areaType)>;
using SynGutterGetTextProc = std::function<void(int aLine, QString& aText)>;
using SynTGutterPaintProc = std::function<void(int aLine, int X, int Y)>;
class SynEdit;
using PSynEdit = std::shared_ptr<SynEdit>;
class SynEdit : public QAbstractScrollArea
{
Q_OBJECT
public:
explicit SynEdit(QWidget *parent = nullptr);
int displayLineCount();
DisplayCoord displayXY();
int displayX();
int displayY();
BufferCoord caretXY();
int caretX();
int caretY();
void setCaretX(int value);
void setCaretY(int value);
void setCaretXY(const BufferCoord& value);
void setCaretXYEx(bool CallEnsureCursorPos, BufferCoord value);
void setCaretXYCentered(bool ForceToMiddle, const BufferCoord& value);
void invalidateGutter();
void invalidateGutterLine(int aLine);
void invalidateGutterLines(int FirstLine, int LastLine);
DisplayCoord pixelsToNearestRowColumn(int aX, int aY);
DisplayCoord pixelsToRowColumn(int aX, int aY);
DisplayCoord bufferToDisplayPos(const BufferCoord& p);
BufferCoord displayToBufferPos(const DisplayCoord& p);
int rowToLine(int aRow);
int lineToRow(int aLine);
int foldRowToLine(int Row);
int foldLineToRow(int Line);
void setDefaultKeystrokes();
void invalidateLine(int Line);
void invalidateLines(int FirstLine, int LastLine);
void invalidateSelection();
void invalidateRect(const QRect& rect);
void invalidate();
void lockPainter();
void unlockPainter();
bool selAvail();
void setCaretAndSelection(const BufferCoord& ptCaret,
const BufferCoord& ptBefore,
const BufferCoord& ptAfter);
void clearUndo();
int topLine() const;
void setTopLine(int value);
int linesInWindow() const;
int leftChar() const;
void setLeftChar(int Value);
BufferCoord blockBegin() const;
void setBlockBegin(BufferCoord value);
BufferCoord blockEnd() const;
void setBlockEnd(BufferCoord Value);
SynSelectionMode activeSelectionMode() const;
void setActiveSelectionMode(const SynSelectionMode &Value);
int charsInWindow() const;
int charWidth() const;
int gutterWidth() const;
void setGutterWidth(int value);
bool modified() const;
void setModified(bool Value);
int maxScrollWidth() const;
void setMaxScrollWidth(int Value);
signals:
void Changed();
void ChainUndoAdded();
void ChainRedoAdded();
void ChainLinesChanging();
void ChainLinesChanged();
void ChainListCleared();
void ChainListDeleted(int Index, int Count);
void ChainListInserted(int Index, int Count);
void ChainListPutted(int Index, int Count);
void FilesDropped(int X,int Y, const QStringList& AFiles);
void GutterClicked(Qt::MouseButton button, int x, int y, int line, PSynEditMark mark);
void ImeInputed(const QString& s);
void contextHelp(const QString& word);
void scrolled(SynScrollBarKind ScrollBar);
void statusChanged(SynStatusChanges changes);
private:
void clearAreaList(SynEditingAreaList areaList);
void computeCaret(int X, int Y);
void computeScroll(int X, int Y);
void doBlockIndent();
void incPaintLock();
void decPaintLock();
bool mouseCapture();
int clientWidth();
int clientHeight();
int clientTop();
int clientLeft();
QRect clientRect();
void synFontChanged();
void doOnPaintTransient(SynTransientType TransientType);
void updateLastCaretX();
void ensureCursorPosVisible();
void ensureCursorPosVisibleEx(bool ForceToMiddle);
void scrollWindow(int dx,int dy);
void setInternalDisplayXY(const DisplayCoord& aPos);
void internalSetCaretXY(const BufferCoord& Value);
void setStatusChanged(SynStatusChanges changes);
void doOnStatusChange(SynStatusChanges changes);
void insertBlock(const BufferCoord& BB, const BufferCoord& BE, const QString& ChangeStr,
bool AddToUndoList);
void updateScrollbars();
void updateCaret();
void recalcCharExtent();
QString expandAtWideGlyphs(const QString& S);
void updateModifiedStatus();
int scanFrom(int Index);
void uncollapse(PSynEditFoldRange FoldRange);
void foldOnListInserted(int Line, int Count);
void foldOnListDeleted(int Line, int Count);
void foldOnListCleared();
void rescan(); // rescan for folds
void rescanForFoldRanges();
void scanForFoldRanges(PSynEditFoldRanges TopFoldRanges);
int lineHasChar(int Line, int startChar, QChar character, const QString& highlighterAttrName);
void findSubFoldRange(PSynEditFoldRanges TopFoldRanges,int FoldIndex, PSynEditFoldRange Parent);
PSynEditFoldRange collapsedFoldStartAtLine(int Line);
void setSelTextPrimitiveEx(SynSelectionMode PasteMode,
const QString& Value, bool AddToUndoList);
void doOnPaintTransientEx(SynTransientType TransientType, bool Lock);
void initializeCaret();
private slots:
void bookMarkOptionsChanged();
void gutterChanged();
void linesChanged();
void linesChanging();
void linesCleared();
void linesDeleted(int index, int count);
void linesInserted(int index, int count);
void linesPutted(int index, int count);
void redoAdded();
void scrollTimerHandler();
void undoAdded();
void sizeOrFontChanged(bool bFont);
void doChange();
private:
SynEditFoldRanges mAllFoldRanges;
SynEditCodeFolding mCodeFolding;
bool mUseCodeFolding;
bool mAlwaysShowCaret;
BufferCoord mBlockBegin;
BufferCoord mBlockEnd;
int mCaretX;
int mLastCaretX;
int mCaretY;
int mCharsInWindow;
int mCharWidth;
QFont mFontDummy;
QColor mColor;
SynFontSmoothMethod mFontSmoothing;
bool mMouseMoved;
/* IME input */
int mImeCount;
bool mMBCSStepAside;
/* end of IME input */
bool mInserting;
bool mPainting;
PSynEditStringList mLines;
PSynEditStringList mOrigLines;
PSynEditUndoList mOrigUndoList;
PSynEditUndoList mOrigRedoList;
int mLinesInWindow;
int mLeftChar;
int mMaxScrollWidth;
int mPaintLock; // lock counter for internal calculations
bool mReadOnly;
int mRightEdge;
QColor mRightEdgeColor;
QColor mScrollHintColor;
SynScrollHintFormat mScrollHintFormat;
SynScrollStyle mScrollBars;
int mTextHeight;
int mTextOffset;
int mTopLine;
PSynHighlighter mHighlighter;
QColor mSelectedForeground;
QColor mSelectedBackground;
QColor mActiveLineColor;
PSynEditUndoList mUndoList;
PSynEditUndoList mRedoList;
SynEditMarkList mBookMarks;
int mMouseDownX;
int mMouseDownY;
SynBookMarkOpt mBookMarkOpt;
bool mHideSelection;
int mMouseWheelAccumulator;
SynEditCaretType mOverwriteCaret;
SynEditCaretType mInsertCaret;
QPoint mCaretOffset;
SynEditKeyStrokes mKeyStrokes;
bool mModified;
QDateTime mLastModifyTime;
SynEditMarkList mMarkList;
int mExtraLineSpacing;
SynSelectionMode mSelectionMode;
SynSelectionMode mActiveSelectionMode; //mode of the active selection
bool mWantReturns;
bool mWantTabs;
SynGutter mGutter;
int mTabWidth;
QRect mInvalidateRect;
SynStateFlags mStateFlags;
SynEditorOptions mOptions;
SynStatusChanges mStatusChanges;
int mLastKey;
Qt::KeyboardModifiers mLastKeyModifiers;
//fSearchEngine: TSynEditSearchCustom;
//fHookedCommandHandlers: TList;
//fKbdHandler: TSynEditKbdHandler;
// fFocusList: TList;
// fPlugins: TList;
QTimer* mScrollTimer;
int mScrollDeltaX;
int mScrollDeltaY;
PSynEdit fChainedEditor;
bool mShowSpecChar;
int mPaintTransientLock;
bool mIsScrolling;
int mPainterLock; // lock counter to prevent repaint while painting
bool mUndoing;
// event handlers
SynPlaceMarkProc mOnClearMark;
SynProcessCommandProc mOnCommandProcessed;
SynMouseCursorProc mOnMouseCursor;
SynPaintProc mOnPaint;
SynPreparePaintHighlightTokenProc mOnPaintHighlightToken;
SynPlaceMarkProc mOnPlaceMark;
SynProcessCommandProc mOnProcessingCommand;
SynProcessCommandProc mOnProcessingUserCommand;
SynReplaceTextProc mOnReplaceText;
SynSpecialLineColorsProc mOnSpecialLineColors;
SynEditingAreasProc mOnEditingAreas;
SynGutterGetTextProc mOnGutterGetText;
SynTGutterPaintProc mOnGutterPaint;
int mGutterWidth;
//caret blink related
int m_blinkTimerId;
int m_bliknStatus;
// QWidget interface
protected:
void paintEvent(QPaintEvent *event) override;
friend class SynEditTextPainter;
};
#endif // SYNEDIT_H

View File

@ -0,0 +1,906 @@
#include "TextBuffer.h"
#include <QDataStream>
#include <QFile>
#include <QTextCodec>
#include <QTextStream>
#include <stdexcept>
#include "../utils.h"
SynEditStringList::SynEditStringList(QObject* parent):
QObject(parent)
{
mAppendNewLineAtEOF = true;
mFileEndingType = FileEndingType::Windows;
mIndexOfLongestLine = -1;
mUpdateCount = 0;
setTabWidth(8);
}
static void ListIndexOutOfBounds(int index) {
throw IndexOutOfRange(index);
}
int SynEditStringList::parenthesisLevels(int Index)
{
if (Index>=0 && Index < mList.size()) {
return mList[Index]->fParenthesisLevel;
} else
return 0;
}
int SynEditStringList::bracketLevels(int Index)
{
if (Index>=0 && Index < mList.size()) {
return mList[Index]->fBracketLevel;
} else
return 0;
}
int SynEditStringList::braceLevels(int Index)
{
if (Index>=0 && Index < mList.size()) {
return mList[Index]->fBraceLevel;
} else
return 0;
}
QString SynEditStringList::expandedStrings(int Index)
{
if (Index>=0 && Index < mList.size()) {
if (mList[Index]->fFlags & SynEditStringFlag::sfHasNoTabs)
return mList[Index]->fString;
else
return ExpandString(Index);
} else
return QString();
}
int SynEditStringList::expandedStringLength(int Index)
{
if (Index>=0 && Index < mList.size()) {
if (mList[Index]->fFlags & sfExpandedLengthUnknown)
return ExpandString(Index).length();
else
return mList[Index]->fExpandedLength;
} else
return 0;
}
int SynEditStringList::lengthOfLongestLine()
{
if (mIndexOfLongestLine < 0) {
int MaxLen = -1;
mIndexOfLongestLine = -1;
if (mList.count() > 0 ) {
for (int i=0;i<mList.size();i++) {
int len = expandedStringLength(i);
if (len > MaxLen) {
MaxLen = len;
mIndexOfLongestLine = i;
}
}
}
}
if (mIndexOfLongestLine >= 0)
return mList[mIndexOfLongestLine]->fExpandedLength;
else
return 0;
}
SynRangeState SynEditStringList::ranges(int Index)
{
if (Index>=0 && Index < mList.size()) {
return mList[Index]->fRange;
} else
return {0,0};
}
void SynEditStringList::InsertItem(int Index, const QString &s)
{
beginUpdate();
PSynEditStringRec line = std::make_shared<SynEditStringRec>();
line->fString = s;
mIndexOfLongestLine = -1;
mList.insert(Index,line);
endUpdate();
}
ConvertTabsProcEx SynEditStringList::getConvertTabsProc() const
{
return mConvertTabsProc;
}
bool SynEditStringList::getAppendNewLineAtEOF() const
{
return mAppendNewLineAtEOF;
}
void SynEditStringList::setAppendNewLineAtEOF(bool appendNewLineAtEOF)
{
mAppendNewLineAtEOF = appendNewLineAtEOF;
}
void SynEditStringList::setRange(int Index, SynRangeState ARange)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
mList[Index]->fRange = ARange;
endUpdate();
}
void SynEditStringList::setParenthesisLevel(int Index, int level)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
mList[Index]->fParenthesisLevel = level;
endUpdate();
}
void SynEditStringList::setBracketLevel(int Index, int level)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
mList[Index]->fBracketLevel = level;
endUpdate();
}
void SynEditStringList::setBraceLevel(int Index, int level)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
mList[Index]->fBraceLevel = level;
endUpdate();
}
QString SynEditStringList::getString(int Index)
{
if (Index<0 || Index>=mList.count()) {
return QString();
}
return mList[Index]->fString;
}
int SynEditStringList::count()
{
return mList.count();
}
void *SynEditStringList::getObject(int Index)
{
if (Index<0 || Index>=mList.count()) {
return nullptr;
}
return mList[Index]->fObject;
}
QString SynEditStringList::text()
{
return GetTextStr();
}
void SynEditStringList::setText(const QString &text)
{
PutTextStr(text);
}
void SynEditStringList::beginUpdate()
{
if (mUpdateCount == 0) {
SetUpdateState(true);
}
mUpdateCount++;
}
void SynEditStringList::endUpdate()
{
mUpdateCount--;
if (mUpdateCount == 0) {
SetUpdateState(false);
}
}
int SynEditStringList::tabWidth()
{
return mTabWidth;
}
void SynEditStringList::setTabWidth(int value)
{
if (value != mTabWidth) {
mTabWidth = value;
mConvertTabsProc = GetBestConvertTabsProcEx(mTabWidth);
mIndexOfLongestLine = -1;
for (PSynEditStringRec& line:mList) {
line->fExpandedLength = -1;
line->fFlags = SynEditStringFlag::sfExpandedLengthUnknown;
}
}
}
int SynEditStringList::add(const QString &s)
{
beginUpdate();
int Result = mList.count();
InsertItem(Result, s);
emit inserted(Result,1);
endUpdate();
return Result;
}
int SynEditStringList::addStrings(const QStringList &Strings)
{
if (Strings.count() > 0) {
mIndexOfLongestLine = -1;
beginUpdate();
auto action = finally([this]{
endUpdate();
});
int FirstAdded = mList.count();
for (const QString& s:Strings) {
add(s);
}
emit inserted(FirstAdded,Strings.count());
}
}
int SynEditStringList::getTextLength()
{
int Result = 0;
for (const PSynEditStringRec& line: mList ) {
Result += line->fString.length();
if (mFileEndingType == FileEndingType::Windows) {
Result += 2;
} else {
Result += 1;
}
}
}
void SynEditStringList::clear()
{
if (!mList.isEmpty()) {
beginUpdate();
mIndexOfLongestLine = -1;
mList.clear();
endUpdate();
}
}
void SynEditStringList::deleteLines(int Index, int NumLines)
{
if (NumLines<=0)
return;
if ((Index < 0) || (Index >= mList.count())) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
auto action = finally([this]{
endUpdate();
});
if (mIndexOfLongestLine>=Index && (mIndexOfLongestLine <Index+NumLines)) {
mIndexOfLongestLine = - 1;
}
int LinesAfter = mList.count() - (Index + NumLines);
if (LinesAfter < 0) {
NumLines = mList.count() - Index;
}
mList.remove(Index,NumLines);
emit deleted(Index,NumLines);
}
void SynEditStringList::Exchange(int Index1, int Index2)
{
if ((Index1 < 0) || (Index1 >= mList.count())) {
ListIndexOutOfBounds(Index1);
}
if ((Index2 < 0) || (Index2 >= mList.count())) {
ListIndexOutOfBounds(Index2);
}
beginUpdate();
mList.swapItemsAt(Index1,Index2);
if (mIndexOfLongestLine == Index1) {
mIndexOfLongestLine = Index2;
} else if (mIndexOfLongestLine == Index2) {
mIndexOfLongestLine = Index1;
}
endUpdate();
}
void SynEditStringList::Insert(int Index, const QString &s)
{
if ((Index < 0) || (Index > mList.count())) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
InsertItem(Index, s);
emit inserted(Index,1);
endUpdate();
}
void SynEditStringList::deleteAt(int Index)
{
if ((Index < 0) || (Index >= mList.count())) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
if (mIndexOfLongestLine == Index)
mIndexOfLongestLine = -1;
mList.removeAt(Index);
emit deleted(Index,1);
endUpdate();
}
QString SynEditStringList::GetTextStr()
{
QString Result;
for (PSynEditStringRec& line:mList) {
Result.append(line->fString);
switch(mFileEndingType) {
case FileEndingType::Linux:
Result.append('\n');
case FileEndingType::Windows:
Result.append("\r\n");
case FileEndingType::Mac:
Result.append("\r");
}
}
return Result;
}
void SynEditStringList::putString(int Index, const QString &s) {
if (Index == mList.count()) {
add(s);
} else {
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
mIndexOfLongestLine = -1;
mList[Index]->fFlags = SynEditStringFlag::sfExpandedLengthUnknown;
mList[Index]->fString = s;
emit putted(Index,1);
endUpdate();
}
}
void SynEditStringList::putObject(int Index, void *AObject)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
beginUpdate();
mList[Index]->fObject = AObject;
endUpdate();
}
void SynEditStringList::SetUpdateState(bool Updating)
{
if (Updating)
emit changing();
else
emit changed();
}
QString SynEditStringList::ExpandString(int Index)
{
QString Result("");
PSynEditStringRec line = mList[Index];
if (line->fString.isEmpty()) {
line->fFlags = SynEditStringFlag::sfHasNoTabs;
line->fExpandedLength = 0;
} else {
bool hasTabs;
Result = mConvertTabsProc(line->fString,mTabWidth,hasTabs);
line->fExpandedLength = Result.length();
if (hasTabs) {
line->fFlags = SynEditStringFlag::sfHasTabs;
} else {
line->fFlags = SynEditStringFlag::sfHasNoTabs;
}
}
return Result;
}
void SynEditStringList::InsertLines(int Index, int NumLines)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
if (NumLines<=0)
return;
beginUpdate();
auto action = finally([this]{
endUpdate();
});
PSynEditStringRec line;
mList.insert(Index,NumLines,line);
for (int i=Index;i<Index+NumLines;i++) {
line = std::make_shared<SynEditStringRec>();
mList[i]=line;
}
emit inserted(Index,NumLines);
}
void SynEditStringList::InsertStrings(int Index, const QStringList &NewStrings)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
if (NewStrings.isEmpty())
return;
beginUpdate();
auto action = finally([this]{
endUpdate();
});
PSynEditStringRec line;
mList.insert(Index,NewStrings.length(),line);
for (int i=0;i<NewStrings.length();i++) {
line = std::make_shared<SynEditStringRec>();
line->fString = NewStrings[i];
mList[i+Index]=line;
}
emit inserted(Index,NewStrings.length());
}
void SynEditStringList::InsertText(int Index, const QString &NewText)
{
if (Index<0 || Index>=mList.count()) {
ListIndexOutOfBounds(Index);
}
if (NewText.isEmpty())
return;
QStringList lines = TextToLines(NewText);
InsertStrings(Index,lines);
}
void SynEditStringList::LoadFromFile(QFile &file, const QByteArray& encoding, QByteArray& realEncoding)
{
if (!file.open(QFile::ReadOnly | QFile::Text))
throw FileError(tr("Can't open file '%1' for read!").arg(file.fileName()));
if (!file.canReadLine())
throw FileError(tr("Can't read from file '%1'!").arg(file.fileName()));
beginUpdate();
auto action = finally([this]{
endUpdate();
});
//test for utf8 / utf 8 bom
if (encoding == ENCODING_AUTO_DETECT) {
QByteArray line = file.readLine();
QTextCodec* codec;
QTextCodec::ConverterState * state;
bool needReread = false;
bool allAscii = true;
//test for BOM
if (line.isEmpty()) {
realEncoding = ENCODING_ASCII;
return;
}
if ((line.length()>=3) && ((unsigned char)line[0]==0xEF) && ((unsigned char)line[1]==0xBB) && ((unsigned char)line[2]==0xBF) ) {
realEncoding = ENCODING_UTF8_BOM;
line = line.mid(3);
codec = QTextCodec::codecForName(ENCODING_UTF8);
} else {
realEncoding = ENCODING_UTF8;
codec = QTextCodec::codecForName(ENCODING_UTF8);
}
clear();
do {
if (allAscii) {
allAscii = isTextAllAscii(line);
}
if (allAscii) {
add(QString::fromLatin1(line));
} else {
QString newLine = codec->toUnicode(line.constData(),line.length(),state);
if (state->invalidChars>0) {
needReread = true;
break;
}
add(newLine);
}
line = file.readLine();
} while (!file.atEnd());
if (!needReread) {
if (allAscii)
realEncoding = ENCODING_ASCII;
return;
}
realEncoding = ENCODING_SYSTEM_DEFAULT;
} else {
realEncoding = encoding;
}
if (realEncoding == ENCODING_SYSTEM_DEFAULT) {
realEncoding = QTextCodec::codecForLocale()->name();
}
file.reset();
QTextStream textStream(&file);
if (realEncoding == ENCODING_UTF8_BOM) {
textStream.setAutoDetectUnicode(true);
textStream.setCodec(ENCODING_UTF8);
} else {
textStream.setAutoDetectUnicode(false);
textStream.setCodec(realEncoding);
}
QString line;
clear();
while (textStream.readLineInto(&line)) {
add(line);
}
}
void SynEditStringList::SaveToFile(QFile &file, const QByteArray& encoding, QByteArray& realEncoding)
{
if (!file.open(QFile::WriteOnly | QFile::Truncate | QFile::Text))
throw FileError(tr("Can't open file '%1' for save!").arg(file.fileName()));
if (mList.isEmpty())
return;
bool allAscii = true;
QTextCodec* codec;
if (realEncoding == ENCODING_UTF8_BOM) {
codec = QTextCodec::codecForName(ENCODING_UTF8_BOM);
} else if (realEncoding == ENCODING_ASCII) {
codec = QTextCodec::codecForLocale();
}
for (PSynEditStringRec& line:mList) {
if (allAscii) {
allAscii = isTextAllAscii(line->fString);
}
if (!allAscii) {
file.write(codec->fromUnicode(line->fString));
} else {
file.write(line->fString.toLatin1());
}
switch (mFileEndingType) {
case FileEndingType::Windows:
file.write("\r\n");
break;
case FileEndingType::Linux:
file.write("\n");
break;
case FileEndingType::Mac:
file.write("\r");
break;
}
}
if (encoding == ENCODING_AUTO_DETECT && allAscii) {
realEncoding = ENCODING_ASCII;
}
}
void SynEditStringList::PutTextStr(const QString &text)
{
beginUpdate();
auto action = finally([this]{
endUpdate();
});
clear();
int pos = 0;
int start;
while (pos < text.length()) {
start = pos;
while (pos<text.length()) {
if (text[pos] == '\r' || text[pos] == '\n') {
break;
}
pos++;
}
add(text.mid(start,pos-start));
if (pos>=text.length())
break;
if (text[pos] == '\r')
pos++;
if (text[pos] == '\n')
pos++;
}
}
FileEndingType SynEditStringList::getFileEndingType() const
{
return mFileEndingType;
}
void SynEditStringList::setFileEndingType(const FileEndingType &fileEndingType)
{
mFileEndingType = fileEndingType;
}
SynEditStringRec::SynEditStringRec():
fString(),
fObject(nullptr),
fRange{0,0},
fExpandedLength(-1),
fParenthesisLevel(0),
fBracketLevel(0),
fBraceLevel(0),
fFlags(SynEditStringFlag::sfExpandedLengthUnknown)
{
}
SynEditUndoList::SynEditUndoList():QObject()
{
mMaxUndoActions = 1024;
mNextChangeNumber = 1;
mInsideRedo = false;
mBlockChangeNumber=0;
mBlockCount=0;
mFullUndoImposible=false;
mLockCount = 0;
mInitialChangeNumber = 0;
}
void SynEditUndoList::AddChange(SynChangeReason AReason, const BufferCoord &AStart,
const BufferCoord &AEnd, const QString &ChangeText,
SynSelectionMode SelMode)
{
if (mLockCount != 0)
return;
int changeNumber;
if (mBlockChangeNumber != 0) {
changeNumber = mBlockChangeNumber;
} else {
changeNumber = mNextChangeNumber;
if (mBlockCount == 0) {
mNextChangeNumber++;
if (mNextChangeNumber == 0) {
mNextChangeNumber++;
}
}
}
PSynEditUndoItem NewItem = std::make_shared<SynEditUndoItem>(AReason,
SelMode,AStart,AEnd,ChangeText,
changeNumber);
PushItem(NewItem);
}
void SynEditUndoList::AddGroupBreak()
{
//Add the GroupBreak even if ItemCount = 0. Since items are stored in
//reverse order in TCustomSynEdit.fRedoList, a GroupBreak could be lost.
if (LastChangeReason() != SynChangeReason::crGroupBreak) {
AddChange(SynChangeReason::crGroupBreak, {0,0}, {0,0}, "", SynSelectionMode::smNormal);
}
}
void SynEditUndoList::BeginBlock()
{
mBlockCount++;
mBlockChangeNumber = mNextChangeNumber;
}
void SynEditUndoList::Clear()
{
mItems.clear();
mFullUndoImposible = false;
}
void SynEditUndoList::DeleteItem(int index)
{
if (index <0 || index>=mItems.count()) {
ListIndexOutOfBounds(index);
}
mItems.removeAt(index);
}
void SynEditUndoList::EndBlock()
{
if (mBlockCount > 0) {
mBlockCount--;
if (mBlockCount == 0) {
int iBlockID = mBlockChangeNumber;
mBlockChangeNumber = 0;
mNextChangeNumber++;
if (mNextChangeNumber == 0)
mNextChangeNumber++;
if (mItems.count() > 0 && PeekItem()->changeNumber() == iBlockID)
emit addedUndo();
}
}
}
SynChangeReason SynEditUndoList::LastChangeReason()
{
if (mItems.count() == 0)
return SynChangeReason::crNothing;
else
mItems.last()->changeReason();
}
void SynEditUndoList::Lock()
{
mLockCount++;
}
PSynEditUndoItem SynEditUndoList::PeekItem()
{
if (mItems.count() == 0)
return PSynEditUndoItem();
else
return mItems.last();
}
PSynEditUndoItem SynEditUndoList::PopItem()
{
if (mItems.count() == 0)
return PSynEditUndoItem();
else {
PSynEditUndoItem item = mItems.last();
mItems.removeLast();
return item;
}
}
void SynEditUndoList::PushItem(PSynEditUndoItem Item)
{
if (!Item)
return;
mItems.append(Item);
EnsureMaxEntries();
if (Item->changeReason()!= SynChangeReason::crGroupBreak)
addedUndo();
}
void SynEditUndoList::Unlock()
{
if (mLockCount > 0)
mLockCount--;
}
bool SynEditUndoList::CanUndo()
{
return mItems.count()>0;
}
int SynEditUndoList::ItemCount()
{
return mItems.count();
}
int SynEditUndoList::maxUndoActions() const
{
return mMaxUndoActions;
}
void SynEditUndoList::setMaxUndoActions(int maxUndoActions)
{
mMaxUndoActions = maxUndoActions;
}
bool SynEditUndoList::initialState()
{
if (ItemCount() == 0) {
return mInitialChangeNumber == 0;
} else {
return PeekItem()->changeNumber() == mInitialChangeNumber;
}
}
PSynEditUndoItem SynEditUndoList::item(int index)
{
if (index <0 || index>=mItems.count()) {
ListIndexOutOfBounds(index);
}
return mItems[index];
}
void SynEditUndoList::setInitialState(const bool Value)
{
if (Value) {
if (ItemCount() == 0)
mInitialChangeNumber = 0;
else
mInitialChangeNumber = PeekItem()->changeNumber();
} else if (ItemCount() == 0) {
if (mInitialChangeNumber == 0) {
mInitialChangeNumber = -1;
}
} else if (PeekItem()->changeNumber() == mInitialChangeNumber) {
mInitialChangeNumber = -1;
}
}
void SynEditUndoList::setItem(int index, PSynEditUndoItem Value)
{
if (index <0 || index>=mItems.count()) {
ListIndexOutOfBounds(index);
}
mItems[index]=Value;
}
int SynEditUndoList::blockChangeNumber() const
{
return mBlockChangeNumber;
}
void SynEditUndoList::setBlockChangeNumber(int blockChangeNumber)
{
mBlockChangeNumber = blockChangeNumber;
}
int SynEditUndoList::blockCount() const
{
return mBlockCount;
}
bool SynEditUndoList::insideRedo() const
{
return mInsideRedo;
}
void SynEditUndoList::setInsideRedo(bool insideRedo)
{
mInsideRedo = insideRedo;
}
bool SynEditUndoList::fullUndoImposible() const
{
return mFullUndoImposible;
}
void SynEditUndoList::EnsureMaxEntries()
{
if (mItems.count() > mMaxUndoActions){
mFullUndoImposible = true;
while (mItems.count() > mMaxUndoActions) {
mItems.removeFirst();
}
}
}
SynSelectionMode SynEditUndoItem::changeSelMode() const
{
return mChangeSelMode;
}
BufferCoord SynEditUndoItem::changeStartPos() const
{
return mChangeStartPos;
}
BufferCoord SynEditUndoItem::changeEndPos() const
{
return mChangeEndPos;
}
QString SynEditUndoItem::changeStr() const
{
return mChangeStr;
}
int SynEditUndoItem::changeNumber() const
{
return mChangeNumber;
}
SynEditUndoItem::SynEditUndoItem(SynChangeReason reason, SynSelectionMode selMode,
BufferCoord startPos, BufferCoord endPos,
const QString &str, int number)
{
mChangeReason = reason;
mChangeSelMode = selMode;
mChangeStartPos = startPos;
mChangeEndPos = endPos;
mChangeStr = str;
mChangeNumber = number;
}
SynChangeReason SynEditUndoItem::changeReason() const
{
return mChangeReason;
}

View File

@ -0,0 +1,228 @@
#ifndef SYNEDITSTRINGLIST_H
#define SYNEDITSTRINGLIST_H
#include <QStringList>
#include "highlighter/base.h"
#include <QVector>
#include <memory>
#include "MiscProcs.h"
#include "../utils.h"
#include "Types.h"
enum SynEditStringFlag {
sfHasTabs = 0x0001,
sfHasNoTabs = 0x0002,
sfExpandedLengthUnknown = 0x0004
};
typedef int SynEditStringFlags;
struct SynEditStringRec {
QString fString;
void * fObject;
SynRangeState fRange;
int fExpandedLength;
SynEditStringFlags fFlags;
int fParenthesisLevel;
int fBracketLevel;
int fBraceLevel;
public:
explicit SynEditStringRec();
};
typedef std::shared_ptr<SynEditStringRec> PSynEditStringRec;
typedef QVector<PSynEditStringRec> SynEditStringRecList;
typedef std::shared_ptr<SynEditStringRecList> PSynEditStringRecList;
class SynEditStringList;
typedef std::shared_ptr<SynEditStringList> PSynEditStringList;
using StringListChangeCallback = std::function<void(PSynEditStringList* object, int index, int count)>;
class QFile;
class SynEditStringList : public QObject
{
Q_OBJECT
public:
explicit SynEditStringList(QObject* parent=nullptr);
int parenthesisLevels(int Index);
int bracketLevels(int Index);
int braceLevels(int Index);
QString expandedStrings(int Index);
int expandedStringLength(int Index);
int lengthOfLongestLine();
SynRangeState ranges(int Index);
void setRange(int Index, SynRangeState ARange);
void setParenthesisLevel(int Index, int level);
void setBracketLevel(int Index, int level);
void setBraceLevel(int Index, int level);
QString getString(int Index);
int count();
void* getObject(int Index);
QString text();
void setText(const QString& text);
void putString(int Index, const QString& s);
void putObject(int Index, void * AObject);
void beginUpdate();
void endUpdate();
int tabWidth();
void setTabWidth(int value);
int add(const QString& s);
int addStrings(const QStringList& Strings);
int getTextLength();
void clear();
void deleteAt(int Index);
void deleteLines(int Index, int NumLines);
void Exchange(int Index1, int Index2);
void Insert(int Index, const QString& s);
void InsertLines(int Index, int NumLines);
void InsertStrings(int Index, const QStringList& NewStrings);
void InsertText(int Index,const QString& NewText);
void LoadFromFile(QFile& file, const QByteArray& encoding, QByteArray& realEncoding);
void SaveToFile(QFile& file, const QByteArray& encoding, QByteArray& realEncoding);
bool getAppendNewLineAtEOF() const;
void setAppendNewLineAtEOF(bool appendNewLineAtEOF);
ConvertTabsProcEx getConvertTabsProc() const;
FileEndingType getFileEndingType() const;
void setFileEndingType(const FileEndingType &fileEndingType);
signals:
void changed();
void changing();
void cleared();
void deleted(int index, int count);
void inserted(int index, int count);
void putted(int index, int count);
protected:
QString GetTextStr();
void SetUpdateState(bool Updating);
void InsertItem(int Index, const QString& s);
void PutTextStr(const QString& text);
private:
SynEditStringRecList mList;
//int mCount;
//int mCapacity;
FileEndingType mFileEndingType;
bool mAppendNewLineAtEOF;
ConvertTabsProcEx mConvertTabsProc;
int mIndexOfLongestLine;
int mTabWidth;
int mUpdateCount;
QString ExpandString(int Index);
};
enum class SynChangeReason {crInsert, crPaste, crDragDropInsert,
//several undo entries can be chained together via the ChangeNumber
//see also TCustomSynEdit.[Begin|End]UndoBlock methods
crDeleteAfterCursor, crDelete,
crLineBreak, crIndent, crUnindent,
crSilentDelete, crSilentDeleteAfterCursor,
crAutoCompleteBegin, crAutoCompleteEnd,
crPasteBegin, crPasteEnd, //for pasting, since it might do a lot of operations
crSpecial1Begin, crSpecial1End,
crSpecial2Begin, crSpecial2End,
crCaret, //just restore the Caret, allowing better Undo behavior
crSelection, //restore Selection
crNothing,
crGroupBreak,
crDeleteAll
};
class SynEditUndoItem {
private:
SynChangeReason mChangeReason;
SynSelectionMode mChangeSelMode;
BufferCoord mChangeStartPos;
BufferCoord mChangeEndPos;
QString mChangeStr;
int mChangeNumber;
public:
SynEditUndoItem(SynChangeReason reason,
SynSelectionMode selMode,
BufferCoord startPos,
BufferCoord endPos,
const QString& str,
int number);
SynChangeReason changeReason() const;
SynSelectionMode changeSelMode() const;
BufferCoord changeStartPos() const;
BufferCoord changeEndPos() const;
QString changeStr() const;
int changeNumber() const;
};
using PSynEditUndoItem = std::shared_ptr<SynEditUndoItem>;
class SynEditUndoList : public QObject {
Q_OBJECT
public:
explicit SynEditUndoList();
void AddChange(SynChangeReason AReason, const BufferCoord& AStart, const BufferCoord& AEnd,
const QString& ChangeText, SynSelectionMode SelMode);
void AddGroupBreak();
void BeginBlock();
void Clear();
void DeleteItem(int index);
void EndBlock();
SynChangeReason LastChangeReason();
void Lock();
PSynEditUndoItem PeekItem();
PSynEditUndoItem PopItem();
void PushItem(PSynEditUndoItem Item);
void Unlock();
bool CanUndo();
int ItemCount();
int maxUndoActions() const;
void setMaxUndoActions(int maxUndoActions);
bool initialState();
PSynEditUndoItem item(int index);
void setInitialState(const bool Value);
void setItem(int index, PSynEditUndoItem Value);
int blockChangeNumber() const;
void setBlockChangeNumber(int blockChangeNumber);
int blockCount() const;
bool insideRedo() const;
void setInsideRedo(bool insideRedo);
bool fullUndoImposible() const;
signals:
void addedUndo();
protected:
int mBlockChangeNumber;
int mBlockCount;
bool mFullUndoImposible;
QVector<PSynEditUndoItem> mItems;
int mLockCount;
int mMaxUndoActions;
int mNextChangeNumber;
int mInitialChangeNumber;
bool mInsideRedo;
void EnsureMaxEntries();
};
using PSynEditUndoList = std::shared_ptr<SynEditUndoList>;
#endif // SYNEDITSTRINGLIST_H

View File

@ -0,0 +1,130 @@
#include "TextPainter.h"
#include "SynEdit.h"
#include "Constants.h"
#include <cmath>
SynEditTextPainter::SynEditTextPainter(SynEdit *edit)
{
this->edit = edit;
}
QColor SynEditTextPainter::colEditorBG()
{
if (edit->mActiveLineColor.isValid() && bCurrentLine) {
return edit->mActiveLineColor;
} else {
QColor result = edit->mColor;
if (edit->mHighlighter) {
PSynHighlighterAttribute attr = edit->mHighlighter->whitespaceAttribute();
if (attr && attr->background().isValid()) {
return attr->background();
}
}
}
return edit->mColor;
}
void SynEditTextPainter::ComputeSelectionInfo()
{
BufferCoord vStart;
BufferCoord vEnd;
bAnySelection = false;
// Only if selection is visible anyway.
if (!edit->mHideSelection || edit->hasFocus()) {
bAnySelection = true;
// Get the *real* start of the selected area.
if (edit->mBlockBegin.Line < edit->mBlockEnd.Line) {
vStart = edit->mBlockBegin;
vEnd = edit->mBlockEnd;
} else if (edit->mBlockBegin.Line > edit->mBlockEnd.Line) {
vEnd = edit->mBlockBegin;
vStart = edit->mBlockEnd;
} else if (edit->mBlockBegin.Char != edit->mBlockEnd.Char) {
// No selection at all, or it is only on this line.
vStart.Line = edit->mBlockBegin.Line;
vEnd.Line = vStart.Line;
if (edit->mBlockBegin.Char < edit->mBlockEnd.Char) {
vStart.Char = edit->mBlockBegin.Char;
vEnd.Char = edit->mBlockEnd.Char;
} else {
vStart.Char = edit->mBlockEnd.Char;
vEnd.Char = edit->mBlockBegin.Char;
}
} else
bAnySelection = false;
// If there is any visible selection so far, then test if there is an
// intersection with the area to be painted.
if (bAnySelection) {
// Don't care if the selection is not visible.
bAnySelection = (vEnd.Line >= vFirstLine) and (vStart.Line <= vLastLine);
if (bAnySelection) {
// Transform the selection from text space into screen space
vSelStart = edit->bufferToDisplayPos(vStart);
vSelEnd = edit->bufferToDisplayPos(vEnd);
// In the column selection mode sort the begin and end of the selection,
// this makes the painting code simpler.
if (edit->mActiveSelectionMode == SynSelectionMode::smColumn && vSelStart.Column > vSelEnd.Column)
std::swap(vSelStart.Column, vSelEnd.Column);
}
}
}
}
void SynEditTextPainter::setDrawingColors(bool Selected)
{
if (Selected) {
painter->setPen(colSelFG);
painter->setBrush(colSelBG);
painter->setBackground(colSelBG);
} else {
painter->setPen(colFG);
painter->setBrush(colBG);
painter->setBackground(colBG);
}
}
int SynEditTextPainter::ColumnToXValue(int Col)
{
return edit->mTextOffset + (Col - 1) * edit->mCharWidth;
}
void SynEditTextPainter::PaintToken(const QString &Token, int TokenLen, int CharsBefore, int First, int Last, bool isSelection)
{
bool startPaint;
int nX;
if (Last >= First && rcToken.right() > rcToken.left()) {
nX = ColumnToXValue(First);
First -= CharsBefore;
Last -= CharsBefore;
if (First > TokenLen) {
} else {
painter->setClipRect(rcToken);
int tokenColLen=0;
startPaint = false;
for (int i=0;i<Token.length();i++) {
int charCols;
if (Token[i] == SynTabChar) {
charCols = edit->mTabWidth - ((CharsBefore+tokenColLen) % edit->mTabWidth);
} else {
charCols = std::ceil(edit->fontMetrics().horizontalAdvance(Token[i]) * edit->fontMetrics().fontDpi() / 96.0 / edit->mCharWidth);
}
if (tokenColLen+charCols>=First) {
startPaint = true;
if (tokenColLen+1!=First) {
nX-= (First - tokenColLen - 1) * edit->mCharWidth;
}
}
painter->drawText(nX,rcToken.bottom(), Token[i]);
tokenColLen += charCols;
nX += charCols * edit->mCharWidth;
if (tokenColLen > Last)
break;
}
}
rcToken.setLeft(rcToken.right());
}
}

View File

@ -0,0 +1,52 @@
#ifndef TEXTPAINTER_H
#define TEXTPAINTER_H
#include <QColor>
#include <QPainter>
#include <QString>
#include "Types.h"
class SynEdit;
class SynEditTextPainter
{
struct TokenAccu {
int Len;
int MaxLen;
int CharsBefore;
QString s;
QColor FG;
QColor BG;
SynFontStyles Style;
};
public:
SynEditTextPainter(SynEdit * edit);
QColor colEditorBG();
void ComputeSelectionInfo();
void setDrawingColors(bool Selected);
int ColumnToXValue(int Col);
void PaintToken(const QString& Token, int TokenLen, int CharsBefore,
int First, int Last, bool isSelection);
private:
SynEdit* edit;
QPainter* painter;
bool bDoRightEdge; // right edge
int nRightEdge;
// selection info
bool bAnySelection; // any selection visible?
DisplayCoord vSelStart; // start of selected area
DisplayCoord vSelEnd; // end of selected area
// info about normal and selected text and background colors
bool bSpecialLine, bLineSelected, bCurrentLine;
QColor colFG, colBG;
QColor colSelFG, colSelBG;
// info about selection of the current line
int nLineSelStart, nLineSelEnd;
bool bComplexLine;
// painting the background and the text
QRect rcLine, rcToken;
int vFirstLine, vLastLine;
};
#endif // TEXTPAINTER_H

View File

@ -0,0 +1,36 @@
#ifndef TYPES_H
#define TYPES_H
#include <QIcon>
#include <QList>
#include <QFlags>
enum class SynSelectionMode {smNormal, smLine, smColumn};
struct BufferCoord {
int Char;
int Line;
};
struct DisplayCoord {
int Column;
int Row;
};
enum SynFontStyle {
fsNone = 0,
fsBold = 0x0001,
fsItalic = 0x0002,
fsUnderline = 0x0004,
fsStrikeOut = 0x0008
};
Q_DECLARE_FLAGS(SynFontStyles,SynFontStyle)
Q_DECLARE_OPERATORS_FOR_FLAGS(SynFontStyles)
using PSynIcon = std::shared_ptr<QIcon>;
using SynIconList = QList<PSynIcon>;
using PSynIconList = std::shared_ptr<SynIconList>;
#endif // TYPES_H

View File

@ -0,0 +1,228 @@
#include "base.h"
#include "../Constants.h"
SynHighlighter::SynHighlighter(QObject *parent) : QObject(parent),
mWordBreakChars{ SynWordBreakChars },
mEnabled(true),
mUpdateCount(0)
{
}
const QMap<QString, PSynHighlighterAttribute>& SynHighlighter::attributes() const
{
return mAttributes;
}
const QSet<QChar>& SynHighlighter::wordBreakChars() const
{
return mWordBreakChars;
}
PSynHighlighterAttribute SynHighlighter::commentAttribute() const
{
return mCommentAttribute;
}
PSynHighlighterAttribute SynHighlighter::identifierAttribute() const
{
return mIdentifierAttribute;
}
PSynHighlighterAttribute SynHighlighter::keywordAttribute() const
{
return mKeywordAttribute;
}
PSynHighlighterAttribute SynHighlighter::stringAttribute() const
{
return mStringAttribute;
}
PSynHighlighterAttribute SynHighlighter::whitespaceAttribute() const
{
return mWhitespaceAttribute;
}
PSynHighlighterAttribute SynHighlighter::symbolAttribute() const
{
return mSymbolAttribute;
}
void SynHighlighter::onAttributeChanged()
{
setAttributesChanged();
}
void SynHighlighter::setAttributesChanged()
{
if (mUpdateCount == 0) {
emit attributesChanged();
}
}
void SynHighlighter::beginUpdate()
{
mUpdateCount++;
}
void SynHighlighter::endUpdate()
{
mUpdateCount--;
if (mUpdateCount == 0) {
setAttributesChanged();
}
if (mUpdateCount<0) {
throw new std::out_of_range("mUpdateCount in SynHighlighterBase < 0");
}
}
SynRangeState SynHighlighter::getRangeState() const
{
return {0,0};
}
int SynHighlighter::getBraceLevel() const
{
return 0;
}
int SynHighlighter::getBracketLevel() const
{
return 0;
}
int SynHighlighter::getParenthesisLevel() const
{
return 0;
}
SynHighlighterTokenType SynHighlighter::getTokenType()
{
return SynHighlighterTokenType::Default;
}
bool SynHighlighter::isKeyword(const QString &)
{
return false;
}
void SynHighlighter::nextToEol()
{
while (!eol())
next();
}
bool SynHighlighter::isSpaceChar(const QChar &ch)
{
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
}
bool SynHighlighter::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 SynHighlighter::addAttribute(PSynHighlighterAttribute attribute)
{
mAttributes[attribute->name()]=attribute;
connect(attribute.get(), &SynHighlighterAttribute::changed,
this, &SynHighlighter::setAttributesChanged);
}
void SynHighlighter::clearAttributes()
{
mAttributes.clear();
}
int SynHighlighter::attributesCount() const
{
return mAttributes.size();
}
PSynHighlighterAttribute SynHighlighter::getAttribute(const QString &name) const
{
auto search = mAttributes.find(name);
if (search!=mAttributes.end()) {
return search.value();
}
return PSynHighlighterAttribute();
}
void SynHighlighterAttribute::setChanged()
{
emit changed();
}
SynFontStyles SynHighlighterAttribute::styles() const
{
return mStyles;
}
void SynHighlighterAttribute::setStyles(const SynFontStyles &styles)
{
if (mStyles!=styles) {
mStyles = styles;
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();
}
}

View File

@ -0,0 +1,146 @@
#ifndef SYNHIGHLIGTERBASE_H
#define SYNHIGHLIGTERBASE_H
#include <QColor>
#include <QObject>
#include <memory>
#include <QMap>
#include <QSet>
#include <QVector>
#include <QVector>
#include "../Types.h"
typedef struct {
int state;
int spaceState;
} SynRangeState;
typedef int SynTokenKind;
enum class SynHighlighterTokenType {
Default, Space, Comment,
PreprocessDirective, String, StringEscapeSequence,
Identifier, Symbol,
Character, Keyword, Number};
enum class SynHighlighterClass {
Composition,
CppHighlighter,
};
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);
SynFontStyles styles() const;
void setStyles(const SynFontStyles &styles);
signals:
void changed();
private:
void setChanged();
private:
QColor mBackground;
QColor mForeground;
QString mName;
SynFontStyles mStyles;
};
typedef std::shared_ptr<SynHighlighterAttribute> PSynHighlighterAttribute;
using SynHighlighterAttributeList = QVector<PSynHighlighterAttribute>;
class SynHighlighter : public QObject
{
Q_OBJECT
public:
explicit SynHighlighter(QObject *parent = nullptr);
const QMap<QString, PSynHighlighterAttribute>& attributes() const;
const QSet<QChar>& 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;
virtual SynHighlighterClass getClass() const = 0;
virtual QString getName() const = 0;
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:
QMap<QString,PSynHighlighterAttribute> mAttributes;
int mUpdateCount;
bool mEnabled;
QSet<QChar> mWordBreakChars;
};
using PSynHighlighter = std::shared_ptr<SynHighlighter>;
using SynHighlighterList = QVector<PSynHighlighter>;
#endif // SYNHIGHLIGTERBASE_H

View File

@ -0,0 +1,93 @@
#include "composition.h"
#include "../Constants.h"
SynHighlightComposition::SynHighlightComposition(QObject *parent):
SynHighlighter(parent)
{
}
SynHighlighterClass SynHighlightComposition::getClass() const
{
return SynHighlighterClass::Composition;
}
QString SynHighlightComposition::getName() const
{
return "SynHighlightComposition";
}
SynScheme::SynScheme(QObject *parent):
QObject(parent),
mCaseSensitive(true)
{
mMarkerAttribute = std::make_shared<SynHighlighterAttribute>(SYNS_AttrMarker);
connect(mMarkerAttribute.get(),&SynHighlighterAttribute::changed,
this, &SynScheme::MarkerAttriChanged);
mMarkerAttribute->setBackground(QColorConstants::Yellow);
mMarkerAttribute->setBold(true);
}
QString SynScheme::endExpr() const
{
return mEndExpr;
}
void SynScheme::setEndExpr(const QString &endExpr)
{
mEndExpr = endExpr;
}
QString SynScheme::getStartExpr() const
{
return StartExpr;
}
void SynScheme::setStartExpr(const QString &value)
{
StartExpr = value;
}
PSynHighlighter SynScheme::getHighlighter() const
{
return mHighlighter;
}
void SynScheme::setHighlighter(const PSynHighlighter &highlighter)
{
mHighlighter = highlighter;
}
PSynHighlighterAttribute SynScheme::getMarkerAttribute() const
{
return mMarkerAttribute;
}
QString SynScheme::getSchemeName() const
{
return mSchemeName;
}
void SynScheme::setSchemeName(const QString &schemeName)
{
mSchemeName = schemeName;
}
int SynScheme::getCaseSensitive() const
{
return mCaseSensitive;
}
void SynScheme::setCaseSensitive(int caseSensitive)
{
mCaseSensitive = caseSensitive;
}
QString SynScheme::ConvertExpression(const QString &Value)
{
if (!mCaseSensitive) {
return Value.toUpper();
} else {
return Value;
}
}

View File

@ -0,0 +1,62 @@
#ifndef SYNHIGHLIGHTCOMPOSITION_H
#define SYNHIGHLIGHTCOMPOSITION_H
#include "base.h"
#include <memory>
#include <QObject>
class SynSchema;
using PSynSchema = std::shared_ptr<SynSchema>;
using OnCheckMarker = std::function<void(PSynSchema Sender,int &StartPos, int &MarkerLen,
std::shared_ptr<QString>& MarkerText , int Line)>;
class SynScheme : public QObject {
Q_OBJECT
public:
explicit SynScheme(QObject* parent=nullptr);
QString endExpr() const;
void setEndExpr(const QString &endExpr);
QString getStartExpr() const;
void setStartExpr(const QString &value);
PSynHighlighter getHighlighter() const;
void setHighlighter(const PSynHighlighter &highlighter);
PSynHighlighterAttribute getMarkerAttribute() const;
QString getSchemeName() const;
void setSchemeName(const QString &schemeName);
int getCaseSensitive() const;
void setCaseSensitive(int caseSensitive);
private:
QString mEndExpr;
QString StartExpr;
PSynHighlighter mHighlighter;
PSynHighlighterAttribute mMarkerAttribute;
QString mSchemeName;
int mCaseSensitive;
OnCheckMarker mOnCheckStartMarker;
OnCheckMarker mOnCheckEndMarker;
QString ConvertExpression(const QString& Value);
private slots:
void MarkerAttriChanged();
};
class SynHighlightComposition : public SynHighlighter
{
Q_OBJECT
public:
explicit SynHighlightComposition(QObject *parent = nullptr);
// SynHighligterBase interface
public:
SynHighlighterClass getClass() const override;
QString getName() const override;
};
#endif // SYNHIGHLIGHTCOMPOSITION_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
#ifndef SYNEDITCPPHIGHLIGHTER_H
#define SYNEDITCPPHIGHLIGHTER_H
#include "base.h"
#include <QSet>
class SynEditCppHighlighter: public SynHighlighter
{
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<QString> 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;
// SynHighligterBase interface
public:
SynHighlighterClass getClass() const override;
// SynHighlighter interface
public:
QString getName() const override;
};
#endif // SYNEDITCPPHIGHLIGHTER_H