work save
This commit is contained in:
parent
813bacebfb
commit
100ceeda6c
|
@ -16,6 +16,9 @@ SOURCES += \
|
||||||
compiler/executablerunner.cpp \
|
compiler/executablerunner.cpp \
|
||||||
compiler/filecompiler.cpp \
|
compiler/filecompiler.cpp \
|
||||||
compiler/stdincompiler.cpp \
|
compiler/stdincompiler.cpp \
|
||||||
|
qsynedit/Search.cpp \
|
||||||
|
qsynedit/SearchBase.cpp \
|
||||||
|
qsynedit/SearchRegex.cpp \
|
||||||
settingsdialog/debuggeneralwidget.cpp \
|
settingsdialog/debuggeneralwidget.cpp \
|
||||||
widgets/cpudialog.cpp \
|
widgets/cpudialog.cpp \
|
||||||
debugger.cpp \
|
debugger.cpp \
|
||||||
|
@ -68,6 +71,9 @@ HEADERS += \
|
||||||
compiler/executablerunner.h \
|
compiler/executablerunner.h \
|
||||||
compiler/filecompiler.h \
|
compiler/filecompiler.h \
|
||||||
compiler/stdincompiler.h \
|
compiler/stdincompiler.h \
|
||||||
|
qsynedit/Search.h \
|
||||||
|
qsynedit/SearchBase.h \
|
||||||
|
qsynedit/SearchRegex.h \
|
||||||
settingsdialog/debuggeneralwidget.h \
|
settingsdialog/debuggeneralwidget.h \
|
||||||
widgets/cpudialog.h \
|
widgets/cpudialog.h \
|
||||||
debugger.h \
|
debugger.h \
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "Search.h"
|
||||||
|
|
||||||
|
SynSearch::SynSearch(QObject *parent):SynSearchBase(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearch::length(int aIndex)
|
||||||
|
{
|
||||||
|
if (aIndex<0 || aIndex >= mResults.length())
|
||||||
|
return 0;
|
||||||
|
return pattern().length();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearch::result(int aIndex)
|
||||||
|
{
|
||||||
|
if (aIndex<0 || aIndex >= mResults.length())
|
||||||
|
return -1;
|
||||||
|
return mResults[aIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearch::resultCount()
|
||||||
|
{
|
||||||
|
return mResults.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearch::findAll(const QString &newText)
|
||||||
|
{
|
||||||
|
mResults.clear();
|
||||||
|
if (pattern().isEmpty())
|
||||||
|
return 0;
|
||||||
|
int start=0;
|
||||||
|
int next=-1;
|
||||||
|
while (true) {
|
||||||
|
if (options.testFlag(ssoMatchCase)) {
|
||||||
|
next = newText.indexOf(pattern(),start,Qt::CaseSensitive);
|
||||||
|
} else {
|
||||||
|
next = newText.indexOf(pattern(),start,Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
if (next<0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mResults.append(next);
|
||||||
|
start = next;
|
||||||
|
}
|
||||||
|
return mResults.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SynSearch::replace(const QString &aOccurrence, const QString &aReplacement)
|
||||||
|
{
|
||||||
|
return aReplacement;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef SYNSEARCH_H
|
||||||
|
#define SYNSEARCH_H
|
||||||
|
#include "SearchBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
class SynSearch : public SynSearchBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SynSearch(QObject* parent = nullptr);
|
||||||
|
|
||||||
|
// SynSearchBase interface
|
||||||
|
public:
|
||||||
|
int length(int aIndex) override;
|
||||||
|
int result(int aIndex) override;
|
||||||
|
int resultCount() override;
|
||||||
|
int findAll(const QString &newText) override;
|
||||||
|
QString replace(const QString &aOccurrence, const QString &aReplacement) override;
|
||||||
|
private:
|
||||||
|
QList<int> mResults;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYNSEARCH_H
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "SearchBase.h"
|
||||||
|
|
||||||
|
SynSearchBase::SynSearchBase(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SynSearchBase::pattern()
|
||||||
|
{
|
||||||
|
return mPattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynSearchBase::setPattern(const QString &value)
|
||||||
|
{
|
||||||
|
mPattern = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
SynSearchOptions SynSearchBase::options() const
|
||||||
|
{
|
||||||
|
return mOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynSearchBase::setOptions(const SynSearchOptions &options)
|
||||||
|
{
|
||||||
|
mOptions = options;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef SYNSEARCHBASE_H
|
||||||
|
#define SYNSEARCHBASE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
enum SynSearchOption {
|
||||||
|
ssoMatchCase, ssoWholeWord, ssoBackwards,
|
||||||
|
ssoEntireScope, ssoSelectedOnly, ssoReplace, ssoReplaceAll, ssoPrompt,
|
||||||
|
ssoRegExp};
|
||||||
|
|
||||||
|
Q_DECLARE_FLAGS(SynSearchOptions, SynSearchOption)
|
||||||
|
Q_DECLARE_OPERATORS_FOR_FLAGS(SynSearchOptions)
|
||||||
|
|
||||||
|
class SynSearchBase : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SynSearchBase(QObject *parent = nullptr);
|
||||||
|
QString pattern();
|
||||||
|
virtual void setPattern(const QString& value);
|
||||||
|
virtual int length(int aIndex) = 0;
|
||||||
|
virtual int result(int aIndex) = 0;
|
||||||
|
virtual int resultCount() = 0;
|
||||||
|
virtual int findAll(const QString& newText) = 0;
|
||||||
|
virtual QString replace(const QString& aOccurrence, const QString& aReplacement) = 0;
|
||||||
|
SynSearchOptions options() const;
|
||||||
|
virtual void setOptions(const SynSearchOptions &options);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString mPattern;
|
||||||
|
SynSearchOptions mOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PSynSearchBase = std::shared_ptr<SynSearchBase>;
|
||||||
|
|
||||||
|
#endif // SYNSEARCHBASE_H
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include "SearchRegex.h"
|
||||||
|
|
||||||
|
#include <QRegExp>
|
||||||
|
|
||||||
|
SynSearchRegex::SynSearchRegex(QObject* parent):SynSearchBase(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearchRegex::length(int aIndex)
|
||||||
|
{
|
||||||
|
if (aIndex<0 || aIndex >= mResults.length())
|
||||||
|
return -1;
|
||||||
|
return mLengths[aIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearchRegex::result(int aIndex)
|
||||||
|
{
|
||||||
|
if (aIndex<0 || aIndex >= mResults.length())
|
||||||
|
return -1;
|
||||||
|
return mResults[aIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearchRegex::resultCount()
|
||||||
|
{
|
||||||
|
return mResults.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SynSearchRegex::findAll(const QString &newText)
|
||||||
|
{
|
||||||
|
if (pattern().isEmpty())
|
||||||
|
return 0;
|
||||||
|
mResults.clear();
|
||||||
|
mLengths.clear();
|
||||||
|
QRegularExpressionMatchIterator it = mRegex.globalMatch(newText);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QRegularExpressionMatch match = it.next();
|
||||||
|
mLengths.append(match.capturedLength());
|
||||||
|
mResults.append(match.capturedStart());
|
||||||
|
}
|
||||||
|
return mResults.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString SynSearchRegex::replace(const QString &aOccurrence, const QString &aReplacement)
|
||||||
|
{
|
||||||
|
QString s=aOccurrence;
|
||||||
|
return s.replace(mRegex,aReplacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynSearchRegex::setPattern(const QString &value)
|
||||||
|
{
|
||||||
|
SynSearchBase::setPattern(value);
|
||||||
|
mRegex.setPattern(value);
|
||||||
|
updateRegexOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynSearchRegex::setOptions(const SynSearchOptions &options)
|
||||||
|
{
|
||||||
|
SynSearchBase::setOptions(options);
|
||||||
|
updateRegexOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynSearchRegex::updateRegexOptions()
|
||||||
|
{
|
||||||
|
if (options().testFlag(SynSearchOption::ssoMatchCase)) {
|
||||||
|
mRegex.setPatternOptions(
|
||||||
|
mRegex.patternOptions() &
|
||||||
|
~QRegularExpression::CaseInsensitiveOption);
|
||||||
|
} else {
|
||||||
|
mRegex.setPatternOptions(
|
||||||
|
mRegex.patternOptions() |
|
||||||
|
QRegularExpression::CaseInsensitiveOption);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef SYNSEARCHREGEX_H
|
||||||
|
#define SYNSEARCHREGEX_H
|
||||||
|
#include "SearchBase.h"
|
||||||
|
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
class SynSearchRegex : public SynSearchBase
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SynSearchRegex(QObject* parent=nullptr);
|
||||||
|
|
||||||
|
// SynSearchBase interface
|
||||||
|
public:
|
||||||
|
int length(int aIndex) override;
|
||||||
|
int result(int aIndex) override;
|
||||||
|
int resultCount() override;
|
||||||
|
int findAll(const QString &newText) override;
|
||||||
|
QString replace(const QString &aOccurrence, const QString &aReplacement) override;
|
||||||
|
void setPattern(const QString &value) override;
|
||||||
|
void setOptions(const SynSearchOptions &options) override;
|
||||||
|
private:
|
||||||
|
void updateRegexOptions();
|
||||||
|
private:
|
||||||
|
QRegularExpression mRegex;
|
||||||
|
QList<int> mLengths;
|
||||||
|
QList<int> mResults;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SYNSEARCHREGEX_H
|
|
@ -3208,6 +3208,16 @@ void SynEdit::doScrolled(int)
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PSynSearchBase SynEdit::searchEngine() const
|
||||||
|
{
|
||||||
|
return mSearchEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynEdit::setSearchEngine(const PSynSearchBase &searchEngine)
|
||||||
|
{
|
||||||
|
mSearchEngine = searchEngine;
|
||||||
|
}
|
||||||
|
|
||||||
int SynEdit::textHeight() const
|
int SynEdit::textHeight() const
|
||||||
{
|
{
|
||||||
return mTextHeight;
|
return mTextHeight;
|
||||||
|
@ -4155,6 +4165,169 @@ void SynEdit::setSelText(const QString &Value)
|
||||||
mActiveSelectionMode);
|
mActiveSelectionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SynEdit::searchReplace(const QString &ASearch, const QString &AReplace, SynSearchOptions AOptions)
|
||||||
|
{
|
||||||
|
if (!mSearchEngine)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// can't search for or replace an empty string
|
||||||
|
if (ASearch.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int Result = 0;
|
||||||
|
// get the text range to search in, ignore the "Search in selection only"
|
||||||
|
// option if nothing is selected
|
||||||
|
bool bBackward = AOptions.testFlag(ssoBackwards);
|
||||||
|
bool bPrompt = AOptions.testFlag(ssoPrompt);
|
||||||
|
bool bReplace = AOptions.testFlag(ssoReplace);
|
||||||
|
bool bReplaceAll = AOptions.testFlag(ssoReplaceAll);
|
||||||
|
bool bFromCursor = !AOptions.testFlag(ssoEntireScope);
|
||||||
|
BufferCoord ptCurrent;
|
||||||
|
BufferCoord ptStart;
|
||||||
|
BufferCoord ptEnd;
|
||||||
|
if (!selAvail())
|
||||||
|
AOptions.setFlag(ssoSelectedOnly,false);
|
||||||
|
if (AOptions.testFlag(ssoSelectedOnly)) {
|
||||||
|
ptStart = blockBegin();
|
||||||
|
ptEnd = blockEnd();
|
||||||
|
// search the whole line in the line selection mode
|
||||||
|
if (mActiveSelectionMode == SynSelectionMode::smLine) {
|
||||||
|
ptStart.Char = 1;
|
||||||
|
ptEnd.Char = mLines->getString(ptEnd.Line - 1).length();
|
||||||
|
} else if (mActiveSelectionMode == SynSelectionMode::smColumn) {
|
||||||
|
// make sure the start column is smaller than the end column
|
||||||
|
if (ptStart.Char > ptEnd.Char)
|
||||||
|
std::swap(ptStart.Char,ptEnd.Char);
|
||||||
|
}
|
||||||
|
// ignore the cursor position when searching in the selection
|
||||||
|
if (bBackward) {
|
||||||
|
ptCurrent = ptEnd;
|
||||||
|
} else {
|
||||||
|
ptCurrent = ptStart;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ptStart.Char = 1;
|
||||||
|
ptStart.Line = 1;
|
||||||
|
ptEnd.Line = mLines->count();
|
||||||
|
ptEnd.Char = mLines->getString(ptEnd.Line - 1).length();
|
||||||
|
if (bFromCursor) {
|
||||||
|
if (bBackward)
|
||||||
|
ptEnd = caretXY();
|
||||||
|
else
|
||||||
|
ptStart = caretXY();
|
||||||
|
}
|
||||||
|
if (bBackward)
|
||||||
|
ptCurrent = ptEnd;
|
||||||
|
else
|
||||||
|
ptCurrent = ptStart;
|
||||||
|
}
|
||||||
|
// initialize the search engine
|
||||||
|
mSearchEngine->setOptions(AOptions);
|
||||||
|
mSearchEngine->setPattern(ASearch);
|
||||||
|
// search while the current search position is inside of the search range
|
||||||
|
int nReplaceLen = 0;
|
||||||
|
bool bEndUndoBlock =false;
|
||||||
|
doOnPaintTransient(SynTransientType::ttBefore);
|
||||||
|
if (bReplaceAll && !bPrompt) {
|
||||||
|
incPaintLock();
|
||||||
|
mUndoList->BeginBlock();
|
||||||
|
bEndUndoBlock = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto action = finally([&,this]{
|
||||||
|
if (bReplaceAll && !bPrompt)
|
||||||
|
decPaintLock();
|
||||||
|
if (bEndUndoBlock)
|
||||||
|
mUndoList->EndBlock();
|
||||||
|
doOnPaintTransient(SynTransientType::ttAfter);
|
||||||
|
});
|
||||||
|
while ((ptCurrent.Line >= ptStart.Line) && (ptCurrent.Line <= ptEnd.Line)) {
|
||||||
|
nInLine := fSearchEngine.FindAll(Lines[ptCurrent.Line - 1]);
|
||||||
|
iResultOffset := 0;
|
||||||
|
if bBackward then
|
||||||
|
n := Pred(fSearchEngine.ResultCount)
|
||||||
|
else
|
||||||
|
n := 0;
|
||||||
|
// Operate on all results in this line.
|
||||||
|
while nInLine > 0 do begin
|
||||||
|
// An occurrence may have been replaced with a text of different length
|
||||||
|
nFound := fSearchEngine.Results[n] + iResultOffset;
|
||||||
|
nSearchLen := fSearchEngine.Lengths[n];
|
||||||
|
if bBackward then
|
||||||
|
Dec(n)
|
||||||
|
else
|
||||||
|
Inc(n);
|
||||||
|
Dec(nInLine);
|
||||||
|
// Is the search result entirely in the search range?
|
||||||
|
if not InValidSearchRange(nFound, nFound + nSearchLen) then
|
||||||
|
continue;
|
||||||
|
Inc(Result);
|
||||||
|
// Select the text, so the user can see it in the OnReplaceText event
|
||||||
|
// handler or as the search result.
|
||||||
|
|
||||||
|
ptCurrent.Char := nFound;
|
||||||
|
BlockBegin := ptCurrent;
|
||||||
|
//Be sure to use the Ex version of CursorPos so that it appears in the middle if necessary
|
||||||
|
SetCaretXYEx(False, BufferCoord(1, ptCurrent.Line));
|
||||||
|
EnsureCursorPosVisibleEx(True);
|
||||||
|
Inc(ptCurrent.Char, nSearchLen);
|
||||||
|
BlockEnd := ptCurrent;
|
||||||
|
InternalCaretXY := ptCurrent;
|
||||||
|
if bBackward then
|
||||||
|
InternalCaretXY := BlockBegin
|
||||||
|
else
|
||||||
|
InternalCaretXY := ptCurrent;
|
||||||
|
// If it's a search only we can leave the procedure now.
|
||||||
|
if not (bReplace or bReplaceAll) then
|
||||||
|
exit;
|
||||||
|
// Prompt and replace or replace all. If user chooses to replace
|
||||||
|
// all after prompting, turn off prompting.
|
||||||
|
if bPrompt and Assigned(fOnReplaceText) then begin
|
||||||
|
nAction := DoOnReplaceText(ASearch, AReplace, ptCurrent.Line, nFound, nSearchLen);
|
||||||
|
if nAction = raCancel then
|
||||||
|
exit;
|
||||||
|
end else
|
||||||
|
nAction := raReplace;
|
||||||
|
if nAction <> raSkip then begin
|
||||||
|
// user has been prompted and has requested to silently replace all
|
||||||
|
// so turn off prompting
|
||||||
|
if nAction = raReplaceAll then begin
|
||||||
|
if (not bReplaceAll) or bPrompt then begin
|
||||||
|
bReplaceAll := TRUE;
|
||||||
|
IncPaintLock;
|
||||||
|
end;
|
||||||
|
bPrompt := False;
|
||||||
|
if bEndUndoBlock = false then
|
||||||
|
BeginUndoBlock;
|
||||||
|
bEndUndoBlock := true;
|
||||||
|
end;
|
||||||
|
//Allow advanced substition in the search engine
|
||||||
|
SelText := fSearchEngine.Replace(SelText, AReplace);
|
||||||
|
nReplaceLen := CaretX - nFound;
|
||||||
|
end;
|
||||||
|
// fix the caret position and the remaining results
|
||||||
|
if not bBackward then begin
|
||||||
|
InternalCaretX := nFound + nReplaceLen;
|
||||||
|
if (nSearchLen <> nReplaceLen) and (nAction <> raSkip) then begin
|
||||||
|
Inc(iResultOffset, nReplaceLen - nSearchLen);
|
||||||
|
if (fActiveSelectionMode <> smColumn) and (CaretY = ptEnd.Line) then begin
|
||||||
|
Inc(ptEnd.Char, nReplaceLen - nSearchLen);
|
||||||
|
BlockEnd := ptEnd;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if not bReplaceAll then
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
// search next / previous line
|
||||||
|
if bBackward then
|
||||||
|
Dec(ptCurrent.Line)
|
||||||
|
else
|
||||||
|
Inc(ptCurrent.Line);
|
||||||
|
end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SynEdit::DoLinesDeleted(int FirstLine, int Count)
|
void SynEdit::DoLinesDeleted(int FirstLine, int Count)
|
||||||
{
|
{
|
||||||
// // gutter marks
|
// // gutter marks
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "TextBuffer.h"
|
#include "TextBuffer.h"
|
||||||
#include "KeyStrokes.h"
|
#include "KeyStrokes.h"
|
||||||
|
#include "SearchBase.h"
|
||||||
|
|
||||||
enum class SynFontSmoothMethod {
|
enum class SynFontSmoothMethod {
|
||||||
None, AntiAlias, ClearType
|
None, AntiAlias, ClearType
|
||||||
|
@ -214,6 +215,8 @@ public:
|
||||||
PSynEditFoldRange foldHidesLine(int line);
|
PSynEditFoldRange foldHidesLine(int line);
|
||||||
void setSelText(const QString& Value);
|
void setSelText(const QString& Value);
|
||||||
|
|
||||||
|
int searchReplace(const QString& ASearch, const QString& AReplace, SynSearchOptions AOptions);
|
||||||
|
|
||||||
int maxScrollWidth() const;
|
int maxScrollWidth() const;
|
||||||
int maxScrollHeight() const;
|
int maxScrollHeight() const;
|
||||||
|
|
||||||
|
@ -322,6 +325,9 @@ public:
|
||||||
|
|
||||||
int textHeight() const;
|
int textHeight() const;
|
||||||
|
|
||||||
|
PSynSearchBase searchEngine() const;
|
||||||
|
void setSearchEngine(const PSynSearchBase &searchEngine);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Changed();
|
void Changed();
|
||||||
|
|
||||||
|
@ -587,6 +593,8 @@ private:
|
||||||
int mScrollDeltaX;
|
int mScrollDeltaX;
|
||||||
int mScrollDeltaY;
|
int mScrollDeltaY;
|
||||||
|
|
||||||
|
PSynSearchBase mSearchEngine;
|
||||||
|
|
||||||
PSynEdit fChainedEditor;
|
PSynEdit fChainedEditor;
|
||||||
|
|
||||||
int mPaintTransientLock;
|
int mPaintTransientLock;
|
||||||
|
|
Loading…
Reference in New Issue