* work save
This commit is contained in:
parent
1dddfc6fea
commit
51434661a0
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#include "TextDrawer.h"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef SYNTEXTDRAWER_H
|
||||
#define SYNTEXTDRAWER_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#endif // SYNTEXTDRAWER_H
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue