* work save

This commit is contained in:
royqh1979@gmail.com 2021-05-06 20:55:55 +08:00
parent 1dddfc6fea
commit 51434661a0
18 changed files with 1656 additions and 107 deletions

View File

@ -19,10 +19,12 @@ SOURCES += \
mainwindow.cpp \
qsynedit/CodeFolding.cpp \
qsynedit/Constants.cpp \
qsynedit/KeyStrokes.cpp \
qsynedit/MiscClasses.cpp \
qsynedit/MiscProcs.cpp \
qsynedit/SynEdit.cpp \
qsynedit/TextBuffer.cpp \
qsynedit/TextDrawer.cpp \
qsynedit/highlighter/base.cpp \
qsynedit/highlighter/composition.cpp \
qsynedit/highlighter/cpp.cpp \
@ -45,10 +47,12 @@ HEADERS += \
mainwindow.h \
qsynedit/CodeFolding.h \
qsynedit/Constants.h \
qsynedit/KeyStrokes.h \
qsynedit/MiscClasses.h \
qsynedit/MiscProcs.h \
qsynedit/SynEdit.h \
qsynedit/TextBuffer.h \
qsynedit/TextDrawer.h \
qsynedit/Types.h \
qsynedit/highlighter/base.h \
qsynedit/highlighter/composition.h \

View File

@ -1,13 +1,13 @@
#include "CodeFolding.h"
int QSynFoldRegions::count()
int SynEditFoldRegions::count()
{
return fRegions.size();
}
int QSynFoldRegions::add(bool addEnding, const QChar &openSymbol, const QChar &closeSymbol, const QString &highlight)
int SynEditFoldRegions::add(bool addEnding, const QChar &openSymbol, const QChar &closeSymbol, const QString &highlight)
{
PSynFoldRegion region = std::make_shared<QSynFoldRegion>();
PSynEditFoldRegion region = std::make_shared<SynEditFoldRegion>();
region->addEnding = addEnding;
region->openSymbol = openSymbol;
region->closeSymbol = closeSymbol;
@ -15,12 +15,12 @@ int QSynFoldRegions::add(bool addEnding, const QChar &openSymbol, const QChar &c
fRegions.push_back(region);
}
PSynFoldRegion QSynFoldRegions::get(int index)
PSynEditFoldRegion SynEditFoldRegions::get(int index)
{
return fRegions.at(index);
}
QSynCodeFolding::QSynCodeFolding():
SynEditCodeFolding::SynEditCodeFolding():
indentGuides(true),
showCollapsedLine(true),
collapsedLineColor(QColor("black")),
@ -31,7 +31,7 @@ QSynCodeFolding::QSynCodeFolding():
}
bool QSynEditFoldRange::parentCollapsed()
bool SynEditFoldRange::parentCollapsed()
{
PSynEditFoldRange parentFold = parent;
// Find first parent that is collapsed
@ -44,13 +44,13 @@ bool QSynEditFoldRange::parentCollapsed()
return false;
}
void QSynEditFoldRange::move(int count)
void SynEditFoldRange::move(int count)
{
fromLine += count;
toLine += count;
}
QSynEditFoldRange::QSynEditFoldRange(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynFoldRegion aFoldRegion, int aToLine):
SynEditFoldRange::SynEditFoldRange(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynEditFoldRegion aFoldRegion, int aToLine):
fromLine(aFromLine),
toLine(aToLine),
linesCollapsed(0),
@ -64,33 +64,33 @@ QSynEditFoldRange::QSynEditFoldRange(PSynEditFoldRange aParent, PSynEditFoldRang
}
PSynEditFoldRange QSynEditFoldRanges::foldRange(int index)
PSynEditFoldRange SynEditFoldRanges::foldRange(int index)
{
return ranges[index];
}
int QSynEditFoldRanges::count()
int SynEditFoldRanges::count()
{
return ranges.size();
}
QSynEditFoldRanges::QSynEditFoldRanges()
SynEditFoldRanges::SynEditFoldRanges()
{
}
PSynEditFoldRange QSynEditFoldRanges::addByParts(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynFoldRegion aFoldRegion, int aToLine)
PSynEditFoldRange SynEditFoldRanges::addByParts(PSynEditFoldRange aParent, PSynEditFoldRanges aAllFold, int aFromLine, PSynEditFoldRegion aFoldRegion, int aToLine)
{
PSynEditFoldRange range=std::make_shared<QSynEditFoldRange>(aParent,aAllFold, aFromLine,aFoldRegion,aToLine);
PSynEditFoldRange range=std::make_shared<SynEditFoldRange>(aParent,aAllFold, aFromLine,aFoldRegion,aToLine);
return range;
}
int QSynEditFoldRanges::remove(int index)
int SynEditFoldRanges::remove(int index)
{
ranges.erase(ranges.begin()+index);
}
void QSynEditFoldRanges::addObject(PSynEditFoldRange foldRange)
void SynEditFoldRanges::addObject(PSynEditFoldRange foldRange)
{
ranges.push_back(foldRange);
}

