* work save

This commit is contained in:
royqh1979@gmail.com 2021-05-03 10:15:40 +08:00
parent 8feda5d762
commit 1dddfc6fea
12 changed files with 877 additions and 84 deletions

View File

@ -21,6 +21,7 @@ SOURCES += \
qsynedit/Constants.cpp \
qsynedit/MiscClasses.cpp \
qsynedit/MiscProcs.cpp \
qsynedit/SynEdit.cpp \
qsynedit/TextBuffer.cpp \
qsynedit/highlighter/base.cpp \
qsynedit/highlighter/composition.cpp \
@ -46,7 +47,9 @@ HEADERS += \
qsynedit/Constants.h \
qsynedit/MiscClasses.h \
qsynedit/MiscProcs.h \
qsynedit/SynEdit.h \
qsynedit/TextBuffer.h \
qsynedit/Types.h \
qsynedit/highlighter/base.h \
qsynedit/highlighter/composition.h \
qsynedit/highlighter/cpp.h \

View File

@ -1,5 +1,7 @@
#include "MiscProcs.h"
#include <QFile>
#include <QPainter>
#include <QTextStream>
#include <algorithm>
int MinMax(int x, int mi, int ma)
@ -437,7 +439,7 @@ bool InternalEnumHighlighterAttris(PSynHighlighter Highlighter,
QString UniqueAttriName = Highlighter->getName()
+ HighlighterList.indexOf(Highlighter) + '.'
+ pAttr->name();
Result = (*highlighterAttriProc)(Highlighter, pAttr,
Result = highlighterAttriProc(Highlighter, pAttr,
UniqueAttriName, Params);
if (!Result)
break;

View File

@ -7,6 +7,7 @@
#include <QSet>
#include "highlighter/base.h"
#include <QPaintDevice>
#include <QTextStream>
#include <QVector>
#include <initializer_list>
//#include <QRect>
@ -31,14 +32,14 @@ void InternalFillRect(QPainter* painter, const QRect& rcPaint, const QColor& col
// Converting tabs to spaces: To use the function several times it's better
// to use a function pointer that is set to the fastest conversion function.
using ConvertTabsProc = QString (*)(const QString& Line, int TabWidth);
using ConvertTabsProc = std::function<QString(const QString&, int)>;
ConvertTabsProc GetBestConvertTabsProc(int TabWidth);
// This is the slowest conversion function which can handle TabWidth <> 2^n.
QString ConvertTabs(const QString& Line, int TabWidth);
using ConvertTabsProcEx = QString (*)(const QString& Line, int TabWidth, bool& HasTabs);
using ConvertTabsProcEx = std::function<QString(const QString&, int, bool& )>;
ConvertTabsProcEx GetBestConvertTabsProcEx(int TabWidth);
// This is the slowest conversion function which can handle TabWidth <> 2^n.
@ -68,9 +69,9 @@ QString EncodeString(const QString & s);
// Decodes string, encoded with EncodeString.
QString DecodeString(const QString& s);
using HighlighterAttriProc = bool (*) (PSynHighlighter Highlighter,
using HighlighterAttriProc = std::function<bool(PSynHighlighter Highlighter,
PSynHighlighterAttribute Attri, const QString& UniqueAttriName,
std::initializer_list<void *> Params);
std::initializer_list<void *> Params)>;
// Enums all child highlighters and their attributes of a TSynMultiSyn through a
// callback function.
@ -85,4 +86,5 @@ uint16_t CalcFCS(unsigned char* ABuf, int ABufSize);
void SynDrawGradient(QPaintDevice* ACanvas, const QColor& AStartColor, const QColor& AEndColor,
int ASteps, const QRect& ARect, bool AHorizontal);
#endif // MISCPROCS_H

View File

@ -0,0 +1,6 @@
#include "SynEdit.h"
SynEdit::SynEdit(QWidget *parent) : QWidget(parent)
{
}

View File

@ -0,0 +1,16 @@
#ifndef SYNEDIT_H
#define SYNEDIT_H
#include <QWidget>
class SynEdit : public QWidget
{
Q_OBJECT
public:
explicit SynEdit(QWidget *parent = nullptr);
signals:
};
#endif // SYNEDIT_H

View File

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

View File

@ -3,9 +3,11 @@
#include <QStringList>
#include "highlighter/base.h"
#include <QList>
#include <QVector>
#include <memory>
#include "MiscProcs.h"
#include "../utils.h"
#include "Types.h"
enum SynEditStringFlag {
sfHasTabs = 0x0001,
@ -24,11 +26,14 @@ struct SynEditStringRec {
int fParenthesisLevel;
int fBracketLevel;
int fBraceLevel;
public:
explicit SynEditStringRec();
};
typedef std::shared_ptr<SynEditStringRec> PSynEditStringRec;
typedef QList<PSynEditStringRec> SynEditStringRecList;
typedef QVector<PSynEditStringRec> SynEditStringRecList;
typedef std::shared_ptr<SynEditStringRecList> PSynEditStringRecList;
@ -36,15 +41,9 @@ class SynEditStringList;
typedef std::shared_ptr<SynEditStringList> PSynEditStringList;
using StringListChangeCallback = void (*) (PSynEditStringList* object, int index, int count);
enum class SynEditFileFormat {
Windows,
Linux,
Mac
};// Windows: CRLF, UNIX: LF, Mac: CR
using StringListChangeCallback = std::function<void(PSynEditStringList* object, int index, int count)>;
class QFile;
class SynEditStringList : public QObject
{
Q_OBJECT
@ -66,6 +65,7 @@ public:
int count();
void* getObject(int Index);
QString text();
void setText(const QString& text);
void put(int Index, const QString& s);
void putObject(int Index, void * AObject);
@ -75,46 +75,29 @@ public:
int tabWidth();
void setTabWidth(int value);
int Add(const QString& s);
int AddStrings(const QStringList& Strings);
int add(const QString& s);
int addStrings(const QStringList& Strings);
int getTextLength();
void Clear();
void Delete(int Index);
procedure DeleteLines(Index, NumLines: integer);
procedure Exchange(Index1, Index2: integer); override;
procedure Insert(Index: integer; const S: string); override;
procedure InsertLines(Index, NumLines: integer);
procedure InsertStrings(Index: integer; NewStrings: TStrings);
procedure InsertText(Index: integer; NewText: string);
procedure LoadFromFile(const FileName: string); override;
procedure SaveToFile(const FileName: string); override;
procedure SaveToStream(Stream: TStream); override;
procedure LoadFromStream(Stream: TStream); override;
property AppendNewLineAtEOF: Boolean read fAppendNewLineAtEOF write fAppendNewLineAtEOF;
property FileFormat: TSynEditFileFormat read fFileFormat write fFileFormat;
property ExpandedStrings[Index: integer]: string read expandedStrings;
property ExpandedStringLengths[Index: integer]: integer read expandedStringLength;
property LengthOfLongestLine: integer read lengthOfLongestLine;
property Ranges[Index: integer]: TSynEditRange read GetRange write setRange;
property ParenthesisLevels[Index: integer]: integer read GetParenthesisLevel write setParenthesisLevel;
property BracketLevels[Index: integer]: integer read GetBracketLevel write setBracketLevel;
property BraceLevels[Index: integer]: integer read GetBraceLevel write setBraceLevel;
property TabWidth: integer read fTabWidth write setTabWidth;
property OnChange: TNotifyEvent read fOnChange write fOnChange;
property OnChanging: TNotifyEvent read fOnChanging write fOnChanging;
property OnCleared: TNotifyEvent read fOnCleared write fOnCleared;
property OnDeleted: TStringListChangeEvent read fOnDeleted write fOnDeleted;
property OnInserted: TStringListChangeEvent read fOnInserted
write fOnInserted;
property OnPutted: TStringListChangeEvent read fOnPutted write fOnPutted;
property ConvertTabsProc: TConvertTabsProcEx read fConvertTabsProc;
void clear();
void deleteAt(int Index);
void deleteLines(int Index, int NumLines);
void Exchange(int Index1, int Index2);
void Insert(int Index, const QString& s);
void InsertLines(int Index, int NumLines);
void InsertStrings(int Index, const QStringList& NewStrings);
void InsertText(int Index,const QString& NewText);
void LoadFromFile(QFile& file, const QByteArray& encoding, QByteArray& realEncoding);
void SaveToFile(QFile& file, const QByteArray& encoding, QByteArray& realEncoding);
bool getAppendNewLineAtEOF() const;
void setAppendNewLineAtEOF(bool appendNewLineAtEOF);
ConvertTabsProcEx getConvertTabsProc() const;
FileEndingType getFileEndingType() const;
void setFileEndingType(const FileEndingType &fileEndingType);
signals:
void changed();
void changing();
@ -126,22 +109,117 @@ protected:
QString GetTextStr();
void SetUpdateState(bool Updating);
void InsertItem(int Index, const QString& s);
void PutTextStr(const QString& text);
private:
SynEditStringRecList mList;
//int mCount;
//int mCapacity;
SynEditFileFormat mFileFormat;
FileEndingType mFileEndingType;
bool mAppendNewLineAtEOF;
ConvertTabsProcEx mConvertTabsProc;
int mIndexOfLongestLine;
int mTabWidth;
int mUpdateCount;
QString ExpandString(int Index);
};
enum class SynChangeReason {crInsert, crPaste, crDragDropInsert,
//several undo entries can be chained together via the ChangeNumber
//see also TCustomSynEdit.[Begin|End]UndoBlock methods
crDeleteAfterCursor, crDelete,
crLineBreak, crIndent, crUnindent,
crSilentDelete, crSilentDeleteAfterCursor,
crAutoCompleteBegin, crAutoCompleteEnd,
crPasteBegin, crPasteEnd, //for pasting, since it might do a lot of operations
crSpecial1Begin, crSpecial1End,
crSpecial2Begin, crSpecial2End,
crCaret, //just restore the Caret, allowing better Undo behavior
crSelection, //restore Selection
crNothing,
crGroupBreak,
crDeleteAll
};
class SynEditUndoItem {
private:
SynChangeReason mChangeReason;
SynSelectionMode mChangeSelMode;
BufferCoord mChangeStartPos;
BufferCoord mChangeEndPos;
QString mChangeStr;
int mChangeNumber;
public:
SynEditUndoItem(SynChangeReason reason,
SynSelectionMode selMode,
BufferCoord startPos,
BufferCoord endPos,
const QString& str,
int number);
SynChangeReason changeReason() const;
SynSelectionMode changeSelMode() const;
BufferCoord changeStartPos() const;
BufferCoord changeEndPos() const;
QString changeStr() const;
int changeNumber() const;
};
using PSynEditUndoItem = std::shared_ptr<SynEditUndoItem>;
class SynEditUndoList {
public:
explicit SynEditUndoList();
void AddChange(SynChangeReason AReason, const BufferCoord& AStart, const BufferCoord& AEnd,
const QString& ChangeText, SynSelectionMode SelMode);
void AddGroupBreak();
void BeginBlock();
void Clear();
void DeleteItem(int index);
void EndBlock();
SynChangeReason LastChangeReason();
void Lock();
PSynEditUndoItem PeekItem();
PSynEditUndoItem PopItem();
void PushItem(PSynEditUndoItem Item);
void Unlock();
bool CanUndo();
int ItemCount();
int maxUndoActions() const;
void setMaxUndoActions(int maxUndoActions);
bool initialState();
PSynEditUndoItem item(int index);
void setInitialState(const bool Value);
void setItem(int index, PSynEditUndoItem Value);
int blockChangeNumber() const;
void setBlockChangeNumber(int blockChangeNumber);
int blockCount() const;
bool insideRedo() const;
void setInsideRedo(bool insideRedo);
bool fullUndoImposible() const;
signals:
void addedUndo();
protected:
int mBlockChangeNumber;
int mBlockCount;
bool mFullUndoImposible;
QVector<PSynEditUndoItem> mItems;
int mLockCount;
int mMaxUndoActions;
int mNextChangeNumber;
int mInitialChangeNumber;
bool mInsideRedo;
void EnsureMaxEntries();
};
#endif // SYNEDITSTRINGLIST_H

View File

@ -0,0 +1,14 @@
#ifndef TYPES_H
#define TYPES_H
enum class SynSelectionMode {smNormal, smLine, smColumn};
struct BufferCoord {
int Char;
int Line;
};
struct DisplayCoord {
int Column;
int Row;
};
#endif // TYPES_H

View File

@ -7,6 +7,7 @@
#include <QMap>
#include <QSet>
#include <QVector>
#include <QVector>
typedef struct {
int state;
@ -151,6 +152,6 @@ private:
};
using PSynHighlighter = std::shared_ptr<SynHighlighter>;
using SynHighlighterList = QList<PSynHighlighter>;
using SynHighlighterList = QVector<PSynHighlighter>;
#endif // SYNHIGHLIGTERBASE_H

View File

@ -7,8 +7,8 @@
class SynSchema;
using PSynSchema = std::shared_ptr<SynSchema>;
using OnCheckMarker = void (*)(PSynSchema Sender,int &StartPos, int &MarkerLen,
std::shared_ptr<QString>& MarkerText , int Line);
using OnCheckMarker = std::function<void(PSynSchema Sender,int &StartPos, int &MarkerLen,
std::shared_ptr<QString>& MarkerText , int Line)>;
class SynScheme : public QObject {
Q_OBJECT

View File

@ -253,3 +253,79 @@ QString toLocalPath(const QString &filename)
newPath.replace("/",QDir::separator());
return newPath;
}
QStringList TextToLines(const QString &text)
{
QTextStream stream(&((QString&)text),QIODevice::ReadOnly);
return ReadStreamToLines(&stream);
}
QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec)
{
QFile file(fileName);
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
stream.setCodec(codec);
stream.setAutoDetectUnicode(false);
return ReadStreamToLines(&stream);
}
return QStringList();
}
QStringList ReadStreamToLines(QTextStream *stream)
{
QStringList list;
QString s;
while (stream->readLineInto(&s)) {
list.append(s);
}
return list;
}
void ReadStreamToLines(QTextStream *stream,
LineProcessFunc lineFunc)
{
QString s;
while (stream->readLineInto(&s)) {
lineFunc(s);
}
}
void TextToLines(const QString &text, LineProcessFunc lineFunc)
{
QTextStream stream(&((QString&)text),QIODevice::ReadOnly);
ReadStreamToLines(&stream,lineFunc);
}
void ReadFileToLines(const QString &fileName, QTextCodec *codec, LineProcessFunc lineFunc)
{
QFile file(fileName);
if (file.open(QFile::ReadOnly)) {
QTextStream stream(&file);
stream.setCodec(codec);
stream.setAutoDetectUnicode(false);
ReadStreamToLines(&stream, lineFunc);
}
}
BaseError::BaseError(const QString &reason):
mReason(reason)
{
}
QString BaseError::reason() const
{
return mReason;
}
IndexOutOfRange::IndexOutOfRange(int Index):
BaseError(QObject::tr("Index %1 out of range").arg(Index))
{
}
FileError::FileError(const QString &reason): BaseError(reason)
{
}

View File

@ -3,10 +3,14 @@
#include <type_traits>
#include <utility>
#include <functional>
#include <QString>
class QByteArray;
class QString;
class QStringList;
class QTextStream;
class QTextCodec;
#define ENCODING_AUTO_DETECT "AUTO"
#define ENCODING_UTF8 "UTF-8"
@ -23,6 +27,31 @@ enum class FileType{
Other // any others
};
enum class FileEndingType {
Windows,
Linux,
Mac
};// Windows: CRLF, UNIX: LF, Mac: CR
class BaseError{
public:
explicit BaseError(const QString& reason);
QString reason() const;
protected:
QString mReason;
};
class IndexOutOfRange:public BaseError {
public:
explicit IndexOutOfRange(int Index);
};
class FileError: public BaseError {
public:
explicit FileError(const QString& reason);
};
typedef void (*LineOutputFunc) (const QString& line);
typedef bool (*CheckAbortFunc) ();
bool isGreenEdition();
@ -46,6 +75,21 @@ void splitStringArguments(const QString& arguments, QStringList& argumentList);
bool programHasConsole(const QString& filename);
QString toLocalPath(const QString& filename);
using LineProcessFunc = std::function<void(const QString&)>;
QStringList ReadStreamToLines(QTextStream* stream);
void ReadStreamToLines(QTextStream* stream, LineProcessFunc lineFunc);
QStringList TextToLines(const QString& text);
void TextToLines(const QString& text, LineProcessFunc lineFunc);
QStringList ReadFileToLines(const QString& fileName, QTextCodec* codec);
void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc lineFunc);
template <class F>
class final_action
{