fix: 修复损坏的搜索上下文显示;增强脚本宏和增加内置宏;

This commit is contained in:
寂静的羽夏 2025-05-05 15:05:33 +08:00
parent 3f26766575
commit 960de3afb6
25 changed files with 1607 additions and 1397 deletions

View File

@ -437,17 +437,17 @@ void QHexDocument::findAllBytes(qsizetype begin, qsizetype end,
}
}
qsizetype QHexDocument::findAllBytesExt(qsizetype begin, qsizetype end,
const QString &pattern,
QList<qsizetype> &results,
const std::function<bool()> &pred) {
void QHexDocument::findAllBytesExt(qsizetype begin, qsizetype end,
const QString &pattern,
QList<qsizetype> &results,
const std::function<bool()> &pred) {
results.clear();
if (end < 0) {
end = m_buffer->length();
}
if (pattern.isEmpty() || end > m_buffer->length() || begin >= end) {
return -1;
return;
}
qsizetype pos = begin;
qsizetype n = pattern.size();
@ -461,7 +461,6 @@ qsizetype QHexDocument::findAllBytesExt(qsizetype begin, qsizetype end,
break;
}
}
return results.isEmpty() ? -1 : results.first();
}
bool QHexDocument::insert(qsizetype offset, uchar b) {

View File

@ -107,7 +107,7 @@ public:
QList<qsizetype> &results,
const std::function<bool()> &pred = [] { return true; });
qsizetype findAllBytesExt(
void findAllBytesExt(
qsizetype begin, qsizetype end, const QString &pattern,
QList<qsizetype> &results,
const std::function<bool()> &pred = [] { return true; });

@ -1 +1 @@
Subproject commit 8d86c185041572bd4735b272669d4117765c2176
Subproject commit 1f53c308498e529e5cfbed16c9f7f68c77a3e8e5

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -55,6 +55,7 @@
<item>typedef</item>
<item>while</item>
<item>xor</item>
<item>co_await</item>
</list>
<list name="types">
<item>void</item>

View File

@ -102,6 +102,15 @@ void AsCompletion::applyEmptyNsNode(QList<CodeInfoTip> &nodes,
tip.name = p.nameSpace;
nodes.append(tip);
}
if (p.type == CodeInfoTip::Type::Class) {
for (auto &c : p.children) {
if (c.type == CodeInfoTip::Type::ClsFunction ||
c.type == CodeInfoTip::Type::Property) {
nodes.append(c);
}
}
}
}
nodes.append(emptyNsNodes);

View File