View File

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

View File

@ -0,0 +1,150 @@
#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(int key, Qt::KeyboardModifiers modifiers, SynEditorCommand command)
{
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();
}
}

View File

@ -0,0 +1,223 @@
#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(int key, Qt::KeyboardModifiers modifiers, SynEditorCommand command);
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);
SynEditKeyStrokeList mList;
};
#endif // SYNEDITKEYSTROKE_H

View File

@ -304,3 +304,177 @@ void SynGutter::setBorderColor(const QColor &value)
}
}
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

@ -4,6 +4,7 @@
#include <QColor>
#include <QFont>
#include <QObject>
#include "Types.h"
enum class SynGutterBorderStyle {
None,
@ -99,7 +100,84 @@ private:
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

@ -1,6 +1,602 @@
#include "SynEdit.h"
#include <QApplication>
#include <QFontMetrics>
#include <algorithm>
SynEdit::SynEdit(QWidget *parent) : QWidget(parent)
SynEdit::SynEdit(QWidget *parent, Qt::WindowFlags f) : QFrame(parent,f)
{
mPaintLock = 0;
mPainting = false;
mLines = std::make_shared<SynEditStringList>();
mOrigLines = mLines;
//fPlugins := TList.Create;
mMouseMoved = false;
mUndoing = false;
mLines->connect(mLines.get(), &SynEditStringList::changed, this, &SynEdit::linesChanged);
mLines->connect(mLines.get(), &SynEditStringList::changing, this, &SynEdit::linesChanging);
mLines->connect(mLines.get(), &SynEditStringList::cleared, this, &SynEdit::linesCleared);
mLines->connect(mLines.get(), &SynEditStringList::deleted, this, &SynEdit::linesDeleted);
mLines->connect(mLines.get(), &SynEditStringList::inserted, this, &SynEdit::linesInserted);
mLines->connect(mLines.get(), &SynEditStringList::putted, this, &SynEdit::linesPutted);
#ifdef Q_OS_WIN
mFontDummy = QFont("Consolas",10);
#elif Q_OS_LINUX
mFontDummy = QFont("terminal",14);
#else
#error "Not supported!"
#endif
mUndoList = std::make_shared<SynEditUndoList>();
mUndoList->connect(mUndoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::undoAdded);
mOrigUndoList = mUndoList;
mRedoList = std::make_shared<SynEditUndoList>();
mRedoList->connect(mRedoList.get(), &SynEditUndoList::addedUndo, this, &SynEdit::redoAdded);
mOrigRedoList = mRedoList;
//DoubleBuffered = false;
mActiveLineColor = QColor();
mSelectedBackground = QColor();
mSelectedForeground = QColor();
mBookMarkOpt.connect(&mBookMarkOpt, &SynBookMarkOpt::changed, this, &SynEdit::bookMarkOptionsChanged);
// fRightEdge has to be set before FontChanged is called for the first time
mRightEdge = 80;
mGutter.setRightOffset(21);
mGutter.connect(&mGutter, &SynGutter::changed, this, &SynEdit::gutterChanged);
mGutterWidth = mGutter.width();
mTextOffset = mGutterWidth + 2;
//ControlStyle := ControlStyle + [csOpaque, csSetCaption, csNeedsBorderPaint];
//Height := 150;
//Width := 200;
this->setCursor(Qt::CursorShape::IBeamCursor);
//TabStop := True;
mInserting = true;
mMaxScrollWidth = 1024;
mScrollBars = SynScrollStyle::ssBoth;
this->setFrameShape(QFrame::Panel);
this->setFrameShadow(QFrame::Sunken);
this->setLineWidth(1);
mInsertCaret = SynEditCaretType::ctVerticalLine;
mOverwriteCaret = SynEditCaretType::ctBlock;
mSelectionMode = SynSelectionMode::smNormal;
mActiveSelectionMode = SynSelectionMode::smNormal;
//stop qt to auto fill background
setAutoFillBackground(false);
//fFocusList := TList.Create;
//fKbdHandler := TSynEditKbdHandler.Create;
//fMarkList.OnChange := MarkListChange;
setDefaultKeystrokes();
mRightEdgeColor = QColorConstants::Svg::silver;
/* IME input */
mImeCount = 0;
mMBCSStepAside = false;
/* end of IME input */
mWantReturns = true;
mWantTabs = false;
mTabWidth = 4;
mLeftChar = 1;
mTopLine = 1;
mCaretX = 1;
mLastCaretX = 1;
mCaretY = 1;
mBlockBegin.Char = 1;
mBlockBegin.Line = 1;
mBlockEnd = mBlockBegin;
mOptions = eoAutoIndent | eoDragDropEditing | eoEnhanceEndKey |
eoScrollPastEol | eoShowScrollHint | eoSmartTabs | eoTabsToSpaces |
eoSmartTabDelete| eoGroupUndo;
mScrollTimer = new QTimer(this);
mScrollTimer->setInterval(100);
connect(mScrollTimer, &QTimer::timeout,this, &SynEdit::scrollTimerHandler);
mScrollHintColor = QColorConstants::Yellow;
mScrollHintFormat = SynScrollHintFormat::shfTopLineOnly;
synFontChanged();
}
int SynEdit::displayLineCount()
{
return lineToRow(mLines->count());
}
BufferCoord SynEdit::caretXY()
{
BufferCoord result;
result.Char = caretX();
result.Line = caretY();
return result;
}
int SynEdit::caretX()
{
return mCaretX;
}
int SynEdit::caretY()
{
return mCaretY;
}
void SynEdit::setCaretXY(const BufferCoord &value)
{
setCaretXYCentered(false,value);
}
void SynEdit::setCaretXYEx(bool CallEnsureCursorPos, BufferCoord value)
{
bool vTriggerPaint=true; //how to test it?
if (vTriggerPaint)
doOnPaintTransient(SynTransientType::ttBefore);
int nMaxX = maxScrollWidth() + 1;
if (value.Line > mLines->count())
value.Line = mLines->count();
if (value.Line < 1) {
// this is just to make sure if Lines stringlist should be empty
value.Line = 1;
if (!mOptions.testFlag(SynEditorOption::eoScrollPastEol)) {
nMaxX = 1;
}
} else {
if (!mOptions.testFlag(SynEditorOption::eoScrollPastEol))
nMaxX = mLines->getString(value.Line-1).length();
}
if ((value.Char > nMaxX) && (! (mOptions.testFlag(SynEditorOption::eoScrollPastEol)) ||
!(mOptions.testFlag(SynEditorOption::eoAutoSizeMaxScrollWidth))) )
value.Char = nMaxX;
if (value.Char < 1)
value.Char = 1;
if ((value.Char != mCaretX) || (value.Line != mCaretY)) {
incPaintLock();
auto action = finally([this]{
decPaintLock();
});
// simply include the flags, fPaintLock is > 0
if (mCaretX != value.Char) {
mCaretX = value.Char;
mStatusChanges.setFlag(SynStatusChange::scCaretX);
}
if (mCaretY != value.Line) {
if (!mActiveLineColor.isValid()) {
invalidateLine(value.Line);
invalidateLine(mCaretY);
}
mCaretY = value.Line;
mStatusChanges.setFlag(SynStatusChange::scCaretY);
}
// Call UpdateLastCaretX before DecPaintLock because the event handler it
// calls could raise an exception, and we don't want fLastCaretX to be
// left in an undefined state if that happens.
updateLastCaretX();
if (CallEnsureCursorPos)
ensureCursorPosVisible();
mStateFlags.setFlag(SynStateFlag::sfCaretChanged);
mStateFlags.setFlag(SynStateFlag::sfScrollbarChanged);
} else {
// Also call UpdateLastCaretX if the caret didn't move. Apps don't know
// anything about fLastCaretX and they shouldn't need to. So, to avoid any
// unwanted surprises, always update fLastCaretX whenever CaretXY is
// assigned to.
// Note to SynEdit developers: If this is undesirable in some obscure
// case, just save the value of fLastCaretX before assigning to CaretXY and
// restore it afterward as appropriate.
updateLastCaretX();
}
if (vTriggerPaint)
doOnPaintTransient(SynTransientType::ttAfter);
}
void SynEdit::setCaretXYCentered(bool ForceToMiddle, const BufferCoord &value)
{
incPaintLock();
auto action = finally([this] {
decPaintLock();
});
mStatusChanges.setFlag(SynStatusChange::scSelection);
setCaretXYEx(ForceToMiddle,value);
if selAvail() then
invalidateSelection();
mBlockBegin.Char = mCaretX;
mBlockBegin.Line = mCaretY;
mBlockEnd = mBlockBegin;
if (ForceToMiddle)
ensureCursorPosVisibleEx(true); // but here after block has been set
}
void SynEdit::invalidateGutter()
{
invalidateGutterLines(-1, -1);
}
void SynEdit::invalidateGutterLine(int aLine)
{
if ((aLine < 1) || (aLine > mLines->count()))
return;
invalidateGutterLines(aLine, aLine);
}
void SynEdit::invalidateGutterLines(int FirstLine, int LastLine)
{
QRect rcInval;
if (!isVisible())
return;
if (FirstLine == -1 && LastLine == -1) {
rcInval = QRect(clientLeft(), clientTop(), mGutterWidth, clientHeight());
if (mStateFlags.testFlag(SynStateFlag::sfLinesChanging))
mInvalidateRect = mInvalidateRect.united(rcInval);
else
update(rcInval);
} else {
// find the visible lines first
if (LastLine < FirstLine)
std::swap(LastLine, FirstLine);
if (mUseCodeFolding) {
FirstLine = lineToRow(FirstLine);
if (LastLine <= mLines->count())
LastLine = lineToRow(LastLine);
else
LastLine = INT_MAX;
}
FirstLine = std::max(FirstLine, topLine());
LastLine = std::min(LastLine, topLine() + linesInWindow());
// any line visible?
if (LastLine >= FirstLine) {
rcInval = {clientLeft(), clientTop()+mTextHeight * (FirstLine - topLine()),
mGutterWidth, mTextHeight * (LastLine - topLine() + 1)};
if (mStateFlags.testFlag(SynStateFlag::sfLinesChanging)) {
mInvalidateRect = mInvalidateRect.united(rcInval);
} else {
update(rcInval);
}
}
}
}
void SynEdit::clearAreaList(SynEditingAreaList areaList)
{
areaList.clear();
}
void SynEdit::computeCaret(int X, int Y)
{
DisplayCoord vCaretNearestPos = pixelsToNearestRowColumn(X, Y);
vCaretNearestPos.Row = MinMax(vCaretNearestPos.Row, 1, displayLineCount());
setInternalDisplayXY(vCaretNearestPos);
}
void SynEdit::computeScroll(int X, int Y)
{
QRect iScrollBounds; // relative to the client area
// don't scroll if dragging text from other control
// if (not MouseCapture) and (not Dragging) then begin
// fScrollTimer.Enabled := False;
// Exit;
// end;
iScrollBounds = QRect(mGutterWidth+this->frameWidth(), this->frameWidth(), mCharsInWindow * mCharWidth,
mLinesInWindow * mTextHeight);
if (X < iScrollBounds.left())
mScrollDeltaX = (X - iScrollBounds.left()) % mCharWidth - 1;
else if (X >= iScrollBounds.right())
mScrollDeltaX = (X - iScrollBounds.right()) % mCharWidth + 1;
else
mScrollDeltaX = 0;
if (Y < iScrollBounds.top())
mScrollDeltaY = (Y - iScrollBounds.top()) % mTextHeight - 1;
else if (Y >= iScrollBounds.bottom())
mScrollDeltaY = (Y - iScrollBounds.bottom()) % mTextHeight + 1;
else
mScrollDeltaY = 0;
if (mScrollDeltaX!=0 || mScrollDeltaY!=0)
mScrollTimer->start();
}
void SynEdit::doBlockIndent()
{
BufferCoord OrgCaretPos;
BufferCoord BB, BE;
QString StrToInsert;
int Run;
int e,x,i,InsertStrLen;
QString Spaces;
SynSelectionMode OrgSelectionMode;
BufferCoord InsertionPos;
OrgSelectionMode = mActiveSelectionMode;
OrgCaretPos = caretXY();
StrToInsert = nullptr;
if (selAvail()) {
auto action = finally([&,this]{
if (BE.Char > 1)
BE.Char+=Spaces.length();
setCaretAndSelection(OrgCaretPos,
{BB.Char + Spaces.length(), BB.Line}, BE);
setActiveSelectionMode(OrgSelectionMode);
});
// keep current selection detail
BB = blockBegin();
BE = blockEnd();
// build text to insert
if (BE.Char == 1) {
e = BE.Line - 1;
x = 1;
} else {
e = BE.Line;
if (mOptions.testFlag(SynEditorOption::eoTabsToSpaces))
x = caretX() + mTabWidth;
else
x = caretX() + 1;
}
if (mOptions.testFlag(eoTabsToSpaces)) {
InsertStrLen = (mTabWidth + 2) * (e - BB.Line) + mTabWidth + 1;
// chars per line * lines-1 + last line + null char
StrToInsert.resize(InsertStrLen);
Run = 0;
Spaces = QString(mTabWidth,' ') ;
} else {
InsertStrLen = 3 * (e - BB.Line) + 2;
// #9#13#10 * lines-1 + (last line's #9 + null char)
StrToInsert.resize(InsertStrLen);
Run = 0;
Spaces = "\t";
}
for (i = BB.Line; i<e;i++) {
StrToInsert.replace(Run,Spaces.length()+2,Spaces+"\r\n");
Run+=Spaces.length()+2;
}
StrToInsert.replace(Run,Spaces.length(),Spaces);
{
mUndoList->BeginBlock();
auto action2=finally([this]{
mUndoList->EndBlock();
});
InsertionPos.Line = BB.Line;
if (mActiveSelectionMode == SynSelectionMode::smColumn)
InsertionPos.Char = std::min(BB.Char, BE.Char);
else
InsertionPos.Char = 1;
insertBlock(InsertionPos, InsertionPos, StrToInsert, true);
mUndoList->AddChange(SynChangeReason::crIndent, BB, BE, "", SynSelectionMode::smColumn);
//We need to save the position of the end block for redo
mUndoList.AddChange(SynChangeReason::crIndent,
{BB.Char + Spaces.length(), BB.Line},
{BE.Char + Spaces.length(), BE.Line},
"", SynSelectionMode::smColumn);
//adjust the x position of orgcaretpos appropriately
OrgCaretPos.Char = X;
}
}
}
void SynEdit::incPaintLock()
{
mPaintLock ++ ;
}
void SynEdit::decPaintLock()
{
Q_ASSERT(mPaintLock > 0);
mPaintLock--;
if (mPaintLock == 0 ) {
if (mStateFlags.testFlag(SynStateFlag::sfScrollbarChanged))
updateScrollbars();
if (mStateFlags.testFlag(SynStateFlag::sfCaretChanged))
updateCaret();
if (mStatusChanges!=0)
doOnStatusChange(mStatusChanges);
}
}
bool SynEdit::mouseCapture()
{
return hasMouseTracking();
}
int SynEdit::clientWidth()
{
return frameRect().width()-2*frameWidth();
}
int SynEdit::clientHeight()
{
return frameRect().height()-2*frameWidth();
}
int SynEdit::clientTop()
{
return frameRect().top()+frameWidth();
}
int SynEdit::clientLeft()
{
return frameRect().left()+frameWidth();
}
QRect SynEdit::clientRect()
{
return QRect(frameRect().left()+frameWidth(),frameRect().top()+frameWidth(), frameRect().width()-2*frameWidth(), frameRect().height()-2*frameWidth());
}
void SynEdit::bookMarkOptionsChanged()
{
invalidateGutter();
}
void SynEdit::linesChanged()
{
SynSelectionMode vOldMode;
mStateFlags.setFlag(SynStateFlag::sfLinesChanging, false);
if (mUseCodeFolding)
rescan();
updateScrollBars();
vOldMode = mActiveSelectionMode;
setBlockBegin(caretXY());
mActiveSelectionMode = vOldMode;
update(mInvalidateRect);
mInvalidateRect = {0,0,0,0};
if (mGutter.showLineNumbers() && (mGutter.autoSize()))
mGutter.autoSizeDigitCount(mLines->count());
if (!mOptions.testFlag(SynEditorOption::eoScrollPastEof))
setTopLine(mTopLine);
}
void SynEdit::linesChanging()
{
mStateFlags.setFlag(SynStateFlag::sfLinesChanging);
}
void SynEdit::linesCleared()
{
if (mUseCodeFolding)
foldOnListCleared();
clearUndo();
// invalidate the *whole* client area
mInvalidateRect={0,0,0,0};
update();
// set caret and selected block to start of text
setCaretXY({1,1});
// scroll to start of text
setTopLine(1);
setLeftChar(1);
mStatusChanges.setFlag(SynStatusChange::scAll);
}
void SynEdit::linesDeleted(int index, int count)
{
if (mUseCodeFolding)
foldOnListDeleted(index + 1, count);
if (mHighlighter && mLines->count() > 0)
scanFrom(index);
invalidateLines(index + 1, INT_MAX);
invalidateGutterLines(index + 1, INT_MAX);
}
void SynEdit::linesInserted(int index, int count)
{
if (mUseCodeFolding)
foldOnListInserted(index + 1, count);
if (mHighlighter && mLines->count() > 0) {
int vLastScan = index;
do {
vLastScan = scanFrom(vLastScan);
vLastScan++;
} while (vLastScan < index + count) ;
}
invalidateLines(index + 1, INT_MAX);
invalidateGutterLines(index + 1, INT_MAX);
if (mOptions.setFlag(SynEditorOption::eoAutoSizeMaxScrollWidth)) {
int L = mLines->expandedStringLength(index);
if (L > mMaxScrollWidth)
setMaxScrollWidth(L);
}
}
void SynEdit::linesPutted(int index, int count)
{
int vEndLine = index + 1;
if (mHighlighter) {
vEndLine = std::max(vEndLine, scanFrom(index) + 1);
// If this editor is chained then the real owner of text buffer will probably
// have already parsed the changes, so ScanFrom will return immediately.
if (mLines != mOrigLines)
vEndLine = INT_MAX;
}
invalidateLines(index + 1, vEndLine);
if (mOptions.setFlag(SynEditorOption::eoAutoSizeMaxScrollWidth)) {
int L = mLines->expandedStringLength(index);
if (L > mMaxScrollWidth)
setMaxScrollWidth(L);
}
}
void SynEdit::undoAdded()
{
updateModifiedStatus();
// we have to clear the redo information, since adding undo info removes
// the necessary context to undo earlier edit actions
if (! mUndoList->insideRedo() &&
mUndoList->PeekItem() && (mUndoList->PeekItem()->changeReason()!=SynChangeReason::crGroupBreak))
mRedoList->Clear();
if (mUndoList->blockCount() == 0 )
doChange();
}
void SynEdit::redoAdded()
{
updateModifiedStatus();
if (mRedoList->blockCount() == 0 )
doChange();
}
void SynEdit::gutterChanged()
{
if (mGutter.showLineNumbers() && mGutter.autoSize())
mGutter.autoSizeDigitCount(mLines->count());
int nW;
if (mGutter.useFontStyle()) {
QFontMetrics fm=QFontMetrics(mGutter.font());
nW = mGutter.realGutterWidth(fm.averageCharWidth());
} else {
nW = mGutter.realGutterWidth(mCharWidth);
}
if (nW == mGutterWidth)
invalidateGutter();
else
setGutterWidth(nW);
}
void SynEdit::scrollTimerHandler()
{
QPoint iMousePos;
DisplayCoord C;
int X, Y;
iMousePos = QCursor::pos();
iMousePos = mapFromGlobal(iMousePos);
C = pixelsToRowColumn(iMousePos.x(), iMousePos.y());
C.Row = MinMax(C.Row, 1, displayLineCount());
if (mScrollDeltaX != 0) {
setLeftChar(leftChar() + mScrollDeltaX);
X = leftChar();
if (mScrollDeltaX > 0) // scrolling right?
X+=charsInWindow();
C.Column = X;
}
if (mScrollDeltaY != 0) {
if (QApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier))
setTopLine(topLine() + mScrollDeltaY * linesInWindow());
else
setTopLine(topLine()) + mScrollDeltaY);
Y = topLine();
if (mScrollDeltaY > 0) // scrolling down?
Y+=linesInWindow() - 1;
C.Row = MinMax(Y, 1, displayLineCount());
}
BufferCoord vCaret = displayToBufferPos(C);
if ((caretX() <> vCaret.Char) || (caretY() != vCaret.Line)) {
// changes to line / column in one go
incPaintLock();
auto action = finally([this]{
decPaintLock();
});
setInternalCaretXY(vCaret);
// if MouseCapture is True we're changing selection. otherwise we're dragging
if (mouseCapture())
setBlockEnd(caretXY());
}
computeScroll(iMousePos.x(), iMousePos.y());
}

