fix: 重构查找对话框;搜索字节支持'?'通配符;
This commit is contained in:
parent
3b4d1a1d4b
commit
90241e89ff
|
@ -65,8 +65,7 @@ add_library(
|
|||
QHexEdit2/chunks.cpp
|
||||
QHexEdit2/chunks.h
|
||||
qhexview.h
|
||||
qhexview.cpp
|
||||
)
|
||||
qhexview.cpp)
|
||||
|
||||
set_target_properties(
|
||||
QHexView
|
||||
|
@ -74,6 +73,8 @@ set_target_properties(
|
|||
CXX_STANDARD 17
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
target_compile_definitions(QHexView PUBLIC QHEXVIEW_FIND_LIMIT=1000)
|
||||
|
||||
target_link_libraries(
|
||||
QHexView PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Gui
|
||||
Qt${QT_VERSION_MAJOR}::Concurrent)
|
||||
|
|
|
@ -414,8 +414,8 @@ void QHexDocument::applyBookMarks(const QMap<qsizetype, QString> &books) {
|
|||
emit documentChanged();
|
||||
}
|
||||
|
||||
void QHexDocument::findAllBytes(qsizetype begin, qsizetype end, QByteArray b,
|
||||
QList<qsizetype> &results,
|
||||
void QHexDocument::findAllBytes(qsizetype begin, qsizetype end,
|
||||
const QByteArray &b, QList<qsizetype> &results,
|
||||
const std::function<bool()> &pred) {
|
||||
results.clear();
|
||||
if (!b.length())
|
||||
|
@ -424,20 +424,59 @@ void QHexDocument::findAllBytes(qsizetype begin, qsizetype end, QByteArray b,
|
|||
qsizetype e = end > begin ? end : -1;
|
||||
auto offset = b.size();
|
||||
while (pred()) {
|
||||
p = m_buffer->indexOf(b, p);
|
||||
p = findNext(p, b);
|
||||
if (p < 0 || (e > 0 && p > e)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (results.size() ==
|
||||
std::numeric_limits<QList<qsizetype>::size_type>::max()) {
|
||||
if (results.size() > QHEXVIEW_FIND_LIMIT) {
|
||||
break;
|
||||
}
|
||||
results.append(p);
|
||||
p += offset + 1;
|
||||
p += offset;
|
||||
}
|
||||
}
|
||||
|
||||
qsizetype QHexDocument::findAllBytesExt(qsizetype begin, qsizetype end,
|
||||
const QString &pattern,
|
||||
QList<qsizetype> &results,
|
||||
const std::function<bool()> &pred) {
|
||||
results.clear();
|
||||
auto patterns = parseConvertPattern(pattern);
|
||||
if (patterns.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
qsizetype p = begin > 0 ? begin : 0;
|
||||
qsizetype e = end > begin ? end : -1;
|
||||
|
||||
qsizetype offset = 0;
|
||||
for (auto &p : patterns) {
|
||||
if (std::holds_alternative<QByteArray>(p)) {
|
||||
offset += std::get<QByteArray>(p).length();
|
||||
} else if (std::holds_alternative<size_t>(p)) {
|
||||
offset += std::get<size_t>(p);
|
||||
} else if (std::holds_alternative<HexWildItem>(p)) {
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (pred()) {
|
||||
p = findNextExt(p, pattern);
|
||||
if (p < 0 || (e > 0 && p > e)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (results.size() > QHEXVIEW_FIND_LIMIT) {
|
||||
break;
|
||||
}
|
||||
results.append(p);
|
||||
p += offset;
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
bool QHexDocument::insert(qsizetype offset, uchar b) {
|
||||
if (m_keepsize || m_readonly || m_islocked ||
|
||||
(offset < m_buffer->length() && m_metadata->hasMetadata()))
|
||||
|
@ -499,6 +538,287 @@ bool QHexDocument::_remove(qsizetype offset, qsizetype len) {
|
|||
return true;
|
||||
}
|
||||
|
||||
qsizetype QHexDocument::findNextExt(qsizetype begin,
|
||||
const QList<FindStep> &patterns) {
|
||||
auto op = [this](qsizetype &pos, const FindStep &step,
|
||||
qsizetype *begin = nullptr) -> bool {
|
||||
if (pos < 0 || pos >= length()) {
|
||||
return false;
|
||||
}
|
||||
if (std::holds_alternative<QByteArray>(step)) {
|
||||
auto v = std::get<QByteArray>(step);
|
||||
auto len = v.length();
|
||||
auto r = findNext(pos, v);
|
||||
if (r >= 0) {
|
||||
if (begin) {
|
||||
*begin = r;
|
||||
} else {
|
||||
if (r != pos) {
|
||||
pos = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pos = r + len;
|
||||
return true;
|
||||
} else {
|
||||
pos = -1;
|
||||
return false;
|
||||
}
|
||||
} else if (std::holds_alternative<HexWildItem>(step)) {
|
||||
auto v = std::get<HexWildItem>(step);
|
||||
auto wc = uchar(at(pos));
|
||||
pos += 1;
|
||||
|
||||
if (v.higher == '?') {
|
||||
if ((wc & 0xf) == v.lower) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ((wc >> 4) == v.higher) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (std::holds_alternative<size_t>(step)) {
|
||||
auto v = std::get<size_t>(step);
|
||||
pos += v;
|
||||
if (v + pos < length()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
while (begin < length()) {
|
||||
auto pos = begin;
|
||||
|
||||
auto p = patterns.cbegin();
|
||||
auto r = op(pos, *p, &begin);
|
||||
if (!r) {
|
||||
if (pos < 0) {
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
++p;
|
||||
|
||||
bool ok = true;
|
||||
for (; p != patterns.cend(); ++p) {
|
||||
auto r = op(pos, *p);
|
||||
if (!r) {
|
||||
ok = false;
|
||||
if (pos < 0) {
|
||||
return -1;
|
||||
}
|
||||
begin = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
return begin;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
qsizetype QHexDocument::findPreviousExt(qsizetype begin,
|
||||
const QList<FindStep> &patterns) {
|
||||
auto op = [this](qsizetype &pos, const FindStep &step,
|
||||
qsizetype *begin = nullptr) -> bool {
|
||||
if (pos < 0 || pos >= length()) {
|
||||
return false;
|
||||
}
|
||||
if (std::holds_alternative<QByteArray>(step)) {
|
||||
auto v = std::get<QByteArray>(step);
|
||||
auto len = v.length();
|
||||
auto r = findPrevious(pos, v);
|
||||
if (r >= 0) {
|
||||
if (begin) {
|
||||
*begin = r;
|
||||
} else {
|
||||
if (r + len != pos) {
|
||||
pos = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pos = r - len;
|
||||
return true;
|
||||
} else {
|
||||
pos = -1;
|
||||
return false;
|
||||
}
|
||||
} else if (std::holds_alternative<HexWildItem>(step)) {
|
||||
auto v = std::get<HexWildItem>(step);
|
||||
auto wc = uchar(at(pos));
|
||||
pos -= 1;
|
||||
|
||||
if (v.higher == '?') {
|
||||
if ((wc & 0xf) == v.lower) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ((wc >> 4) == v.higher) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (std::holds_alternative<size_t>(step)) {
|
||||
auto v = std::get<size_t>(step);
|
||||
pos -= v;
|
||||
if (v - pos >= 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
while (begin >= 0) {
|
||||
auto pos = begin;
|
||||
|
||||
auto p = patterns.crbegin();
|
||||
auto r = op(pos, *p, &begin);
|
||||
if (!r) {
|
||||
if (pos < 0) {
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
++p;
|
||||
|
||||
bool ok = true;
|
||||
for (; p != patterns.crend(); ++p) {
|
||||
auto r = op(pos, *p);
|
||||
if (!r) {
|
||||
ok = false;
|
||||
if (pos < 0) {
|
||||
return -1;
|
||||
}
|
||||
begin = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
return begin;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
QList<QHexDocument::FindStep>
|
||||
QHexDocument::parseConvertPattern(const QString &pattern) {
|
||||
// process hex pattern
|
||||
QList<HexWildItem> words;
|
||||
std::optional<uchar> higher;
|
||||
for (auto pchar = pattern.cbegin(); pchar != pattern.cend(); ++pchar) {
|
||||
if (pchar->isSpace()) {
|
||||
if (higher) {
|
||||
return {};
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto c = pchar->unicode();
|
||||
if (c >= '0' && c <= '9') {
|
||||
if (higher) {
|
||||
HexWildItem item;
|
||||
item.higher = higher.value();
|
||||
item.lower = uchar(c) - '0';
|
||||
words.append(item);
|
||||
higher.reset();
|
||||
} else {
|
||||
higher = uchar(c) - '0';
|
||||
}
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
if (higher) {
|
||||
HexWildItem item;
|
||||
item.higher = higher.value();
|
||||
item.lower = uchar(c) - 'A' + 10;
|
||||
words.append(item);
|
||||
higher.reset();
|
||||
} else {
|
||||
higher = uchar(c) - 'A' + 10;
|
||||
}
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
if (higher) {
|
||||
HexWildItem item;
|
||||
item.higher = higher.value();
|
||||
item.lower = uchar(c) - 'a' + 10;
|
||||
words.append(item);
|
||||
higher.reset();
|
||||
} else {
|
||||
higher = uchar(c) - 'a' + 10;
|
||||
}
|
||||
} else if (c == '?') {
|
||||
if (higher) {
|
||||
HexWildItem item;
|
||||
item.higher = higher.value();
|
||||
item.lower = '?';
|
||||
words.append(item);
|
||||
higher.reset();
|
||||
} else {
|
||||
higher = '?';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (higher) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!words.isEmpty()) {
|
||||
QList<FindStep> steps;
|
||||
|
||||
// parsing...
|
||||
QByteArray buffer;
|
||||
size_t len = 0;
|
||||
for (auto pw = words.cbegin(); pw != words.cend(); ++pw) {
|
||||
auto higher = pw->higher;
|
||||
auto lower = pw->lower;
|
||||
if (higher == '?' || lower == '?') {
|
||||
if (higher == '?' && lower == '?') {
|
||||
if (!buffer.isEmpty()) {
|
||||
steps.append(buffer);
|
||||
buffer.clear();
|
||||
}
|
||||
len++;
|
||||
} else {
|
||||
if (len != 0) {
|
||||
steps.append(len);
|
||||
len = 0;
|
||||
}
|
||||
if (!buffer.isEmpty()) {
|
||||
steps.append(buffer);
|
||||
buffer.clear();
|
||||
}
|
||||
HexWildItem item;
|
||||
item.higher = higher;
|
||||
item.lower = lower;
|
||||
steps.append(item);
|
||||
}
|
||||
} else {
|
||||
if (len != 0) {
|
||||
steps.append(len);
|
||||
len = 0;
|
||||
}
|
||||
buffer.append(char(pw->higher << 4 | pw->lower));
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
if (len != 0) {
|
||||
steps.append(len);
|
||||
}
|
||||
if (!buffer.isEmpty()) {
|
||||
steps.append(buffer);
|
||||
}
|
||||
return steps;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/*======================*/
|
||||
|
||||
// modified by wingsummer
|
||||
|
@ -728,20 +1048,39 @@ bool QHexDocument::saveTo(QIODevice *device, bool cleanUndo) {
|
|||
return true;
|
||||
}
|
||||
|
||||
qsizetype QHexDocument::searchForward(qsizetype begin, const QByteArray &ba) {
|
||||
qsizetype QHexDocument::findNext(qsizetype begin, const QByteArray &ba) {
|
||||
if (begin < 0) {
|
||||
return -1;
|
||||
}
|
||||
return m_buffer->indexOf(ba, begin);
|
||||
}
|
||||
|
||||
qsizetype QHexDocument::searchBackward(qsizetype begin, const QByteArray &ba) {
|
||||
qsizetype QHexDocument::findPrevious(qsizetype begin, const QByteArray &ba) {
|
||||
if (begin < 0) {
|
||||
return -1;
|
||||
}
|
||||
return m_buffer->lastIndexOf(ba, begin);
|
||||
}
|
||||
|
||||
qsizetype QHexDocument::findNextExt(qsizetype begin, const QString &pattern) {
|
||||
auto patterns = parseConvertPattern(pattern);
|
||||
if (patterns.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return findNextExt(begin, patterns);
|
||||
}
|
||||
|
||||
qsizetype QHexDocument::findPreviousExt(qsizetype begin,
|
||||
const QString &pattern) {
|
||||
auto patterns = parseConvertPattern(pattern);
|
||||
if (patterns.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return findPreviousExt(begin, patterns);
|
||||
}
|
||||
|
||||
QHexDocument *QHexDocument::fromLargeFile(const QString &filename,
|
||||
bool readonly) {
|
||||
|
||||
|
|
|
@ -103,7 +103,13 @@ public:
|
|||
bool existBookMark(qsizetype pos);
|
||||
|
||||
void findAllBytes(
|
||||
qsizetype begin, qsizetype end, QByteArray b, QList<qsizetype> &results,
|
||||
qsizetype begin, qsizetype end, const QByteArray &b,
|
||||
QList<qsizetype> &results,
|
||||
const std::function<bool()> &pred = [] { return true; });
|
||||
|
||||
qsizetype findAllBytesExt(
|
||||
qsizetype begin, qsizetype end, const QString &pattern,
|
||||
QList<qsizetype> &results,
|
||||
const std::function<bool()> &pred = [] { return true; });
|
||||
|
||||
bool isDocSaved();
|
||||
|
@ -179,8 +185,11 @@ public slots:
|
|||
/*================================*/
|
||||
// added by wingsummer
|
||||
|
||||
qsizetype searchForward(qsizetype begin, const QByteArray &ba);
|
||||
qsizetype searchBackward(qsizetype begin, const QByteArray &ba);
|
||||
qsizetype findNext(qsizetype begin, const QByteArray &ba);
|
||||
qsizetype findPrevious(qsizetype begin, const QByteArray &ba);
|
||||
|
||||
qsizetype findNextExt(qsizetype begin, const QString &pattern);
|
||||
qsizetype findPreviousExt(qsizetype begin, const QString &pattern);
|
||||
|
||||
bool insert(qsizetype offset, uchar b);
|
||||
bool insert(qsizetype offset, const QByteArray &data);
|
||||
|
@ -194,6 +203,20 @@ public slots:
|
|||
bool _replace(qsizetype offset, const QByteArray &data);
|
||||
bool _remove(qsizetype offset, qsizetype len);
|
||||
|
||||
private:
|
||||
// AB
|
||||
struct HexWildItem {
|
||||
uchar higher; // A
|
||||
uchar lower; // B
|
||||
};
|
||||
|
||||
// std::variant< find-content, hex with wildcard, all-wildcards >
|
||||
using FindStep = std::variant<QByteArray, HexWildItem, size_t>;
|
||||
|
||||
QList<FindStep> parseConvertPattern(const QString &pattern);
|
||||
qsizetype findNextExt(qsizetype begin, const QList<FindStep> &patterns);
|
||||
qsizetype findPreviousExt(qsizetype begin, const QList<FindStep> &patterns);
|
||||
|
||||
/*================================*/
|
||||
|
||||
/*================================*/
|
||||
|
|
|
@ -321,6 +321,9 @@ void QHexRenderer::unprintableChars(QByteArray &ascii) const {
|
|||
}
|
||||
|
||||
QByteArray QHexRenderer::toHexSequence(const QByteArray &arr) {
|
||||
if (arr.isEmpty()) {
|
||||
return QByteArray(1, '\t');
|
||||
}
|
||||
const int length = arr.size() * 4;
|
||||
QByteArray hex(length, Qt::Uninitialized);
|
||||
char *hexData = hex.data();
|
||||
|
|
|
@ -336,21 +336,21 @@ void QHexView::setCopyLimit(qsizetype newCopylimit) {
|
|||
|
||||
qreal QHexView::scaleRate() const { return m_scaleRate; }
|
||||
|
||||
qsizetype QHexView::searchForward(qsizetype begin, const QByteArray &ba) {
|
||||
qsizetype QHexView::findNext(qsizetype begin, const QByteArray &ba) {
|
||||
if (begin < 0) {
|
||||
begin = m_cursor->position().offset();
|
||||
}
|
||||
return m_document->searchForward(begin, ba);
|
||||
return m_document->findNext(begin, ba);
|
||||
}
|
||||
|
||||
qsizetype QHexView::searchBackward(qsizetype begin, const QByteArray &ba) {
|
||||
qsizetype QHexView::findPrevious(qsizetype begin, const QByteArray &ba) {
|
||||
qsizetype startPos;
|
||||
if (begin < 0) {
|
||||
startPos = m_cursor->position().offset() - 1;
|
||||
} else {
|
||||
startPos = begin;
|
||||
}
|
||||
return m_document->searchBackward(startPos, ba);
|
||||
return m_document->findPrevious(startPos, ba);
|
||||
}
|
||||
|
||||
bool QHexView::RemoveSelection(int nibbleindex) {
|
||||
|
|
|
@ -122,8 +122,8 @@ public:
|
|||
void setScaleRate(qreal rate);
|
||||
qreal scaleRate() const;
|
||||
|
||||
qsizetype searchForward(qsizetype begin, const QByteArray &ba);
|
||||
qsizetype searchBackward(qsizetype begin, const QByteArray &ba);
|
||||
qsizetype findNext(qsizetype begin, const QByteArray &ba);
|
||||
qsizetype findPrevious(qsizetype begin, const QByteArray &ba);
|
||||
|
||||
bool RemoveSelection(int nibbleindex = 1);
|
||||
bool removeSelection();
|
||||
|
|
|
@ -207,7 +207,8 @@ set(CONTROL_SRC
|
|||
src/control/qtlonglongspinbox.cpp
|
||||
src/control/qtlonglongspinbox.h
|
||||
src/control/dockwidgettab.h
|
||||
src/control/dockwidgettab.cpp)
|
||||
src/control/dockwidgettab.cpp
|
||||
src/control/qhextextedit.h src/control/qhextextedit.cpp)
|
||||
|
||||
set(CLASS_SRC
|
||||
src/class/logger.cpp
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -775,15 +775,15 @@ void WingAngelAPI::installHexReaderAPI(asIScriptEngine *engine) {
|
|||
|
||||
registerAPI<qsizetype(qsizetype, const CScriptArray &)>(
|
||||
engine,
|
||||
std::bind(&WingAngelAPI::_HexReader_searchForward, this,
|
||||
std::bind(&WingAngelAPI::_HexReader_findNext, this,
|
||||
std::placeholders::_1, std::placeholders::_2),
|
||||
QSIZETYPE_WRAP("searchForward(" QSIZETYPE " begin, byte[] &in ba)"));
|
||||
QSIZETYPE_WRAP("findNext(" QSIZETYPE " begin, byte[] &in ba)"));
|
||||
|
||||
registerAPI<qsizetype(qsizetype, const CScriptArray &)>(
|
||||
engine,
|
||||
std::bind(&WingAngelAPI::_HexReader_searchBackward, this,
|
||||
std::bind(&WingAngelAPI::_HexReader_findPrevious, this,
|
||||
std::placeholders::_1, std::placeholders::_2),
|
||||
QSIZETYPE_WRAP("searchBackward(" QSIZETYPE " begin, byte[] &in ba)"));
|
||||
QSIZETYPE_WRAP("findPrevious(" QSIZETYPE " begin, byte[] &in ba)"));
|
||||
|
||||
registerAPI<CScriptArray *(qsizetype, qsizetype, const CScriptArray &)>(
|
||||
engine,
|
||||
|
@ -2374,8 +2374,8 @@ CScriptArray *WingAngelAPI::_HexReader_readBytes(qsizetype offset,
|
|||
});
|
||||
}
|
||||
|
||||
qsizetype WingAngelAPI::_HexReader_searchForward(qsizetype begin,
|
||||
const CScriptArray &ba) {
|
||||
qsizetype WingAngelAPI::_HexReader_findNext(qsizetype begin,
|
||||
const CScriptArray &ba) {
|
||||
// If called from the script, there will always be an active
|
||||
// context, which can be used to obtain a pointer to the engine.
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
|
@ -2386,14 +2386,14 @@ qsizetype WingAngelAPI::_HexReader_searchForward(qsizetype begin,
|
|||
auto byteID = engine->GetTypeIdByDecl("byte");
|
||||
Q_ASSERT(byteID);
|
||||
auto bab = cArray2ByteArray(ba, byteID, &ok);
|
||||
return emit reader.searchForward(begin, bab);
|
||||
return emit reader.findNext(begin, bab);
|
||||
} else {
|
||||
return qsizetype(-1);
|
||||
}
|
||||
}
|
||||
|
||||
qsizetype WingAngelAPI::_HexReader_searchBackward(qsizetype begin,
|
||||
const CScriptArray &ba) {
|
||||
qsizetype WingAngelAPI::_HexReader_findPrevious(qsizetype begin,
|
||||
const CScriptArray &ba) {
|
||||
// If called from the script, there will always be an active
|
||||
// context, which can be used to obtain a pointer to the engine.
|
||||
asIScriptContext *ctx = asGetActiveContext();
|
||||
|
@ -2404,7 +2404,7 @@ qsizetype WingAngelAPI::_HexReader_searchBackward(qsizetype begin,
|
|||
auto byteID = engine->GetTypeIdByDecl("byte");
|
||||
auto bab = cArray2ByteArray(ba, byteID, &ok);
|
||||
if (ok) {
|
||||
return emit reader.searchBackward(begin, bab);
|
||||
return emit reader.findPrevious(begin, bab);
|
||||
} else {
|
||||
return qsizetype(-1);
|
||||
}
|
||||
|
|
|
@ -223,10 +223,9 @@ private:
|
|||
|
||||
CScriptArray *_HexReader_readBytes(qsizetype offset, qsizetype len);
|
||||
|
||||
qsizetype _HexReader_searchForward(qsizetype begin, const CScriptArray &ba);
|
||||
qsizetype _HexReader_findNext(qsizetype begin, const CScriptArray &ba);
|
||||
|
||||
qsizetype _HexReader_searchBackward(qsizetype begin,
|
||||
const CScriptArray &ba);
|
||||
qsizetype _HexReader_findPrevious(qsizetype begin, const CScriptArray &ba);
|
||||
|
||||
CScriptArray *_HexReader_findAllBytes(qsizetype begin, qsizetype end,
|
||||
const CScriptArray &ba);
|
||||
|
|
|
@ -204,17 +204,20 @@ EditorView::FindError EditorView::find(const FindDialog::Result &result) {
|
|||
} break;
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
QString data;
|
||||
data = result.str;
|
||||
|
||||
qsizetype contextLen = 0;
|
||||
|
||||
if (result.isStringFind) {
|
||||
data = Utilities::encodingString(result.str, result.encoding);
|
||||
auto raw = Utilities::encodingString(data, result.encoding);
|
||||
contextLen = raw.length();
|
||||
m_findResults->setEncoding(result.encoding);
|
||||
d->findAllBytes(begin, end, raw, results);
|
||||
} else {
|
||||
data = result.buffer;
|
||||
contextLen = d->findAllBytesExt(begin, end, result.str, results);
|
||||
}
|
||||
|
||||
d->findAllBytes(begin, end, data, results);
|
||||
|
||||
m_findResults->beginUpdate();
|
||||
m_findResults->clear();
|
||||
|
||||
|
@ -226,7 +229,7 @@ EditorView::FindError EditorView::find(const FindDialog::Result &result) {
|
|||
r.col = r.offset % lineWidth;
|
||||
m_findResults->results().append(r);
|
||||
m_findResults->findData().append(
|
||||
readContextFinding(ritem, data.size(), FIND_CONTEXT_SIZE,
|
||||
readContextFinding(ritem, contextLen, FIND_CONTEXT_SIZE,
|
||||
FIND_MAX_DISPLAY_FIND_CHARS));
|
||||
}
|
||||
|
||||
|
@ -234,8 +237,7 @@ EditorView::FindError EditorView::find(const FindDialog::Result &result) {
|
|||
|
||||
m_findResults->endUpdate();
|
||||
|
||||
if (m_findResults->size() ==
|
||||
std::numeric_limits<QList<qsizetype>::size_type>::max()) {
|
||||
if (m_findResults->size() >= QHEXVIEW_FIND_LIMIT) {
|
||||
return FindError::MayOutOfRange;
|
||||
} else {
|
||||
return FindError::Success;
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "qhextextedit.h"
|
||||
|
||||
#include <QKeyEvent>
|
||||
#include <QLineEdit>
|
||||
|
||||
QHexTextEdit::QHexTextEdit(QWidget *parent)
|
||||
: QTextEdit(parent), m_isHexMode(true) {
|
||||
setLineWrapMode(QTextEdit::NoWrap);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
mCurserPositionPre = 0;
|
||||
}
|
||||
|
||||
void QHexTextEdit::keyPressEvent(QKeyEvent *event) {
|
||||
if (!m_isHexMode) {
|
||||
QTextEdit::keyPressEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
auto pressedKey = event->key();
|
||||
QTextCursor cursor = textCursor();
|
||||
auto cursorPosition = cursor.position();
|
||||
auto newCursorPosition = cursorPosition;
|
||||
auto index = cursorPosition - cursorPosition / 3;
|
||||
if (((pressedKey >= Qt::Key_0) && (pressedKey <= Qt::Key_9)) ||
|
||||
((pressedKey >= Qt::Key_A) && (pressedKey <= Qt::Key_F)) ||
|
||||
pressedKey == Qt::Key_Question) {
|
||||
mText.insert(index, event->text());
|
||||
newCursorPosition = cursorPosition + (cursorPosition % 3 + 1);
|
||||
} else if (pressedKey == Qt::Key_Backspace) {
|
||||
if (index != 0) {
|
||||
mText.remove(index - 1, 1);
|
||||
newCursorPosition = cursorPosition - 2 + (cursorPosition) % 3;
|
||||
}
|
||||
} else if (pressedKey == Qt::Key_Delete) {
|
||||
if (index != mText.length()) {
|
||||
mText.remove(index, 1);
|
||||
newCursorPosition = cursorPosition;
|
||||
}
|
||||
} else if (pressedKey == Qt::Key_Left) {
|
||||
if (index != 0) {
|
||||
newCursorPosition = cursorPosition - 2 + (cursorPosition) % 3;
|
||||
}
|
||||
} else if (pressedKey == Qt::Key_Right) {
|
||||
if (index != mText.length()) {
|
||||
newCursorPosition = cursorPosition + (cursorPosition + 1) % 3;
|
||||
}
|
||||
}
|
||||
// Allow only single-line editing
|
||||
else if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
|
||||
event->ignore(); // Ignore Enter key press to prevent new lines
|
||||
}
|
||||
|
||||
QString temp;
|
||||
for (int i = 0; i < mText.length(); i++) {
|
||||
temp.append(mText.at(i).toUpper());
|
||||
if (i % 2 == 1)
|
||||
temp.append(' ');
|
||||
}
|
||||
|
||||
setText(temp);
|
||||
cursor.setPosition(newCursorPosition);
|
||||
setTextCursor(cursor);
|
||||
mCurserPositionPre = newCursorPosition;
|
||||
}
|
||||
|
||||
void QHexTextEdit::mousePressEvent(QMouseEvent *event) {
|
||||
if (!m_isHexMode) {
|
||||
QTextEdit::mousePressEvent(event);
|
||||
return;
|
||||
}
|
||||
|
||||
QTextCursor cursor = cursorForPosition(event->pos());
|
||||
int cursorPosition = cursor.position();
|
||||
if (cursorPosition % 3 == 2) {
|
||||
cursorPosition++;
|
||||
cursor.setPosition(cursorPosition);
|
||||
mCurserPositionPre = cursorPosition;
|
||||
}
|
||||
QTextEdit::mousePressEvent(event);
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
|
||||
QSize QHexTextEdit::sizeHint() const {
|
||||
QFont font = this->font();
|
||||
QFontMetrics fontMetrics(font);
|
||||
int lineHeight = fontMetrics.lineSpacing();
|
||||
return QSize(0, lineHeight);
|
||||
}
|
||||
|
||||
bool QHexTextEdit::isHexMode() const { return m_isHexMode; }
|
||||
|
||||
void QHexTextEdit::setIsHexMode(bool newIsHexMode) {
|
||||
m_isHexMode = newIsHexMode;
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef QHEXTEXTEDIT_H
|
||||
#define QHEXTEXTEDIT_H
|
||||
|
||||
#include <QTextEdit>
|
||||
|
||||
class QHexTextEdit : public QTextEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QHexTextEdit(QWidget *parent = nullptr);
|
||||
|
||||
bool isHexMode() const;
|
||||
void setIsHexMode(bool newIsHexMode);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
private:
|
||||
QString mText;
|
||||
int mCurserPositionPre;
|
||||
bool m_isHexMode;
|
||||
};
|
||||
|
||||
#endif // QHEXTEXTEDIT_H
|
|
@ -25,60 +25,70 @@
|
|||
#include <QShortcut>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "control/toast.h"
|
||||
|
||||
FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
|
||||
: FramelessDialogBase(parent) {
|
||||
|
||||
auto widget = new QWidget(this);
|
||||
auto layout = new QVBoxLayout(widget);
|
||||
|
||||
m_string = new QRadioButton(this);
|
||||
m_string->setText(tr("findstring"));
|
||||
layout->addWidget(m_string);
|
||||
layout->addWidget(new QLabel(tr("Mode:"), this));
|
||||
m_findMode = new QComboBox(this);
|
||||
m_findMode->addItem(QStringLiteral("HEX"));
|
||||
m_findMode->addItems(Utilities::getEncodings());
|
||||
m_findMode->setCurrentIndex(1);
|
||||
|
||||
layout->addWidget(m_findMode);
|
||||
layout->addSpacing(3);
|
||||
|
||||
m_encodings = new QComboBox(this);
|
||||
m_encodings->addItems(Utilities::getEncodings());
|
||||
m_encodings->setCurrentIndex(0);
|
||||
m_encodings->setEnabled(false);
|
||||
connect(m_string, &QRadioButton::toggled, m_encodings,
|
||||
&QComboBox::setEnabled);
|
||||
layout->addWidget(m_encodings);
|
||||
layout->addSpacing(3);
|
||||
|
||||
m_lineeditor = new QLineEdit(this);
|
||||
m_lineeditor->setEnabled(false);
|
||||
connect(m_string, &QRadioButton::toggled, m_lineeditor,
|
||||
&QLineEdit::setEnabled);
|
||||
layout->addWidget(new QLabel(tr("Content:"), this));
|
||||
m_lineeditor = new QHexTextEdit(this);
|
||||
layout->addWidget(m_lineeditor);
|
||||
layout->addSpacing(3);
|
||||
|
||||
m_hex = new QRadioButton(this);
|
||||
m_hex->setText(tr("findhex"));
|
||||
layout->addWidget(m_hex);
|
||||
layout->addSpacing(3);
|
||||
layout->addWidget(new QLabel(tr("EncBytes:"), this));
|
||||
m_preview = new QTextEdit(this);
|
||||
m_preview->setFocusPolicy(Qt::NoFocus);
|
||||
m_preview->setReadOnly(true);
|
||||
m_preview->setUndoRedoEnabled(false);
|
||||
m_preview->setWordWrapMode(QTextOption::WordWrap);
|
||||
m_preview->setAcceptRichText(false);
|
||||
m_preview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
layout->addWidget(m_preview);
|
||||
|
||||
m_hexeditor = new QHexView(this);
|
||||
m_hexeditor->setAsciiVisible(false);
|
||||
m_hexeditor->setAddressVisible(false);
|
||||
m_hexeditor->setEnabled(true);
|
||||
connect(m_hex, &QRadioButton::toggled, m_hexeditor, &QHexView::setEnabled);
|
||||
layout->addWidget(m_hexeditor);
|
||||
layout->addSpacing(10);
|
||||
connect(m_lineeditor, &QHexTextEdit::textChanged, this, [this]() {
|
||||
auto text = m_lineeditor->toPlainText();
|
||||
if (m_findMode->currentIndex()) {
|
||||
auto encoding = m_findMode->currentText();
|
||||
auto dbytes = Utilities::encodingString(text, encoding);
|
||||
m_preview->setText(dbytes.toHex(' '));
|
||||
} else {
|
||||
m_preview->setText(text);
|
||||
}
|
||||
});
|
||||
connect(m_findMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
|
||||
this, [this](int index) {
|
||||
auto oldva = m_lineeditor->isHexMode();
|
||||
auto newva = index == 0;
|
||||
m_lineeditor->setIsHexMode(newva);
|
||||
if (oldva != newva) {
|
||||
m_lineeditor->clear();
|
||||
} else {
|
||||
// force update
|
||||
emit m_lineeditor->textChanged();
|
||||
}
|
||||
});
|
||||
|
||||
if (info.isStringFind) {
|
||||
m_string->setChecked(true);
|
||||
m_lineeditor->setEnabled(true);
|
||||
m_hexeditor->setEnabled(false);
|
||||
if (!info.encoding.isEmpty()) {
|
||||
m_encodings->setCurrentText(info.encoding);
|
||||
m_findMode->setCurrentText(info.encoding);
|
||||
}
|
||||
} else {
|
||||
m_hex->setChecked(true);
|
||||
m_lineeditor->setEnabled(false);
|
||||
m_hexeditor->setEnabled(true);
|
||||
m_findMode->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
m_lineeditor->setText(info.str);
|
||||
m_hexeditor->document()->_insert(0, info.buffer);
|
||||
|
||||
auto regionw = new QWidget(this);
|
||||
auto regionLayout = new QHBoxLayout(regionw);
|
||||
|
@ -106,8 +116,6 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
|
|||
m_regionStop->setPrefix(QStringLiteral("0x"));
|
||||
regionLayout->addWidget(m_regionStop, 1);
|
||||
|
||||
layout->addWidget(regionw);
|
||||
|
||||
auto group = new QButtonGroup(this);
|
||||
group->setExclusive(true);
|
||||
|
||||
|
@ -134,8 +142,8 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
|
|||
if (b) {
|
||||
_result.dir = SearchDirection::Region;
|
||||
}
|
||||
m_regionStart->setEnabled(b);
|
||||
m_regionStop->setEnabled(b);
|
||||
regionw->setVisible(b);
|
||||
regionw->setEnabled(b);
|
||||
});
|
||||
group->addButton(b, id++);
|
||||
buttonLayout->addWidget(b);
|
||||
|
@ -177,7 +185,7 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
|
|||
group->button(info.isBigFile ? 1 : 0)->setChecked(true);
|
||||
|
||||
layout->addWidget(btnBox);
|
||||
layout->addSpacing(20);
|
||||
|
||||
auto dbbox = new QDialogButtonBox(
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
|
||||
connect(dbbox, &QDialogButtonBox::accepted, this, &FindDialog::on_accept);
|
||||
|
@ -185,25 +193,42 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
|
|||
auto key = QKeySequence(Qt::Key_Return);
|
||||
auto s = new QShortcut(key, this);
|
||||
connect(s, &QShortcut::activated, this, &FindDialog::on_accept);
|
||||
|
||||
layout->addWidget(regionw);
|
||||
regionw->hide();
|
||||
|
||||
layout->addSpacing(20);
|
||||
layout->addWidget(dbbox);
|
||||
|
||||
buildUpContent(widget);
|
||||
this->setWindowTitle(tr("find"));
|
||||
|
||||
m_lineeditor->setFocus();
|
||||
}
|
||||
|
||||
FindDialog::Result FindDialog::getResult() const { return _result; }
|
||||
|
||||
void FindDialog::on_accept() {
|
||||
_result.start = 0;
|
||||
_result.stop = 0;
|
||||
_result.isStringFind = m_findMode->currentIndex() > 0;
|
||||
_result.str = m_lineeditor->toPlainText().trimmed();
|
||||
|
||||
if (!_result.isStringFind) {
|
||||
// check the last byte nibbles
|
||||
if (std::next(_result.str.rbegin())->isSpace()) {
|
||||
Toast::toast(this, NAMEICONRES("find"), tr("InvalidHexSeq"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_regionStart->isEnabled()) {
|
||||
_result.start = m_regionStart->value();
|
||||
_result.stop = m_regionStop->value();
|
||||
} else {
|
||||
_result.start = 0;
|
||||
_result.stop = 0;
|
||||
}
|
||||
_result.encoding = m_encodings->currentText();
|
||||
_result.isStringFind = m_string->isChecked();
|
||||
_result.buffer = m_hexeditor->document()->read(0);
|
||||
_result.str = m_lineeditor->text();
|
||||
|
||||
_result.encoding = m_findMode->currentText();
|
||||
done(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef FINDDIALOG_H
|
||||
#define FINDDIALOG_H
|
||||
|
||||
#include "QHexView/qhexview.h"
|
||||
#include "control/qhextextedit.h"
|
||||
#include "control/qtlonglongspinbox.h"
|
||||
#include "framelessdialogbase.h"
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
|||
#include <QLineEdit>
|
||||
#include <QObject>
|
||||
#include <QRadioButton>
|
||||
#include <QTextEdit>
|
||||
|
||||
enum class SearchDirection { None, Region, Foreword, Backword, Selection };
|
||||
|
||||
|
@ -39,7 +40,6 @@ public:
|
|||
|
||||
// for searching info
|
||||
bool isStringFind;
|
||||
QByteArray buffer;
|
||||
QString encoding;
|
||||
QString str;
|
||||
};
|
||||
|
@ -66,11 +66,9 @@ private:
|
|||
void on_reject();
|
||||
|
||||
private:
|
||||
QHexView *m_hexeditor;
|
||||
QLineEdit *m_lineeditor;
|
||||
QRadioButton *m_string;
|
||||
QRadioButton *m_hex;
|
||||
QComboBox *m_encodings;
|
||||
QHexTextEdit *m_lineeditor;
|
||||
QComboBox *m_findMode;
|
||||
QTextEdit *m_preview;
|
||||
|
||||
QtLongLongSpinBox *m_regionStart;
|
||||
QtLongLongSpinBox *m_regionStop;
|
||||
|
|
|
@ -661,9 +661,6 @@ MainWindow::buildUpFindResultDock(ads::CDockManager *dock,
|
|||
m_findresult->setModel(_findEmptyResult);
|
||||
m_findEncoding.value(_findEmptyResult->encoding())->setChecked(true);
|
||||
|
||||
header->setSectionResizeMode(3, QHeaderView::Stretch);
|
||||
header->setSectionResizeMode(4, QHeaderView::Stretch);
|
||||
|
||||
connect(m_findresult, &QTableView::doubleClicked, this,
|
||||
[=](const QModelIndex &index) {
|
||||
auto editor =
|
||||
|
@ -2301,7 +2298,6 @@ void MainWindow::on_findfile() {
|
|||
auto r = fd.getResult();
|
||||
info.isStringFind = r.isStringFind;
|
||||
info.encoding = r.encoding;
|
||||
info.buffer = r.buffer;
|
||||
info.str = r.str;
|
||||
|
||||
ExecAsync<EditorView::FindError>(
|
||||
|
@ -2775,8 +2771,7 @@ void MainWindow::on_exportfindresult() {
|
|||
|
||||
auto d = findresitem->lastFindData();
|
||||
|
||||
fobj.insert(QStringLiteral("find"),
|
||||
QString::fromLatin1(d.toHex(' ').toUpper()));
|
||||
fobj.insert(QStringLiteral("find"), d);
|
||||
QJsonArray arr;
|
||||
for (int i = 0; i < c; i++) {
|
||||
auto data = findresitem->resultAt(i);
|
||||
|
|
|
@ -133,7 +133,7 @@ QList<FindResultModel::FindInfo> &FindResultModel::findData() {
|
|||
return m_findData;
|
||||
}
|
||||
|
||||
QByteArray &FindResultModel::lastFindData() { return m_lastFindData; }
|
||||
QString &FindResultModel::lastFindData() { return m_lastFindData; }
|
||||
|
||||
void FindResultModel::beginUpdate() { this->beginResetModel(); }
|
||||
|
||||
|
@ -146,6 +146,7 @@ WingHex::FindResult FindResultModel::resultAt(qsizetype index) const {
|
|||
void FindResultModel::clear() {
|
||||
m_results.clear();
|
||||
m_findData.clear();
|
||||
emit layoutChanged();
|
||||
}
|
||||
|
||||
QList<WingHex::FindResult>::size_type FindResultModel::size() const {
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
|
||||
QList<WingHex::FindResult> &results();
|
||||
QList<FindInfo> &findData();
|
||||
QByteArray &lastFindData();
|
||||
QString &lastFindData();
|
||||
|
||||
void beginUpdate();
|
||||
void endUpdate();
|
||||
|
@ -63,7 +63,7 @@ public:
|
|||
private:
|
||||
QList<WingHex::FindResult> m_results;
|
||||
QList<FindInfo> m_findData;
|
||||
QByteArray m_lastFindData;
|
||||
QString m_lastFindData;
|
||||
|
||||
QString m_encoding;
|
||||
};
|
||||
|
|
|
@ -142,10 +142,9 @@ signals:
|
|||
const QString &encoding = QString());
|
||||
Q_REQUIRED_RESULT QByteArray readBytes(qsizetype offset, qsizetype count);
|
||||
|
||||
Q_REQUIRED_RESULT qsizetype searchForward(qsizetype begin,
|
||||
const QByteArray &ba);
|
||||
Q_REQUIRED_RESULT qsizetype searchBackward(qsizetype begin,
|
||||
const QByteArray &ba);
|
||||
Q_REQUIRED_RESULT qsizetype findNext(qsizetype begin, const QByteArray &ba);
|
||||
Q_REQUIRED_RESULT qsizetype findPrevious(qsizetype begin,
|
||||
const QByteArray &ba);
|
||||
Q_REQUIRED_RESULT QList<qsizetype>
|
||||
findAllBytes(qsizetype begin, qsizetype end, const QByteArray &b);
|
||||
|
||||
|
|
|
@ -1875,9 +1875,9 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
|
|||
_rwlock.lockForRead();
|
||||
auto hexeditor = e->hexEditor();
|
||||
auto doc = hexeditor->document();
|
||||
auto pos = doc->searchForward(offset, QByteArray(1, 0));
|
||||
auto pos = doc->findNext(offset, QByteArray(1, 0));
|
||||
if (pos < 0) {
|
||||
pos = doc->searchForward(offset, QByteArray(1, '\n'));
|
||||
pos = doc->findNext(offset, QByteArray(1, '\n'));
|
||||
if (pos < 0) {
|
||||
return QString();
|
||||
}
|
||||
|
@ -1900,20 +1900,19 @@ void PluginSystem::connectReaderInterface(IWingPlugin *plg) {
|
|||
}
|
||||
return results;
|
||||
});
|
||||
connect(preader, &WingPlugin::Reader::searchForward, _win,
|
||||
connect(preader, &WingPlugin::Reader::findNext, _win,
|
||||
[=](qsizetype begin, const QByteArray &ba) -> qsizetype {
|
||||
auto e = pluginCurrentEditor(plg);
|
||||
if (e) {
|
||||
return e->hexEditor()->document()->searchForward(begin, ba);
|
||||
return e->hexEditor()->document()->findNext(begin, ba);
|
||||
}
|
||||
return qsizetype(-1);
|
||||
});
|
||||
connect(preader, &WingPlugin::Reader::searchBackward, _win,
|
||||
connect(preader, &WingPlugin::Reader::findPrevious, _win,
|
||||
[=](qsizetype begin, const QByteArray &ba) -> qsizetype {
|
||||
auto e = pluginCurrentEditor(plg);
|
||||
if (e) {
|
||||
return e->hexEditor()->document()->searchBackward(begin,
|
||||
ba);
|
||||
return e->hexEditor()->document()->findPrevious(begin, ba);
|
||||
}
|
||||
return qsizetype(-1);
|
||||
});
|
||||
|
|
|
@ -149,6 +149,7 @@ public:
|
|||
}
|
||||
}
|
||||
#endif
|
||||
encodings.sort();
|
||||
}
|
||||
|
||||
return encodings;
|
||||
|
|
Loading…
Reference in New Issue