@ -40,7 +40,8 @@ ASDataBase::ASDataBase(asIScriptEngine *engine) {
"function", "interface", "shared", "this", "explicit", "override",
"namespace", "get", "set", "super", "mixin", "false",
"true", "null", "typename", "return", "typedef", "funcdef",
"from", "import", "not", "xor", "or", "is"};
"from", "import", "not", "xor", "or", "is",
"co_await"};
for (auto &k : kws) {
CodeInfoTip t;
t.type = CodeInfoTip::Type::KeyWord;

View File

@ -16,17 +16,25 @@
*/
#include "aspreprocesser.h"
#include "class/languagemanager.h"
#include "class/qascodeparser.h"
#include "class/scriptmachine.h"
#include "class/skinmanager.h"
#include "scriptaddon/aspromise.hpp"
#include <QDir>
#include <QFileInfo>
#include <QLibraryInfo>
#include <QMetaEnum>
#include <QStack>
#include <QVersionNumber>
Q_GLOBAL_STATIC_WITH_ARGS(
QByteArrayList, DEFAULT_MARCO,
({"__AS_ARRAY__", "__AS_ANY__", "__AS_GRID__", "__AS_HANDLE__",
({// special marcos
"__LINE__", "__SECTION__",
// functions
"__AS_ARRAY__", "__AS_ANY__", "__AS_GRID__", "__AS_HANDLE__",
"__AS_MATH__", "__AS_WEAKREF__", "__AS_COROUTINE__", "__WING_FILE__",
"__WING_STRING__", "__WING_COLOR__", "__WING_JSON__", "__WING_REGEX__",
"__WING_DICTIONARY__", "__WING_PRINT_VAR__", "__WING_PRINT_LN__",
@ -44,6 +52,55 @@ AsPreprocesser::AsPreprocesser(asIScriptEngine *engine) : engine(engine) {
for (auto &m : *DEFAULT_MARCO) {
definedWords.insert(m, {});
}
static QHash<QString, QByteArray> addInfos;
if (addInfos.isEmpty()) {
// software infos
auto ver = QVersionNumber::fromString(WINGHEX_VERSION);
addInfos.insert(QStringLiteral("__WING_VERSION__"),
"\"" WINGHEX_VERSION "\"");
addInfos.insert(QStringLiteral("__WING_VERSION_MAJOR__"),
QByteArray::number(ver.majorVersion()));
addInfos.insert(QStringLiteral("__WING_VERSION_MINOR__"),
QByteArray::number(ver.minorVersion()));
addInfos.insert(QStringLiteral("__WING_VERSION_PATCH__"),
QByteArray::number(ver.microVersion()));
addInfos.insert(QStringLiteral("__ANGELSCRIPT_VERSION__"),
"\"" ANGELSCRIPT_VERSION_STRING "\"");
addInfos.insert(QStringLiteral("__ANGELSCRIPT_VERSION_MAJOR__"),
QByteArray::number(ANGELSCRIPT_VERSION / 10000));
addInfos.insert(QStringLiteral("__ANGELSCRIPT_VERSION_MINOR__"),
QByteArray::number((ANGELSCRIPT_VERSION / 100) % 100));
addInfos.insert(QStringLiteral("__ANGELSCRIPT_VERSION_PATCH__"),
QByteArray::number(ANGELSCRIPT_VERSION % 100));
addInfos.insert(QStringLiteral("__WINGHEX_APPNAME__"),
"\"" APP_NAME "\"");
addInfos.insert(QStringLiteral("__WINGHEX_AUTHOR__"), "\"wingsummer\"");
ver = QLibraryInfo::version();
addInfos.insert(QStringLiteral("__QT_VERSION__"),
ver.toString().toUtf8().prepend('"').append('"'));
addInfos.insert(QStringLiteral("__QT_VERSION_MAJOR__"),
QByteArray::number(ver.majorVersion()));
addInfos.insert(QStringLiteral("__QT_VERSION_MINOR__"),
QByteArray::number(ver.minorVersion()));
addInfos.insert(QStringLiteral("__QT_VERSION_PATCH__"),
QByteArray::number(ver.microVersion()));
// UI
addInfos.insert(QStringLiteral("__LANG__"), LanguageManager::instance()
.defaultLocale()
.name()
.toUtf8()
.prepend('"')
.append('"'));
auto theme = SkinManager::instance().currentTheme();
auto te = QMetaEnum::fromType<SkinManager::Theme>();
addInfos.insert(
QStringLiteral("__THEME__"),
QByteArray(te.valueToKey(int(theme))).prepend('"').append('"'));
}
definedWords.insert(addInfos);
}
AsPreprocesser::~AsPreprocesser() { void ClearAll(); }
@ -130,6 +187,8 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
QStack<std::optional<bool>> m_condtionStack;
while (pos < modifiedScript.size()) {
auto SECTION = sectionname.toUtf8();
asUINT len = 0;
asETokenClass t = engine->ParseToken(modifiedScript.data() + pos,
modifiedScript.size() - pos, &len);
@ -164,7 +223,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
}
auto str = QObject::tr("IfDefNoWord");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -209,7 +268,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
#endif
} else {
auto str = QObject::tr("IfDefInvalidWord");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -218,7 +277,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
// ensure end line
if (endLinePassFailed(modifiedScript, pos)) {
auto str = QObject::tr("UnexceptedToken");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -246,11 +305,15 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
auto &sm = ScriptMachine::instance();
bool ok = false;
auto ret = sm.evaluateDefine(codes, ok);
// if expression should processed the marcos
auto ret = sm.evaluateDefine(
processIfExpression(
codes, getLineCount(modifiedScript, pos), SECTION),
ok);
if (ret < 0) {
auto str = QObject::tr("CalIfFailed");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -314,7 +377,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
default:
auto str = QObject::tr("UnexceptedToken");
engine->WriteMessage(
sectionname.toUtf8(),
SECTION,
getLineCount(modifiedScript, pos), 1,
asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -329,8 +392,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
if (endLinePassFailed(modifiedScript, pos)) {
auto str = QObject::tr("UnexceptedToken");
engine->WriteMessage(
sectionname.toUtf8(),
getLineCount(modifiedScript, pos), 1,
SECTION, getLineCount(modifiedScript, pos), 1,
asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
}
@ -348,7 +410,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
continue;
}
auto str = QObject::tr("InvalidDef");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -376,16 +438,14 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
// Warning
auto str = QObject::tr("ReservedMarcoType");
engine->WriteMessage(
sectionname.toUtf8(),
getLineCount(modifiedScript, pos), 1,
SECTION, getLineCount(modifiedScript, pos), 1,
asMSGTYPE_WARNING, str.toUtf8());
} else {
if (!definedWords.remove(word)) {
auto str = QObject::tr("MarcoNotFound:") + word;
engine->WriteMessage(
sectionname.toUtf8(),
getLineCount(modifiedScript, pos), 1,
asMSGTYPE_WARNING, str.toUtf8());
SECTION, getLineCount(modifiedScript, pos),
1, asMSGTYPE_WARNING, str.toUtf8());
}
}
@ -393,14 +453,13 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
if (endLinePassFailed(modifiedScript, pos)) {
auto str = QObject::tr("UnexceptedToken");
engine->WriteMessage(
sectionname.toUtf8(),
getLineCount(modifiedScript, pos), 1,
SECTION, getLineCount(modifiedScript, pos), 1,
asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
}
} else {
auto str = QObject::tr("InvalidDef");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -413,7 +472,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
}
if (m_condtionStack.isEmpty()) {
auto str = QObject::tr("NoMatchingIf");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos), 1,
asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -430,14 +489,13 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
if (endLinePassFailed(modifiedScript, pos - 1)) {
auto str = QObject::tr("UnexceptedToken");
engine->WriteMessage(
sectionname.toUtf8(),
getLineCount(modifiedScript, pos), 1,
SECTION, getLineCount(modifiedScript, pos), 1,
asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
}
} else {
auto str = QObject::tr("DupElseDef");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -454,7 +512,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
// Only remove the #endif if there was a matching #if
if (m_condtionStack.isEmpty()) {
auto str = QObject::tr("NoMatchingIf");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos), 1,
asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -466,7 +524,7 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
// ensure end line
if (endLinePassFailed(modifiedScript, pos)) {
auto str = QObject::tr("UnexceptedToken");
engine->WriteMessage(sectionname.toUtf8(),
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos), 1,
asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
@ -476,13 +534,59 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
#endif
}
} else {
if (t == asTC_IDENTIFIER) {
// define replace
auto word = modifiedScript.sliced(pos, len);
auto rword = findReplaceResult(word);
if (word != rword) {
modifiedScript.replace(pos, len, rword);
len = rword.length();
if (!_isCodeCompleteMode) {
if (t == asTC_IDENTIFIER) {
// define replace
auto word = modifiedScript.sliced(pos, len);
if (word == PROMISE_AWAIT) {
auto npos = pos + len;
asUINT total = 0;
auto t = engine->ParseToken(
modifiedScript.data() + npos,
modifiedScript.size() - npos, &total);
if (t == asTC_WHITESPACE) {
npos += total;
t = engine->ParseToken(modifiedScript.data() + npos,
modifiedScript.size() - npos,
&total);
if (t == asTC_IDENTIFIER) {
// ok
auto word = modifiedScript.sliced(npos, total);
auto data = "(" + word +
")." PROMISE_YIELD
"()." PROMISE_UNWRAP "()";
auto oldLen = npos - pos + word.length();
modifiedScript.replace(pos, oldLen, data);
pos = npos;
pos += data.length() - oldLen + word.length();
continue;
}
}
auto str = QObject::tr("UnexceptedToken");
engine->WriteMessage(SECTION,
getLineCount(modifiedScript, pos),
1, asMSGTYPE_ERROR, str.toUtf8());
return asERROR;
} else if (word == "__LINE__") {
auto data = QByteArray::number(
getLineCount(modifiedScript, pos));
modifiedScript.replace(pos, len, data);
pos += data.length();
continue;
} else if (word == "__SECTION__") {
auto data = SECTION;
data.prepend('"').append('"');
modifiedScript.replace(pos, len, data);
pos += data.length();
continue;
} else {
auto rword = findReplaceResult(word);
if (word != rword) {
modifiedScript.replace(pos, len, rword);
len = rword.length();
}
}
}
}
pos += len;
@ -658,12 +762,6 @@ int AsPreprocesser::processScriptSection(const QByteArray &script,
}
}
// asPromise co_await keyword expansion
size_t len = modifiedScript.size();
auto data = AsGeneratePromiseEntrypoints(modifiedScript.data(), &len);
modifiedScript = QByteArray(data, len);
asFreeMem(data);
// Build the actual script
engine->SetEngineProperty(asEP_COPY_SCRIPT_SECTIONS, true);
@ -720,9 +818,6 @@ int AsPreprocesser::loadScriptSection(const QString &filename) {
QFileInfo(filename).absoluteFilePath() + QStringLiteral("'");
engine->WriteMessage(filename.toUtf8(), 0, 0, asMSGTYPE_ERROR,
msg.toUtf8());
// TODO: Write the file where this one was included from
return -1;
}
@ -888,6 +983,37 @@ bool AsPreprocesser::endLinePassFailed(const QByteArray &modifiedScript,
return endError;
}
QByteArray
AsPreprocesser::processIfExpression(const QByteArray &codes, int currentLine,
const QByteArray &currentSection) {
QByteArray ret;
int pos = 0;
auto total = codes.length();
while (pos < total) {
asUINT len = 0;
auto t =
engine->ParseToken(codes.data() + pos, codes.size() - pos, &len);
auto word = codes.sliced(pos, len);
if (t == asTC_IDENTIFIER) {
if (word == "__LINE__") {
ret.append(currentLine);
} else if (word == "__SECTION__") {
auto s = currentSection;
s.prepend('"').append('"');
ret.append(s);
} else {
ret.append(findReplaceResult(word));
}
} else {
ret.append(word);
}
pos += len;
}
return ret;
}
QByteArray AsPreprocesser::findReplaceResult(const QByteArray &v) {
QByteArray r = v;
while (definedWords.contains(r)) {

View File

@ -138,6 +138,9 @@ protected:
bool endLinePassFailed(const QByteArray &modifiedScript, int pos);
QByteArray processIfExpression(const QByteArray &codes, int currentLine,
const QByteArray &currentSection);
QByteArray findReplaceResult(const QByteArray &v);
asIScriptEngine *engine;

View File

@ -3126,8 +3126,8 @@ void PluginSystem::applyFunctionTables(IWingPluginBase *plg,
plg->setProperty("__CALL_POINTER__", quintptr(this));
}
QString PluginSystem::type2AngelScriptString(IWingPlugin::MetaType type,
bool isArg, bool noModifier) {
QString PluginSystem::type2AngelScriptString(uint type, bool isArg,
bool noModifier) {
auto isArray = !!(type & WingHex::IWingPlugin::Array);
auto isList = !!(type & WingHex::IWingPlugin::List);
auto isContainer = isArray || isList;

View File

@ -175,8 +175,8 @@ public:
static QString getPUID(IWingPluginBase *p);
static QString type2AngelScriptString(IWingPlugin::MetaType type,
bool isArg, bool noModifier = false);
static QString type2AngelScriptString(uint type, bool isArg,
bool noModifier = false);
private:
void loadExtPlugin();

View File

@ -147,7 +147,6 @@ bool ScriptMachine::isRunning(ConsoleMode mode) const {
#define INS_2 INS_1 ", " INS_1
#define INS_4 INS_2 ", " INS_2
#define INS_8 INS_4 ", " INS_4
#define INS_16 INS_8 ", " INS_8
bool ScriptMachine::configureEngine() {
if (_engine == nullptr) {
@ -219,7 +218,7 @@ bool ScriptMachine::configureEngine() {
// Register a couple of extra functions for the scripts
r = _engine->RegisterGlobalFunction(
"void print(const ? &in obj, const ? &in = null," INS_16 ")",
"void print(const ? &in obj, const ? &in = null," INS_8 ")",
asFUNCTION(print), asCALL_GENERIC);
Q_ASSERT(r >= 0);
if (r < 0) {
@ -227,7 +226,7 @@ bool ScriptMachine::configureEngine() {
}
r = _engine->RegisterGlobalFunction(
"void println(const ? &in obj, const ? &in = null," INS_16 ")",
"void println(const ? &in obj, const ? &in = null," INS_8 ")",
asFUNCTION(println), asCALL_GENERIC);
Q_ASSERT(r >= 0);
if (r < 0) {
@ -680,7 +679,7 @@ int ScriptMachine::evaluateDefine(const QString &code, bool &result) {
QScopeGuard guard([this, oldMode]() { _curMsgMode = oldMode; });
auto ccode = code;
ccode.prepend("bool f(){ return (").append(");}");
ccode.prepend("bool f(){ return bool(").append(");}");
// start to compile
_curMsgMode = DefineEvaluator;

View File

@ -95,7 +95,7 @@ WingCStruct::WingCStruct() : WingHex::IWingPlugin() {
info.fn = std::bind(
QOverload<const QVariantList &>::of(&WingCStruct::structTypes),
this, std::placeholders::_1);
info.ret = MetaType(MetaType::String | MetaType::Array);
info.ret = MetaType::String | MetaType::Array;
_scriptInfo.insert(QStringLiteral("structTypes"), info);
}
@ -125,7 +125,7 @@ WingCStruct::WingCStruct() : WingHex::IWingPlugin() {
info.fn = std::bind(
QOverload<const QVariantList &>::of(&WingCStruct::constDefines),
this, std::placeholders::_1);
info.ret = MetaType(MetaType::String | MetaType::Array);
info.ret = MetaType::String | MetaType::Array;
_scriptInfo.insert(QStringLiteral("constDefines"), info);
}
@ -166,7 +166,7 @@ WingCStruct::WingCStruct() : WingHex::IWingPlugin() {
info.fn = std::bind(
QOverload<const QVariantList &>::of(&WingCStruct::readRaw), this,
std::placeholders::_1);
info.ret = MetaType(MetaType::Byte | MetaType::Array);
info.ret = MetaType::Byte | MetaType::Array;
info.params.append(
qMakePair(getqsizetypeMetaType(), QStringLiteral("offset")));
@ -542,7 +542,6 @@ CScriptDictionary *WingCStruct::convert2AsDictionary(const QVariantHash &hash) {
switch (type) {
case QMetaType::Bool:
case QMetaType::UChar:
case QMetaType::Char:
case QMetaType::Int:
case QMetaType::Long:
case QMetaType::LongLong:
@ -564,6 +563,13 @@ CScriptDictionary *WingCStruct::convert2AsDictionary(const QVariantHash &hash) {
case QMetaType::Float:
dic->Set(p->first, var.toDouble());
break;
case QMetaType::Char: {
auto v = var.value<char>();
auto ch = new QChar(v);
auto id = engine->GetTypeIdByDecl("char");
dic->Set(p->first, ch, id);
break;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
case QMetaType::Char16: {
auto v = var.value<char16_t>();

View File

@ -242,8 +242,12 @@ EditorView::FindError EditorView::find(const FindDialog::Result &result) {
contextLen = raw.length();
m_findResults->setEncoding(result.encoding);
d->findAllBytes(begin, end, raw, results);
m_findResults->lastFindData() = qMakePair(data, contextLen);
} else {
contextLen = d->findAllBytesExt(begin, end, result.str, results);
// assuming the find pattern is 'xx xx xx xx'
contextLen = std::count(data.begin(), data.end(), ' ') + 1;
d->findAllBytesExt(begin, end, result.str, results);
m_findResults->lastFindData() = qMakePair(data, contextLen);
}
m_findResults->beginUpdate();
@ -257,12 +261,9 @@ EditorView::FindError EditorView::find(const FindDialog::Result &result) {
r.col = r.offset % lineWidth;
m_findResults->results().append(r);
m_findResults->findData().append(
readContextFinding(ritem, contextLen, FIND_CONTEXT_SIZE,
FIND_MAX_DISPLAY_FIND_CHARS));
readContextFinding(ritem, contextLen));
}
m_findResults->lastFindData() = data;
m_findResults->endUpdate();
if (m_findResults->size() >= QHEXVIEW_FIND_LIMIT) {
@ -804,34 +805,50 @@ bool EditorView::checkHasUnsavedState() const {
}
FindResultModel::FindInfo EditorView::readContextFinding(qsizetype offset,
qsizetype findSize,
int contextSize,
int maxDisplayBytes) {
qsizetype findSize) {
constexpr long DISPLAY_SIZE = 16;
constexpr long FIND_CONTENXT_LEN = 10;
constexpr long HT_SIZE = (DISPLAY_SIZE - FIND_CONTENXT_LEN) / 2;
auto doc = m_hex->document();
if (findSize <= FIND_CONTENXT_LEN) {
long leftsize = FIND_CONTENXT_LEN - findSize;
auto rs = std::div(leftsize, 2l);
qsizetype halfSize = maxDisplayBytes / 2;
auto header = doc->read(offset, qMin(findSize, halfSize));
QByteArray tailer;
if (header.size() < findSize) {
auto len = qMin(findSize, qsizetype(maxDisplayBytes) - halfSize);
tailer = doc->read(offset + findSize - len, len);
auto headerlen = HT_SIZE + rs.quot + rs.rem;
auto taillen = HT_SIZE + rs.quot;
auto begin = qMax(offset - headerlen, 0);
auto end = qMin(offset + findSize + taillen, doc->length());
auto boff = offset - begin;
auto buffer = doc->read(begin, end - begin + 1);
FindResultModel::FindInfo info;
info.cheader = buffer.left(boff);
info.hbuffer = buffer.sliced(boff, findSize);
info.tbuffer = {};
info.ctailer = buffer.sliced(boff + findSize);
return info;
} else {
constexpr long FIND_CONTENXT_HALF = FIND_CONTENXT_LEN / 2;
auto hbegin = qMax(offset - HT_SIZE, 0);
auto hlen = offset - hbegin + FIND_CONTENXT_HALF;
auto header = doc->read(hbegin, hlen);
auto toff = offset - hbegin;
auto tbegin = offset + findSize - FIND_CONTENXT_HALF;
auto tlen = HT_SIZE + FIND_CONTENXT_HALF;
auto tailer = doc->read(tbegin, tlen);
FindResultModel::FindInfo info;
info.cheader = header.left(toff);
info.hbuffer = header.sliced(toff);
info.tbuffer = tailer.left(FIND_CONTENXT_HALF);
info.ctailer = tailer.sliced(FIND_CONTENXT_HALF);
return info;
}
auto left = qsizetype(maxDisplayBytes) - header.size() - tailer.size();
// append to contextSize
contextSize += (left / 2);
auto cheader = doc->read(offset - contextSize, contextSize);
auto ctailer = doc->read(offset + findSize, contextSize);
FindResultModel::FindInfo info;
info.cheader = cheader;
info.hbuffer = header;
info.tbuffer = tailer;
info.ctailer = ctailer;
return info;
}
void EditorView::applyFunctionTables(WingEditorViewWidget *view,

View File

@ -225,9 +225,7 @@ private:
bool checkHasUnsavedState() const;
FindResultModel::FindInfo readContextFinding(qsizetype offset,
qsizetype findSize,
int contextSize,
int maxDisplayBytes);
qsizetype findSize);
void applyFunctionTables(WingHex::WingEditorViewWidget *view,
const CallTable &fns);

View File

@ -102,3 +102,17 @@ bool QHexTextEdit::isHexMode() const { return m_isHexMode; }
void QHexTextEdit::setIsHexMode(bool newIsHexMode) {
m_isHexMode = newIsHexMode;
}
void QHexTextEdit::setFindText(const QString &text) {
mText = text;
mText = mText
.removeIf([](const QChar &ch) {
return !std::isalnum(ch.unicode()) && ch != '?';
})
.toUpper();
setText(text);
auto cur = this->textCursor();
cur.movePosition(QTextCursor::End);
setTextCursor(cur);
mCurserPositionPre = cur.position();
}

View File

@ -28,6 +28,10 @@ public:
bool isHexMode() const;
void setIsHexMode(bool newIsHexMode);
public:
// must be 'xx xx xx' style
void setFindText(const QString &text);
protected:
void keyPressEvent(QKeyEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;

View File

@ -52,6 +52,7 @@ void ScrollableLabel::wheelEvent(QWheelEvent *event) {
void ScrollableLabel::resizeEvent(QResizeEvent *event) {
QScrollArea::resizeEvent(event);
updateLabelSize();
adjustDisplayLogic();
}
void ScrollableLabel::setupUI() {
@ -60,7 +61,7 @@ void ScrollableLabel::setupUI() {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
label.setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
label.setAlignment(Qt::AlignRight | Qt::AlignVCenter);
label.setWordWrap(false);
label.setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
@ -82,3 +83,18 @@ void ScrollableLabel::updateLabelSize() {
bool ScrollableLabel::shouldScroll() const {
return label.width() > viewport()->width();
}
void ScrollableLabel::adjustDisplayLogic() {
QFontMetrics fm(label.font());
const int contentWidth = fm.horizontalAdvance(label.text());
const int containerWidth = width();
if (contentWidth > containerWidth) {
label.setFixedSize(contentWidth, fm.height());
label.setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
horizontalScrollBar()->setValue(0);
} else {
label.setFixedSize(containerWidth, fm.height());
label.setAlignment(Qt::AlignRight | Qt::AlignVCenter);
}
}

View File

@ -47,6 +47,8 @@ private:
void updateLabelSize();
bool shouldScroll() const;
void adjustDisplayLogic();
};
#endif // MARQUEELABEL_H

View File

@ -89,7 +89,7 @@ FindDialog::FindDialog(const FindInfo &info, QWidget *parent)
m_findMode->setCurrentIndex(0);
}
m_lineeditor->setText(info.str);
m_lineeditor->setFindText(info.str);
auto regionw = new QWidget(this);
auto regionLayout = new QHBoxLayout(regionw);

View File

@ -714,10 +714,17 @@ MainWindow::buildUpFindResultDock(ads::CDockManager *dock,
cursor->moveTo(fm->resultAt(index.row()).offset);
if (cursor->selectionCount() <= 1 && index.column() >= 3) {
cursor->select(fm->lastFindData().length());
cursor->select(fm->lastFindData().second);
}
});
auto header = m_findresult->horizontalHeader();
auto font = QFontMetrics(m_findresult->font());
auto len = font.horizontalAdvance('F') * (15 + 16 * 2);
if (header->sectionSize(3) < len) {
header->resizeSection(3, len);
}
auto dw = buildDockWidget(dock, QStringLiteral("FindResult"),
tr("FindResult") + QStringLiteral(" (ASCII)"),
m_findresult);
@ -2127,7 +2134,6 @@ void MainWindow::on_findfile() {
ExecAsync<EditorView::FindError>(
[this, r]() -> EditorView::FindError {
m_isfinding = true;
return currentEditor()->find(r);
},
[this](EditorView::FindError err) {
@ -2151,6 +2157,14 @@ void MainWindow::on_findfile() {
if (result) {
m_findEncoding.value(result->encoding())->setChecked(true);
}
auto header = m_findresult->horizontalHeader();
auto font = QFontMetrics(m_findresult->font());
auto len = font.horizontalAdvance('F') * (15 + 16 * 2);
if (header->sectionSize(3) < len) {
header->resizeSection(3, len);
}
m_find->raise();
m_isfinding = false;
@ -2595,7 +2609,7 @@ void MainWindow::on_exportfindresult() {
auto d = findresitem->lastFindData();
fobj.insert(QStringLiteral("find"), d);
fobj.insert(QStringLiteral("find"), d.first);
QJsonArray arr;
for (int i = 0; i < c; i++) {
auto data = findresitem->resultAt(i);

View File

@ -135,7 +135,9 @@ QList<FindResultModel::FindInfo> &FindResultModel::findData() {
return m_findData;
}
QString &FindResultModel::lastFindData() { return m_lastFindData; }
QPair<QString, qsizetype> &FindResultModel::lastFindData() {
return m_lastFindData;
}
void FindResultModel::beginUpdate() { this->beginResetModel(); }

View File

@ -42,7 +42,7 @@ public:
QList<FindResult> &results();
QList<FindInfo> &findData();
QString &lastFindData();
QPair<QString, qsizetype> &lastFindData();
void beginUpdate();
void endUpdate();
@ -67,7 +67,7 @@ public:
private:
QList<FindResult> m_results;
QList<FindInfo> m_findData;
QString m_lastFindData;
QPair<QString, qsizetype> m_lastFindData;
QString m_encoding;
};

View File

@ -52,9 +52,6 @@
#define PROEXT ".wingpro"
Q_DECL_UNUSED constexpr auto FIND_CONTEXT_SIZE = 3;
Q_DECL_UNUSED constexpr auto FIND_MAX_DISPLAY_FIND_CHARS = 8;
Q_DECL_UNUSED static inline QString NAMEICONRES(const QString &name) {
return ":/com.wingsummer.winghex/images/" + name + ".png";
}