View File

@ -1,16 +1,328 @@
#ifndef SYNEDIT_H
#define SYNEDIT_H
#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"
class SynEdit : public QWidget
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 {
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 QFrame
{
Q_OBJECT
public:
explicit SynEdit(QWidget *parent = nullptr);
explicit SynEdit(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
int displayLineCount();
BufferCoord caretXY();
int caretX();
int caretY();
void setCaretXY(const BufferCoord& value);
void setCaretXYEx(bool CallEnsureCursorPos, BufferCoord value);
void setCaretXYCentered(bool ForceToMiddle, const BufferCoord& value);
void invalidateGutter();
void invalidateGutterLine(int aLine);
//todo:
void invalidateGutterLines(int FirstLine, int LastLine);
DisplayCoord pixelsToNearestRowColumn(int aX, int aY);
int lineToRow(int aLine);
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 statusChange(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();
//todo
void setInternalDisplayXY(const DisplayCoord& aPos);
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();
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;
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;
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;
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;
SynPaintTransientProc mOnPaintTransient;
SynGutterGetTextProc mOnGutterGetText;
SynTGutterPaintProc mOnGutterPaint;
int mGutterWidth;
};
#endif // SYNEDIT_H

View File

@ -6,7 +6,8 @@
#include <stdexcept>
#include "../utils.h"
SynEditStringList::SynEditStringList()
SynEditStringList::SynEditStringList(QObject* parent):
QObject(parent)
{
mAppendNewLineAtEOF = true;
mFileEndingType = FileEndingType::Windows;
@ -159,7 +160,7 @@ void SynEditStringList::setBraceLevel(int Index, int level)
endUpdate();
}
QString SynEditStringList::get(int Index)
QString SynEditStringList::getString(int Index)
{
if (Index<0 || Index>=mList.count()) {
return QString();
@ -355,7 +356,7 @@ QString SynEditStringList::GetTextStr()
return Result;
}
void SynEditStringList::put(int Index, const QString &s) {
void SynEditStringList::putString(int Index, const QString &s) {
if (Index == mList.count()) {
add(s);
} else {
@ -631,7 +632,7 @@ SynEditStringRec::SynEditStringRec():
}
SynEditUndoList::SynEditUndoList()
SynEditUndoList::SynEditUndoList():QObject()
{
mMaxUndoActions = 1024;
mNextChangeNumber = 1;
@ -644,7 +645,9 @@ SynEditUndoList::SynEditUndoList()
mInitialChangeNumber = 0;
}
void SynEditUndoList::AddChange(SynChangeReason AReason, const BufferCoord &AStart, const BufferCoord &AEnd, const QString &ChangeText, SynSelectionMode SelMode)
void SynEditUndoList::AddChange(SynChangeReason AReason, const BufferCoord &AStart,
const BufferCoord &AEnd, const QString &ChangeText,
SynSelectionMode SelMode)
{
if (mLockCount != 0)
return;

View File

@ -48,7 +48,7 @@ class SynEditStringList : public QObject
{
Q_OBJECT
public:
explicit SynEditStringList();
explicit SynEditStringList(QObject* parent=nullptr);
int parenthesisLevels(int Index);
int bracketLevels(int Index);
@ -61,13 +61,13 @@ public:
void setParenthesisLevel(int Index, int level);
void setBracketLevel(int Index, int level);
void setBraceLevel(int Index, int level);
QString get(int Index);
QString getString(int Index);
int count();
void* getObject(int Index);
QString text();
void setText(const QString& text);
void put(int Index, const QString& s);
void putString(int Index, const QString& s);
void putObject(int Index, void * AObject);
void beginUpdate();
@ -167,7 +167,8 @@ public:
};
using PSynEditUndoItem = std::shared_ptr<SynEditUndoItem>;
class SynEditUndoList {
class SynEditUndoList : public QObject {
Q_OBJECT
public:
explicit SynEditUndoList();
@ -222,4 +223,6 @@ protected:
void EnsureMaxEntries();
};
using PSynEditUndoList = std::shared_ptr<SynEditUndoList>;
#endif // SYNEDITSTRINGLIST_H

View File

@ -0,0 +1,2 @@
#include "TextDrawer.h"

View File

@ -0,0 +1,6 @@
#ifndef SYNTEXTDRAWER_H
#define SYNTEXTDRAWER_H
#include "Types.h"
#endif // SYNTEXTDRAWER_H

View File

@ -1,5 +1,10 @@
#ifndef TYPES_H
#define TYPES_H
#include <QIcon>
#include <QList>
#include <QFlags>
enum class SynSelectionMode {smNormal, smLine, smColumn};
struct BufferCoord {
@ -11,4 +16,20 @@ struct DisplayCoord {
int Column;
int Row;
};
enum SynFontStyle {
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

@ -166,51 +166,15 @@ void SynHighlighterAttribute::setChanged()
emit changed();
}
bool SynHighlighterAttribute::strikeOut() const
SynFontStyles SynHighlighterAttribute::styles() const
{
return mStrikeOut;
return mStyles;
}
void SynHighlighterAttribute::setStrikeOut(bool strikeOut)
void SynHighlighterAttribute::setStyles(const SynFontStyles &styles)
{
if (mStrikeOut!=strikeOut) {
mStrikeOut = strikeOut;
setChanged();
}
}
bool SynHighlighterAttribute::underline() const
{
return mUnderline;
}
void SynHighlighterAttribute::setUnderline(bool underline)
{
mUnderline = underline;
}
bool SynHighlighterAttribute::italic() const
{
return mItalic;
}
void SynHighlighterAttribute::setItalic(bool italic)
{
if (mItalic!=italic) {
mItalic = italic;
setChanged();
}
}
bool SynHighlighterAttribute::bold() const
{
return mBold;
}
void SynHighlighterAttribute::setBold(bool bold)
{
if (mBold!=bold) {
mBold = bold;
if (mStyles!=styles) {
mStyles = styles;
setChanged();
}
}

View File

@ -8,6 +8,7 @@
#include <QSet>
#include <QVector>
#include <QVector>
#include "../Types.h"
typedef struct {
int state;
@ -40,17 +41,8 @@ public:
QString name() const;
void setName(const QString &name);
bool bold() const;
void setBold(bool bold);
bool italic() const;
void setItalic(bool italic);
bool underline() const;
void setUnderline(bool underline);
bool strikeOut() const;
void setStrikeOut(bool strikeOut);
SynFontStyles styles() const;
void setStyles(const SynFontStyles &styles);
signals:
void changed();
@ -60,10 +52,7 @@ private:
QColor mBackground;
QColor mForeground;
QString mName;
bool mBold;
bool mItalic;
bool mUnderline;
bool mStrikeOut;
SynFontStyles mStyles;
};
typedef std::shared_ptr<SynHighlighterAttribute> PSynHighlighterAttribute;

View File

@ -329,3 +329,24 @@ FileError::FileError(const QString &reason): BaseError(reason)
{
}
void decodeKey(const int combinedKey, int &key, Qt::KeyboardModifiers &modifiers)
{
modifiers = Qt::NoModifier;
if (combinedKey & Qt::ShiftModifier) {
modifiers|=Qt::ShiftModifier;
}
if (combinedKey & Qt::ControlModifier) {
modifiers|=Qt::ControlModifier;
}
if (combinedKey & Qt::AltModifier) {
modifiers|=Qt::AltModifier;
}
if (combinedKey & Qt::MetaModifier) {
modifiers|=Qt::MetaModifier;
}
if (combinedKey & Qt::KeypadModifier) {
modifiers|= Qt::KeypadModifier;
}
key = combinedKey & ~(Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier);
}

View File

@ -90,6 +90,8 @@ QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec);
void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers);
template <class F>
class final_action
{